:root{
  --color-bg:#202020;
  --color-black:#000;
  --color-text:#b9b9b9;
  --color-text-muted:#8b8b8b;
  --color-border:#4d4d4d;
  --color-white:#fff;
  --color-paper:#fff;
  --color-accent:#19A9E6;          /* was #ff5841 (red) — the only changed colour value */
  --color-accent-rgb:25,169,230;
  --font-display:"BarlowCondensed",sans-serif;
  --font-body:"NonSans",sans-serif;
  --font-mono:"Archivo",sans-serif;
  /* Custom noise overlay tuning */
  --mz-noise-opacity:0.4;
  --mz-noise-blend:normal;
  --mz-noise-z:9998;
}

/* Disable the captured site's JS TV-static canvas */
canvas.-noise{display:none!important;}

/* Replace the WebGL form background with a flat blue painted on the section itself (behind all content) */
.form-gl{display:none!important;}
.form-bg{display:none!important;}
.-component.form{background:var(--color-accent)!important;}

@font-face{
  font-family:Archivo;
  src:url("/fonts/archivo-latin-600-normal.woff2") format("woff2");
  font-display:swap;
  font-style:normal;
  /* single 600 cut mapped to all weights so every old AuxMono rule renders it */
  font-weight:100 900;
}
@font-face{
  font-family:BarlowCondensed;
  src:url("/fonts/barlow-condensed-latin-500-normal.woff2") format("woff2");
  font-display:swap;
  font-style:normal;
  font-weight:500;
}
@font-face{
  font-family:BarlowCondensed;
  src:url("/fonts/barlow-condensed-latin-600-normal.woff2") format("woff2");
  font-display:swap;
  font-style:normal;
  font-weight:600;
}
@font-face{
  font-family:BarlowCondensed;
  src:url("/fonts/barlow-condensed-latin-700-normal.woff2") format("woff2");
  font-display:swap;
  font-style:normal;
  font-weight:700;
}

/* ============================================================================
   Approach — second homepage section under the hero. Clean editorial block in
   the shared section rhythm (marker + headline/lede + two columns), matching the
   spacing, type scales and IntersectionObserver reveal of .mz-about / .mz-faq.
   Global because the page <head> is built via set:html.
   ============================================================================ */
/* ============================================================================
   ROI & Image Section — Split-screen "Aside" Layout
   (Modelled after the GPS Jamming section on Warehouse & Industrial)
   ============================================================================ */
.mz-roi-split{
  position:relative;
  width:100%;
  background:var(--color-bg);
  color:var(--color-text);
  border-top:1px solid var(--color-border);
  padding:clamp(6rem,8vw,12rem) clamp(3.2rem,5vw,7rem);
}
.mz-roi-split__inner{
  display:grid;
  grid-template-columns:minmax(0, 1fr) minmax(320px, 420px);
  gap:clamp(3rem, 6vw, 8rem);
  align-items:start;
}
@media (max-width: 980px) {
  .mz-roi-split__inner{
    grid-template-columns:1fr;
  }
}
.mz-roi-split__media{
  position:relative;
  width:100%;
  height:clamp(360px, 50vh, 600px);
  border-radius:12px;
  overflow:hidden;
  border:1px solid var(--color-border);
}
.mz-roi-split__media img{
  width:100%;
  height:100%;
  object-fit:cover;
  display:block;
}
.mz-roi-split__aside{
  display:flex;
  flex-direction:column;
  border-top:1px solid var(--color-border);
  padding-top:2.4rem;
}
.mz-roi-split__header{
  display:flex;
  align-items:flex-start;
  gap:1.6rem;
  margin-bottom:3.2rem;
}
.mz-roi-split__icon{
  width:40px;
  height:40px;
  flex:0 0 auto;
}
.mz-roi-split__title{
  margin:0;
  font-family:var(--font-mono),monospace;
  font-size:12px;
  letter-spacing:.08em;
  text-transform:uppercase;
  color:var(--color-white);
  padding-top:4px;
}
.mz-roi-split__content{
  display:flex;
  flex-direction:column;
  gap:2.4rem;
}
.mz-roi-split__headline{
  margin:0;
  font-family:var(--font-display),sans-serif;
  font-weight:500;
  font-size:clamp(2.8rem, 3.5vw, 4rem);
  line-height:1.05;
  letter-spacing:-.02em;
  color:var(--color-white);
}
.mz-roi-split__lead{
  margin:0;
  font-family:var(--font-body),sans-serif;
  font-weight:500;
  font-size:clamp(1.6rem, 1.4vw, 2rem);
  line-height:1.4;
  color:var(--color-white);
}
.mz-roi-split__body{
  margin:0;
  font-family:var(--font-body),sans-serif;
  font-size:clamp(1.4rem, 1.2vw, 1.6rem);
  line-height:1.6;
  color:var(--color-text-muted);
}

/* CTA button in the projects panel. Single source of truth: overrides the
   captured .insight-button rule (fixed 120px / 48px) so the pill sizes to its
   label with balanced padding, one height, perfectly centred text, and a clean
   invert on hover with no layout shift (border stays 1px in both states). */
.insightsBlock .mz-ctabtn{
  display:inline-flex!important;
  align-items:center;
  justify-content:center;
  width:auto!important;
  min-width:0!important;
  height:4.6rem!important;
  padding:0 2.6rem!important;
  border:1px solid var(--color-text)!important;
  border-radius:999px!important;
  background:var(--color-white);
  color:var(--color-bg);
  font-size:1.3rem;
  font-weight:500;
  letter-spacing:.04em;
  line-height:1;
  white-space:nowrap;
  text-align:center;
  box-sizing:border-box;
  transition:background .2s ease,color .2s ease;
}
.insightsBlock .mz-ctabtn:hover{
  background:transparent;
  color:var(--color-text)!important;
  border:1px solid var(--color-text)!important;
}

.mz-approach{
  background:var(--color-bg);color:var(--color-text);
  border-top:1px solid var(--color-border);
}
.mz-approach__inner{
  padding:clamp(5.5rem,8vw,10rem) clamp(3.2rem,5vw,7rem);
}
.mz-approach__marker{
  display:inline-flex;align-items:center;gap:1rem;margin:0 0 clamp(3rem,5vw,4.5rem);
  font-family:var(--font-mono),monospace;font-size:12px;letter-spacing:.08em;
  text-transform:uppercase;color:var(--color-white);
}
.mz-approach__dot{width:7px;height:7px;border-radius:50%;background:var(--color-accent);display:inline-block}

.mz-approach__lede{
  display:grid;grid-template-columns:minmax(0,1.12fr) minmax(0,.88fr);
  gap:clamp(2.5rem,6vw,6rem);align-items:start;
  padding-bottom:clamp(4rem,7vw,7rem);
}
.mz-approach__headline{
  margin:0;font-family:var(--font-body),sans-serif;font-weight:500;
  font-size:clamp(3rem,4vw,5rem);line-height:1.02;letter-spacing:-.03em;
  text-transform:uppercase;color:var(--color-white);
}
.mz-approach__hl-line{display:block;white-space:nowrap}
.mz-approach__support{display:flex;flex-direction:column;gap:1.4rem;padding-top:.6rem}
.mz-approach__lead{
  margin:0;font-family:var(--font-body),sans-serif;font-weight:500;
  font-size:clamp(1.9rem,1.6vw,2.3rem);line-height:1.3;letter-spacing:-.01em;
  color:var(--color-white);max-width:30ch;
}
.mz-approach__body{
  margin:0;font-family:var(--font-body),sans-serif;
  font-size:clamp(1.5rem,1.2vw,1.7rem);line-height:1.6;color:var(--color-text-muted);
  max-width:46ch;text-wrap:pretty;
}

.mz-approach__cols{
  display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:clamp(2rem,4vw,4rem);
}
.mz-approach__col{
  display:flex;flex-direction:column;gap:1.4rem;
  padding-top:clamp(1.2rem,1.6vw,1.6rem);border-top:1px solid var(--color-border);
}
.mz-approach__eyebrow{
  display:flex;align-items:center;gap:1rem;margin:0;
  font-family:var(--font-mono),monospace;font-size:12px;letter-spacing:.08em;
  text-transform:uppercase;color:var(--color-white);
}
.mz-approach__tick{width:7px;height:7px;background:var(--color-accent);display:inline-block}
.mz-approach__coltext{
  margin:0;font-family:var(--font-body),sans-serif;
  font-size:clamp(1.5rem,1.2vw,1.7rem);line-height:1.6;color:var(--color-text-muted);
  text-wrap:pretty;
}
.mz-approach__link{
  display:inline-flex;align-items:center;gap:1rem;margin-top:.4rem;
  font-family:var(--font-mono),monospace;font-size:12px;letter-spacing:.06em;
  text-transform:uppercase;color:var(--color-white);text-decoration:none;transition:color .25s ease;
}
.mz-approach__arrow{transition:transform .25s ease,color .25s ease}
.mz-approach__link:hover{color:var(--color-accent)}
.mz-approach__link:hover .mz-approach__arrow{transform:translateX(6px);color:var(--color-accent)}

/* Entrance reveal (IntersectionObserver toggles [data-revealed]) — matches siblings. */
.mz-approach .mz-approach__support,
.mz-approach .mz-approach__cols,
.mz-approach .mz-approach__hl-line{
  opacity:0;transform:translateY(18px);
  transition:opacity .8s cubic-bezier(.22,1,.36,1),transform .8s cubic-bezier(.22,1,.36,1);
  will-change:opacity,transform;
}
.mz-approach .mz-approach__hl-line:nth-child(2){transition-delay:.08s}
.mz-approach .mz-approach__hl-line:nth-child(3){transition-delay:.16s}
.mz-approach[data-revealed] .mz-approach__support,
.mz-approach[data-revealed] .mz-approach__cols,
.mz-approach[data-revealed] .mz-approach__hl-line{opacity:1;transform:translateY(0)}
.mz-approach[data-revealed] .mz-approach__support{transition-delay:.12s}
.mz-approach[data-revealed] .mz-approach__cols{transition-delay:.2s}

@media (max-width:980px) and (min-width:751px){
  .mz-approach__lede{grid-template-columns:1fr;gap:clamp(1.6rem,4vw,2.6rem)}
  .mz-approach__support{padding-top:0}
  .mz-approach__lead{max-width:none}
}
@media (max-width:750px){
  .mz-approach__lede{grid-template-columns:1fr;gap:1.8rem;padding-bottom:3rem}
  .mz-approach__support{padding-top:0}
  .mz-approach__headline{font-size:clamp(2.6rem,9vw,3.4rem);letter-spacing:-.02em}
  .mz-approach__hl-line{white-space:normal}
  .mz-approach__lead{max-width:none}
  .mz-approach__cols{grid-template-columns:1fr;gap:2rem}
}
@media (prefers-reduced-motion:reduce){
  .mz-approach .mz-approach__support,
  .mz-approach .mz-approach__cols,
  .mz-approach .mz-approach__hl-line{opacity:1!important;transform:none!important;transition:none!important}
}

/* Native scroll restore — pairs with isSmooth=!1 patch in the JS bundle.
   The captured native-scroll path reads scroll from pageContent.parentNode,
   where pageContent = .app, so BODY is the scroll container the engine expects.
   getScroll()/ScrollTrigger read body.scrollTop, so every section reveal fires.
   This is the exact path the real site runs on mobile. */
html { overflow: hidden !important; height: 100vh !important; }
body { height: var(--vh, 100vh) !important; overflow-y: auto !important; overflow-x: hidden !important; }

/* Insights sticky-scroll pin — native CSS replacement for the disabled smooth engine.
   Original design pinned .sticky-content via per-frame transform; with smooth off,
   the JS pin is dead and the .-fixed fallback loses to the scoped position:absolute.
   Re-implement as native position:sticky: lay the two columns side by side in flow,
   the 72rem left panel sticks while the taller 72rem articles column scrolls past.
   Scoped to the same min-width:750px the captured desktop rules use, so the mobile
   .insightsBlock-nonSticky stacked variant is untouched. */
@media screen and (min-width:750px){
  .insightsBlock .insightsBlock-sticky{
    display:flex !important;
    align-items:flex-start !important;
  }
  .insightsBlock .sticky-content{
    position:sticky !important;
    top:0 !important;
    height:100vh !important;
    height:var(--vh,100vh) !important;
    width:72rem !important;
    flex:0 0 72rem !important;
    transform:none !important;
  }
  /* Neutralise the dead JS .-fixed toggle: keep it sticky, never position:fixed full-screen. */
  .insightsBlock .sticky-content.-fixed{
    position:sticky !important;
    top:0 !important;
    left:auto !important;
    width:72rem !important;
    height:100vh !important;
    height:var(--vh,100vh) !important;
  }
  /* Articles is now the second flex column, not an absolute-overlay offset. */
  .insightsBlock .sticky-articles{
    margin-left:0 !important;
    flex:1 1 auto !important;
  }
}

/* ============================================================================
   Mezzanine Floor 3D — scroll-driven wireframe section (ported from Mezzanine
   Production, themed to this site). Styles live here (global) because the page
   <head> is built via set:html, so Astro cannot inject scoped <style>.
   Selectors are prefixed (.mz-floor3d / .mz-morph / .mz-floor3d__tick); the
   .mezzfloor3d / .mezzfloor3d__canvas rules are kept verbatim — the renderer
   appends its <canvas> into .mezzfloor3d__canvas.
   ============================================================================ */
.mz-floor3d{
  position:relative;
  display:grid;
  grid-template-columns:1fr 1fr;
  background:var(--color-bg);
  color:var(--color-text);
  border-top:1px solid var(--color-border);
}
/* Brand accent line down the centre divide. */
.mz-floor3d::before{
  content:"";
  position:absolute;
  top:0;bottom:0;left:50%;
  width:1px;
  background:var(--color-accent);
  z-index:2;
  pointer-events:none;
}
.mz-floor3d > *{position:relative;z-index:1;}

/* Left copy column — sticky on desktop so it holds while the right track scrolls. */
.mz-floor3d__copy{
  display:flex;
  flex-direction:column;
  gap:clamp(1.8rem,2vw,2.6rem);
  padding:clamp(3.2rem,5vw,7rem);
  align-self:start;
}
.mz-floor3d__title{
  font-family:var(--font-body);
  font-weight:500;
  color:var(--color-white);
  font-size:clamp(3.4rem,4vw,5.4rem);
  line-height:1.05;
  letter-spacing:-.01em;
  margin:0;
  max-width:18ch;
}
.mz-floor3d__lead{
  font-family:var(--font-body);
  font-size:clamp(1.4rem,1.1vw,1.6rem);
  line-height:1.55;
  color:var(--color-text);
  margin:0;
  max-width:46ch;
}
.mz-floor3d__lead--muted{color:rgba(255,255,255,0.55);}
.mz-floor3d__support{display:flex;flex-direction:column;gap:clamp(1.4rem,1.6vw,2rem);max-width:48ch;}

/* Right viz column — the tall pinned scroll track. */
.mz-floor3d__viz{position:relative;}
.mz-morph{height:250vh;}
.mz-morph__sticky{
  position:sticky;
  top:0;
  height:100vh;
  height:var(--vh,100vh);
  display:flex;
  flex-direction:column;
}
.mz-floor3d__canvas-wrap{
  position:absolute;
  inset:0;
  z-index:1;
}
/* Drafting data labels sit above the 3D canvas. */
.mz-floor3d__data{
  position:absolute;
  left:clamp(1.6rem,2.5vw,3.2rem);
  bottom:clamp(1.6rem,2.5vw,3.2rem);
  z-index:2;
  display:flex;
  flex-direction:column;
  gap:0.2rem;
}
.mz-floor3d__tick{
  font-family:var(--font-mono);
  font-size:clamp(9px,0.625rem,11px);
  line-height:1.25;
  letter-spacing:0.02em;
  color:var(--color-text-muted);
  opacity:0;
  transform:translateY(6px);
  transition:opacity .5s ease-out, transform .5s ease-out;
}
.mz-floor3d__tick.is-on{opacity:1;transform:translateY(0);}

/* Canvas container (kept verbatim from the source MezzanineFloor3D style). */
.mezzfloor3d{
  position:absolute;
  inset:0;
  width:100%;
  height:100%;
}
.mezzfloor3d__canvas{
  position:absolute;
  inset:0;
  width:100%;
  height:100%;
  background:transparent;
  opacity:0;
  transition:opacity 600ms ease-out;
}
.mezzfloor3d__canvas.is-ready{opacity:1;}
.mezzfloor3d__canvas canvas{
  display:block;
  width:100%!important;
  height:100%!important;
}

/* Desktop: pin the copy column while the right track scrolls. */
@media (min-width:981px){
  .mz-floor3d__copy{position:sticky;top:0;height:100vh;height:var(--vh,100vh);justify-content:space-between;padding-top:clamp(4rem,7vw,8rem);padding-bottom:clamp(4rem,7vw,8rem);}
}

@media (prefers-reduced-motion: reduce){
  .mz-floor3d__tick{opacity:1;transform:none;transition:none;}
}

/* Tablet + mobile keep the SAME pinned 100vh scroll-scrub as desktop — the
   250vh track, sticky viewport and scroll-driven build all stay live at every
   width. Only the column layout adapts: side-by-side down to 750px, stacked
   (copy above, full-screen pinned canvas below) on phones. */
@media (max-width:980px){
  .mz-floor3d::before{display:none;}
  .mz-floor3d__copy{padding-bottom:1.5rem;}
}
@media (max-width:749px){
  .mz-floor3d{grid-template-columns:1fr;}
}

/* ============================================================================
   About Mezzanine — editorial proof section (ported from Mezzanine Production
   Section_About, themed dark for this site). Global (page head is set:html).
   Type scales mirror .mz-approach so they survive the site's fluid root size.
   Sits between InsightsBlock and the email CTA.
   ============================================================================ */
.mz-about{
  background:var(--color-bg);
  color:var(--color-text);
  border-top:1px solid var(--color-border);
}
.mz-about__inner{
  padding:clamp(5.5rem,8vw,10rem) clamp(3.2rem,5vw,7rem);
}
.mz-about__marker{
  display:inline-flex;align-items:center;gap:1rem;margin:0 0 clamp(3rem,5vw,4.5rem);
  font-family:var(--font-mono),monospace;font-size:12px;letter-spacing:.08em;
  text-transform:uppercase;color:var(--color-white);
}
.mz-about__dot{width:7px;height:7px;border-radius:50%;background:var(--color-accent);display:inline-block}

.mz-about__lede{
  display:grid;grid-template-columns:minmax(0,1.12fr) minmax(0,.88fr);
  gap:clamp(2.5rem,6vw,6rem);align-items:start;
  padding-bottom:clamp(4rem,7vw,7rem);
}
.mz-about__headline{
  margin:0;font-family:var(--font-body),sans-serif;font-weight:500;
  font-size:clamp(3rem,4vw,5rem);line-height:1.02;letter-spacing:-.03em;
  text-transform:uppercase;color:var(--color-white);
}
.mz-about__hl-line{display:block;white-space:nowrap}
.mz-about__support{display:flex;flex-direction:column;gap:1.4rem;padding-top:.6rem}
.mz-about__body{
  margin:0;font-family:var(--font-body),sans-serif;
  font-size:clamp(1.5rem,1.2vw,1.7rem);line-height:1.6;color:var(--color-text-muted);
  max-width:46ch;text-wrap:pretty;
}
.mz-about__body:first-child{color:var(--color-text)}

.mz-about__stats{
  list-style:none;margin:0;padding:0;display:grid;
  grid-template-columns:repeat(4,minmax(0,1fr));gap:clamp(1.8rem,3vw,3rem);
}
.mz-about__stat{
  display:flex;flex-direction:column;padding-top:clamp(1.2rem,1.6vw,1.6rem);
  border-top:1px solid var(--color-border);
}
.mz-about__stat-body{display:flex;flex-direction:column;gap:.9rem}
.mz-about__figure{
  font-family:var(--font-body),sans-serif;font-weight:500;
  font-size:clamp(2.8rem,3.2vw,3.6rem);line-height:1;letter-spacing:-.03em;
  color:var(--color-white);font-variant-numeric:tabular-nums;
}
.mz-about__kicker{
  font-family:var(--font-body),sans-serif;font-weight:500;
  font-size:clamp(1.7rem,1.6vw,2.1rem);line-height:1.15;letter-spacing:-.01em;
  color:var(--color-white);text-wrap:balance;
}
.mz-about__label{
  font-family:var(--font-mono),monospace;font-size:12px;line-height:1.5;
  letter-spacing:.01em;color:var(--color-text-muted);max-width:30ch;
}

/* Entrance reveal (IntersectionObserver toggles [data-revealed]). */
.mz-about .mz-about__support,
.mz-about .mz-about__stats,
.mz-about .mz-about__hl-line{
  opacity:0;transform:translateY(18px);
  transition:opacity .8s cubic-bezier(.22,1,.36,1),transform .8s cubic-bezier(.22,1,.36,1);
  will-change:opacity,transform;
}
.mz-about .mz-about__hl-line:nth-child(2){transition-delay:.08s}
.mz-about .mz-about__hl-line:nth-child(3){transition-delay:.16s}
.mz-about[data-revealed] .mz-about__support,
.mz-about[data-revealed] .mz-about__stats,
.mz-about[data-revealed] .mz-about__hl-line{opacity:1;transform:translateY(0)}
.mz-about[data-revealed] .mz-about__support{transition-delay:.12s}
.mz-about[data-revealed] .mz-about__stats{transition-delay:.2s}

@media (max-width:980px) and (min-width:751px){
  .mz-about__lede{grid-template-columns:1fr;gap:clamp(1.6rem,4vw,2.6rem)}
  .mz-about__support{padding-top:0}
  .mz-about__body{max-width:60ch}
  .mz-about__stats{grid-template-columns:repeat(2,minmax(0,1fr))}
}
@media (max-width:750px){
  .mz-about__lede{grid-template-columns:1fr;gap:1.8rem;padding-bottom:3rem}
  .mz-about__support{padding-top:0}
  .mz-about__headline{font-size:clamp(2.6rem,9vw,3.4rem);letter-spacing:-.02em}
  .mz-about__hl-line{white-space:normal}
  .mz-about__body{max-width:none}
  .mz-about__stats{grid-template-columns:repeat(2,minmax(0,1fr));gap:2rem 1.4rem}
}
@media (prefers-reduced-motion:reduce){
  .mz-about .mz-about__support,
  .mz-about .mz-about__stats,
  .mz-about .mz-about__hl-line{opacity:1!important;transform:none!important;transition:none!important}
}

/* ============================================================================
   Value accordion / FAQ (ported from Mezzanine Production Section08). Three
   options that expand/collapse with sibling auto-close. Global (set:html head).
   Sits between InsightsBlock and the email CTA. Type scales mirror .mz-approach
   so they survive the site's fluid root size.
   ============================================================================ */
.mz-faq{
  background:var(--color-bg);
  color:var(--color-text);
  border-top:1px solid var(--color-border);
}
.mz-faq__inner{
  display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1.05fr);
  gap:clamp(2.5rem,6vw,7rem);align-items:start;
  padding:clamp(5.5rem,8vw,10rem) clamp(3.2rem,5vw,7rem);
}
.mz-faq__marker{
  display:inline-flex;align-items:center;gap:1rem;margin:0 0 clamp(1.8rem,2.5vw,2.6rem);
  font-family:var(--font-mono),monospace;font-size:12px;letter-spacing:.08em;
  text-transform:uppercase;color:var(--color-white);
}
.mz-faq__dot{width:7px;height:7px;border-radius:50%;background:var(--color-accent);display:inline-block}
.mz-faq__headline{
  margin:0;font-family:var(--font-body),sans-serif;font-weight:500;
  font-size:clamp(2.4rem,3vw,3.6rem);line-height:1.08;letter-spacing:-.02em;
  color:var(--color-white);max-width:18ch;
}

/* ---- Accordion ---- */
.mz-faq__list{display:flex;flex-direction:column;border-top:1px solid var(--color-border)}
.mz-faq__item{border-bottom:1px solid var(--color-border)}
.mz-faq__head{
  display:flex;align-items:center;justify-content:space-between;gap:2rem;
  padding:clamp(1.8rem,2.2vw,2.4rem) 0;cursor:pointer;outline:none;
}
.mz-faq__head:focus-visible{outline:2px solid var(--color-accent);outline-offset:4px}
.mz-faq__title{
  font-family:var(--font-body),sans-serif;font-weight:500;
  font-size:clamp(1.6rem,1.7vw,2.1rem);line-height:1.15;letter-spacing:-.01em;
  color:var(--color-white);transition:color .25s ease;
}
.mz-faq__item.is-open .mz-faq__title{color:var(--color-accent)}

/* Plus icon that becomes a minus on open. */
.mz-faq__icon{position:relative;flex:0 0 auto;width:18px;height:18px;transition:transform .4s cubic-bezier(.53,0,0,1)}
.mz-faq__icon::before,.mz-faq__icon::after{
  content:"";position:absolute;top:50%;left:50%;background:var(--color-accent);
  transform:translate(-50%,-50%);
}
.mz-faq__icon::before{width:100%;height:2px}
.mz-faq__icon::after{width:2px;height:100%;transition:transform .4s cubic-bezier(.53,0,0,1)}
.mz-faq__item.is-open .mz-faq__icon{transform:rotate(90deg)}
.mz-faq__item.is-open .mz-faq__icon::after{transform:translate(-50%,-50%) scaleY(0)}

.mz-faq__panel{height:0;overflow:hidden;transition:height .6s cubic-bezier(.53,0,0,1)}
.mz-faq__panel-inner{padding:0 0 clamp(1.8rem,2.2vw,2.4rem)}
.mz-faq__body{
  margin:0 0 1.6rem;font-family:var(--font-body),sans-serif;
  font-size:clamp(1.5rem,1.2vw,1.7rem);line-height:1.6;color:var(--color-text-muted);
  max-width:52ch;text-wrap:pretty;
}
/* Supporting copy under the headline */
.mz-faq__sub{
  margin:clamp(1.8rem,2.5vw,2.6rem) 0 0;max-width:38ch;
  font-family:var(--font-body),sans-serif;
  font-size:clamp(1.5rem,1.2vw,1.7rem);line-height:1.6;
  color:var(--color-text-muted);text-wrap:pretty;
}
/* "Still have a question?" prompt, given extra space above */
.mz-faq__prompt{
  margin:clamp(4.5rem,7vw,7rem) 0 clamp(1.6rem,2vw,2rem);
  font-family:var(--font-mono),monospace;font-size:12px;letter-spacing:.06em;
  text-transform:uppercase;color:var(--color-white);
}
/* Talk To Us button */
.mz-faq__btn{
  display:inline-flex;align-items:center;gap:1.2rem;
  padding:1.4rem 2.4rem;border-radius:4px;
  background:var(--color-accent);color:var(--color-bg);
  font-family:var(--font-mono),monospace;font-size:12px;letter-spacing:.06em;
  text-transform:uppercase;text-decoration:none;
  transition:background .25s ease,transform .25s ease;
}
.mz-faq__arrow{transition:transform .25s ease}
.mz-faq__btn:hover{background:var(--color-white)}
.mz-faq__btn:hover .mz-faq__arrow{transform:translateX(5px)}
.mz-faq__btn:focus-visible{outline:2px solid var(--color-accent);outline-offset:4px}

@media (max-width:900px){
  .mz-faq__inner{grid-template-columns:1fr;gap:clamp(2.5rem,6vw,3.5rem)}
  .mz-faq__headline{max-width:none}
}
@media (prefers-reduced-motion:reduce){
  .mz-faq__panel,.mz-faq__icon,.mz-faq__icon::after{transition:none!important}
}

/* Note: mz-band has been removed and merged into mz-roi-combined */

/* Hero description — lift the intro line clear of the big wordmark (the captured
   left:52rem/top:25rem sat it right against the title). Desktop only; the
   stacked tablet/mobile layout is static so top/left are ignored there. */
@media (min-width:1024px){
  .heroHome .hero-description{ top:9rem !important; left:56rem !important; }
}

/* Tablet hero: the captured absolute position puts the supporting line across
   the H1 between 750px and 1023px. Keep both elements in normal flow at this
   range so the spacing responds to line wrapping instead of fixed coordinates. */
@media (min-width:750px) and (max-width:1023px){
  .heroHome .block-item{padding-top:18rem!important;}
  .heroHome .hero-description{
    position:relative!important;
    inset:auto!important;
    width:min(320px,50%)!important;
    margin:0 0 3.2rem auto!important;
  }
  .heroHome .hero-title{max-width:100%!important;}
}

/* Narrow desktop hero: the fixed side rail can be taller than the left column,
   which stretches .hero-block and leaves a blank white strip below the three
   detail cards. Let the image take up that flexible height so the cards remain
   compact and finish flush with the bottom of the hero. */
@media (min-width:1025px) and (max-width:1279px){
  .heroHome .hero-block{
    display:flex!important;
    flex-direction:column;
  }
  .heroHome .hero-video{
    flex:1 1 60rem;
    height:auto!important;
    min-height:60rem;
  }
  .heroHome .hero-news.news-1{flex:0 0 auto;}
}

/* Americana grey flag block (homepage) — fill space, intro on top */
.data-flag[data-astro-cid-7qqgpkyr]{justify-content:space-between!important;}
/* The white flag panel pins to the viewport top while its column is sticky, which
   parked the intro copy underneath the fixed MENU pill. Clear the header zone on
   sticky layouts (>=750px); the stacked mobile flow never sits under the pill. */
@media (min-width:750px){
  .data-flag[data-astro-cid-7qqgpkyr]{padding-top:104px!important;}
}
.data-flagIntro{margin:0;color:var(--color-bg);font-family:var(--font-body),sans-serif;font-size:clamp(1.4rem,1.1vw,1.6rem);line-height:1.5;max-width:34ch;}
.data-flagBottom{display:flex;flex-direction:column;}

/* Homepage 3D wireframe section (.mz-tab3d) — dark-grey + blue text blocks on the
   LEFT (sticky), scroll-driven 3D wireframe on a black RIGHT. Original block fonts
   come from the -p2 / -p type classes; only colour, spacing and layout set here. */
.mz-tab3d{align-items:start !important;background:var(--color-black) !important;}
.mz-tab3d::before{display:none !important;}
@media (min-width:981px){ .mz-tab3d{grid-template-columns:36rem 1fr !important;} }
.mz-tab3d__aside{
  position:sticky;top:0;height:100vh;height:var(--vh,100vh);
  display:flex;flex-direction:column;z-index:2;grid-column:1 / 2;
}
.mz-tab3d__grey{
  flex:1 1 auto;background:var(--color-bg);
  display:flex;flex-direction:column;justify-content:center;
  gap:clamp(1.4rem,2vw,2rem);padding:clamp(2.8rem,4vw,5rem) clamp(2.4rem,3vw,4rem);
}
.mz-tab3d__blue{
  flex:0 0 auto;min-height:34%;background:var(--color-accent);
  display:flex;flex-direction:column;justify-content:center;
  padding:clamp(2.8rem,4vw,5rem) clamp(2.4rem,3vw,4rem);
}
.mz-tab3d__title{margin:0;color:var(--color-white);}        /* font: -p2 (NonSans) */
.mz-tab3d__text{margin:0;color:var(--color-text);max-width:36ch;line-height:1.5;}  /* font: -p (mono) */
.mz-tab3d__bluetext{margin:0;color:var(--color-bg);max-width:30ch;}  /* font: -p2 (NonSans) */
.mz-tab3d .mz-floor3d__viz{grid-column:2 / 3;}
/* Tablet: keep the desktop pin (sticky aside + scrubbed canvas) with a fixed
   300px text column so the canvas keeps most of the width. */
@media (min-width:750px) and (max-width:980px){
  .mz-tab3d{grid-template-columns:300px 1fr !important;}
}
/* Phones: the WHOLE section locks as one 100vh screen, like desktop. Copy and
   canvas share the same grid cell — the compacted copy pins over the top of the
   full-screen canvas for the entire 250vh scrub, model framed in the space
   below it (camera drops the model lower on narrow canvases in JS). */
@media (max-width:749px){
  .mz-tab3d__aside{
    grid-row:1;grid-column:1 / -1;
    position:sticky;top:0;height:auto;align-self:start;z-index:3;
  }
  .mz-tab3d .mz-floor3d__viz{grid-row:1;grid-column:1 / -1;}
  .mz-tab3d__blue{min-height:0;}
  /* Compact copy so the canvas keeps most of the locked screen; top padding
     clears the fixed header logo, which floats over the pinned copy. */
  .mz-tab3d__grey{padding:8rem 1.6rem 2rem;gap:1rem;}
  .mz-tab3d__blue{padding:1.6rem;}
}


/* Americana CTA panel on mobile — the captured 6.4rem arrow icon overlapped the
   "Book a free site assessment" title in the short 20rem panel. Shrink the icon,
   start the title below it, and let the panel grow with its copy. */
@media screen and (max-width:749px){
  .aside-cta[data-astro-cid-giso643g]{height:auto!important;min-height:20rem;padding-bottom:1.6rem;}
  .aside-cta[data-astro-cid-giso643g] .cta-icon[data-astro-cid-giso643g]{height:4.4rem;width:4.4rem;}
  .aside-cta[data-astro-cid-giso643g] .cta-label[data-astro-cid-giso643g]{margin-top:6.4rem;padding-right:0;}
}

/* Americana white flag on mobile — the captured markup swaps in the .asset-2
   clone below 750px with a fixed 20rem height, which clips our longer copy
   ("Created in South Africa" was cut by the section edge). Let it grow. */
@media screen and (max-width:749px){
  .CTALayout[data-astro-cid-7qqgpkyr] .asset-2[data-astro-cid-7qqgpkyr]{height:auto!important;min-height:20rem;}
}

/* Hero "What We Handle" panel on tablet (750-1024) — the captured grid gives the
   right column two 300px rows, stretching the charcoal stats panel to 600px for
   ~260px of content. Tighten the rows and spread title/list so the panel reads
   composed instead of bottom-heavy. */
@media (min-width:750px) and (max-width:1024px){
  .heroHome[data-astro-cid-ndoubqpd] .hero-aside[data-astro-cid-ndoubqpd]{grid-template-rows:220px 220px!important;}
  .heroHome[data-astro-cid-ndoubqpd] .aside-stats[data-astro-cid-ndoubqpd]{justify-content:space-between!important;}
  /* The CTA keeps a captured 300px fixed height, which the 220px row crops —
     match it to the row so the "Explore Our Solutions" label stays visible. */
  .heroHome[data-astro-cid-ndoubqpd] .aside-cta[data-astro-cid-giso643g]{height:220px!important;}
  .heroHome[data-astro-cid-ndoubqpd] .aside-cta[data-astro-cid-giso643g] .cta-link[data-astro-cid-giso643g]{height:100%!important;}
}

/* ============================================================================
   Menu overlay on phones — match the desktop look: floating white rounded
   panel top-right with dark links, instead of the captured full-screen blue
   takeover. Same markup, same GSAP open/close timeline.
   ============================================================================ */
@media screen and (max-width:749px){
  .mobile-menu{
    background:transparent!important;
    top:1.6rem!important;
    right:1.6rem!important;
    left:auto!important;
    width:calc(100% - 3.2rem)!important;
    min-width:0!important;
    height:auto!important;
    min-height:0!important;
    max-height:calc(100vh - 3.2rem)!important;
    border-radius:8px!important;
    overflow:hidden!important;
  }
  .mobile-menu .mobile-bg{background:var(--color-white)!important;}
  .mobile-menu .mobile-content{
    min-height:0!important;
    height:auto!important;
    align-items:flex-start!important;
    /* top padding clears the LOGO / close row so it reads as the panel header */
    padding:7.2rem 2.4rem 3.6rem!important;
  }
  .mobile-menu .menu-list{display:flex!important;flex-direction:column!important;gap:1.6rem!important;}
  .mobile-menu .menu-item{font-size:3.2rem!important;line-height:1.15!important;}
  /* margin, not padding — the engine's accordion measures clientHeight to
     decide open/closed, and padding would keep it non-zero when collapsed */
  .mobile-menu .submenu-list{margin-top:.6rem!important;}
  .mobile-menu .submenu-item{padding-top:.4rem!important;padding-bottom:.4rem!important;}
  /* The header (logo included) stacks above the panel so the close button stays
     reachable — fade the logo out while the menu is open so it sits "behind". */
  .header.isOpen .logo-link{opacity:0!important;pointer-events:none!important;transition:opacity .25s ease!important;}
}

/* ============================================================================
   Contextual header pill — over light sections/panels the white burger pill
   disappears; an IntersectionObserver in SiteLayout adds .mz-light-ctx to the
   header while anything light sits in the band behind the pill.
   ============================================================================ */
.header.mz-light-ctx:not(.isOpen) .burger{background:var(--color-accent)!important;}
.header.mz-light-ctx:not(.isOpen) .burger .burger-line{background:var(--color-white)!important;}
.header.mz-light-ctx:not(.isOpen) .burger .burger-label{color:var(--color-white)!important;}

/* Hero aside checklist ("What We Handle") — a little larger now the binary
   block below it has been removed, to fill the space. */
.heroHome .stats-title{font-size:15px}
.heroHome .stats-item{font-size:14px;padding:3px 0}

/* Hero right column — the "What We Handle" panel and the "Explore Our
   Solutions" CTA panel together fill the viewport. The panel height is set in
   PIXELS by JS (see HeroHome.astro) rather than `vh`, because viewport units
   on an element inside the ScrollSmoother-pinned, transformed column stutter
   on every frame. Only the (jank-free) top alignment lives here. */
@media (min-width:1024px){
  .heroHome .sticky-aside .aside-stats{
    justify-content:flex-start;
  }
}
/* News items (Who we are / What we do / Why it works) are no longer links:
   drop the clickable cursor and the bottom horizontal divider line. */
.heroHome .news-item{cursor:default!important}
.heroHome .news-item__line[data-line="x"]:nth-child(2){display:none!important}

/* Footer — layout lives in src/components/layout/Footer.astro (design option
   1d: flat two-column nav, three-up contact strip, wordmark on the card's
   baseline). The old .block-content / .footer-copy / .footer-address
   overrides were removed with the markup they targeted. */

/* ── Our Process · Section 2 (solutions showcase) ─────────────────────── */
/* Sticky, scroll-driven showcase: full-bleed image on the left with the
   vertical industry label over it, the solution title + description in the
   grey block, and a blue CTA through to the solution page. Tab buttons
   hidden — the inline controller switches panels by scroll position. */

/* Track pins the section for four viewport-steps (one per solution). */
.mz-solutions-track { position: relative; }

/* The pinned scroll-showcase now runs at EVERY width (it was desktop-only,
   which left tablet/mobile with a broken captured fallback: no way to switch
   solutions and a 78px-wide description). Only the aside layout adapts per
   breakpoint below. */
@media screen and (min-width: 0px) {
  .mz-solutions-track { height: 400vh; }
  /* Sticky pin: the section stays in <body>'s flow (so the wheel keeps
     scrolling the page) and sticks for the length of the track. position:
     fixed cannot be used here because <html> is overflow:hidden, which traps
     a fixed element's scroll chain and freezes the page. */
  .tab-images.tabPanel { position: sticky; top: 0; height: 100vh; overflow: hidden; }

  /* Hide the tab list — scrolling drives the switch now */
  .tab-images .tabPanel-controls { display: none !important; }

  /* Neutralise the captured grid so children anchor to the pinned section.
     Make the section the positioning context, then place image / label /
     aside absolutely against it. */
  .tab-images .content { height: 100vh !important; padding: 0 !important; position: static !important; }
  .tab-images .tabPanel-container,
  .tab-images .item-block { position: static !important; height: 100vh !important; padding: 0 !important; margin: 0 !important; display: block !important; overflow: visible !important; }

  /* Full-bleed image fills the whole section */
  .tab-images .item-assets { position: absolute !important; inset: 0 !important; height: 100% !important; width: 100% !important; margin: 0 !important; z-index: 1 !important; }
  .tab-images .item-asset { position: absolute !important; inset: 0 !important; height: 100% !important; width: 100% !important; transform: none !important; margin: 0 !important; }
  .tab-images .item-asset .asset-bg { display: none !important; }
  .tab-images .item-asset .figure,
  .tab-images .item-asset .picture { position: absolute !important; inset: 0 !important; height: 100% !important; width: 100% !important; transform: none !important; border-radius: 0 !important; }
  .tab-images .item-asset img { object-fit: cover !important; border-radius: 0 !important; }

  /* Subtle gradient so white overlays read on bright images */
  .tab-images .item-assets:after {
    content: ""; position: absolute; inset: 0; z-index: 2; pointer-events: none;
    background: linear-gradient(90deg, rgba(0,0,0,.45) 0%, rgba(0,0,0,0) 30%);
  }

  /* The middle More/Less description block is redundant here — aside carries it */
  .tab-images .item-descriptions { display: none !important; }

  /* Vertical industry label over the image, left edge, vertically centred */
  .tab-images .tabPanel-title {
    position: absolute !important;
    left: 3.5rem !important; right: auto !important; top: 0 !important;
    width: 6rem !important; height: 100vh !important;
    transform: none !important;
    display: flex !important;
    align-items: center !important;
    justify-content: flex-start !important;
    overflow: visible !important;
    z-index: 6 !important;
    pointer-events: none !important;
  }
  .tab-images .tabPanel-title h2 {
    writing-mode: vertical-rl !important;
    transform: none !important;
    font-family: var(--font-display) !important;
    font-size: 5vh !important;
    font-weight: 600 !important;
    letter-spacing: 0.06em !important;
    text-transform: uppercase !important;
    line-height: 1 !important;
    white-space: nowrap !important;
    color: var(--color-white) !important;
    text-shadow: 0 2px 30px rgba(0,0,0,.6) !important;
  }

  /* Right column (grey block + blue CTA) pinned to the right.
     The captured .item-aside-panel already handles is-active opacity and the
     grey/blue split — we only reposition the column and stack the title. */
  .tab-images .item-aside { position: absolute !important; top: 0 !important; right: 0 !important; width: 36rem !important; height: 100vh !important; z-index: 5 !important; }

  /* Stack the solution title above the description, bottom-aligned in the grey block */
  .tab-images .aside-description { flex-direction: column !important; align-items: flex-start !important; justify-content: flex-end !important; }
  .tab-images .mz-aside-title { position: relative !important; z-index: 1 !important; color: var(--color-bg) !important; font-family: var(--font-display) !important; font-size: 2.8rem !important; line-height: 1.05 !important; margin-bottom: 1.6rem !important; display: block !important; }
  .tab-images .description-text { color: var(--color-bg) !important; width: auto !important; }
}

/* Tablet: same pinned showcase, fixed 300px aside (36rem shrinks with the
   fluid rem and gets too narrow). */
@media screen and (min-width: 750px) and (max-width: 1024px) {
  .tab-images .item-aside { width: 300px !important; }
}

/* Phones: the aside becomes a bottom sheet — white description above the blue
   CTA — and the vertical industry label flips horizontal across the top. */
@media screen and (max-width: 749px) {
  .tab-images .tabPanel-title {
    position: absolute !important;
    left: 1.6rem !important; right: 1.6rem !important; top: 7rem !important;
    width: auto !important; height: auto !important;
    display: block !important;
    overflow: visible !important;
  }
  .tab-images .tabPanel-title h2 {
    writing-mode: horizontal-tb !important;
    font-size: 3.6rem !important;
    white-space: normal !important;
    line-height: 1.05 !important;
  }
  .tab-images .item-aside {
    display: block !important;   /* captured CSS removes the aside on phones */
    top: auto !important; bottom: 0 !important;
    left: 0 !important; right: 0 !important;
    width: 100% !important; height: 40rem !important;
  }
  .tab-images .item-aside .aside-cta { display: block !important; width: 100% !important; }
  .tab-images .aside-description {
    height: calc(100% - 20rem) !important;
    padding: 2rem 1.6rem !important;
  }
  .tab-images .item-aside .aside-cta { height: 20rem !important; min-height: 0 !important; }
}

/* The captured reveal animations (SplitText opacity, data-mask clip-path) can
   leave content in a hidden initial state because their scroll triggers don't
   fire inside our custom pin. Force the active panel's content visible; keep
   inactive vertical labels hidden so they don't stack. */
.tab-images [data-mask] { clip-path: none !important; }
.tab-images .title-text { opacity: 0 !important; visibility: visible !important; }
.tab-images .title-text.is-active,
.tab-images .title-text.is-active * { opacity: 1 !important; visibility: visible !important; transform: none !important; }
.tab-images .item-aside-panel.is-active .mz-aside-title,
.tab-images .item-aside-panel.is-active .description-text,
.tab-images .item-aside-panel.is-active .description-text *,
.tab-images .item-aside-panel.is-active .cta-label,
.tab-images .item-aside-panel.is-active .cta-label *,
.tab-images .item-asset.is-active .figure,
.tab-images .item-asset.is-active img { opacity: 1 !important; visibility: visible !important; transform: none !important; }

/* Smooth crossfade between solutions. The captured `transition: all` plus
   visibility:hidden produced a hard, jumpy cut; here every layer fades on a
   single shared timing so switching reads as one clean dissolve. Inactive
   layers stay visibility:visible at opacity 0 so they can fade out (and
   pointer-events:none keeps their CTA/links from intercepting clicks). */
.tab-images .item-asset,
.tab-images .tabPanel-title .title-text,
.tab-images .item-aside-panel { transition: opacity .6s cubic-bezier(0.33, 1, 0.68, 1) !important; }
.tab-images .item-asset:not(.is-active),
.tab-images .tabPanel-title .title-text:not(.is-active),
.tab-images .item-aside-panel:not(.is-active) { opacity: 0 !important; visibility: visible !important; pointer-events: none !important; }
.tab-images .item-asset.is-active,
.tab-images .tabPanel-title .title-text.is-active,
.tab-images .item-aside-panel.is-active { opacity: 1 !important; visibility: visible !important; }

/* Mobile: stack normally, no pin */
@media screen and (max-width: 1024px) {
  .tab-images .tabPanel-controls { display: none !important; }
  .tab-images .mz-aside-title { color: var(--color-bg) !important; margin-bottom: 1.2rem !important; display: block !important; }
}

/* ============================================================================
   About Us — solutions tab panel (.tab-video). The captured design floated bare
   12px labels straight onto the photograph: unreadable over a bright image and
   with nothing to say they were clickable. Replaced with one solid menu card
   (desktop/tablet) and a full-width option list (phones) so the control always
   sits on its own surface instead of competing with the picture.
   NOTE: this site's root font-size is fluid (~5.3px at 768 vs 10px at 1440),
   so these controls are sized in px — rem collapses them at tablet.
   ============================================================================ */

/* Scrim keeps the overlaid title readable over any photo. */
.tab-video .item-bg::after{
  content:"";position:absolute;inset:0;z-index:1;pointer-events:none;
  background:linear-gradient(180deg,rgba(0,0,0,.5) 0%,rgba(0,0,0,.12) 30%,rgba(0,0,0,0) 50%,rgba(0,0,0,.72) 100%);
}
.tab-video .item-bg > img{position:relative;z-index:0;}
/* The capture also blended the overlaid title into the photo, which washed it
   out over busy images. Opt out and let the scrim carry the contrast. */
.tab-video .item-info,
.tab-video .item-info .info-title{mix-blend-mode:normal!important;}
.tab-video .item-info{position:relative;z-index:2;}

/* The control group is one opaque card, so contrast never depends on the photo. */
.tab-video .tabPanel-controls{
  z-index:3!important;
  width:auto!important;min-width:230px;
  padding:14px!important;
  /* The capture blended these controls into the photo (mix-blend-mode:
     difference), which is what made the labels invert and wash out. Opt out
     and paint a fully solid card: readability never depends on the picture. */
  mix-blend-mode:normal!important;
  background:#141414!important;
  border:1px solid rgba(255,255,255,.18)!important;
  border-radius:14px;
  box-shadow:0 18px 50px rgba(0,0,0,.55);
}
.tab-video .mz-tabhint{
  margin:0 0 10px;padding:0 10px;
  font-family:var(--font-mono),sans-serif;
  font-size:10px;letter-spacing:.12em;text-transform:uppercase;
  color:rgba(255,255,255,.55);
}
.tab-video .controls-content{
  display:flex!important;flex-direction:column!important;align-items:stretch!important;gap:2px;
}
.tab-video .tabPanel-button{
  display:flex;align-items:center;justify-content:flex-start;
  width:100%!important;min-height:38px;padding:0 12px;
  border:0!important;border-radius:8px;
  background:transparent!important;
  color:rgba(255,255,255,.86)!important;
  font-size:12.5px;line-height:1.2;letter-spacing:.03em;
  text-align:left;white-space:nowrap;cursor:pointer;
  transition:background .18s ease,color .18s ease;
}
/* The captured 8px dot marked the active row; the filled row does that now. */
.tab-video .tabPanel-button::before{display:none!important;}
.tab-video .tabPanel-button:hover{
  background:rgba(255,255,255,.1)!important;color:#fff!important;
}
.tab-video .tabPanel-button.is-active{
  background:var(--color-accent)!important;
  color:var(--color-bg)!important;font-weight:500;
}
.tab-video .tabPanel-button:focus-visible{outline:2px solid var(--color-white);outline-offset:2px;}

@media screen and (min-width:750px) and (max-width:1024px){
  .tab-video .tabPanel-controls{left:24px!important;min-width:210px;}
}

/* Phones: the captured layout collapsed the image to ~124px with the display
   title overflowing it and the controls running off-screen. Give the image a
   real height, scale the title to fit, and lay the options out as a full-width
   list — one line each, 48px targets — instead of a cramped two-up grid. */
@media screen and (max-width:749px){
  .tab-video .item-block{min-height:26rem!important;}
  .tab-video .item-bg{position:absolute!important;inset:0!important;}
  .tab-video .item-info{
    font-size:2.6rem!important;line-height:1.05!important;
    padding:0 16px 16px!important;white-space:normal!important;
  }
  .tab-video .tabPanel-controls{
    position:relative!important;
    width:auto!important;min-width:0;
    margin:0 16px;padding:20px 0 0!important;
    background:none!important;border:0!important;border-radius:0;box-shadow:none;
    mix-blend-mode:normal!important;
    -webkit-backdrop-filter:none;backdrop-filter:none;
  }
  .tab-video .mz-tabhint{padding:0;color:var(--color-text-muted);}
  .tab-video .controls-content{gap:6px;flex-direction:column!important;align-items:stretch!important;}
  .tab-video .tabPanel-button{
    width:100%!important;min-height:48px;padding:0 16px;border-radius:10px;
    background:rgba(255,255,255,.07)!important;
    font-size:13px;white-space:nowrap!important;
  }
}

/* The solution name was set twice on every width above 749: once large over
   the photo (.info-title) and again at the top of the aside
   (.description-title). Phones already dropped the aside copy; Cameron
   flagged the doubling on iPad, but it was on desktop too — the two just sit
   further apart there. Same treatment at every width: the photo carries the
   name, the aside carries the description and the CTA. */
.tab-video .aside-panel .description-title{display:none!important;}



/* Process list (.list — solution pages) on phones: the captured layout keeps
   two side-by-side columns at 390px with no gap, so the heading touches the
   steps. Stack them: heading full width, steps below. */
@media screen and (max-width:749px){
  .list .list-block{flex-direction:column!important;}
  .list .list-items{width:100%!important;}
  /* .list-title is used by BOTH the section heading and each step heading, so
     width:100% has to reach the step rows and their copy too (captured 180px). */
  .list .list-block > .list-title{margin-bottom:2.4rem!important;}
  .list .list-item,
  .list .list-title,
  .list .list-description,
  .list .list-block__line{width:100%!important;}
}

/* Stat cards (.numbers — every solution page) on phones: two 170px columns give
   the title a 120px box, but the 2.4rem type needs ~140px for the longest word
   ("Relocatable"), so it broke mid-word. Size the type to the column: every
   stat now sets on one line. */
@media screen and (max-width:749px){
  .numbers .item-title{font-size:1.9rem!important;line-height:1.15!important;}
}

/* "How it works" intro: the captured design injects an 11.4rem spacer span to
   force an editorial first-line indent, which reads as a broken line break.
   Remove it everywhere — the split-text lines recompute naturally on load. */
.interactiveChart .spacer{display:none!important;}

/* Projects list title (multipleInsights, Our Process + solution pages): the
   captured 16rem side rail collapses to ~85px on tablet widths and crushes the
   heading. Use the stacked full-width mobile treatment through 1024px. */
@media screen and (min-width:750px) and (max-width:1024px){
  .multipleInsights .multipleInsights-block{flex-wrap:wrap!important;}
  .multipleInsights .multipleInsights-title{
    width:100%!important;
    border-bottom:1px solid var(--color-border)!important;
    margin-bottom:2.4rem!important;
    padding-bottom:1.6rem!important;
  }
}

/* Shared solutions carousel: use one native snap track at every breakpoint.
   The captured clone/translate engine could retain a desktop offset after a
   resize and make a later card appear half visible when the section entered.
   Native scrolling keeps the first card deterministic and makes touch,
   trackpad, keyboard and arrow navigation use the same card boundaries. */
.pullupSlider .slider-block{
  overflow-x:auto!important;
  transform:none!important;
  scroll-snap-type:x mandatory;
  scroll-behavior:smooth;
  overscroll-behavior-inline:contain;
  scrollbar-width:none;
  -webkit-overflow-scrolling:touch;
}
.pullupSlider .slider-block::-webkit-scrollbar{display:none;}
.pullupSlider .slider-block.is-resetting{
  scroll-behavior:auto!important;
  scroll-snap-type:none!important;
}
.pullupSlider .slider-item{
  scroll-snap-align:start;
  scroll-snap-stop:always;
}
.pullupSlider .slider-block:focus-visible{
  outline:2px solid var(--color-accent);
  outline-offset:-2px;
}
.pullupSlider.is-static .slider-controls{
  opacity:0!important;
  pointer-events:none!important;
}
@media (prefers-reduced-motion:reduce){
  .pullupSlider .slider-block{scroll-behavior:auto;}
}

/* Key features / solutions carousel cards on phones: use real track padding
   and gaps instead of shifting every card with margin-left. This gives the
   first card a clean inset and lets each following card snap fully into view. */
@media screen and (max-width:749px){
  .pullupSlider .slider-block{
    grid-auto-columns:min(32rem,calc(100vw - 4.8rem))!important;
    column-gap:1.6rem;
    padding:1px 1.6rem 1.6rem!important;
    scroll-padding-inline:1.6rem;
  }
  .pullupSlider .slider-item{margin-left:0!important;}
  .pullupSlider .item-icon{height:20rem!important;margin-bottom:3.2rem!important;}
  .pullupSlider .pullupSlider-item{padding-top:4rem!important;}
}

/* Solutions slider: storage/racking icon is a raster image, not an inline SVG.
   Runtime JS strips inline style attributes, so size it via a stylesheet rule
   to keep it inside its .item-icon block instead of overflowing at intrinsic size. */
.item-icon img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: contain;
}

/* ============================================================================
   Contact form (.default-form). White panel, black type, accent-blue submit.
   Sized in px: the site's root font-size is fluid and rem collapses at tablet.
   ============================================================================ */

.-component.form:has(.default-form){background:#fff!important;}
.default-form{background:#fff!important;color:var(--color-bg);}

.default-form .name{
  color:var(--color-bg)!important;
  font-size:28px!important;
  line-height:1.2!important;
  letter-spacing:-.02em;
}

.default-form .form-label{
  color:var(--color-bg)!important;
  font-size:13px!important;
  font-weight:600;
  letter-spacing:.04em!important;
  line-height:1.3!important;
  opacity:1;
  margin-bottom:10px!important;
}
.default-form .form-label .required{color:var(--color-bg)!important;opacity:.7;}
.default-form .form-text,
.default-form .form-select,
.default-form .form-textarea{
  color:var(--color-bg)!important;
  caret-color:var(--color-bg);
}
.default-form .form-text::placeholder,
.default-form .form-textarea::placeholder{color:rgba(32,32,32,.45)!important;}
.default-form .form-select.placeholder{color:rgba(32,32,32,.45)!important;}
.default-form select option{color:var(--color-bg);background:var(--color-white);}
.default-form .form-container .success-message{color:var(--color-bg)!important;}

/* Field rules: visible at rest, solid on focus so the active field is obvious. */
.default-form .form-item__line,
.default-form .default-form__line{background:rgba(32,32,32,.28)!important;}
.default-form .form-item{transition:opacity .2s ease;padding-top:28px!important;}
.default-form .form-item:focus-within .form-item__line{
  background:var(--color-bg)!important;height:2px!important;
}
.default-form .form-text:focus,
.default-form .form-select:focus,
.default-form .form-textarea:focus{outline:none;}
.default-form .form-item:focus-within .form-label{opacity:1;}

/* One chevron only: captured CSS paints a background arrow AND an SVG icon. */
.default-form .form-select{
  -webkit-appearance:none;
  appearance:none;
  background-image:none!important;
  padding-right:28px!important;
}
.default-form .select-icon{width:14px!important;height:14px!important;fill:var(--color-bg);}

/* A message box you can actually write in. */
.default-form .form-textarea{
  min-height:148px!important;
  resize:vertical;
  padding-top:6px;
  font-size:18px!important;
  line-height:1.45!important;
  border-color:rgba(32,32,32,.28)!important;
}
.default-form .form-text:-webkit-autofill,
.default-form .form-text:-webkit-autofill:hover,
.default-form .form-text:-webkit-autofill:focus{
  -webkit-text-fill-color:var(--color-bg);
  caret-color:var(--color-bg);
  box-shadow:0 0 0 1000px #fff inset;
  transition:background-color 9999s ease-out;
}

/* Human check: sit on one line with readable sentence-case copy. */
.default-form .form-item.checkField .form-label{
  display:flex;
  align-items:center;
  gap:12px;
  text-transform:none!important;
  letter-spacing:0!important;
  font-size:15px!important;
  font-weight:500;
  cursor:pointer;
  margin-bottom:0!important;
}
.default-form .form-check{
  width:20px!important;height:20px!important;flex:0 0 20px;
  border:2px solid rgba(32,32,32,.55)!important;border-radius:4px!important;
  background-color:transparent!important;
  transform:none!important;
  cursor:pointer;transition:background .15s ease,border-color .15s ease;
}
.default-form .form-check:hover{border-color:var(--color-bg)!important;}
.default-form .form-check:checked{
  background-color:var(--color-accent)!important;border-color:var(--color-accent)!important;
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20' fill='none' stroke='%23fff' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M4 10.5l4 4 8-8'/%3E%3C/svg%3E");
  background-size:14px 14px;background-position:center;background-repeat:no-repeat;
}
.default-form .form-check:focus-visible{outline:2px solid var(--color-accent);outline-offset:2px;}

/* Submit: accent-blue pill, white label. */
.default-form .form-submit{
  min-height:48px;cursor:pointer;
  background:var(--color-accent)!important;
  color:#fff!important;
  border:1px solid var(--color-accent)!important;
  transition:background .2s ease,color .2s ease,border-color .2s ease;
}
.default-form .form-submit:hover{
  background:var(--color-bg)!important;
  color:#fff!important;
  border-color:var(--color-bg)!important;
}
.default-form .form-submit:focus-visible{outline:2px solid var(--color-accent);outline-offset:3px;}

/* Pair the short fields two-up only where the form column is genuinely wide
   enough (the tablet column is ~363px, too tight for two 24px fields).
   minmax(0,1fr) is required: a plain 1fr keeps each column at min-content and
   overflows.

   Which fields pair is keyed off `.halfField`, NOT off nth-child. It was
   nth-child(2)/(3) until 2026-08-20, which silently meant "first and last
   name" only because a hidden Netlify `form-name` input happened to be
   child 1. Removing that input when the real endpoint landed shifted every
   position by one and the pairing jumped to last name / email. Position-based
   selectors over a form that gains fields are a trap; the class is not. */
@media screen and (min-width:1025px){
  .default-form .form-container{
    display:grid!important;
    grid-template-columns:minmax(0,1fr) minmax(0,1fr);
    column-gap:32px;
    width:min(720px,100%)!important;
    align-content:start;
  }
  .default-form .form-container > *{grid-column:1 / -1;min-width:0;}
  .default-form .form-container > .form-item.halfField{grid-column:span 1;}
  .default-form .form-container > .form-item.checkField{grid-column:span 1;align-self:end;}
  .default-form .form-container > .form-submit{grid-column:span 1;justify-self:end;margin-top:28px;}
  .default-form .form-container .form-text,
  .default-form .form-container .form-select,
  .default-form .form-container .form-textarea{width:100%;max-width:100%;}
}

/* ============================================================================
   Key-details icons (.numbers-item) — Why Us "what you can expect" and the
   four solution-page key-details bands. The captured item was a corner-boxed
   text block with no mark; each item now carries a sprite icon above the
   title, sized to the column and stroked in the muted body colour so it
   reads on the dark band without competing with the heading.
   ========================================================================= */
.numbers[data-astro-cid-y2cypv2k] .numbers-item[data-astro-cid-y2cypv2k] .numbers-item__icon{
  display:block;
  width:100%;
  max-width:12.8rem;
  height:8.6rem;
  margin-bottom:2rem;
  pointer-events:none;
  fill:none;
  stroke:var(--color-text-muted);
}
.numbers[data-astro-cid-y2cypv2k] .numbers-item[data-astro-cid-y2cypv2k] .numbers-item__icon .icon{
  display:block;
  width:100%;
  height:100%;
  fill:inherit;
  stroke:inherit;
}
@media screen and (max-width:1024px){
  .numbers[data-astro-cid-y2cypv2k] .numbers-item[data-astro-cid-y2cypv2k] .numbers-item__icon{
    max-width:10rem;
    height:6.8rem;
    margin-bottom:1.6rem;
  }
}
@media screen and (max-width:749px){
  .numbers[data-astro-cid-y2cypv2k] .numbers-item[data-astro-cid-y2cypv2k] .numbers-item__icon{
    max-width:8.8rem;
    height:6rem;
    margin-bottom:1.2rem;
  }
}

/* ============================================================================
   Projects teaser rows (.multipleInsights) — "Floors we have put to work",
   bottom of Our Process and all four solution pages.

   Two captured-layout faults:

   1) Tablet (750-1024). The title was already forced to stack full width
      (rule above), but the row list kept its 104rem desktop measure. Because
      1rem tracks the viewport, 104rem is ~555px inside a ~725px block, so
      every row sat left-huddled with a dead ~200px strip down the right of
      the screen.

   2) Desktop (>=1025). The row is a flex pair whose height is set by the
      40rem image, while the text column carries roughly 130px of copy. With
      the default top alignment that left ~270px of empty column under every
      caption and stretched the section past 1.7 viewports for three items.
      Centring the pair closes the void without touching the image scale.
   ========================================================================= */
@media screen and (min-width:750px) and (max-width:1024px){
  .multipleInsights .multipleInsights-list{width:100%!important;}
  .multipleInsights .multipleInsights-item{align-items:center;}
  .multipleInsights .multipleInsights-content{
    width:auto!important;
    flex:1 1 0;
    min-width:0;
    padding-right:3.2rem!important;
  }
  .multipleInsights .multipleInsights-image{
    flex:0 0 auto;
    width:58%!important;
    height:auto!important;
    aspect-ratio:17 / 10;
  }
}
@media screen and (min-width:1025px){
  .multipleInsights .multipleInsights-item{align-items:center;}
}

/* Carousel arrows: dimmed and inert at the ends of the track (the controller
   clamps instead of looping back to card one). */
.pullupSlider .slider-controls .controls.is-disabled{
  opacity:.3;
  cursor:default;
  pointer-events:none;
}

/* ============================================================================
   Carousel frame (Home, Our Process, all four solution pages).

   Two faults, both from the captured markup meeting a scroll container:

   1) The track only ever declares `overflow-x`. CSS will not leave the other
      axis as `visible` when one axis is not, so `overflow-y` computed to
      `auto`: the block gained an implicit vertical scroll axis with no fixed
      height, and at 1024 its scroll height already exceeded its client height
      by 1px. `overflow-y:hidden` gives it back a fixed height and keeps the
      horizontal scroll.

   2) The rules are drawn by the cards at `top:-1px` and `bottom:-0.5px` —
      outside the content box. In an overflow container that is exactly the
      clip boundary, so the top and bottom rules were painted and then cut off
      at 1440, 1024 and 768. Only phones showed them, because the card's
      padding-top happened to push the line back inside. Moving them to 0 puts
      them inside the box at every width.

   The left edge comes from the first card's divider, but nothing drew the
   right edge, so the block never closed. That one belongs on the track rather
   than a card: a border on a scroll container stays pinned to the viewport
   edge instead of scrolling away with the last slide.
   ========================================================================= */
.pullupSlider .slider-block{
  overflow-y:hidden!important;
  border-right:1px solid var(--color-text-muted);
}
.pullupSlider .pullupSlider-item__line:first-child{top:0!important;}
.pullupSlider .pullupSlider-item__line:nth-child(2){bottom:0!important;}

/* ============================================================================
   Intro / statement block — About Us, Why Us, Our Process and all four
   solution pages.

   The captured rule pins the section to `min-height:100vh` at >=1025, so it
   holds a full screen whether the intro runs to six lines or two. Measured at
   1440: Why Us left 372px of empty below its last line, the solution pages
   452px, About Us 212px — which is what reads as "huge blank space before the
   next section". Height now comes from the copy, with the section's own
   padding doing the spacing instead of a viewport unit. The lower padding is
   a little deeper than the upper so the block still breathes into whatever
   follows it.
   ========================================================================= */
@media screen and (min-width:1025px){
  .statement{
    min-height:0!important;
    padding:8rem 0 11rem!important;
  }
}

/* ============================================================================
   Solution pages, phones: the run-out between the detection list and the
   section under it.

   Measured on Retail & Showroom at 393px: 188px of empty between the last
   design-input line and the heading below it — 112px of trailing padding
   stacked inside the detection aside (a 4rem inner box, plus the aside's own
   1.6rem, plus the data block's 1.6rem) and 8rem of top padding on the
   section that follows. Both are desktop measures that were never brought
   down for phones, where 1rem is a full 10px. Trimmed to land around 100px,
   which still reads as a section break at this width.

   Tablet (750-1024) is already tight at 85px and is left alone.
   ========================================================================= */
@media screen and (max-width:749px){
  /* px, not rem: the root font size tracks the viewport on phones, so a rem
     value that reads well at 393 balloons back to ~180px by 749. */
  .detection .aside-data{padding-bottom:0!important;}
  .detection .aside-data > div{padding-bottom:16px!important;}
  .numbers{padding-top:32px!important;}
}

/* What We Do aside copy (.tab-video). With the duplicate title gone the
   description is the only text in a 360px panel, and the captured size is a
   flat 12px uppercase at every width — caption scale next to a full-bleed
   photograph. Sized up on desktop so it reads as supporting copy. Phones and
   small tablets keep 12px, where the panel is narrow and it already works. */
@media screen and (min-width:1025px){
  .tab-video .aside-panel .description-text{
    font-size:14px!important;
    line-height:1.5!important;
    letter-spacing:.01em;
  }
}
@media screen and (min-width:1280px){
  .tab-video .aside-panel .description-text{font-size:15px!important;}
}

/* ============================================================================
   Two leftovers from the same habit: captured spacing and widths that were
   sized for a 1440 canvas and never revisited.

   1. `.list` carries `padding:16rem 0`. Combined with the intro block's own
      bottom padding that put 300-473px of nothing between the intro and the
      list under it on phones, and 382px at 1440 — the "huge blank spaces"
      Cameron flagged on About Us and Why Us.

   2. The Why Us "what you can expect" item titles are pinned to `width:120px`
      on phones while the items sit four across, so each column renders about
      109px wide and "Site assessment" breaks over four lines, "Agreed
      installation plan" over six. Two across with the title free to use the
      column fixes the breaking without shrinking the type.
   ========================================================================= */
.list{padding-top:9rem!important;padding-bottom:9rem!important;}

@media screen and (max-width:749px){
  /* px again, not rem: at 600 a 7rem/9rem pair balloons back to 107px and
     138px, which is most of the gap coming straight back. */
  .statement{padding-bottom:48px!important;}
  .list{padding-top:56px!important;padding-bottom:56px!important;}
  .numbers .numbers-list{gap:0 16px!important;}
  .numbers .numbers-item{width:calc(50% - 8px)!important;padding-right:0!important;}
  .numbers .item-title{width:auto!important;margin-bottom:2.4rem!important;}
}

/* Projects hero: the only hero on the site with `padding-bottom:0` — every
   other one carries 4rem. At 200px type the descender of the "j" in
   "Projects" sits 24px below the section box, so it fell out of the blue band
   onto the dark section underneath and simply vanished. Matching the others
   puts the whole glyph back inside its own background. */
.heroInsights{padding-bottom:4rem;}
@media screen and (max-width:749px){
  .heroInsights{padding-bottom:2.4rem;}
}

/* ============================================================================
   All Projects list — height follows the content
   The captured section reserves min-height:800px, sized for a full four card
   grid. The list now renders only case studies that have a page behind them
   (src/content/projects.ts), so with one published article that reserve left
   roughly 400px of empty white below the single card. Height comes from the
   cards instead; when the other five articles land the section grows back on
   its own.
   ========================================================================= */
/* Two classes, because tokens.css loads before the captured sheet and a
   single-class rule would lose the cascade on equal specificity. */
.-component.pullupAllInsights{min-height:0;}

/* ============================================================================
   Header logo — 2026-08-24.  Contract: Docs/pages/header-logo.md
   Replaces the placeholder "LOGO" wordmark that shipped on all 13 pages.

   Two variants ship stacked and cross-fade. White is the DEFAULT because it is
   the one that works on three of the site's four grounds: the accent blue hero,
   the #202020 sections and the photographic solution heroes. Colour takes over
   only on light ground.

   Measured, not assumed — the colour lockup's wordmark samples at #00a8f0 and
   the site accent is #19A9E6, so on the blue hero the wordmark IS the
   background and disappears. That is the whole reason there is a swap at all.

   Both files are cropped from the SAME rectangle of the 2048px originals, so
   they are pixel registered and the mark neither moves nor resizes on swap.
   Cropping each to its own alpha bounding box would jump it 78px in height and
   23px across, because the two supplied files are not registered to each other.
   Aspect ratio 851:320 = 2.659.
   ============================================================================ */
/* The class is repeated on purpose, the same trick used further up this file.
   The captured rule is `.desktop-menu[data-astro-cid-…] .logo-link[data-astro-cid-…]`
   — two classes plus two attributes, specificity (0,4,0) — and tokens.css loads
   BEFORE the captured sheet, so a (0,4,0) rule here would tie and lose on source
   order. Measured, not guessed: without this the anchor computed to the captured
   175px while the mark only needs 106px, leaving 69px of link over empty space. */
.header .desktop-menu .logo-link.mz-logo.mz-logo{
  position:relative;
  display:block;
  /* The captured rule pins an explicit 175x40 box sized for a wordmark that no
     longer exists. Height drives it now; width follows the real aspect ratio.

     68px, and the history is worth keeping. The captured box was 40, sized for
     a single line of 34px placeholder caps. The real lockup stacks MEZZANINE
     over WORLD inside that height, so at 40px each line is ~14px and "WORLD"
     stops being legible; 52 fixed the legibility but still read light beside
     the 36px MENU pill. 68 gives the emblem real presence in the corner and
     puts the wordmark at ~24px, which is the first size where the lockup holds
     the header rather than sitting in it. */
  height:68px;
  width:calc(68px * 2.659);
  fill:none;
}
.mz-logo__img{
  position:absolute;
  inset:0;
  display:block;
  height:100%;
  width:100%;
  object-fit:contain;
  object-position:left center;
  transition:opacity .3s ease;
}
.mz-logo__img--white{opacity:1}
.mz-logo__img--colour{opacity:0}
/* Set by the contextual probe in Header.astro when the ground behind the LOGO is
   light. Deliberately a separate class from .mz-light-ctx, which probes the
   burger: on the homepage the left half of the hero is accent blue while the
   right column is white, so the two ends of the header sit on different grounds
   at the same moment. One class driving both would be wrong half the time. */
.header.mz-logo-light .mz-logo__img--white{opacity:0}
.header.mz-logo-light .mz-logo__img--colour{opacity:1}

@media screen and (max-width:749px){
  .header .desktop-menu .logo-link.mz-logo.mz-logo{height:52px;width:calc(52px * 2.659)}
}
@media (prefers-reduced-motion:reduce){
  .mz-logo__img{transition:none}
}

/* ── Project photography crops ─────────────────────────────────────────────
   The "Featured Project" band is 1360x640, roughly 2.1:1, and site photographs
   come off a phone at 4:3. `object-fit:cover` centres that crop, which on a
   mezzanine photograph throws away the thing the photograph is of: the steel
   is overhead, in the top third of every frame, and the middle of the picture
   is whatever happens to be stacked on the floor that day. Biasing the crop
   upward keeps the structure in the band. Applies to the feature card only —
   the article body shows these images whole. */
.featureInsight .feature-asset img{object-position:50% 22%}

/* ============================================================================
   PROJECT CASE STUDY  (.mzp-*)
   Paper direction D, approved by Cameron 2026-08-25. Contract:
   Docs/pages/project-case-study.md.

   Global, not scoped: every page on this site builds its <head> through
   set:html, so Astro's scoped <style> blocks never inject. Namespaced .mzp-*
   so no captured stylesheet reaches this page's own sections.

   WHY THE TYPE IS IN px, NOT rem
   The captured site sets html{font-size:clamp(1px,100px,10*100vw/1440)} above
   750px, so 1rem is 5.2px at 750, 7.1px at 1024 and only reaches 10px at 1440.
   Any rem-sized type in the tablet band renders unreadably small — that is the
   root cause of the "unreadable 78px description" already recorded in the
   ledger. These sections size everything with px clamp(min, vw, max) instead,
   which is deterministic at every width and immune to the fluid root.
   ============================================================================ */

:root{
  /* One step below the site's --color-bg (#202020). Photographs sit on it, and
     the extra depth is what stops a dark image reading as a grey panel. */
  --mzp-ink:#0E0E0E;
  --mzp-rule:#2C2C2C;
  --mzp-text:#DCDCDC;
  --mzp-muted:#9A9A9A;
  --mzp-dim:#7A7A7A;
  /* Page gutter. 56px at the 1440 design width, 20px on the smallest phone. */
  --mzp-gutter:clamp(20px,3.9vw,56px);
  /* Vertical rhythm between written sections, measured off the artboard:
     120px above, 100px below. The asymmetry is deliberate — a written section
     is followed by a band label, which carries its own space. */
  --mzp-block:clamp(64px,8.4vw,120px);
  --mzp-block-end:clamp(56px,6.9vw,100px);
  --mzp-ease:cubic-bezier(.22,1,.36,1);
}

/* The page ground. Applied to the taxi view so no sub-pixel seam between
   sections can show the site's lighter --color-bg through. */
.mzp-page{background:var(--mzp-ink);}

.mzp-section{
  background:var(--mzp-ink);
  padding:var(--mzp-block) var(--mzp-gutter) var(--mzp-block-end);
  position:relative;
}
/* The spec table sits evenly between two bands: 110px both ends. */
.mzp-spec{padding-block:clamp(60px,7.64vw,110px);}

/* ── shared type ─────────────────────────────────────────────────────────── */

.mzp-label{
  font-family:var(--font-mono),sans-serif;
  font-size:clamp(10px,.82vw,11px);
  font-weight:600;
  letter-spacing:.12em;
  text-transform:uppercase;
  line-height:1.4;
  margin:0;
}
.mzp-label--accent{color:var(--color-accent);}
.mzp-label--muted{color:var(--mzp-dim);}

.mzp-rule{display:block;width:44px;height:1.5px;background:#4A4A4A;margin-top:10px;}
.mzp-rule--accent{background:var(--color-accent);}

.mzp-lede{
  font-family:var(--font-body),arial;
  font-size:clamp(21px,2.08vw,30px);
  font-weight:400;
  letter-spacing:-.02em;
  line-height:1.4;
  color:#FFFFFF;
  margin:0;
}
.mzp-heading{
  font-family:var(--font-body),arial;
  font-size:clamp(20px,1.81vw,26px);
  font-weight:400;
  letter-spacing:-.02em;
  line-height:1.38;
  color:#FFFFFF;
  margin:0;
}
.mzp-body{
  font-family:var(--font-body),arial;
  font-size:clamp(15px,1.18vw,17px);
  font-weight:400;
  line-height:1.7;
  color:var(--mzp-muted);
  margin:0;
}

/* ── hero ────────────────────────────────────────────────────────────────── */

/* The hero fills the screen: the photograph, the headline and the figures are
   one view, and the first band label is what the reader finds by scrolling.
   `--vh` is the real viewport height in px, set by the site's own engine, so
   this stays correct when a mobile browser's toolbars come and go. min-height
   rather than height, so a very short window grows the section instead of
   clipping the headline off the top of the strip. */
.mzp-hero{
  position:relative;
  width:100%;
  min-height:var(--vh,100vh);
  display:flex;
  background:var(--mzp-ink);
  overflow:hidden;
}
.mzp-hero__media{position:absolute;inset:0;}
.mzp-hero__media img{
  display:block;width:100%;height:100%;
  object-fit:cover;object-position:50% 40%;
}
/* The dark top stop is load bearing: the site header's contrast probe reads the
   rendered pixels under the pill to decide whether the logo goes white. */
.mzp-hero__scrim{
  position:absolute;inset:0;
  background:linear-gradient(180deg,
    rgba(14,14,14,.78) 0%,
    rgba(14,14,14,.10) 30%,
    rgba(14,14,14,.55) 58%,
    rgba(14,14,14,.97) 88%,
    rgba(14,14,14,1) 100%);
}
.mzp-hero__inner{
  position:relative;z-index:2;
  display:flex;flex-direction:column;justify-content:flex-end;
  width:100%;
}
.mzp-hero__title{
  padding:clamp(120px,14vw,180px) var(--mzp-gutter) clamp(32px,4.2vw,60px);
  display:flex;flex-direction:column;gap:clamp(14px,1.7vw,24px);
  max-width:1066px;
}
/* The dot is an inline mark, not a flex item. As a flex item it was orphaned
   onto its own line the moment the eyebrow wrapped, which happens at 360px. */
.mzp-hero__eyebrow{
  font-family:var(--font-mono),sans-serif;
  font-size:clamp(10px,.82vw,11px);
  font-weight:600;letter-spacing:.12em;text-transform:uppercase;
  color:#FFFFFF;margin:0;line-height:1.6;
}
.mzp-dot{
  display:inline-block;vertical-align:middle;
  width:9px;height:9px;border-radius:999px;
  background:var(--color-accent);
  margin-right:12px;position:relative;top:-1px;
}
.mzp-hero__headline{
  font-family:var(--font-body),arial;
  font-size:clamp(34px,6.11vw,88px);
  font-weight:400;
  letter-spacing:-.04em;
  line-height:.96;
  color:#FFFFFF;
  margin:0;
}

/* With no figures to show there is no strip, and the headline would otherwise
   sit hard on the bottom edge of the screen. Give it back the room the strip
   would have taken, so a project with no confirmed numbers reads as a
   deliberate composition rather than a page missing a piece. */
.mzp-hero--nostats .mzp-hero__title{padding-bottom:clamp(56px,8vw,120px);}

.mzp-hero__stats{
  display:grid;
  grid-template-columns:repeat(4,minmax(0,1fr));
  border-top:1px solid rgba(255,255,255,.22);
  margin:0;
}
.mzp-stat{
  display:flex;flex-direction:column;gap:10px;
  padding:clamp(20px,2.5vw,36px) clamp(16px,2.8vw,40px) clamp(24px,3vw,44px);
  border-right:1px solid rgba(255,255,255,.22);
  min-width:0;
}
.mzp-stat:first-child{padding-left:var(--mzp-gutter);}
.mzp-stat:last-child{padding-right:var(--mzp-gutter);border-right:0;}
.mzp-stat__label{
  font-family:var(--font-mono),sans-serif;
  font-size:clamp(10px,.82vw,11px);
  font-weight:600;letter-spacing:.12em;text-transform:uppercase;
  color:rgba(255,255,255,.62);margin:0;line-height:1.4;
}
.mzp-stat__value{
  font-family:var(--font-body),arial;
  font-size:clamp(24px,3.2vw,46px);
  font-weight:400;letter-spacing:-.035em;line-height:1.05;
  color:#FFFFFF;margin:0;
}
.mzp-stat__value[data-accent]{color:var(--color-accent);}

/* ── three column sections (intro, detail, outcome) ──────────────────────── */

.mzp-cols{
  display:grid;
  grid-template-columns:clamp(140px,13.9vw,200px) minmax(0,640px) minmax(0,1fr);
  gap:clamp(28px,6.9vw,100px);
  align-items:start;
}
.mzp-cols--wide{grid-template-columns:clamp(140px,13.9vw,200px) minmax(0,840px);}
.mzp-cols__main{display:flex;flex-direction:column;gap:clamp(18px,1.8vw,26px);min-width:0;}
.mzp-cols__aside{min-width:0;padding-top:6px;}

.mzp-ruled{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;}
.mzp-cols__aside .mzp-label{padding-bottom:16px;}
.mzp-ruled__row{
  font-family:var(--font-body),arial;
  font-size:clamp(14px,1.11vw,16px);
  line-height:1.5;
  color:#C9C9C9;
  padding:14px 0;
  border-top:1px solid var(--mzp-rule);
  margin:0;
}
.mzp-ruled__row:last-child{border-bottom:1px solid var(--mzp-rule);}
.mzp-ruled--pairs .mzp-ruled__row{
  display:flex;align-items:baseline;justify-content:space-between;gap:16px;
}
.mzp-ruled--pairs dt{margin:0;}
.mzp-ruled__value{
  font-family:var(--font-body),arial;
  font-size:clamp(14px,1.11vw,15px);
  color:#FFFFFF;margin:0;text-align:right;white-space:nowrap;
}
.mzp-ruled__value[data-accent]{color:var(--color-accent);}

.mzp-outcome__statement{
  font-family:var(--font-body),arial;
  font-size:clamp(24px,2.5vw,36px);
  font-weight:400;letter-spacing:-.025em;line-height:1.34;
  color:#FFFFFF;margin:0;
}

/* ── labelled image band ─────────────────────────────────────────────────── */

.mzp-band{display:block;background:var(--mzp-ink);}
.mzp-band__label{
  display:flex;align-items:flex-end;justify-content:space-between;
  gap:clamp(24px,4.2vw,60px);
  padding:0 var(--mzp-gutter) clamp(16px,1.7vw,24px);
  border-bottom:1px solid var(--mzp-rule);
}
.mzp-band__title{
  display:flex;align-items:baseline;gap:clamp(14px,1.95vw,28px);
  margin:0;min-width:0;
}
.mzp-band__number{
  font-family:var(--font-body),arial;
  font-size:clamp(32px,3.89vw,56px);
  font-weight:400;letter-spacing:-.04em;line-height:1;
  color:var(--color-accent);flex-shrink:0;
}
.mzp-band__name{
  font-family:var(--font-body),arial;
  font-size:clamp(26px,3.06vw,44px);
  font-weight:400;letter-spacing:-.03em;line-height:1.1;
  color:#FFFFFF;
}
.mzp-band__caption{
  font-family:var(--font-body),arial;
  font-size:clamp(14px,1.11vw,16px);
  line-height:1.56;
  color:var(--mzp-muted);
  width:clamp(280px,36.1vw,520px);
  flex-shrink:0;text-align:right;margin:0;
}
.mzp-band__media{width:100%;height:clamp(300px,54.2vw,780px);overflow:hidden;}
.mzp-band__media img{
  display:block;width:100%;height:100%;
  object-fit:cover;object-position:50% 50%;
}

/* ── specification table ─────────────────────────────────────────────────── */

.mzp-spec__head{
  display:flex;align-items:flex-end;justify-content:space-between;
  gap:clamp(24px,4.2vw,60px);
  padding-bottom:clamp(20px,1.8vw,26px);
}
.mzp-spec__heading{
  font-family:var(--font-body),arial;
  font-size:clamp(24px,2.64vw,38px);
  font-weight:400;letter-spacing:-.03em;line-height:1.16;
  color:#FFFFFF;width:clamp(280px,43vw,620px);margin:0;
}
.mzp-spec__intro{
  font-family:var(--font-body),arial;
  font-size:clamp(14px,1.11vw,16px);
  line-height:1.62;color:var(--mzp-muted);
  width:clamp(280px,36.1vw,520px);flex-shrink:0;margin:0;
}
.mzp-table{display:flex;flex-direction:column;}
.mzp-table__head,
.mzp-table__row{
  display:grid;
  grid-template-columns:clamp(150px,15.3vw,220px) clamp(200px,27.8vw,400px) minmax(0,1fr);
  gap:clamp(16px,2vw,28px);
  align-items:start;
}
.mzp-table__head{
  padding:12px 0;
  border-top:1.5px solid #FFFFFF;
  border-bottom:1px solid var(--mzp-rule);
}
.mzp-table__row{padding:22px 0;border-bottom:1px solid var(--mzp-rule);}
.mzp-table__row:last-child{border-bottom:1.5px solid #FFFFFF;}
.mzp-table__item,
.mzp-table__spec,
.mzp-table__why{
  font-family:var(--font-body),arial;
  font-size:clamp(14px,1.11vw,16px);
  line-height:1.56;margin:0;
}
.mzp-table__item{font-weight:500;color:#FFFFFF;}
.mzp-table__spec{color:var(--mzp-text);}
.mzp-table__why{color:var(--mzp-muted);}

/* ── next project ────────────────────────────────────────────────────────── */

.mzp-next{background:var(--mzp-ink);border-top:1px solid var(--mzp-rule);}
.mzp-next__link{
  display:flex;align-items:center;justify-content:space-between;
  gap:clamp(20px,2.8vw,40px);
  padding:clamp(36px,3.9vw,56px) var(--mzp-gutter);
  text-decoration:none;color:inherit;
}
.mzp-next__text{display:flex;flex-direction:column;gap:12px;min-width:0;}
.mzp-next__title{
  font-family:var(--font-body),arial;
  font-size:clamp(26px,3.06vw,44px);
  font-weight:400;letter-spacing:-.03em;line-height:1.12;
  color:#FFFFFF;
}
.mzp-next__meta{
  font-family:var(--font-body),arial;
  font-size:clamp(14px,1.11vw,16px);color:var(--mzp-dim);
}
.mzp-next__arrow{
  display:flex;align-items:center;justify-content:center;
  width:clamp(56px,6.1vw,88px);height:clamp(56px,6.1vw,88px);
  border:1px solid var(--color-accent);border-radius:999px;
  color:var(--color-accent);flex-shrink:0;
  transition:background .3s var(--mzp-ease),color .3s var(--mzp-ease);
}
.mzp-next__arrow svg{width:clamp(18px,1.8vw,26px);height:clamp(18px,1.8vw,26px);display:block;}
.mzp-next__link:hover .mzp-next__arrow{background:var(--color-accent);color:var(--mzp-ink);}

/* ── closing CTA ─────────────────────────────────────────────────────────── */

.mzp-cta{
  background:var(--mzp-ink);
  border-top:1px solid var(--mzp-rule);
  padding:var(--mzp-block) var(--mzp-gutter);
  display:flex;flex-direction:column;align-items:center;
  gap:clamp(28px,3vw,44px);
  text-align:center;
}
.mzp-cta__line{
  font-family:var(--font-body),arial;
  font-size:clamp(26px,3.61vw,52px);
  font-weight:400;letter-spacing:-.035em;line-height:1.19;
  color:#FFFFFF;max-width:960px;margin:0;text-wrap:balance;
}
.mzp-cta__button{
  display:inline-flex;align-items:center;justify-content:center;
  background:var(--color-accent);color:var(--mzp-ink);
  border-radius:999px;
  padding:clamp(16px,1.53vw,22px) clamp(28px,3.06vw,44px);
  font-family:var(--font-mono),sans-serif;
  font-size:clamp(13px,1.04vw,15px);
  font-weight:600;letter-spacing:.04em;text-transform:uppercase;
  text-decoration:none;
  transition:transform .3s var(--mzp-ease),filter .3s var(--mzp-ease);
}
.mzp-cta__button:hover{transform:translateY(-2px);filter:brightness(1.08);}

/* ── entrance reveal ─────────────────────────────────────────────────────── */
/* Hidden state and transition are declared together, so a page where the
   observer never runs still shows every section. */
@media (prefers-reduced-motion:no-preference){
  [data-mzp-reveal]{
    opacity:0;transform:translateY(18px);
    transition:opacity .8s var(--mzp-ease),transform .8s var(--mzp-ease);
    will-change:opacity,transform;
  }
  [data-mzp-reveal][data-revealed]{opacity:1;transform:none;}
}

/* ── responsive ──────────────────────────────────────────────────────────── */

/* Laptops and small tablets: the aside loses its own column, the label row goes
   full width above the text. The aside stays beside the prose all the way down
   to the site's 750px tablet boundary, because at 834 a single column leaves
   half the screen empty.

   NOTE: every measure below is px, never `ch`. `ch` is relative to the font
   size, and this site's root font size is 5.2px at 750 and 7.1px at 1024 (see
   the note at the top of this block), so a `66ch` measure collapses to about
   250px through the whole tablet band. That defect is easy to reintroduce. */
@media screen and (max-width:1199px){
  .mzp-cols{
    grid-template-columns:minmax(0,1fr) minmax(220px,300px);
    gap:clamp(24px,4vw,48px) clamp(28px,4.4vw,56px);
  }
  .mzp-cols--wide{grid-template-columns:minmax(0,1fr);}
  .mzp-cols__label{grid-column:1 / -1;}
  .mzp-cols__aside{padding-top:0;}
  .mzp-cols--wide .mzp-cols__main{max-width:840px;}
}

/* Tablet: band captions drop under the title, and the spec table stops being a
   table. Three columns of prose at this width is four words per line. */
@media screen and (max-width:899px){
  .mzp-band__label{
    flex-direction:column;align-items:flex-start;
    gap:clamp(10px,1.6vw,14px);
  }
  .mzp-band__caption{width:100%;text-align:left;max-width:640px;}

  .mzp-spec__head{flex-direction:column;align-items:flex-start;gap:16px;}
  .mzp-spec__heading,
  .mzp-spec__intro{width:100%;max-width:640px;}

  /* A three column table at phone width is four words per line. Each row
     becomes a labelled block instead: the item as the heading, what was
     specified beside it, and the reason underneath. */
  .mzp-table__head{display:none;}
  .mzp-table{border-top:1.5px solid #FFFFFF;}
  .mzp-table__row{
    grid-template-columns:minmax(0,1fr);
    gap:6px;
    padding:20px 0;
  }
  .mzp-table__item{font-size:clamp(16px,2.2vw,18px);}
  .mzp-table__spec{color:#FFFFFF;}
  .mzp-table__why{padding-top:4px;}
}

/* Phones. One column, and the hero keeps a real height so the photograph is
   still the first thing the page says. */
@media screen and (max-width:749px){
  .mzp-cols{grid-template-columns:minmax(0,1fr);}
  .mzp-cols__main{max-width:680px;}

  .mzp-hero__title{padding-top:clamp(110px,30vw,150px);}
  .mzp-hero__headline{line-height:1.02;}
  /* The eyebrow is sector, place and year: at 390px it is wider than the
     screen, so it wraps rather than running under the edge. */
  .mzp-hero__eyebrow{letter-spacing:.08em;}

  /* Four figures across a 390px screen is 90px per column. Two by two keeps
     the numbers at a size worth reading, which is the only reason they exist. */
  .mzp-hero__stats{grid-template-columns:repeat(2,minmax(0,1fr));}
  .mzp-stat{
    border-bottom:1px solid rgba(255,255,255,.22);
    padding:18px var(--mzp-gutter) 20px;
  }
  .mzp-stat:nth-child(odd){padding-left:var(--mzp-gutter);padding-right:16px;}
  .mzp-stat:nth-child(even){padding-left:16px;padding-right:var(--mzp-gutter);border-right:0;}
  .mzp-stat:nth-last-child(-n+2){border-bottom:0;}

  .mzp-next__link{align-items:flex-start;}
  .mzp-next__arrow{margin-top:6px;}
}

/* Small phones: the headline is the only thing that needs the extra room. */
@media screen and (max-width:400px){
  .mzp-hero__headline{font-size:clamp(30px,8.6vw,34px);}
  .mzp-band__title{gap:12px;}
}
