/* ── DZ Hero styles ── */
@import url('./colors_and_type.css');

.dz-hero *,
.dz-navbar *,
.dz-btn * { box-sizing: border-box; }

/* ── Decorative-video belt-and-suspenders ──
   iOS Safari shows a tiny floating PiP/airplay button on autoplay-muted-
   inline <video> even when controls are off. The video element itself
   carries disablePictureInPicture + controlsList, but Safari sometimes
   still renders the overlay buttons. Hide them at the CSS layer too. */
.dz-hero__video::-webkit-media-controls,
.dz-hero__video::-webkit-media-controls-enclosure,
.dz-hero__video::-webkit-media-controls-panel,
.dz-hero__video::-webkit-media-controls-overlay-play-button,
.dz-hero__video::-webkit-media-controls-start-playback-button,
.dz-vdc-reel__panel video::-webkit-media-controls,
.dz-vdc-reel__panel video::-webkit-media-controls-enclosure,
.dz-vdc-reel__panel video::-webkit-media-controls-panel,
.dz-vdc-reel__panel video::-webkit-media-controls-overlay-play-button,
.dz-vdc-reel__panel video::-webkit-media-controls-start-playback-button,
.dz-vdc-lens__slide video::-webkit-media-controls,
.dz-vdc-lens__slide video::-webkit-media-controls-enclosure,
.dz-vdc-lens__slide video::-webkit-media-controls-panel,
.dz-vdc-lens__slide video::-webkit-media-controls-overlay-play-button,
.dz-vdc-lens__slide video::-webkit-media-controls-start-playback-button,
.dz-tms-uc__video::-webkit-media-controls,
.dz-tms-uc__video::-webkit-media-controls-enclosure,
.dz-tms-uc__video::-webkit-media-controls-panel,
.dz-tms-uc__video::-webkit-media-controls-overlay-play-button,
.dz-tms-uc__video::-webkit-media-controls-start-playback-button {
  display: none !important;
  -webkit-appearance: none !important;
  pointer-events: none !important;
  opacity: 0 !important;
}

body {
  margin: 0;
  background: var(--dz-navy);
  zoom: 0.8;

  /* iOS auto text-size adjustment can shift our explicit responsive type
     when the user rotates the device or pinches. Pin at 100%. */
  -webkit-text-size-adjust: 100%;
  text-size-adjust: 100%;

  /* iOS Safari adds a default grey flash on tap. We have our own hover/
     focus styles, kill the default. */
  -webkit-tap-highlight-color: transparent;

  /* Better kerning on supported browsers. */
  text-rendering: optimizeLegibility;
}

/* ─── Touch-action manipulation on every interactive element ──────────
   iOS Safari ships a 300-350 ms tap delay on non-mobile-optimized
   elements. WebKit's documented fix (https://webkit.org/blog/5610/)
   is to set touch-action: manipulation on every element that handles
   a tap — single taps fire immediately, double-tap-zoom is suppressed
   only on that element. Eliminates the "first tap doesn't respond"
   class of bugs across the site. */
a, button, [role="button"], summary, label,
.dz-btn, .dz-nav-btn, .dz-stage-card,
.dz-tms-hero__play, .dz-clients__dot,
.dz-step__btn, .dz-lifecycle__btn,
.dz-aij__step, .dz-aij__badge {
  touch-action: manipulation;
}

/* Hover-state reset on touch devices — prevents iOS sticky-hover where
   the previously-tapped element keeps its :hover state until something
   else gets tapped. Source: web.dev / Apple WebKit blog. */
@media (hover: none) and (pointer: coarse) {
  a:hover,
  button:hover,
  .dz-btn:hover,
  .dz-stage-card:hover,
  .dz-tms-uc:hover {
    /* Force the non-hovered visual state on touch */
    transform: none !important;
    filter: none !important;
  }
}

/* Touch-device buttons: enlarge tap target without changing visual size,
   for any element under 44×44pt. Uses an invisible ::before overlay. */
@media (hover: none) and (pointer: coarse) {
  .dz-clients__dot,
  .dz-footer__office-toggle.is-active,
  .dz-footer__social a,
  .dz-nav__close,
  .dz-pagination button,
  .dz-aij__step:hover { /* placeholder — keeps rule usable */ }

  .dz-clients__dot::before,
  .dz-footer__social a::before,
  .dz-nav__social a::before,
  .dz-pagination button::before {
    content: "";
    position: absolute;
    inset: -8px;
    z-index: -1;
  }

  .dz-clients__dot,
  .dz-footer__social a,
  .dz-nav__social a,
  .dz-pagination button {
    position: relative;
  }
}

/* ── Buttons ── */
.dz-btn {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 14px 22px;
  border-radius: var(--dz-radius);
  font-family: var(--dz-font);
  font-size: 15px;
  font-weight: var(--dz-fw-semibold);
  line-height: 1;
  text-decoration: none;
  cursor: pointer;
  border: 1px solid transparent;
  transition: transform .18s ease, background .18s ease, border-color .18s ease, color .18s ease, box-shadow .18s ease;
  letter-spacing: -0.005em;
  white-space: nowrap;
}
.dz-btn--sm { padding: 9px 16px; font-size: 13px; }
.dz-btn--aqua {
  background: var(--dz-aqua);
  color: var(--dz-navy);
  box-shadow: 0 6px 24px rgba(79, 200, 244, 0.28);
}
.dz-btn--aqua:hover { transform: translateY(-2px); box-shadow: 0 10px 30px rgba(79, 200, 244, 0.4); }
.dz-btn--aqua:active { transform: translateY(0); }
.dz-btn--ghost {
  background: transparent;
  color: var(--dz-white);
  border-color: rgba(255,255,255,0.25);
}
.dz-btn--ghost:hover { background: rgba(255,255,255,0.06); border-color: rgba(255,255,255,0.4); }

/* ── Navbar ── */
.dz-navbar {
  /* Fixed so the Navbar stays sticky across every page (was absolute,
     scrolled away with the home hero). Translucent navy bg + blur keeps
     the logo and nav legible over both dark hero AND light services bgs. */
  position: fixed;
  top: 0; left: 0; right: 0;
  z-index: 100;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 32px;
  padding: 20px 48px;
  font-family: var(--dz-font);
  background: rgba(26, 45, 62, 0.7);
  backdrop-filter: blur(14px) saturate(1.2);
  -webkit-backdrop-filter: blur(14px) saturate(1.2);
  border-bottom: 1px solid rgba(79, 200, 244, 0.06);
}
.dz-navbar__logo { display: flex; align-items: center; }
.dz-navbar__logo-img {
  height: 44px;
  width: auto;
  display: block;
  /* Invert navy artwork to white for the dark hero navbar */
  filter: brightness(0) invert(1);
}
.dz-navbar__nav {
  display: flex;
  align-items: center;
  gap: 4px;
  padding: 6px;
  background: rgba(10, 18, 32, 0.35);
  border: 1px solid rgba(79, 200, 244, 0.14);
  backdrop-filter: blur(14px) saturate(1.2);
  -webkit-backdrop-filter: blur(14px) saturate(1.2);
  border-radius: var(--dz-radius-pill);
  box-shadow:
    0 0 0 1px rgba(255, 255, 255, 0.02),
    0 12px 32px -8px rgba(0, 0, 0, 0.4),
    inset 0 1px 0 rgba(255, 255, 255, 0.05);
}
.dz-navbar__link {
  padding: 9px 16px;
  border-radius: var(--dz-radius-pill);
  font-size: 14px;
  font-weight: var(--dz-fw-regular);
  color: rgba(255,255,255,0.82);
  text-decoration: none;
  transition: color .15s ease, background .15s ease;
}
.dz-navbar__link:hover { color: var(--dz-white); background: rgba(255,255,255,0.06); }
/* Active page — aria-current="page" rendered when this link matches the URL.
   Subtle aqua underline + brighter text. Avoids competing with hover. */
.dz-navbar__link,
.dz-navbar__link--has-children { position: relative; }
.dz-navbar__link[aria-current="page"],
.dz-navbar__link--has-children[aria-current="page"] { color: var(--dz-white); }
.dz-navbar__link[aria-current="page"]::after,
.dz-navbar__link--has-children[aria-current="page"]::after {
  content: '';
  position: absolute;
  left: 14px;
  right: 14px;
  bottom: 4px;
  height: 1px;
  background: var(--dz-aqua, #4FC8F4);
  border-radius: 1px;
}
.dz-navbar__sublink[aria-current="page"] { color: var(--dz-aqua, #4FC8F4); }

/* ── Dropdown nav item (e.g. "Solutions" → TwinMs / TwinMaq) ── */
.dz-navbar__dropdown {
  position: relative;
}
.dz-navbar__link--has-children {
  /* Inherit the same base look as a regular .dz-navbar__link, but it's a
     <button> so reset native button chrome. */
  background: transparent;
  border: 0;
  font: inherit;
  font-size: 14px;
  font-weight: var(--dz-fw-regular);
  color: rgba(255,255,255,0.82);
  cursor: pointer;
  padding: 9px 14px;
  border-radius: var(--dz-radius-pill);
  display: inline-flex;
  align-items: center;
  gap: 6px;
  transition: color .15s ease, background .15s ease;
}
.dz-navbar__link--has-children:hover,
.dz-navbar__dropdown.is-open .dz-navbar__link--has-children {
  color: var(--dz-white);
  background: rgba(255,255,255,0.06);
}
.dz-navbar__chevron {
  flex-shrink: 0;
  opacity: 0.65;
  transition: transform 260ms cubic-bezier(0.34, 1.4, 0.64, 1), opacity 200ms ease;
}
.dz-navbar__dropdown.is-open .dz-navbar__chevron {
  transform: rotate(180deg);
  opacity: 1;
}

/* Invisible bridge between parent and submenu so the cursor can cross the
   gap without closing the dropdown */
.dz-navbar__dropdown::after {
  content: "";
  position: absolute;
  top: 100%;
  left: 0;
  right: 0;
  height: 14px;
}

.dz-navbar__submenu {
  position: absolute;
  top: calc(100% + 12px);
  left: 50%;
  min-width: 180px;
  list-style: none;
  margin: 0;
  padding: 6px;
  background: rgba(10, 18, 32, 0.86);
  border: 1px solid rgba(79, 200, 244, 0.2);
  backdrop-filter: blur(16px) saturate(1.2);
  -webkit-backdrop-filter: blur(16px) saturate(1.2);
  border-radius: 14px;
  box-shadow:
    0 0 0 1px rgba(255, 255, 255, 0.02),
    0 22px 48px -14px rgba(0, 0, 0, 0.55);
  opacity: 0;
  visibility: hidden;
  transform: translateX(-50%) translateY(-6px);
  transition: opacity 200ms ease,
              transform 280ms cubic-bezier(0.34, 1.4, 0.64, 1),
              visibility 0s linear 200ms;
  z-index: 50;
}
.dz-navbar__dropdown.is-open .dz-navbar__submenu {
  opacity: 1;
  visibility: visible;
  transform: translateX(-50%) translateY(0);
  transition: opacity 200ms ease,
              transform 280ms cubic-bezier(0.34, 1.4, 0.64, 1);
}

.dz-navbar__sublink {
  display: block;
  padding: 9px 14px;
  border-radius: 8px;
  font-size: 13.5px;
  font-weight: var(--dz-fw-regular);
  color: rgba(255,255,255,0.85);
  text-decoration: none;
  letter-spacing: -0.005em;
  transition: background .15s ease, color .15s ease;
  white-space: nowrap;
}
.dz-navbar__sublink:hover {
  background: rgba(79, 200, 244, 0.12);
  color: var(--dz-white);
}

/* The Solutions parent link is now an <a> (navigates to /solutions/),
   not a <button>. Make sure the link's text-decoration doesn't bleed
   through and that the cursor reads as a link. */
a.dz-navbar__link--has-children {
  text-decoration: none;
  cursor: pointer;
}

.dz-navbar__cta { display: flex; align-items: center; gap: 16px; }
.dz-navbar__iso {
  color: var(--dz-aqua);
  /* The badge is now an <a> linking to /iso-19650/ (was a <span>);
     these two rules kill the default underline and add a subtle
     hover treatment so it reads as interactive. */
  text-decoration: none;
  transition: opacity .18s ease, color .18s ease;
  display: flex;
  align-items: center;
  gap: 8px;
}
.dz-navbar__iso:hover { opacity: 0.8; }
.dz-navbar__iso::before {
  content: "";
  width: 6px; height: 6px; border-radius: 999px;
  background: var(--dz-aqua);
  box-shadow: 0 0 0 4px rgba(79,200,244,0.18);
}

/* ── Hero ── */
.dz-hero {
  position: relative;
  /* body has zoom: 0.8, which shrinks rendered output to 80% of CSS px.
     To make the hero fill the *actual* viewport, ask for 100vh ÷ 0.8 = 125vh.
     If the body zoom value ever changes, update both numbers in lockstep. */
  min-height: 125vh;
  /* dvh changes when the iOS chrome retracts (causes flicker on scroll).
     svh is locked at the SMALLEST viewport size (chrome-visible state)
     so the hero never grows mid-scroll. WebKit blog 2024 — preferred
     for "anchored" floor heights. We still keep 125vh as a fallback for
     older browsers, then svh wins where supported. */
  min-height: 125svh;
  width: 100%;
  overflow: hidden;
  background: var(--dz-navy-deep);
  color: var(--dz-white);
  font-family: var(--dz-font);
  isolation: isolate;
}
.dz-hero__scene {
  position: absolute;
  top: 0;
  right: 8%;     /* shifted in from the right edge so the bigger StageBracket card doesn't overlap the model */
  bottom: 140px; /* leave space for the timeline dock */
  left: 32%;     /* shifted left by ~8% so the model centers further from the card */
  z-index: 1;
}
/* radial vignette keeps text legible — only tints the left text column */
.dz-hero__vignette {
  position: absolute;
  top: 0; bottom: 0; left: 0;
  width: 42%;
  background:
    linear-gradient(90deg, var(--dz-navy-deep) 0%, rgba(26,45,62,0.7) 50%, rgba(26,45,62,0.1) 85%, transparent 100%);
  z-index: 2;
  pointer-events: none;
}
.dz-hero__pattern {
  position: absolute; inset: 0;
  background-image: url('../assets/patterns/dz-pattern-dark.svg');
  background-size: 180px 180px;
  opacity: 0.12;
  z-index: 2;
  pointer-events: none;
  /* fade out from edges so center stays clean for 3D */
  -webkit-mask-image: radial-gradient(ellipse 70% 60% at 50% 50%, transparent 20%, #000 80%);
          mask-image: radial-gradient(ellipse 70% 60% at 50% 50%, transparent 20%, #000 80%);
}

.dz-hero__content {
  position: relative;
  z-index: 3;
  /* Cluster grows with viewport: keeps the laptop layout, expands on big screens */
  max-width: clamp(620px, 38vw, 820px);
  margin: 0;
  padding: clamp(120px, 12vh, 180px) 48px clamp(180px, 18vh, 260px) clamp(72px, 5vw, 140px);
  display: grid;
  gap: clamp(22px, 1.6vw, 32px);
}

.dz-hero__eyebrow {
  display: inline-flex;
  align-items: center;
  gap: 12px;
  color: var(--dz-aqua);
}
.dz-hero__eyebrow-dot {
  width: 8px; height: 8px; border-radius: 999px;
  background: var(--dz-aqua);
  box-shadow: 0 0 0 4px rgba(79,200,244,0.18);
  animation: dz-pulse 2.2s ease-in-out infinite;
}
@keyframes dz-pulse {
  0%, 100% { box-shadow: 0 0 0 4px rgba(79,200,244,0.18); }
  50% { box-shadow: 0 0 0 10px rgba(79,200,244,0); }
}

.dz-hero__title {
  /* Ceiling raised so the title keeps scaling on wide monitors */
  font-size: clamp(38px, 4.4vw, 88px);
  font-weight: var(--dz-fw-bold);
  line-height: 1.04;
  letter-spacing: -0.025em;
  margin: 0;
  max-width: 18ch;
}
.dz-hero__title-accent {
  color: var(--dz-aqua);
  font-style: normal;
  position: relative;
  display: inline-block;
}
.dz-hero__title-accent::after {
  content: "";
  position: absolute;
  left: 0; right: 0; bottom: 0.08em;
  height: 2px;
  background: linear-gradient(90deg, var(--dz-aqua) 0%, transparent 100%);
  opacity: 0.5;
}

.dz-hero__lead {
  font-size: clamp(15px, 1.15vw, 22px);
  font-weight: var(--dz-fw-regular);
  line-height: 1.55;
  color: var(--dz-text-on-dark-muted);
  max-width: clamp(540px, 32vw, 680px);
  text-wrap: pretty;
  margin: 0;
}

.dz-hero__ctas {
  display: flex;
  gap: 12px;
  flex-wrap: wrap;
  margin-top: 8px;
}

/* ── Service pillars list (below lead) ── */
.dz-hero__pillars {
  list-style: none;
  margin: 4px 0 0 0;
  padding: 0;
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 10px 18px;
  max-width: 520px;
}
.dz-hero__pillars li {
  display: flex;
  align-items: center;
  gap: 10px;
  font-size: clamp(14px, 0.95vw, 17px);
  font-weight: var(--dz-fw-regular);
  color: rgba(255,255,255,0.82);
  line-height: 1.35;
}
.dz-hero__pillar-dot {
  width: 6px; height: 6px;
  border-radius: 999px;
  background: var(--dz-aqua);
  flex-shrink: 0;
  box-shadow: 0 0 0 3px rgba(79,200,244,0.18);
}

/* ── Lifecycle timeline (bottom dock) ── */
.dz-lifecycle {
  position: absolute;
  left: 48px;
  right: 48px;
  bottom: 28px;
  z-index: 4;
  background: linear-gradient(180deg, rgba(26,45,62,0.55) 0%, rgba(26,45,62,0.88) 100%);
  backdrop-filter: blur(14px);
  -webkit-backdrop-filter: blur(14px);
  border: 1px solid rgba(79,200,244,0.18);
  border-radius: var(--dz-radius-lg);
  padding: 18px 22px 20px;
  box-shadow: 0 30px 80px rgba(0,0,0,0.35);
}
.dz-lifecycle__head {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: 16px;
  margin-bottom: 14px;
}
.dz-lifecycle__eyebrow {
  color: var(--dz-aqua);
  display: block;
  margin-bottom: 6px;
}
.dz-lifecycle__current {
  font-size: 24px;
  font-weight: var(--dz-fw-semibold);
  color: var(--dz-white);
  letter-spacing: -0.01em;
  line-height: 1.1;
  animation: dz-label-in 0.5s cubic-bezier(0.22, 1, 0.36, 1);
}
@keyframes dz-label-in {
  from { opacity: 0; transform: translateY(6px); }
  to   { opacity: 1; transform: translateY(0); }
}
.dz-lifecycle__controls { display: flex; gap: 8px; }
/* Mobile-only nav arrow row — hidden on desktop, shown again at
   ≤700px in the mobile media block. Default-hide here keeps it out
   of the desktop layout entirely. */
.dz-lifecycle__nav-mobile { display: none; }
.dz-lifecycle__btn {
  width: 36px; height: 36px;
  border-radius: 999px;
  border: 1px solid rgba(255,255,255,0.18);
  background: rgba(255,255,255,0.06);
  color: var(--dz-white);
  cursor: pointer;
  display: grid; place-items: center;
  transition: background .15s ease, border-color .15s ease, transform .15s ease;
}
.dz-lifecycle__btn:hover { background: rgba(255,255,255,0.12); border-color: rgba(255,255,255,0.3); }
.dz-lifecycle__btn--primary {
  background: var(--dz-aqua); color: var(--dz-navy); border-color: transparent;
}
.dz-lifecycle__btn--primary:hover { background: #6fd2f7; transform: scale(1.05); }

.dz-lifecycle__steps {
  list-style: none;
  margin: 0; padding: 0;
  display: grid;
  /* minmax(0, 1fr) lets grid columns shrink below their content's
     intrinsic min-width — without this, long labels like "Operation
     & Maintenance" force the column wider than 1fr, so the rightmost
     stages overflow the lifecycle container at narrow desktop widths
     (1366px laptops cut off stage 09 / 10 / 11). */
  grid-template-columns: repeat(11, minmax(0, 1fr));
  gap: 4px;
}
.dz-step {
  display: flex;
  min-width: 0;            /* allow flex child to shrink under content */
}
.dz-step__btn {
  width: 100%;
  min-width: 0;            /* allow shrinking inside narrow grid columns */
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 6px;
  padding: 8px 8px 10px;
  background: transparent;
  border: none;
  color: inherit;
  cursor: pointer;
  text-align: left;
  font-family: var(--dz-font);
  border-radius: var(--dz-radius-sm);
  transition: background .15s ease;
}
.dz-step__btn:hover { background: rgba(255,255,255,0.04); }
.dz-step__num {
  font-size: 11px;
  font-weight: var(--dz-fw-semibold);
  letter-spacing: 0.1em;
  font-variant-numeric: tabular-nums;
  color: rgba(255,255,255,0.45);
  transition: color .2s ease;
}
.dz-step__label {
  font-size: 11.5px;
  font-weight: var(--dz-fw-regular);
  line-height: 1.25;
  color: rgba(255,255,255,0.55);
  transition: color .2s ease;
  min-height: 28px;
  /* Wrap long labels onto 2 lines instead of forcing the grid column
     wider than 1fr. Combined with min-width: 0 on .dz-step and
     minmax(0, 1fr) on the grid, this guarantees all 11 stages fit. */
  overflow-wrap: break-word;
  word-break: break-word;
  hyphens: auto;
}
.dz-step__bar {
  display: block;
  width: 100%;
  height: 2px;
  border-radius: 2px;
  background: rgba(255,255,255,0.12);
  position: relative;
  overflow: hidden;
  transition: background .25s ease;
}
/* Desktop: hide the mobile-only services list inside each step */
.dz-step__services { display: none; }

.dz-step--done .dz-step__bar { background: rgba(79,200,244,0.55); }
.dz-step--done .dz-step__num { color: rgba(79,200,244,0.75); }
.dz-step--done .dz-step__label { color: rgba(255,255,255,0.75); }

.dz-step--active .dz-step__bar {
  background: linear-gradient(90deg, var(--dz-aqua) 0%, var(--dz-aqua) 100%);
  box-shadow: 0 0 12px rgba(79,200,244,0.6);
}
.dz-step--active .dz-step__num { color: var(--dz-aqua); }
.dz-step--active .dz-step__label { color: var(--dz-white); font-weight: var(--dz-fw-semibold); }

.dz-step--active .dz-step__bar::after {
  content: "";
  position: absolute; inset: 0;
  background: linear-gradient(90deg, transparent 0%, rgba(255,255,255,0.8) 50%, transparent 100%);
  animation: dz-bar-shimmer 1.6s ease-in-out infinite;
}
@keyframes dz-bar-shimmer {
  0% { transform: translateX(-100%); }
  100% { transform: translateX(100%); }
}

/* ── Bracket callout (services per stage) ── */
.dz-bracket {
  position: absolute;
  top: 150px;
  right: 56px;
  z-index: 2;
  width: 400px;
  padding: 26px 24px;
  pointer-events: auto;
  font-family: var(--dz-font);
  color: var(--dz-white);
  /* Scale 0.78 trims the card so a clear ~40-50px breathing gap sits
     between the BIM ring's right edge and the service pills at the
     common 1366px laptop width. transform-origin: top right keeps
     the card anchored against the right edge so the inner padding
     doesn't shift inward. */
  transform: scale(0.78);
  transform-origin: top right;
}

/* Video-frame corner brackets (top-left + bottom-right) */
.dz-bracket__corner {
  position: absolute;
  width: 28px; height: 28px;
  border-color: var(--dz-aqua);
  border-style: solid;
  border-width: 0;
  pointer-events: none;
}
.dz-bracket__corner--tl {
  top: 0; left: 0;
  border-top-width: 2px;
  border-left-width: 2px;
}
.dz-bracket__corner--br {
  bottom: 0; right: 0;
  border-bottom-width: 2px;
  border-right-width: 2px;
}

.dz-bracket__head { margin-bottom: 18px; }
.dz-bracket__phase {
  display: flex;
  align-items: baseline;
  gap: 12px;
  margin-bottom: 8px;
  animation: dz-label-in 0.5s cubic-bezier(0.22,1,0.36,1);
}
.dz-bracket__phase-num {
  font-size: 13px;
  font-weight: var(--dz-fw-bold);
  letter-spacing: 0.08em;
  color: var(--dz-aqua);
  font-variant-numeric: tabular-nums;
  font-family: ui-monospace, 'SF Mono', Menlo, monospace;
}
.dz-bracket__phase-name {
  font-size: 24px;
  font-weight: var(--dz-fw-semibold);
  letter-spacing: -0.01em;
  line-height: 1.1;
  color: var(--dz-white);
}
.dz-bracket__meta {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: 10px;
  font-weight: var(--dz-fw-semibold);
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: rgba(79,200,244,0.85);
  white-space: nowrap;
}
.dz-bracket__count {
  font-variant-numeric: tabular-nums;
  color: var(--dz-aqua);
  font-size: 10px;
  font-weight: var(--dz-fw-bold);
}

.dz-bracket__list {
  list-style: none;
  margin: 0; padding: 0;
  display: flex;
  flex-direction: column;
  gap: 12px;
}
.dz-bracket__pill {
  display: flex;
  align-items: stretch;
  gap: 0;             /* the inner anchor sets its own padding + gap */
  padding: 0;
  background: rgba(79,200,244,0.04);
  border: 1px solid rgba(79,200,244,0.32);
  border-radius: var(--dz-radius-pill);
  color: var(--dz-white);
  font-size: 16px;          /* ↑ from 13 — more readable inside the bigger card */
  font-weight: var(--dz-fw-semibold);
  letter-spacing: -0.005em;
  white-space: nowrap;
  opacity: 0;
  transform: translateX(10px);
  animation: dz-pill-in 0.4s cubic-bezier(0.22,1,0.36,1) forwards;  /* ↓ 0.6s → 0.4s */
  transition: background .18s ease, border-color .18s ease, transform .18s ease;
  overflow: hidden;
}
.dz-bracket__pill:hover {
  background: rgba(79,200,244,0.14);
  border-color: var(--dz-aqua);
  transform: translateX(0) translateY(-1px);
}
/* The anchor that wraps the letter + name and routes to the service
   detail page. Fills the pill so the entire chip is the click target. */
.dz-bracket__pill-link {
  display: flex;
  align-items: center;
  gap: 14px;
  padding: 13px 20px 13px 13px;     /* ↑ more vertical breathing room */
  width: 100%;
  color: inherit;
  text-decoration: none;
}
.dz-bracket__pill-letter {
  width: 32px; height: 32px;        /* ↑ from 26x26 */
  flex-shrink: 0;
  border-radius: 999px;
  background: rgba(79,200,244,0.16);
  border: 1px solid rgba(79,200,244,0.45);
  color: var(--dz-aqua);
  font-family: ui-monospace, 'SF Mono', Menlo, monospace;
  font-size: 13px;                  /* ↑ from 11 */
  font-weight: var(--dz-fw-bold);
  display: grid;
  place-items: center;
  letter-spacing: 0;
}
.dz-bracket__pill-name {
  /* Service name now reads in bright white instead of aqua-on-aqua-
     tinted-pill (which read muddy at the smaller pill size + dark
     glassy bg). The aqua identity stays on the letter chip + border. */
  color: var(--dz-white);
  flex: 1 1 auto;
  overflow: visible;
}
@keyframes dz-pill-in {
  from { opacity: 0; transform: translateX(12px); }
  to   { opacity: 1; transform: translateX(0); }
}

/* ── Responsive ── */
@media (max-width: 1024px) {
  .dz-navbar { padding: 16px 24px; }
  .dz-navbar__nav { display: none; }
  .dz-hero__content { margin-left: 0; padding: 120px 24px 24px 32px; max-width: 100%; }
  .dz-lifecycle { left: 16px; right: 16px; padding: 14px 14px 16px; }
  .dz-lifecycle__steps { grid-template-columns: repeat(4, 1fr); }
  .dz-step:nth-child(n+9) { display: none; }
  /* Bracket: hide on narrow screens — services live in the bottom rail instead */
  .dz-bracket { display: none; }
}
@media (max-width: 640px) {
  .dz-navbar__iso { display: none; }
  .dz-lifecycle__steps { grid-template-columns: repeat(3, 1fr); }
  .dz-step:nth-child(n+4) { display: none; }
  .dz-lifecycle__current { font-size: 20px; }
}

/* ─── Hero · video fallback for WebGL-blocked browsers ──────────────────
   When js/Hero.jsx detects no usable WebGL (missing context OR software-only
   renderer like SwiftShader, common on enterprise-managed Chrome 137+), it
   swaps <BIMScene> for a <video> that plays a recording of the SAME 3D
   scene. Stage clicks seek + play through the recorded transition.
   The recording was captured at 30fps with renderer.setClearColor matching
   the page bg, so the video looks identical to the live WebGL render. ── */
/* Scene container in fallback mode:
   - Solid navy bg so letterbox/pillarbox margins from object-fit:contain
     blend invisibly with the page bg.
   - z-index raised above .dz-hero__vignette and .dz-hero__pattern so the
     video isn't dimmed by the left-column vignette overlay (which is
     designed to darken the empty area behind the WebGL canvas's
     alpha-transparent zones — but in fallback mode the video is opaque
     and doesn't need that compositing). */
.dz-hero__scene--video {
  background: var(--dz-navy-deep, #1A2D3E);
  z-index: 2;
}

/* ── Locked-stage pulse ────────────────────────────────────────────────
   When the user taps a stage, the video plays that stage's clip once
   then pauses on the last frame (Hero.jsx onEnded handler). The scene
   container picks up `.is-locked`, which renders a soft radial glow
   centered on the 3D model — NOT a rectangular halo around the whole
   container. The glow pulses in opacity + scale so it reads as the
   model itself "breathing", not a frame around the video panel. ──── */
@keyframes dz-hero-locked-pulse {
  0%, 100% { opacity: 0.35; transform: translate(-50%, -50%) scale(1); }
  50%      { opacity: 0.85; transform: translate(-50%, -50%) scale(1.08); }
}
/* No position override — both .dz-hero__scene (position: absolute on
   desktop) and .dz-hero__scene--video (position: relative on mobile)
   already create positioning contexts that anchor the ::before pseudo.
   Adding `position: relative` here would have collapsed desktop's
   absolute positioning (top/right/bottom/left), zero-ing the scene's
   height. */
/* ── Locked-stage glow REMOVED (2026-05-10) ───────────────────────────
   The radial aqua pulse on the 3D model when a stage was locked was
   distracting on both desktop and mobile. The user requested removal.
   The .is-locked CLASS is still applied by Hero.jsx (used elsewhere
   for video-pause UX); just no visual decoration tied to it now. */
.dz-hero__scene.is-locked::before,
.dz-hero__scene--video.is-locked::before {
  display: none !important;
}
.dz-hero__video {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  /* The recording was made with the camera zoomed out 30% so the entire
     ring fits inside the recorded frame with margin. `contain` preserves
     that aspect, and the .dz-hero__scene--video's navy background fills
     any letterbox/pillarbox margin invisibly. */
  object-fit: contain;
  object-position: center;
  pointer-events: none;
  user-select: none;
  display: block;
}

/* ── Accessibility ──────────────────────────────────────────────────────
   Skip-to-main link, global focus-visible baseline, and a top-level
   prefers-reduced-motion guard for motion that wasn't already opted in.
   ──────────────────────────────────────────────────────────────────── */

/* Skip-link — first focusable element on every page. WCAG 2.4.1 (Bypass
   Blocks) AA. Visually hidden until keyboard focus moves it to the top
   of the viewport. Click/Enter jumps the cursor to #dz-main and screen
   readers continue from there. */
.dz-skip-link {
  position: fixed;
  top: 8px;
  left: 8px;
  z-index: 1000;
  padding: 12px 18px;
  background: var(--dz-aqua, #4FC8F4);
  color: var(--dz-navy-deep, #1A2D3E);
  font-family: var(--dz-font, 'Outfit', system-ui, sans-serif);
  font-size: 14px;
  font-weight: 600;
  letter-spacing: -0.005em;
  text-decoration: none;
  border-radius: var(--dz-radius, 10px);
  /* Hidden via the visually-hidden technique (Lighthouse-friendly,
     2026-05-11): clip-path + 1×1 size keeps the link fully focusable
     and announced by screen readers but invisible until tab-focused.
     On :focus the dimensions restore (see :focus rule below) and the
     pill paints at top-left. The old transform:translateY(-200%)
     approach was technically focusable too, but Lighthouse's
     skip-link audit flags it because off-screen transforms can be
     treated as obscured. */
  width: 1px;
  height: 1px;
  clip-path: inset(50%);
  transform: translateY(0);
  transition: transform 200ms cubic-bezier(0.22, 1, 0.36, 1);
}
/* Lighthouse a11y fix 2026-05-11: was hidden via transform:translateY(-200%)
   which Lighthouse classifies as "not focusable" because the offset can
   make Chrome treat the link as obscured even when focused. Switching to
   the visually-hidden technique (clip-path + 1px size) is the canonical
   pattern that auditors recognise. The element stays tab-reachable;
   focus brings it back to a 1×1 corner for an instant before the
   visible-on-focus rule below paints the full pill at the top. */
.dz-skip-link:focus,
.dz-skip-link:focus-visible {
  transform: translateY(0);
  clip-path: none;
  width: auto;
  height: auto;
  outline: 0;
  box-shadow: 0 0 0 3px rgba(79, 200, 244, 0.45), 0 8px 24px rgba(26, 45, 62, 0.4);
}

/* Global focus-visible baseline — every interactive element that lacks an
   explicit :focus-visible rule gets a sane aqua focus ring. Per-component
   rules in home.css override this where they exist (and they should: the
   pill, the lifecycle tick, the FAQ toggle all have richer treatments). */
:where(a, button, [role="button"], input, select, textarea, summary, [tabindex]:not([tabindex="-1"])):focus-visible {
  outline: 2px solid var(--dz-aqua, #4FC8F4);
  outline-offset: 3px;
  border-radius: var(--dz-radius-sm, 6px);
}

/* Reduced-motion guard. Targeted, not blanket — heavy/parallax effects
   already opt in via per-section rules in home.css (the cold-open hero,
   the scroll-driven reveals, the FAQ toggle, etc.).  Here we only cap
   scroll-behavior so JS-driven smooth scrolls don't become vestibular,
   and stop the eyebrow's looping pulse animation. */
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto !important; }
  .dz-hero__eyebrow-dot { animation: none !important; }
}

/* ──────────────────────────────────────────────────────────────────────
   MOBILE NAVIGATION (hamburger + drawer) — added 2026-05-06
   ──────────────────────────────────────────────────────────────────────
   The desktop navbar lays out as logo + nav + cta in a row. On phones
   (<= 900px) the centre nav and the right-side ISO caption + Contact
   button are HIDDEN, replaced by a hamburger that opens a full-width
   drawer with every link.

   Why 900px not 768px: under body{zoom:0.8} (which we keep on phones for
   layout consistency below 700px), 900 CSS px renders ~720 actual px —
   a comfortable point to switch from condensed desktop nav to drawer.
   ─────────────────────────────────────────────────────────────────── */

/* Hamburger button — hidden on desktop, shown on mobile via media query */
.dz-navbar__hamburger {
  display: none;
  position: relative;
  width: 44px;
  height: 44px;
  padding: 0;
  margin: 0;
  background: transparent;
  border: 1px solid rgba(255,255,255,0.2);
  border-radius: 10px;
  cursor: pointer;
  z-index: 105;
  transition: border-color .25s ease, background .25s ease;
  -webkit-tap-highlight-color: transparent;
}
.dz-navbar__hamburger:hover {
  border-color: rgba(79,200,244,0.5);
  background: rgba(79,200,244,0.06);
}
.dz-navbar__hamburger-line {
  position: absolute;
  left: 50%;
  width: 18px;
  height: 1.5px;
  background: var(--dz-text-on-dark, #FFFFFF);
  border-radius: 1px;
  transform: translateX(-50%);
  transition: transform .3s cubic-bezier(.4,0,.2,1), opacity .2s ease, top .3s cubic-bezier(.4,0,.2,1);
}
.dz-navbar__hamburger-line:nth-child(1) { top: 14px; }
.dz-navbar__hamburger-line:nth-child(2) { top: 21px; }
.dz-navbar__hamburger-line:nth-child(3) { top: 28px; }

/* Hamburger morphs into X when menu is open */
.dz-navbar.is-mobile-open .dz-navbar__hamburger {
  border-color: rgba(79,200,244,0.5);
}
.dz-navbar.is-mobile-open .dz-navbar__hamburger-line:nth-child(1) {
  top: 21px;
  transform: translateX(-50%) rotate(45deg);
}
.dz-navbar.is-mobile-open .dz-navbar__hamburger-line:nth-child(2) {
  opacity: 0;
}
.dz-navbar.is-mobile-open .dz-navbar__hamburger-line:nth-child(3) {
  top: 21px;
  transform: translateX(-50%) rotate(-45deg);
}

/* Mobile drawer — slides down from below the header */
/* ════════════════════════════════════════════════════════════════════
   MOBILE MENU — "Concierge" design L (deployed 2026-05-09)
   Hospitality-grade asymmetric menu. Opens to a soft greeting, a tiered
   nav (featured pair + compact secondary list), and a signed-invitation
   CTA. Solid navy panel — no glassmorphism per DESIGN.md.

   IMPORTANT: rendered as a SIBLING of <header> in JSX (not a child) so
   it escapes the navbar's backdrop-filter containing block. Open state
   driven by body.dz-nav-mobile-open (managed by useEffect in Navbar.jsx).
   ════════════════════════════════════════════════════════════════════ */
.dz-navbar__mobile {
  position: fixed;
  top: 72px;
  left: 0;
  right: 0;
  bottom: 0;
  background: var(--dz-navy, #2B3D4F);
  color: #FFFFFF;
  z-index: 1000;
  display: none;
  flex-direction: column;
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
  visibility: hidden;
  transform: translateY(-12px);
  opacity: 0;
  transition: transform .38s cubic-bezier(.16,1,.3,1),
              opacity .28s cubic-bezier(.16,1,.3,1),
              visibility 0s linear .38s;
  font-family: 'Outfit', system-ui, sans-serif;
  padding: 28px 24px 24px;
}
body.dz-nav-mobile-open .dz-navbar__mobile {
  visibility: visible;
  transform: translateY(0);
  opacity: 1;
  transition: transform .38s cubic-bezier(.16,1,.3,1),
              opacity .28s cubic-bezier(.16,1,.3,1);
}

/* Backdrop scrim (no blur per DESIGN.md). Behind navbar (z 99 < 100)
   so navbar stays readable. Tap closes (handled in JSX). */
.dz-navbar__mobile-backdrop {
  position: fixed;
  inset: 0;
  z-index: 99;
  background: rgba(0,0,0,0.45);
  opacity: 0;
  visibility: hidden;
  pointer-events: none;
  transition: opacity .28s cubic-bezier(.16,1,.3,1),
              visibility 0s linear .28s;
}
body.dz-nav-mobile-open .dz-navbar__mobile-backdrop {
  opacity: 1;
  visibility: visible;
  pointer-events: auto;
  transition: opacity .28s cubic-bezier(.16,1,.3,1);
}

/* Solid navbar bg while menu is open — no compounded backdrop-filter */
body.dz-nav-mobile-open .dz-navbar {
  background: var(--dz-navy, #2B3D4F);
  backdrop-filter: none;
  -webkit-backdrop-filter: none;
}

/* ── GREETING — tonal anchor ── */
.dz-navbar__mobile-greeting {
  margin-bottom: 26px;
  opacity: 0;
  animation: dz-mmenu-fade-up 520ms cubic-bezier(.16,1,.3,1) forwards;
  animation-delay: 120ms;
}
.dz-navbar__mobile-greeting-eyebrow {
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: #4FC8F4;
  margin-bottom: 14px;
  opacity: 0.85;
}
.dz-navbar__mobile-greeting-line {
  font-size: 36px;
  font-weight: 300;
  letter-spacing: -0.025em;
  line-height: 1.05;
  color: rgba(255,255,255,0.96);
}
.dz-navbar__mobile-greeting-line em {
  font-style: normal;       /* italic reserved for product names only */
  color: #4FC8F4;
  font-weight: 400;
}

/* ── FEATURED PAIR (tier 1) — slight asymmetric 1.2:1 ──
   Was 3:2; that was too aggressive — Solutions ended up only ~84px of
   content width and copy looked centered (it wasn't, just narrow). */
.dz-navbar__mobile-featured {
  display: grid;
  grid-template-columns: 1.2fr 1fr;
  grid-auto-flow: dense;
  gap: 10px;
  margin-bottom: 28px;
}
.dz-navbar__mobile-feat {
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  padding: 14px 16px 16px;
  background: rgba(255,255,255,0.06);
  border: 1px solid rgba(255,255,255,0.10);   /* hairline edge defines the card */
  border-radius: 8px;
  text-decoration: none;
  color: rgba(255,255,255,0.96);
  cursor: pointer;
  position: relative;
  overflow: hidden;
  min-height: 120px;
  text-align: left;
  font-family: inherit;
  opacity: 0;
  animation: dz-mmenu-fade-up 520ms cubic-bezier(.16,1,.3,1) forwards;
  transition: background .28s cubic-bezier(.16,1,.3,1),
              border-color .28s cubic-bezier(.16,1,.3,1),
              transform .28s cubic-bezier(.16,1,.3,1);
  -webkit-tap-highlight-color: transparent;
}
.dz-navbar__mobile-feat:hover {
  background: rgba(255,255,255,0.09);
  border-color: rgba(79, 200, 244,0.40);
}
.dz-navbar__mobile-feat:active { transform: scale(0.985); }
.dz-navbar__mobile-feat--primary { animation-delay: 320ms; }
.dz-navbar__mobile-feat--solutions { animation-delay: 380ms; }
.dz-navbar__mobile-feat-name {
  font-size: 19px;
  font-weight: 500;
  letter-spacing: -0.018em;
  line-height: 1.1;
  text-align: left;
  color: rgba(255,255,255,0.96);
  transition: color .22s cubic-bezier(.16,1,.3,1);
}
.dz-navbar__mobile-feat-desc {
  font-size: 12.5px;
  font-weight: 400;
  line-height: 1.45;
  text-align: left;            /* force left — button UA defaults to center */
  color: rgba(255,255,255,0.56);
  margin-top: 8px;
  padding-right: 26px;          /* clear of bottom-right chevron */
}
.dz-navbar__mobile-feat-chev {
  position: absolute;
  bottom: 14px;            /* bottom-right anchor — never crowds the name */
  right: 14px;
  width: 16px;
  height: 16px;
  color: rgba(255,255,255,0.42);
  transition: transform .32s cubic-bezier(.16,1,.3,1),
              color .22s cubic-bezier(.16,1,.3,1);
}
/* Hover — name and chevron turn aqua in sync */
.dz-navbar__mobile-feat:hover .dz-navbar__mobile-feat-name { color: #4FC8F4; }
.dz-navbar__mobile-feat:hover .dz-navbar__mobile-feat-chev { color: #4FC8F4; }

/* Solutions card open state */
.dz-navbar__mobile-feat--solutions[data-open="true"] .dz-navbar__mobile-feat-chev {
  transform: rotate(90deg);
  color: #4FC8F4;
}

/* ── Solutions children — reveal under the featured grid ── */
.dz-navbar__mobile-feat-children {
  grid-column: 1 / -1;
  display: grid;
  grid-template-rows: 0fr;
  transition: grid-template-rows .42s cubic-bezier(.16,1,.3,1);
}
.dz-navbar__mobile-feat-children-inner {
  overflow: hidden;
  min-height: 0;
}
.dz-navbar__mobile-feat-children[data-open="true"] {
  grid-template-rows: 1fr;
}
.dz-navbar__mobile-feat-children-list {
  list-style: none;
  padding: 6px 18px 4px;
  margin-top: 4px;
}
.dz-navbar__mobile-feat-children-list li {
  opacity: 0;
  transform: translateY(-4px);
  transition: opacity .32s cubic-bezier(.16,1,.3,1),
              transform .32s cubic-bezier(.16,1,.3,1);
}
.dz-navbar__mobile-feat-children[data-open="true"] .dz-navbar__mobile-feat-children-list li {
  opacity: 1;
  transform: translateY(0);
}
.dz-navbar__mobile-feat-children[data-open="true"] .dz-navbar__mobile-feat-children-list li:nth-child(1) { transition-delay: 60ms; }
.dz-navbar__mobile-feat-children[data-open="true"] .dz-navbar__mobile-feat-children-list li:nth-child(2) { transition-delay: 120ms; }
.dz-navbar__mobile-feat-children[data-open="true"] .dz-navbar__mobile-feat-children-list li:nth-child(3) { transition-delay: 180ms; }

.dz-navbar__mobile-feat-child {
  display: block;
  padding: 12px 0;
  font-size: 19px;
  font-style: italic;       /* product names — italic per brand */
  font-weight: 400;
  letter-spacing: -0.01em;
  color: rgba(255,255,255,0.78);
  text-decoration: none;
  transition: color .22s cubic-bezier(.16,1,.3,1),
              transform .22s cubic-bezier(.16,1,.3,1);
}
.dz-navbar__mobile-feat-child + .dz-navbar__mobile-feat-child {
  border-top: 1px solid rgba(255,255,255,0.06);
}
.dz-navbar__mobile-feat-child:hover {
  color: #4FC8F4;
  transform: translateX(2px);
}
/* Overview / hub link — concierge voice, not a product, so non-italic + aqua */
.dz-navbar__mobile-feat-child--overview {
  font-style: normal;
  font-weight: 500;
  font-size: 16px;
  letter-spacing: 0.02em;
  color: #4FC8F4;
  display: inline-flex;
  align-items: baseline;
  gap: 8px;
  transition: gap .22s cubic-bezier(.16,1,.3,1), color .22s;
}
.dz-navbar__mobile-feat-child--overview:hover {
  color: #A8E2F8;
  transform: none;
  gap: 14px;
}
.dz-navbar__mobile-feat-child--overview span {
  font-weight: 400;
}
.dz-navbar__mobile-feat-child small {
  font-style: normal;
  font-weight: 400;
  font-size: 12px;
  color: rgba(255,255,255,0.32);
  margin-left: 8px;
  letter-spacing: 0.04em;
}

/* ── SECONDARY LIST (tier 2) ── */
.dz-navbar__mobile-secondary {
  list-style: none;
  margin: 0 0 32px;
  padding: 0;
}
.dz-navbar__mobile-secondary li {
  opacity: 0;
  animation: dz-mmenu-fade-up 460ms cubic-bezier(.16,1,.3,1) forwards;
}
.dz-navbar__mobile-secondary li:nth-child(1) { animation-delay: 480ms; }
.dz-navbar__mobile-secondary li:nth-child(2) { animation-delay: 540ms; }
.dz-navbar__mobile-secondary li:nth-child(3) { animation-delay: 600ms; }
.dz-navbar__mobile-secondary li:nth-child(4) { animation-delay: 660ms; }
.dz-navbar__mobile-secondary li:nth-child(5) { animation-delay: 720ms; }

.dz-navbar__mobile-secondary-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 13px 2px;
  font-size: 17px;
  font-weight: 400;
  letter-spacing: -0.005em;
  color: rgba(255,255,255,0.78);
  text-decoration: none;
  border-bottom: 1px solid rgba(255,255,255,0.06);
  min-height: 46px;
  transition: color .22s cubic-bezier(.16,1,.3,1),
              padding .22s cubic-bezier(.16,1,.3,1);
  -webkit-tap-highlight-color: rgba(79, 200, 244,0.10);
}
.dz-navbar__mobile-secondary li:last-child .dz-navbar__mobile-secondary-row {
  border-bottom: 0;
}
/* Hover — name and arrow turn aqua in sync */
.dz-navbar__mobile-secondary-row:hover {
  color: #4FC8F4;
  padding-left: 6px;
}
.dz-navbar__mobile-secondary-row:hover .dz-navbar__mobile-secondary-arrow {
  opacity: 1;
  transform: translateX(0);
  color: #4FC8F4;
}
.dz-navbar__mobile-secondary-arrow {
  width: 14px;
  height: 14px;
  color: #4FC8F4;
  opacity: 0;
  transform: translateX(-6px);
  transition: opacity .22s cubic-bezier(.16,1,.3,1),
              transform .22s cubic-bezier(.16,1,.3,1);
}

/* ── CTA — signed-message pattern, bottom-right anchor ── */
.dz-navbar__mobile-cta-section {
  margin-top: auto;
  padding: 22px 0 6px;
  border-top: 1px solid rgba(255,255,255,0.06);
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  text-align: right;
  opacity: 0;
  animation: dz-mmenu-fade-up 520ms cubic-bezier(.16,1,.3,1) forwards;
  animation-delay: 800ms;
}
.dz-navbar__mobile-cta-lead {
  font-size: 13px;
  font-weight: 400;
  line-height: 1.45;
  color: rgba(255,255,255,0.56);
  max-width: 220px;
  margin: 0 0 8px;
}
.dz-navbar__mobile-cta-link {
  display: inline-flex;
  align-items: baseline;
  gap: 8px;
  font-size: 17px;
  font-weight: 600;
  letter-spacing: -0.005em;
  color: #4FC8F4;
  text-decoration: none;
  padding: 4px 0;
  transition: gap .26s cubic-bezier(.16,1,.3,1),
              color .22s cubic-bezier(.16,1,.3,1);
}
.dz-navbar__mobile-cta-link:hover {
  gap: 14px;
  color: #FFFFFF;
}
.dz-navbar__mobile-cta-arrow {
  font-weight: 400;
  font-size: 18px;
  line-height: 1;
  transform: translateY(1px);
}

/* ── FOOTER LINE ── */
.dz-navbar__mobile-foot {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding-top: 18px;
  margin-top: 14px;
  font-size: 10.5px;
  font-weight: 400;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: rgba(255,255,255,0.32);
  opacity: 0;
  animation: dz-mmenu-fade-up 460ms cubic-bezier(.16,1,.3,1) forwards;
  animation-delay: 880ms;
}
.dz-navbar__mobile-foot-lang {
  display: inline-flex;
  align-items: center;
  gap: 6px;
}
.dz-navbar__mobile-foot-lang em {
  color: #4FC8F4;
  font-style: normal;
  font-weight: 600;
}

@keyframes dz-mmenu-fade-up {
  from { opacity: 0; transform: translateY(8px); }
  to   { opacity: 1; transform: translateY(0); }
}

body.dz-nav-mobile-open {
  overflow: hidden;     /* prevent page scroll while menu is open */
}

/* ════════════════════════════════════════════════════════════════════
   THE BREAKPOINT — show hamburger / hide desktop nav at <= 900px
   ════════════════════════════════════════════════════════════════════ */
@media (max-width: 900px) {
  .dz-navbar {
    padding: 14px 20px;
    /* iOS Safari: backdrop-filter is less effective on mobile and content
       bleeds through the 0.7-alpha navbar. Bump to 0.94 so the navbar
       reads as a solid bar on top of light AND dark page content. */
    background: rgba(26, 45, 62, 0.94);
  }
  .dz-navbar__nav,
  .dz-navbar__cta {
    display: none;        /* hide desktop nav and right-side CTA */
  }
  .dz-navbar__hamburger {
    display: block;
    margin-left: auto;
  }
  /* Mobile menu — flex (column) so the children stack as designed */
  .dz-navbar__mobile {
    display: flex;
  }
}

/* ──────────────────────────────────────────────────────────────────────
   GLOBAL MOBILE OVERRIDES — added 2026-05-06
   ──────────────────────────────────────────────────────────────────────
   The site uses body{zoom:0.8} for desktop layout density. On phones
   (<= 700px) we restore zoom:1 because:

     1. iOS Safari and Android Chrome interpret `zoom` inconsistently
     2. Combined with viewport meta tag, can produce subtle horizontal
        scroll and broken vh calculations
     3. At phone widths, the desktop density isn't relevant — content
        already stacks vertically

   We keep zoom:0.8 between 700-900px (small tablet / large phone in
   landscape) where it still gives useful density. Below 700px, the
   real device pixels drive layout 1:1.
   ─────────────────────────────────────────────────────────────────── */
@media (max-width: 700px) {
  body {
    zoom: 1 !important;
  }
  /* Touch target safety — anything that handles a tap should be ≥ 44px tall */
  .dz-btn,
  .dz-navbar__mobile-link,
  .dz-navbar__mobile-cta,
  .dz-navbar__hamburger {
    min-height: 44px;
  }
  /* Body text should not get smaller than 15px on phones for readability */
  body, p {
    font-size: max(15px, 1em);
  }

  /* ─── HERO — mobile reflow (2026-05-09 simplified) ───────────────────
     Previous mobile rules hid the 3D/video scene entirely and surrounded
     the lifecycle in a heavy translucent panel with header copy + control
     buttons. That made the hero feel like a desktop port — the BIM scene
     wasn't visible AND the timeline ate too much space.
     New behaviour: video plays at the top of the hero as an inline
     7:6 panel (matching the recording's native aspect), content sits
     below it, and the lifecycle becomes a clean swipeable pill strip
     with no chrome. ─────────────────────────────────────────────── */
  .dz-hero {
    min-height: auto;
    /* Zero out the inherited desktop side padding (20px L+R) on
       mobile because (a) box-sizing: content-box adds it to the
       width, pushing the whole hero section 5px past the viewport
       right edge, and (b) the inner children that need horizontal
       insets (.dz-hero__content, .dz-hero__scene--video,
       .dz-lifecycle__nav-mobile) all carry their own padding. */
    padding: 0 !important;
    display: flex;
    flex-direction: column;
  }
  /* Static 3D scene stays hidden on mobile — Three.js + WebGL is heavy
     for phones and the recorded video version covers the same content. */
  .dz-hero__scene:not(.dz-hero__scene--video) {
    display: none !important;
  }
  /* Recorded video — promoted to a relative-positioned banner at the top
     of the mobile hero. Native aspect 7:6 (1428x1224 source). */
  .dz-hero__scene--video {
    display: block !important;
    position: relative !important;
    inset: auto !important;
    top: auto !important; right: auto !important;
    bottom: auto !important; left: auto !important;
    width: calc(100% - 24px) !important;
    margin: 14px auto 0 !important;
    /* Bumped from 16:10 to 4:3 — gives the BIM model more pixels
       so it actually reads as the hero element. Combined with
       object-fit: cover on the inner <video>, the empty navy
       margin around the model gets cropped and the model fills
       the frame. ~293px tall on a 366px wide phone. */
    aspect-ratio: 4 / 3 !important;
    border-radius: 14px !important;
    overflow: hidden !important;
    z-index: 1 !important;
    order: 1;
  }
  /* On mobile only, switch object-fit from contain → cover so the
     model fills the bigger 4:3 frame instead of being letterboxed
     inside it. The recording has built-in headroom (camera zoomed
     out 30% to fit the full ring with margin) so cropping a bit at
     top/bottom doesn't lose the model — it just removes the
     dead space around it. */
  .dz-hero__scene--video .dz-hero__video {
    object-fit: cover !important;
  }
  .dz-hero__vignette,
  .dz-hero__pattern { display: none !important; }
  .dz-hero__content {
    max-width: 100%;
    /* Tightened top + bottom padding to lift the title + CTAs
       closer to the video above (per "move buttons up"). */
    padding: 10px 20px 14px !important;
    gap: 10px;
    order: 2;
  }
  .dz-hero__title {
    /* Reduced again so the title yields visual weight to the
       enlarged 3D model above. Was clamp(26, 7vw, 32) — now
       clamp(20, 5.5vw, 26). Still readable on a phone, just less
       dominant; the model is now the hero element, the headline
       supports it. */
    font-size: clamp(20px, 5.5vw, 26px);
    line-height: 1.15;
  }
  /* Mobile simplification — drop the eyebrow + lead paragraph so the
     hero reads: title → CTAs → story cards. The story cards now carry
     the per-stage detail that the lead used to summarize. */
  .dz-hero__eyebrow,
  .dz-hero__lead {
    display: none !important;
  }
  .dz-hero__ctas {
    flex-wrap: wrap;
    gap: 10px;
  }
  .dz-hero__ctas .dz-btn {
    flex: 1 1 auto;
    min-width: 140px;
    justify-content: center;
  }

  /* ─── LIFECYCLE — simplified pill strip ────────────────────────────
     Drop the panel chrome (border + bg + padding), the header text
     (eyebrow + active stage name — redundant with the active pill), and
     the playback controls (autoplay handles itself). What remains: 11
     compact pills in a horizontal swipe rail. Active pill = aqua tint. */
  .dz-lifecycle {
    position: relative;
    left: auto;
    right: auto;
    bottom: auto;
    margin: 6px 0 24px !important;
    padding: 0 !important;
    background: transparent !important;
    border: none !important;
    backdrop-filter: none;
    -webkit-backdrop-filter: none;
    box-shadow: none !important;
    order: 3;
  }
  .dz-lifecycle__head { display: none !important; }
  .dz-lifecycle__controls { display: none !important; }

  /* Mobile-only prev/next nav row above the stage carousel.
     Sibling of __head so it's not affected by the rules that hide
     the desktop chrome. Visitor swipes the cards OR taps these
     arrows; either way the active card scroll-syncs (Hero.jsx).
     Arrows sit at the viewport edges (16px breathing room) with
     the stage identifier centred between them. */
  .dz-lifecycle__nav-mobile {
    display: flex !important;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    padding: 0 16px 8px;
    margin: 0;       /* no auto-centring — full viewport width */
    /* No max-width: arrows hug the screen edges. */
  }
  .dz-lifecycle__nav-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 44px;
    height: 44px;
    flex-shrink: 0;
    border-radius: 999px;
    background: rgba(255,255,255,0.06);
    border: 1px solid rgba(255,255,255,0.18);
    color: rgba(255,255,255,0.85);
    cursor: pointer;
    transition: background .18s, border-color .18s, transform .12s;
    -webkit-tap-highlight-color: transparent;
  }
  .dz-lifecycle__nav-btn:active {
    background: rgba(79,200,244,0.18);
    border-color: rgba(79,200,244,0.55);
    color: var(--dz-aqua);
    transform: scale(0.96);
  }
  /* Stage identifier between the two arrows: stacked layout —
     stage name on top (visual focus), faint "Stage N" ghost
     subtitle underneath. Column flex centres both lines. */
  .dz-lifecycle__nav-meta {
    flex: 1 1 auto;
    min-width: 0;
    display: inline-flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 2px;
    font-family: var(--dz-font, inherit);
    text-align: center;
    overflow: hidden;
  }
  .dz-lifecycle__nav-name {
    font-size: 17px;
    font-weight: 600;
    letter-spacing: -0.005em;
    color: var(--dz-white);
    line-height: 1.15;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    max-width: 240px;
  }
  /* "Stage N" ghost subtitle — quiet position indicator at very
     low opacity so it reads as background metadata, not as primary
     content. Doesn't compete with the stage name above or with the
     LOD numbers in service rows below. */
  .dz-lifecycle__nav-ghost {
    font-size: 10px;
    font-weight: 600;
    letter-spacing: 0.18em;
    text-transform: uppercase;
    color: rgba(255,255,255,0.30);
    line-height: 1;
    white-space: nowrap;
    font-variant-numeric: tabular-nums;
  }

  /* MOBILE STORY MODE: each step is a full-width card with services.
     Active card is bright; neighbours dim to 0.4 to let the centered
     card read as the focus. Swipe horizontally to peek at upcoming
     stages — the autoplay timer keeps cycling regardless. */
  .dz-lifecycle__steps {
    display: flex !important;
    grid-template-columns: none !important;
    overflow-x: auto;
    overflow-y: hidden;
    scroll-snap-type: x mandatory;
    overscroll-behavior-x: contain;
    -webkit-overflow-scrolling: touch;
    scrollbar-width: none;
    /* No gap between cards: combined with flex:0 0 100% on .dz-step,
       this means each card fills the viewport exactly with no peek
       of the neighbouring stage. Visitors swipe (or tap the prev /
       next arrows above) to move between stages. */
    gap: 0 !important;
    padding: 4px 0 12px !important;
    margin-inline: 0 !important;
    scroll-padding-inline: 0 !important;
  }
  .dz-lifecycle__steps::-webkit-scrollbar { display: none; }

  .dz-step {
    /* Full-viewport-width cards — no peek of stage 2 on the right.
       The previous calc(100% - 40px) intentionally showed the next
       card's edge for "swipe affordance" but the partial label was
       reading as broken layout instead. */
    flex: 0 0 100% !important;
    scroll-snap-align: center !important;
    min-width: 0 !important;
    max-width: none !important;
    padding: 0 16px !important;
    transition: opacity .22s !important;   /* ↓ snappier than .35s */
    opacity: 0.4;
    display: block !important;
  }
  .dz-step--active { opacity: 1 !important; }

  /* Per-row stagger when a stage becomes active — services fade in
     sequentially over ~280ms total instead of arriving as a block. */
  .dz-step--active .dz-step__services li {
    animation: dz-mob-svc-in 0.32s cubic-bezier(0.22,1,0.36,1) both;
  }
  .dz-step--active .dz-step__services li:nth-child(1) { animation-delay: 0ms; }
  .dz-step--active .dz-step__services li:nth-child(2) { animation-delay: 70ms; }
  .dz-step--active .dz-step__services li:nth-child(3) { animation-delay: 140ms; }
  @keyframes dz-mob-svc-in {
    from { opacity: 0; transform: translateX(8px); }
    to   { opacity: 1; transform: translateX(0); }
  }

  .dz-step__btn {
    width: 100% !important;
    box-sizing: border-box;
    background: transparent !important;
    border: none !important;
    border-radius: 0 !important;
    padding: 0 !important;
    flex-direction: column !important;
    align-items: flex-start !important;
    gap: 0 !important;
    text-align: left !important;
    cursor: pointer;
    /* Override any min-height / hover from the desktop pill button */
    min-height: 0 !important;
  }
  .dz-step__btn:hover {
    background: transparent !important;
  }

  /* The big "01" + "Programming" inside the card are now hidden on
     mobile because the same identifier lives between the prev/next
     arrows above. Keeping both was redundant and pushed the services
     below the fold. The card header is now just the services list. */
  .dz-step__num,
  .dz-step__label,
  .dz-step__bar { display: none !important; }

  /* Services list — visible on mobile only. Now the only content
     inside the stage card (no big number/label above), so it gets
     the full vertical attention. */
  .dz-step__services {
    display: block !important;
    list-style: none !important;
    padding: 0 !important;
    margin: 0 !important;
    border-top: 1px solid rgba(255,255,255,0.12);
    width: 100%;
  }
  .dz-step__services li + li {
    border-top: 1px solid rgba(255,255,255,0.08);
  }
  .dz-step__service {
    display: flex !important;
    /* Left-aligned: name on the left, arrow pushed to the right
       edge of the row. Standard list-row affordance — visitors
       parse it instantly as a tappable nav item. The previous
       centered-with-arrow treatment made the row read asymmetric
       (the arrow shifted the visual centre). */
    justify-content: space-between !important;
    align-items: center !important;
    gap: 10px;
    /* Tightened from 17px so 3 services fit in the viewport budget
       below the title + CTAs + nav row. Still ≥44px tap target. */
    padding: 13px 16px !important;
    box-sizing: border-box;
    max-width: 100%;
    color: rgba(255,255,255,0.70) !important;
    text-decoration: none !important;
    font-size: 15px !important;
    font-weight: 500 !important;
    line-height: 1.3 !important;
    text-align: left;
    transition: color .22s, transform .22s;
  }
  .dz-step__service:hover, .dz-step__service:active {
    color: var(--dz-white) !important;
  }
  .dz-step__service-arrow {
    color: var(--dz-aqua) !important;
    margin-left: 12px;
    transition: transform .22s;
  }
  .dz-step__service:hover .dz-step__service-arrow,
  .dz-step__service:active .dz-step__service-arrow {
    transform: translateX(4px);
  }
}
