/* ── DBM Global · prototype ─────────────────────────────────────────
   Fluid canvas · content on a 1200 rail that shrinks with the viewport
   Type: Archivo (display/body) + JetBrains Mono (labels)
   ------------------------------------------------------------------ */

:root {
  --navy-deep: #0A1A32;
  --navy-900:  #0D1F3B;
  --navy-700:  #12294D;
  --navy-rule: #24405E;

  --blue:      #007CBB;
  --blue-lt:   #7FC4EA;
  --blue-pale: #9FD4F0;
  --blue-soft: #68A6DB;

  --ink:   #12294D;
  --body:  #43505F;
  --muted: #8095AC;
  --dim:   #A9BCD0;

  --mist:  #E9EEF4;
  --mist2: #EDF2F8;
  --rule:  #C9D4E1;
  --rule-lt: #D5DEE9;

  --rail-max: 1200px;
  --gut: 120px;

  --f-display: 'Archivo', system-ui, sans-serif;
  --f-mono: 'JetBrains Mono', ui-monospace, monospace;

  --ease: cubic-bezier(.22,.61,.36,1);
  /* the header fold travels 138px both ways, so it wants a slow both-ends curve
     rather than the snappy ease-out the rest of the interface uses */
  --hdr-dur: 620ms;
  --hdr-ease: cubic-bezier(.33,.02,.18,1);
}

@media (max-width: 1280px) { :root { --gut: 64px; } }
@media (max-width: 900px)  { :root { --gut: 24px; } }

* { box-sizing: border-box; }
html { scroll-behavior: smooth; }

body {
  margin: 0;
  overflow-x: hidden;
  font-family: var(--f-display);
  font-weight: 400;
  color: var(--body);
  background: #fff;
  -webkit-font-smoothing: antialiased;
}

img { display: block; }
/* figure carries a 40px UA side margin that silently offset the carousel */
figure { margin: 0; }
a { text-decoration: none; color: inherit; }

.rail { width: min(var(--rail-max), 100% - var(--gut) * 2); margin-inline: auto; }

.mono { font-family: var(--f-mono); font-weight: 400; letter-spacing: .12em; font-size: 11px; line-height: 18px; }
.lbl { color: var(--muted); }

.h2 { margin: 0; font-weight: 300; font-size: clamp(28px, 2.8vw, 40px); line-height: 1.3; letter-spacing: -.02em; color: var(--ink); }
.h2--accent { color: var(--blue); }
.h2--onnavy { color: #fff; }
.h3 { margin: 0; font-weight: 300; font-size: 32px; line-height: 40px; letter-spacing: -.02em; color: var(--ink); }
.body { margin: 0; font-size: 16px; line-height: 28px; color: var(--body); }
.body--onnavy { color: var(--dim); }

.split { display: flex; align-items: flex-start; gap: 80px; }
.split__l { flex: 0 1 520px; }
.split__r { flex: 0 1 600px; display: flex; flex-direction: column; gap: 26px; }
/* Once the row stacks, flex-basis stops meaning width and starts meaning HEIGHT,
   so the 520/600 bases were padding every split section with ~1120px of nothing.
   Reset the basis and let both columns take the full width. */
@media (max-width: 1000px) {
  .split { flex-direction: column; gap: 32px; }
  .split__l, .split__r { flex: 0 0 auto; width: 100%; }
}

/* ── button ─────────────────────────────────────────────────────── */
.btn { display: inline-flex; align-items: center; gap: 8px; padding: 6px 6px 6px 24px; border-radius: 2px; width: max-content; }
.btn--white { background: #fff; }
.btn--white .btn__label { color: var(--ink); }
.btn__label { font-size: 14px; line-height: 18px; }
.btn__label.mono { font-size: 11px; line-height: 16px; font-weight: 500; }
.btn__tile {
  width: 40px; height: 40px; flex-shrink: 0; border-radius: 2px; background: var(--blue);
  display: flex; align-items: center; justify-content: center; color: #fff; font-size: 15px; line-height: 1;
  transition: background-color .18s var(--ease), transform .18s var(--ease);
}
.btn__tile--sm { width: 30px; height: 30px; font-size: 13px; }
.btn:hover .btn__tile { background: var(--navy-700); transform: translateX(3px); }

/* Unplated CTA — label, arrow, rule. No box, so it inherits whatever ground it
   sits on and reads as a peer to the nav rather than the only chrome on the page.
   The whole block is the target, not the words: 48px tall clears the touch
   minimum and gives the pointer somewhere to land above and below the text. */
.cta {
  display: inline-flex; flex-direction: column; justify-content: center;
  gap: 11px; height: 48px; width: max-content; color: #fff;
}
.cta__row { display: flex; align-items: center; gap: 14px; }
.cta__label { font-size: 15px; line-height: 22px; }
.cta__arrow { font-size: 14px; line-height: 22px; transition: transform .18s var(--ease); }
.cta__rule {
  display: block; height: 1px; width: 100%; background: currentColor; opacity: .5;
  transition: opacity .18s var(--ease), height .18s var(--ease);
}
.cta:hover .cta__arrow { transform: translateX(6px); }
.cta:hover .cta__rule { opacity: 1; height: 2px; }
/* keyboard focus gets its own outline rather than borrowing the rule, so it is
   never mistaken for a hover */
.cta:focus-visible { outline: 2px solid var(--blue); outline-offset: 6px; }

/* ── header ─────────────────────────────────────────────────────── */
/* Fixed from the first pixel. It used to start absolute and switch to fixed at
   200px, so scrolling from the top let it ride away with the page and then snap
   back — a disappear/reappear rather than a move. Same element throughout now;
   only the backdrop plate changes, and that just fades. */
.hdr { position: fixed; top: 0; left: 0; width: 100%; z-index: 60; }
/* Scrolling down folds it away; scrolling up or hovering the top edge brings it back.
   The IES / investor bar stays put through all of it: the header travels up by its own
   height and the bar is pushed back down by the same amount, so it never leaves. */
/* the fold is a live value now, not a binary state: it tracks scroll directly for
   the first nav-row's worth of travel, then the directional reveal drives it */
.hdr { transform: translateY(calc(-1 * var(--fold, 0px))); }
.hdr.is-eased { transition: transform var(--hdr-dur) var(--hdr-ease); }

.topbar { transform: translateY(var(--fold, 0px)); }
.hdr.is-eased .topbar { transition: transform var(--hdr-dur) var(--hdr-ease); }

/* A transformed element becomes the containing block for its position:fixed
   descendants. The header is transformed for the scroll fold, so the mobile
   takeover — fixed, inset 0, and a child of the header — was resolving against
   the header's own 138px box instead of the viewport. It opened as a sliver
   tucked under the folded bar with the page showing through everywhere else.
   Opening the menu drops the fold, which removes the transform and hands the
   takeover back to the viewport. The header belongs at the top with a menu
   open regardless. */
.hdr.is-open, .hdr.is-open .topbar { transform: none; }

/* invisible catcher along the very top so a hover can summon the folded header */
.peek { position: fixed; top: 0; left: 0; width: 100%; height: 24px; z-index: 59; pointer-events: none; }
.peek.is-armed { pointer-events: auto; }
.hdr__plate {
  position: absolute; inset: 0 0 auto 0; height: 138px; background: var(--navy-deep);
  opacity: 0; pointer-events: none; transition: opacity .22s var(--ease);
}
/* at the very top the bar floats over the hero; hovering it brings the plate in
   so the links stay legible, and it leaves again when the pointer does */
.hdr.is-stuck .hdr__plate, .hdr.is-peeking .hdr__plate { opacity: 1; }

/* the bar outranks the nav row so the fold slides away UNDER it, never across it */
.topbar { position: relative; z-index: 3; height: 34px; background: var(--navy-700); }
.topbar__inner { display: flex; align-items: center; justify-content: space-between; height: 34px; }
.topbar__lede { font-size: 9px; line-height: 12px; color: #8FA6BC; }
.topbar__links { display: flex; gap: 26px; }
.topbar__links a { font-size: 9px; line-height: 12px; color: #fff; opacity: .9; transition: color .16s var(--ease); }
.topbar__links a:hover { color: var(--blue-lt); }

.navrow { position: relative; z-index: 2; height: 104px; display: flex; align-items: center; justify-content: space-between; }
.navrow__logo img { width: 104px; height: 52px; }
.nav { display: flex; align-items: center; gap: 30px; }
.nav a { font-size: 15px; line-height: 18px; color: #fff; padding: 8px 0; position: relative; transition: color .16s var(--ease); }
.nav a::after {
  content: ''; position: absolute; left: 0; right: 0; bottom: 0; height: 2px; background: var(--blue);
  transform: scaleX(0); transform-origin: left; transition: transform .22s var(--ease);
}
/* the underline is a hover affordance — nothing opens from the nav any more */
.nav a:hover, .nav a.is-on { color: var(--blue-lt); }
.nav a:hover::after, .nav a.is-on::after { transform: scaleX(1); }
@media (max-width: 1100px) { .nav { display: none; } }


/* ── hero ───────────────────────────────────────────────────────── */
/* Full viewport, and pinned: the cover holds at the top of the screen while every
   section after it scrolls up and covers it. That is the whole effect — the copy
   and the logo strip stay put rather than travelling with the page. Sections are
   already z-index 0 and paint in document order, so each one rides over this. */
.hero { position: sticky; top: 0; width: 100%; height: 100vh; height: 100svh; min-height: 640px; overflow: hidden; background: var(--navy-900); }
.hero__stage {
  position: absolute; left: 0; top: -30%; width: 100%; height: 160%;
  background-size: cover; background-position: 50%;
  opacity: 0; transition: opacity .8s var(--ease);
  will-change: transform, opacity;
}
.hero__stage.is-on { opacity: 1; }
/* The cross-fade puts an inline z-index on the incoming layer. Everything that sits
   over the photograph therefore needs to outrank it explicitly, or the image paints
   over the headline, dots, credit and logo strip. */
.hero__scrim, .hero__topfade { z-index: 3; }
.hero__head, .hero__dots, .credit, .powered { z-index: 4; }
.hero__scrim {
  position: absolute; inset: 0;
  /* Taken from the Paper board, not approximated. The bottom stop is a LIGHT BLUE,
     not navy — that lift is what gives the carousel its cast. Rebuilding it in navy
     alone read as a grey wash and lost the colour entirely. */
  background: linear-gradient(0deg,
    rgba(23,108,168,.94) 0%,
    rgba(13,31,59,.62) 46%,
    rgba(13,31,59,.30) 66%,
    rgba(13,31,59,.10) 84%,
    rgba(13,31,59,0) 100%);
  background: linear-gradient(0deg,
    oklab(44.9% -0.035 -0.130 / 94%) 0%,
    oklab(21.9% -0.011 -0.051 / 62%) 46%,
    oklab(21.9% -0.011 -0.051 / 30%) 66%,
    oklab(21.9% -0.011 -0.051 / 10%) 84%,
    oklab(21.9% -0.011 -0.051 / 0%) 100%);
}
.hero__topfade { position: absolute; left: 0; top: 0; width: 100%; height: 190px; background: linear-gradient(180deg, rgba(13,31,59,.58) 0%, rgba(13,31,59,.22) 60%, rgba(13,31,59,0) 100%); }
.hero__head { position: absolute; left: 50%; translate: -50%; top: 30%; }
.hero__title { margin: 0; font-weight: 200; font-size: clamp(64px, 7.8vw, 112px); line-height: 1.07; letter-spacing: -.025em; color: #fff; }
/* the two lines are deliberately far apart in weight — the qualifier recedes, the word carries it */
.hero__title--bold, .ftr__we--bold { font-weight: 500; }
.hero__body { margin: 20px 0 0; max-width: 620px; min-height: 84px; font-size: 17px; line-height: 28px; color: #fff; }

/* Slide changes are a real out-then-in: the copy leaves completely before it is
   replaced, so two slides' text is never on screen at once, then it rises back. */
.hero__body, .credit { transition: opacity .26s var(--ease), transform .26s var(--ease); }
.hero.is-out .credit { opacity: 0; transform: translateY(-10px); }
/* the sub-copy's words now rise out of their own masks, so a block-level rise on
   top of that would be two animations doing one job — the credit keeps it */
.hero.is-in .credit { animation: copyIn .52s var(--ease) both; }
.hero.is-in .credit { animation-delay: 90ms; }
@keyframes copyIn { from { opacity: 0; transform: translateY(16px); } to { opacity: 1; transform: none; } }
.hero__dots { position: absolute; left: 50%; translate: -50%; bottom: 168px; display: flex; align-items: center; gap: 12px; }
.hero__dots button { width: 34px; height: 3px; border: 0; padding: 0; cursor: pointer; background: rgba(255,255,255,.34); transition: background-color .25s var(--ease); }
.hero__dots button.is-active { background: #fff; }

/* label above, logos as a seamless marquee below */
/* no backplate — the logos ride on the photograph, with only enough tonal
   protection under them to keep white marks legible */
.powered {
  position: absolute; left: 0; bottom: 0; width: 100%; height: 158px;
  background: linear-gradient(180deg, rgba(10,26,50,0) 0%, rgba(10,26,50,.30) 34%, rgba(10,26,50,.42) 100%);
  padding-top: 26px; overflow: hidden;
}
.powered__label { display: block; color: var(--blue-lt); letter-spacing: .14em; }
.marquee { position: relative; margin-top: 30px; overflow: hidden; }
/* the track holds the sequence twice; translating by exactly one copy loops seamlessly */
.marquee__track { display: flex; align-items: center; width: max-content; animation: marquee var(--dur, 42s) linear infinite; }
.marquee__track img { width: 108px; height: 36px; margin-right: 132px; object-fit: contain; opacity: .92; }
@keyframes marquee { to { transform: translate3d(calc(var(--loop) * -1), 0, 0); } }
.powered:hover .marquee__track { animation-play-state: paused; }
/* No edge fades on the logo scroll. They were meant to soften where the marquee
   leaves the viewport, but over a photograph they read as two navy panels sitting
   on the image rather than as a fade. The track just clips at the edge. */

/* subtle project credit on the hero photograph */
.credit {
  position: absolute; right: var(--gut); bottom: 186px; margin: 0; z-index: 3;
  text-align: right; font-family: var(--f-mono); font-size: 10px; line-height: 16px; letter-spacing: .12em;
  transition: opacity .5s var(--ease);
}
.credit b { display: block; font-weight: 400; color: rgba(255,255,255,.72); }
.credit span { display: block; color: rgba(255,255,255,.4); }

/* ── knockout quote: scroll-linked word highlight ───────────────── */
/* Sections layer in document order. Without this a positioned child — a portfolio
   cell, which needs position for its hover reveal — paints over the section that
   follows it, so the grid animated in on top of Markets instead of under it. */
.page > section { position: relative; z-index: 0; }
/* .page > section outranks .hero on specificity, so the pin has to match it */
.page > .hero { position: sticky; top: 0; }

.statement { background: var(--blue); padding: clamp(64px, 8vw, 110px) 0; }
.statement__copy { margin: 0; max-width: 900px; font-weight: 300; font-size: clamp(28px, 3.4vw, 46px); line-height: 1.35; letter-spacing: -.02em; }
.statement__copy w {
  color: rgba(255,255,255,.28);
  transition: color .32s var(--ease);
}
.statement__copy w.is-lit { color: #fff; }

/* ── integrated delivery · pinned scroll ────────────────────────── */
.delivery { position: relative; background: var(--mist); }
.delivery__pin { position: sticky; top: 0; height: 100vh; min-height: 720px; display: flex; flex-direction: column; justify-content: center; overflow: hidden; }
.delivery__head { padding-bottom: 48px; }
/* scroll-linked handoff at both ends of the pin — see the delivery module */
.delivery__head, .delivery__stage {
  opacity: var(--enter, 1);
  transform: translate3d(0, var(--shift, 0px), 0);
  will-change: opacity, transform;
}
.delivery__stage {
  position: relative; display: flex; align-items: center;
  padding-right: max(var(--gut), calc((100% - var(--rail-max)) / 2));
}
/* The phase names line up with the body copy above them, and the photograph stops
   90px short of the rule so the two never crowd each other. */
.delivery__visuals { position: relative; flex: 1 1 auto; min-width: 0; margin-right: 90px; aspect-ratio: 5 / 4; max-height: 54vh; overflow: hidden; }
.delivery__visuals figure { position: absolute; inset: 0; margin: 0; background-size: cover; background-position: 50%; opacity: 0; transform: scale(1.06); transition: opacity .55s var(--ease), transform .8s var(--ease); }
.delivery__visuals figure.is-on { opacity: 1; transform: none; }
/* 600, not 630 — the stage is padded to the rail on the right, so a 600 column
   puts the rule exactly on the viewport centre line at every width. It was landing
   30px left of centre, which put it out of step with the services rail below. */
.delivery__phases { flex: 0 1 600px; display: flex; flex-direction: column; }

.phase__list { position: relative; padding-left: 30px; }
.phase__rule { position: absolute; left: 0; top: 0; bottom: 0; width: 2px; background: var(--rule); }
/* the marker spans the open phase: its name plus the copy beneath it */
.phase__marker {
  position: absolute; left: 0; top: 0; width: 2px; background: var(--blue);
  height: calc(var(--row, 67px) + var(--dh, 0px));
  transition: transform .58s var(--ease), height .5s var(--ease);
}
.phase { cursor: pointer; border-bottom: 1px solid var(--rule-lt); }
.phase:first-child { border-top: 1px solid var(--rule-lt); }
.phase__row { display: flex; align-items: center; height: 66px; }
.phase__t {
  font-size: 26px; line-height: 34px; letter-spacing: -.02em; color: #8095AC;
  transition: color .3s var(--ease);
}
.phase.is-on .phase__t { color: var(--ink); }
.phase:hover .phase__t { color: var(--ink); }

/* every phase opens to the same reserved height, set at runtime from the longest
   paragraph, so the list is one size and each opens at one rate */
.phase__d {
  height: 0; overflow: hidden; opacity: 0;
  transition: height .5s var(--ease), opacity .32s var(--ease);
}
.phase.is-on .phase__d { height: var(--dh, 0px); opacity: 1; }
.phase__inner { padding-bottom: 0; }
.phase__d p { margin: 0; max-width: 500px; font-size: 16px; line-height: 28px; color: var(--body); }
.phase__pending { display: block; font-size: 10px; letter-spacing: .12em; color: var(--blue); }

/* measuring must see the real content height, not the collapsed state */
.phase__list.is-measuring .phase__d { height: auto; opacity: 1; transition: none; }

@media (max-width: 1000px) {
  /* The pin holds here too — image and rail lock to the screen while the phases
     step through, same as desktop. It used to go static, which is why the section
     just scrolled past on a phone. The stage stacks instead of splitting, and the
     photograph is capped so image + list still fit one screen. --dh stays reserved
     (see lockHeight) so the pinned block is one height and never reflows. */
  /* The sticky header sits over the top of the pin, and now that the photograph
     takes every spare pixel the head is pushed right under it — the first line of
     the title was hidden. Reserve the folded header's height. */
  .delivery__pin { height: 100svh; min-height: 0; padding: 46px 0 0; }
  .delivery__stage { flex-direction: column; align-items: stretch; padding-right: 0; }
  .delivery__phases { flex: 0 0 auto; margin-left: 0; padding-top: 24px; }
  .delivery__visuals { margin-right: 0; aspect-ratio: 16 / 11; max-height: 28svh; }
}

/* ── portfolio wall ─────────────────────────────────────────────── */
.portfolio { background: var(--navy-900); padding-top: 96px; }
.split--onnavy { padding-bottom: 56px; }
.wall { display: grid; grid-template-columns: repeat(4, 1fr); }
@media (max-width: 1000px) { .wall { grid-template-columns: repeat(2, 1fr); } }
.wall__cell { position: relative; aspect-ratio: 1 / 1; overflow: hidden; }
.wall__bg { position: absolute; inset: 0; background-size: cover; background-position: 50%; transform: scale(1); transition: transform .7s var(--ease); }
.wall__cell:hover .wall__bg { transform: scale(1.06); }
/* rest gradient — light, only where the logo and location sit */
.wall__cell::after {
  content: ''; position: absolute; inset: 0; pointer-events: none;
  background: linear-gradient(0deg, rgba(10,26,50,.92) 0%, rgba(10,26,50,.72) 30%, rgba(10,26,50,.12) 66%, rgba(10,26,50,0) 84%);
  transition: opacity .4s var(--ease);
}
/* hover gradient — deeper and taller, so the revealed copy has something to sit on */
.wall__cell::before {
  content: ''; position: absolute; inset: 0; z-index: 1; pointer-events: none; opacity: 0;
  background: linear-gradient(0deg, rgba(10,26,50,.95) 0%, rgba(10,26,50,.88) 44%, rgba(10,26,50,.5) 74%, rgba(10,26,50,.18) 100%);
  transition: opacity .4s var(--ease);
}
.wall__cell:hover::before { opacity: 1; }
.wall__cell:hover::after { opacity: 0; }

.wall__copy { position: absolute; left: 32px; bottom: 32px; right: 32px; z-index: 2; display: flex; flex-direction: column; gap: 14px; }
.wall__copy img { width: 150px; height: 34px; object-fit: contain; object-position: left center; }
.wall__loc { font-size: 10px; color: #B9CBDD; }

/* the block is bottom-anchored, so the reveal grows upward without shifting the logo lane */
.wall__reveal {
  display: grid; grid-template-rows: 0fr; opacity: 0;
  transition: grid-template-rows .42s var(--ease), opacity .3s var(--ease);
}
.wall__cell:hover .wall__reveal,
.wall__cell:focus-within .wall__reveal { grid-template-rows: 1fr; opacity: 1; }
.wall__revealed { min-height: 0; overflow: hidden; display: flex; flex-direction: column; gap: 14px; }
.wall__desc { margin: 0; font-size: 15px; line-height: 24px; color: #D3DFEC; }
.wall__cta { display: inline-flex; align-items: center; gap: 10px; width: max-content; cursor: pointer; }
.wall__cta:hover .mono { color: var(--blue-lt); }
.wall__cta:hover i { transform: translate(2px, -2px); }
.wall__cta .mono { font-size: 10px; font-weight: 500; color: #fff; }
/* no tile behind the arrow — it was the only filled block left on the wall and
   read as a button pasted onto the photograph */
.wall__cta i {
  flex-shrink: 0; font-style: normal; font-size: 13px; color: #fff;
  transition: transform .2s var(--ease);
}
.wall__cell:hover .wall__cta i { transform: translate(2px, -2px); }

/* ── markets ────────────────────────────────────────────────────── */
.markets { background: var(--mist2); padding: clamp(72px, 8vw, 118px) 0 clamp(72px, 8vw, 110px); overflow: hidden; }
.markets__head { padding-bottom: 64px; }
/* the copy column narrows so the photography can run wider, and both start level */
.markets__body { display: flex; align-items: flex-start; gap: 56px; padding-left: max(var(--gut), calc((100% - var(--rail-max)) / 2)); }
.markets__col { width: 344px; flex-shrink: 0; display: flex; flex-direction: column; }

.switch { display: flex; align-items: flex-end; gap: 36px; margin-top: 26px; }
.switch__tab {
  border: 0; background: none; padding: 0; cursor: pointer; display: flex; flex-direction: column; gap: 12px;
  font-family: var(--f-display); font-size: 22px; line-height: 30px; letter-spacing: -.01em; color: var(--muted); font-weight: 400;
  transition: color .2s var(--ease);
}
.switch__tab i { display: block; height: 2px; background: var(--rule); transition: background-color .2s var(--ease); }
.switch__tab:hover { color: var(--ink); }
.switch__tab.is-active { color: var(--ink); font-weight: 300; }
.switch__tab.is-active i { background: var(--blue); }

.markets__project { margin: -6px 0 26px; font-size: 24px; line-height: 32px; }
.spec { margin: 0; display: flex; flex-direction: column; transition: opacity .25s var(--ease); }
.spec__row { display: flex; flex-direction: column; gap: 5px; padding: 15px 0; border-top: 1px solid var(--rule-lt); }
.spec__row:last-child { border-bottom: 1px solid var(--rule-lt); }
.spec__row dt { font-family: var(--f-mono); font-size: 10px; line-height: 18px; letter-spacing: .12em; color: var(--muted); flex-shrink: 0; }
.spec__row dd { margin: 0; font-size: 15px; line-height: 24px; color: var(--ink); }
/* project copy: out, replace, then rise back with the rows staggered */
/* the counter holds still — only the project copy transitions */
.markets__project, .spec__row { transition: opacity .26s var(--ease), transform .26s var(--ease); }
.markets__col.is-out .markets__project,
.markets__col.is-out .spec__row { opacity: 0; transform: translateY(-10px); }
.markets__col.is-in .markets__project,
.markets__col.is-in .spec__row { animation: copyIn .52s var(--ease) both; animation-delay: var(--d, 0ms); }

.pager { display: flex; align-items: center; gap: 16px; margin-top: 32px; }
.circ {
  width: 48px; height: 48px; flex-shrink: 0; border-radius: 24px; border: 1px solid #B9C7D6; background: none; cursor: pointer;
  display: flex; align-items: center; justify-content: center; font-size: 15px; color: var(--ink);
  transition: background-color .2s var(--ease), color .2s var(--ease), border-color .2s var(--ease);
}
.circ:hover { background: var(--navy-700); border-color: var(--navy-700); color: #fff; }
.circ--fill { background: var(--blue); border-color: var(--blue); color: #fff; }
.circ--fill:hover { background: var(--navy-700); border-color: var(--navy-700); }
.pager__count { margin-left: 12px; color: var(--muted); }

/* carousel — a real track that slides, with the next slide bleeding off-canvas */
.carousel { flex: 1; min-width: 0; overflow: hidden; cursor: grab; }
.carousel.is-dragging { cursor: grabbing; }
.carousel__track { display: flex; gap: 20px; will-change: transform; transition: transform .68s var(--ease); }
.carousel__slide {
  position: relative; width: 760px; height: 500px; flex-shrink: 0; overflow: hidden;
  background-size: cover; background-position: 50%;
  filter: saturate(.92); transition: filter .5s var(--ease);
}
.carousel__slide.is-on { filter: none; }
.carousel__slide figcaption {
  position: absolute; left: 28px; bottom: 24px; z-index: 2;
  font-family: var(--f-mono); font-size: 10px; letter-spacing: .12em; color: #fff;
  opacity: 0; transform: translateY(6px); transition: opacity .4s var(--ease), transform .4s var(--ease);
}
.carousel__slide::after {
  content: ''; position: absolute; inset: 0;
  background: linear-gradient(0deg, rgba(10,26,50,.7) 0%, rgba(10,26,50,0) 42%);
  opacity: 0; transition: opacity .4s var(--ease);
}
.carousel__slide.is-on figcaption { opacity: 1; transform: none; }
.carousel__slide.is-on::after { opacity: 1; }
/* stretch again once stacked, or flex-start collapses the column to its content */
@media (max-width: 1000px) { .markets__body { flex-direction: column; align-items: stretch; padding-right: var(--gut); } .markets__col { width: 100%; } }

/* ── fast facts ─────────────────────────────────────────────────── */
.facts { display: grid; grid-template-columns: 1fr 1fr; background: var(--navy-900); }
@media (max-width: 1000px) { .facts { grid-template-columns: 1fr; } }
.facts__hero { position: relative; min-height: 620px; overflow: hidden; }
.facts__img { position: absolute; left: 0; top: -30%; width: 100%; height: 160%; background-size: cover; background-position: 50%; transition: opacity .5s var(--ease); will-change: transform; }
.facts__scrim { position: absolute; inset: 0; background: linear-gradient(0deg, rgba(10,26,50,.94) 0%, rgba(10,26,50,.82) 32%, rgba(10,26,50,.2) 58%, rgba(10,26,50,0) 78%); }
/* sits on the page gutter like every other block, not on its own 60px inset */
.facts__herocopy { position: absolute; left: var(--gut); right: 60px; bottom: 56px; display: flex; flex-direction: column; gap: 16px; }
.facts__grid { display: grid; grid-template-columns: 1fr 1fr; }
.facts__cell {
  padding: 44px; display: flex; flex-direction: column; gap: 12px; cursor: pointer;
  border-bottom: 1px solid var(--navy-rule); border-right: 1px solid var(--navy-rule);
  transition: background-color .28s var(--ease);
}
/* the outer column stops on the rail rather than running to the page edge */
.facts__cell:nth-child(2n) { border-right: 0; padding-right: var(--gut); }
.facts__cell:nth-child(n+3) { border-bottom: 0; }
.facts__cell:hover { background: rgba(255,255,255,.04); }
.facts__cell:hover .num { color: var(--blue-pale); }

.num { margin: 0; font-weight: 300; letter-spacing: -.04em; color: #fff; font-size: 72px; line-height: 80px; display: flex; align-items: baseline; gap: 8px; transition: color .25s var(--ease); }
.num--xl { font-size: clamp(88px, 9vw, 140px); line-height: 1.06; gap: 10px; }
.num__unit { font-weight: 400; font-size: 26px; line-height: 34px; color: var(--blue-lt); letter-spacing: -.02em; }
.num--xl .num__unit { font-size: 44px; line-height: 52px; }
.sub { color: #8FA6BC; }
.facts .lbl--bright { color: var(--blue-lt); }
.facts__herocopy .lbl--bright { color: var(--blue-pale); }
.facts__herocopy .sub { color: #B9CBDD; }
.facts__herocopy > * { animation: fadeUp .5s var(--ease); }
@keyframes fadeUp { from { opacity: 0; transform: translateY(10px); } to { opacity: 1; transform: none; } }

/* ── safety ─────────────────────────────────────────────────────── */
.safety { background: #fff; }
.safety__band { position: relative; width: 100%; height: clamp(420px, 46vw, 560px); overflow: hidden; }
/* the layer overhangs its frame top and bottom — that surplus is the parallax travel */
.safety__img { position: absolute; left: 0; top: -35%; width: 100%; height: 170%; background: url('assets/img/safety.jpg') 50% / cover; will-change: transform; }
.safety__scrim { position: absolute; inset: 0; background: linear-gradient(180deg, rgba(18,41,77,.16) 0%, rgba(18,41,77,.22) 34%, rgba(18,41,77,.62) 66%, rgba(18,41,77,.76) 100%); }
.safety__copy { position: absolute; left: 50%; translate: -50%; bottom: 60px; }
.safety__t1, .safety__t2 { margin: 0; font-size: clamp(34px, 3.7vw, 52px); line-height: 1.2; letter-spacing: -.02em; color: #fff; }
.safety__t1 { font-weight: 300; }
.safety__t2 { font-weight: 200; }
.safety__detail { padding: 88px 0 96px; }

/* ── footer ─────────────────────────────────────────────────────── */
/* the page sits above the footer; scrolling down slides it off and uncovers the footer */
.page { position: relative; z-index: 2; background: #fff; }

.ftr {
  position: fixed; left: 0; bottom: 0; width: 100%; z-index: 1;
  background: var(--navy-900); color: #fff; overflow: hidden;
}
.ftr__bg { position: absolute; inset: 0; overflow: hidden; }
.ftr__img {
  position: absolute; left: 0; top: -18%; width: 100%; height: 136%;
  background: url('assets/img/field-crew.jpg') 50% 40% / cover;
  will-change: transform;
}
.ftr__inner, .ftr__legal { will-change: transform, opacity; }
.ftr::before {
  content: ''; position: absolute; inset: 0; z-index: 1; pointer-events: none;
  background: linear-gradient(180deg, rgba(10,26,50,.86) 0%, rgba(13,31,59,.94) 44%, rgba(18,41,77,.985) 100%);
}
/* five proportional columns that fill the 1200 rail exactly, so the last one ends
   on the rail edge instead of wherever its content happened to run to */
/* Four columns per the board: brand lockup, one link column, companies, address.
   Connect sits under the brand and Follow under the address, on a second row. */
.ftr__inner { position: relative; z-index: 2; display: grid; grid-template-columns: 1.7fr .8fr 1.05fr 1.25fr; gap: 60px 48px; padding: 88px 0 64px; }
/* The lockup sits at the TOP of the row, not centred in it — otherwise the mark
   floats below the columns beside it. Its own three parts stay centred on each
   other, so the logo top lines up with the labels on the right. */
.ftr__brand { grid-column: 1; grid-row: 1; align-self: start; display: flex; align-items: center; gap: 29px; }
.ftr__links { grid-column: 2; grid-row: 1; }
.ftr__cos   { grid-column: 3; grid-row: 1; }
.ftr__addr  { grid-column: 4; grid-row: 1; }
.ftr__links a { white-space: nowrap; }
/* Hairline between the mark and the statement. Measured off the board: 103px,
   the height of the statement block — not the full column. Stretching it made it
   read as a long thin ruler running past both sides of the lockup. */
.ftr__divide { width: 1px; height: 103px; flex-shrink: 0; background: rgba(255,255,255,.38); }
@media (max-width: 1100px) { .ftr__inner { grid-template-columns: repeat(2, 1fr); } }
/* The reveal parks the footer with position: fixed. Once it is taller than the
   viewport that clips its top off with no way to reach it, so below the desktop
   layout it goes back to being an ordinary block that scrolls. */
@media (max-width: 1000px) {
  .ftr { position: static; }
  .page { margin-bottom: 0 !important; }
}
.ftr__we { margin: 0; font-weight: 200; font-size: 42px; line-height: 50px; letter-spacing: -.02em; color: #fff; }
/* the mark tops out with the labels on the right rather than centring against
   the taller statement beside it */
.ftr__logo { width: 183px; flex-shrink: 0; align-self: flex-start; }
.ftr__logo img { width: 183px; height: 88px; }
/* The other columns carry a mono label above their content. The links have none,
   so they get that label's height plus its gap as padding — otherwise the column
   sits one line proud of everything beside it. */
.ftr__links { display: flex; flex-direction: column; gap: 6px; padding-top: 30px; }
.ftr__links a { font-size: 14px; line-height: 20px; color: #C6CACE; transition: color .16s var(--ease); }
.ftr__links a:hover { color: #fff; }
.ftr__addr p, .ftr__cos li { margin: 0; font-size: 14px; line-height: 20px; color: #C6CACE; }
.ftr__addr { display: flex; flex-direction: column; gap: 12px; }
.ftr__cos { display: flex; flex-direction: column; gap: 12px; }
.ftr__cos ul { margin: 0; padding: 0; list-style: none; display: flex; flex-direction: column; gap: 6px; }
.ftr__connect { grid-column: 1; grid-row: 2; display: flex; flex-direction: column-reverse; align-items: flex-start; gap: 14px; }
.ftr__connectline { margin: 0; width: 298px; font-size: 14px; line-height: 20px; color: #C6CACE; }
/* footer sits on navy, so the CTA inherits white from .cta and needs no variant */
.ftr__cta { width: 170px; }
.ftr__follow { grid-column: 4; grid-row: 2; display: flex; flex-direction: column; gap: 16px; }
.ftr__social { display: flex; gap: 12px; }
.ftr__social a { width: 34px; height: 34px; border: 1px solid rgba(255,255,255,.28); display: flex; align-items: center; justify-content: center; color: #fff; transition: background-color .18s var(--ease), border-color .18s var(--ease); }
.ftr__social a:hover { background: var(--blue); border-color: var(--blue); }
.ftr__legal { position: relative; z-index: 2; height: 68px; border-top: 1px solid rgba(255,255,255,.14); }
.ftr__legalrow { display: flex; align-items: center; justify-content: space-between; height: 67px; font-family: var(--f-mono); font-size: 11px; letter-spacing: .12em; color: #8FA6BC; }

@media (prefers-reduced-motion: reduce) {
  * { animation: none !important; transition-duration: .01ms !important; }
}

/* ═══ MOBILE ═══════════════════════════════════════════════════════
   Matches the Paper artboard `DBMG — Landing page · MOBILE @390`
   ================================================================ */

.burger { display: none; }
.mobnav { display: none; }

@media (max-width: 760px) {
  :root { --gut: 20px; }

  /* header ------------------------------------------------------- */
  .topbar__links { display: none; }
  .topbar__lede { font-size: 8px; }
  .topbar, .topbar__inner { height: 30px; }
  .navrow { height: 82px; }
  .navrow__logo img { width: 84px; height: 42px; }
  .navrow__cta { display: none; }
  .hdr__plate { height: 112px; }

  .burger {
    display: flex; flex-direction: column; justify-content: space-between;
    width: 36px; height: 22px; padding: 0; border: 0; background: none; cursor: pointer;
  }
  .burger i { display: block; height: 2px; background: #fff; transition: transform .3s var(--ease), opacity .2s var(--ease), width .3s var(--ease); }
  .burger i:nth-child(1) { width: 36px; }
  .burger i:nth-child(2) { width: 36px; }
  .burger i:nth-child(3) { width: 24px; }
  .burger[aria-expanded="true"] i:nth-child(1) { transform: translateY(10px) rotate(45deg); }
  .burger[aria-expanded="true"] i:nth-child(2) { opacity: 0; }
  .burger[aria-expanded="true"] i:nth-child(3) { width: 36px; transform: translateY(-10px) rotate(-45deg); }

  /* Full-screen takeover, matching the Paper board: hero photograph under a heavy
     navy wash, five rules, then the contact CTA and the standing details. */
  .mobnav {
    position: fixed; inset: 0; z-index: 1;
    display: flex; flex-direction: column; justify-content: flex-end;
    background: var(--navy-deep); overflow: hidden;
    animation: mob .3s var(--ease);
  }
  .mobnav[hidden] { display: none; }
  @keyframes mob { from { opacity: 0; } to { opacity: 1; } }

  .mobnav__bg {
    position: absolute; inset: 0;
    background: url('assets/img/hero.jpg') 60% 40% / cover;
  }
  .mobnav__scrim {
    position: absolute; inset: 0;
    background: linear-gradient(180deg, rgba(10,26,50,.97) 0%, rgba(10,26,50,.93) 42%, rgba(10,26,50,.86) 72%, rgba(10,26,50,.94) 100%);
  }
  /* the topbar and logo stay above the takeover, and the burger itself is the
     close control — it already morphs into the X the board shows */
  .topbar { z-index: 3; }
  .navrow { z-index: 2; }
  .navrow { position: relative; }

  .mobnav__inner {
    position: relative; z-index: 2;
    padding: 136px var(--gut) 34px; display: flex; flex-direction: column;
    height: 100%; overflow-y: auto;
  }
  .mobnav__list { list-style: none; margin: 0; padding: 0; }
  .mobnav__list a {
    display: block; padding: 20px 0; border-bottom: 1px solid var(--navy-rule);
    font-size: 32px; line-height: 40px; font-weight: 300; letter-spacing: -.02em; color: #fff;
  }
  /* scaled up in the takeover so it reads as a peer to the 32px nav items and
     keeps a comfortable touch target */
  .mobnav__cta { margin-top: 34px; align-self: flex-start; height: 52px; min-width: 170px; }
  .mobnav__cta .cta__label { font-size: 19px; line-height: 26px; }
  .mobnav__cta .cta__arrow { font-size: 17px; line-height: 26px; }

  .mobnav__media { margin-top: 40px; display: flex; flex-direction: column; gap: 14px; }
  .mobnav__lbl { color: var(--blue-lt); font-size: 10px; line-height: 16px; }
  .mobnav__sub { display: flex; flex-wrap: wrap; column-gap: 28px; row-gap: 10px; }
  .mobnav__sub a { font-size: 15px; line-height: 24px; color: var(--dim); }

  .mobnav__foot {
    margin-top: auto; padding-top: 22px; border-top: 1px solid var(--navy-rule);
    display: flex; align-items: flex-end; justify-content: space-between; gap: 20px;
  }
  .mobnav__where { display: flex; flex-direction: column; gap: 6px; }
  .mobnav__where .mono, .mobnav__lang .mono { font-size: 10px; line-height: 16px; color: var(--muted); }
  .mobnav__lang { display: flex; align-items: center; gap: 14px; }
  .mobnav__lang .mono.is-on { color: #fff; font-weight: 500; }
  .mobnav__lang i { width: 1px; height: 12px; background: #3A5878; }

  /* hero --------------------------------------------------------- */
  .hero__head { top: auto; bottom: 208px; }
  .hero__title { font-size: 52px; line-height: 58px; }
  .hero__body { margin-top: 18px; font-size: 15px; line-height: 26px; min-height: 104px; }
  .hero__dots { left: var(--gut); translate: none; bottom: 158px; gap: 8px; }
  .credit { bottom: 166px; }
  .powered { height: 140px; padding-top: 20px; }
  .marquee__track img { width: 92px; height: 30px; margin-right: 56px; }
  .hero__dots button { width: 28px; }


  /* statement ---------------------------------------------------- */
  .statement { padding: 52px 0; }
  .statement__copy { font-size: 28px; line-height: 38px; }

  /* delivery ----------------------------------------------------- */
  /* the runway set in JS has to survive here — clearing the height was what
     unpinned the section on phones */
  .delivery__pin { min-height: 0; }
  /* Everything in the pin has to clear one phone screen: head, photograph, the
     four rows and the open paragraph. The head goes compact and the photograph
     becomes a band rather than a panel so the rail keeps its room. */
  .delivery__head { padding-bottom: 18px; gap: 18px; }
  .delivery__head .h2 { font-size: 24px; }
  .delivery__head .split__r { font-size: 14px; line-height: 22px; }
  .delivery__stage { padding-right: 0; }
  /* Edge to edge, and the height is measured in JS from whatever the head and the
     rail leave behind — a fixed svh cap turned the photograph into a letterbox on
     every phone. The value here is only the pre-measurement fallback. */
  .delivery__visuals { margin-right: 0; aspect-ratio: 3 / 2; max-height: 26svh; }
  .delivery__phases { padding: 16px var(--gut) 0; }
  .phase__row { height: 52px; }
}

/* The fourth phase was running off the bottom on every phone shorter than 844
   once the real copy arrived — the reserved open height grew with it. This trades
   image height and type size, never the number of rows, so all four stay on one
   screen. Threshold raised from 700 to 860 because almost no phone cleared it. */
@media (max-width: 760px) and (max-height: 860px) {
  .delivery__head .h2 { font-size: 21px; }
  .delivery__head .split__r { font-size: 13px; line-height: 20px; }
  .delivery__head { padding-bottom: 12px; gap: 12px; }
  .delivery__phases { padding-top: 12px; }
  .phase__row { height: 46px; }
  /* These two were declared twice, and the looser pair won — which is why the
     tightening this block exists for never actually happened. */
  .phase__t { font-size: 19px; line-height: 26px; }
  .phase__d p { font-size: 13px; line-height: 21px; }

  /* portfolio ---------------------------------------------------- */
  .portfolio { padding-top: 56px; }
  .split--onnavy { padding-bottom: 36px; }
  .wall { grid-template-columns: repeat(2, 1fr); }
  .wall__cell { aspect-ratio: 1 / 1; }
  .wall__copy { left: 20px; right: 20px; bottom: 20px; gap: 10px; }
  .wall__copy img { width: 104px; height: 26px; }
  .wall__loc { font-size: 9px; }
  .wall__desc { font-size: 13px; line-height: 21px; }
  .wall__cta .mono { font-size: 9px; }

  /* markets ------------------------------------------------------ */
  .markets { padding: 56px 0; }
  .markets__head { padding-bottom: 32px; }
  .markets__body { flex-direction: column; gap: 28px; padding-left: var(--gut); padding-right: 0; }
  .markets__col { width: auto; padding-right: var(--gut); }
  .switch { margin-top: 18px; margin-bottom: 0; gap: 28px; }
  .switch__tab { font-size: 19px; line-height: 26px; }
  .markets__project { font-size: 22px; line-height: 30px; }
  .spec__row dt { font-size: 9px; }
  .spec__row dd { font-size: 14px; line-height: 22px; }
  .circ { width: 44px; height: 44px; }
  .carousel__slide { width: 300px; height: 360px; }
  .carousel__track { gap: 12px; }

  /* facts -------------------------------------------------------- */
  .facts { grid-template-columns: 1fr; }
  .facts__hero { min-height: 340px; }
  .facts__herocopy { left: var(--gut); right: var(--gut); bottom: 28px; gap: 10px; }
  .num--xl { font-size: 82px; line-height: 88px; }
  .num--xl .num__unit { font-size: 28px; line-height: 34px; }
  .facts__cell { padding: 24px var(--gut); gap: 8px; }
  .num { font-size: 44px; line-height: 50px; }
  .num__unit { font-size: 18px; line-height: 24px; }
  .facts .mono { font-size: 9px; }

  /* safety ------------------------------------------------------- */
  .safety__band { height: 320px; }
  .safety__copy { bottom: 28px; }
  .safety__t1, .safety__t2 { font-size: 32px; line-height: 40px; }
  .safety__detail { padding: 48px 0 56px; }

  /* footer ------------------------------------------------------- */
  .ftr__inner { grid-template-columns: 1fr 1fr; gap: 36px 40px; padding: 52px 0 40px; }
  .ftr__logo { width: 152px; }
  .ftr__logo img { width: 152px; height: 73px; }
  .ftr__statement { grid-column: 1 / -1; }
  .ftr__we { font-size: 34px; line-height: 42px; }
  .ftr__addr, .ftr__cos { grid-column: 1 / -1; }
  .ftr__connect { grid-column: 1 / -1; }
  .ftr__follow { grid-column: 1 / -1; }
  .ftr__legalrow { font-size: 9px; }
}

@media (max-width: 380px) {
  .carousel__slide { width: 260px; height: 320px; }
  .hero__title { font-size: 46px; line-height: 52px; }
}

/* ── services accordion ─────────────────────────────────────────── */
/* Text on the rail's left edge, photograph bleeding to the right edge of the
   viewport, and the rule sitting in the gutter between them — 30px off the copy,
   which puts it on the frame's centre line at 1440. */
.services { background: var(--mist); padding: 96px 0 104px; overflow: hidden; }
.services__inner {
  display: flex; align-items: flex-start;
  padding-left: max(var(--gut), calc((100% - var(--rail-max)) / 2));
}
/* the column, not the section, owns the rail — so the rule is exactly as tall as
   the list and never runs on past the last row */
.services__col { position: relative; flex: 0 0 570px; min-width: 0; }
.services__rail {
  position: absolute; top: 0; left: calc(100% + 30px);
  width: 2px; height: 100%; background: var(--rule); display: block;
}
/* the lit segment belongs to its row, so it is exactly as tall as that row with
   no measurement at all */
.sv { position: relative; }
.sv__mark {
  position: absolute; top: 0; left: calc(100% + 30px);
  width: 2px; height: 100%; background: var(--blue); display: block;
  opacity: 0; transition: opacity .34s var(--ease);
}
.sv.is-on .sv__mark { opacity: 1; }
.services__visual {
  flex: 1 1 auto; margin-left: 150px; align-self: stretch; min-height: 482px;
  background-size: cover; background-position: 50%;
}

.sv { border-bottom: 1px solid var(--rule); cursor: pointer; }
.sv:first-child { border-top: 1px solid var(--rule); }
.sv__t {
  display: block; padding: 22px 0; font-size: 26px; line-height: 34px;
  letter-spacing: -.02em; color: #5A6C82;
  transition: color .3s var(--ease), font-size .3s var(--ease);
}
.sv.is-on .sv__t { font-size: 32px; color: var(--ink); font-weight: 500; padding-bottom: 0; }
.sv:hover .sv__t { color: var(--ink); }
/* every row opens to the same reserved height, taken from the longest entry, so
   the rail and the rows beneath it move the same distance whichever you pick */
.sv__d { height: 0; overflow: hidden; opacity: 0; transition: height .5s var(--ease), opacity .32s var(--ease); }
.sv.is-on .sv__d { height: var(--sh, 0px); opacity: 1; }
.sv__d p { margin: 16px 0 30px; font-size: 16px; line-height: 28px; color: var(--body); }
.sv__list.is-measuring .sv__d { height: auto; opacity: 1; transition: none; }

@media (max-width: 1000px) {
  .services { padding: 64px 0 72px; }
  .services__inner { flex-direction: column; gap: 32px; padding-left: 0; }
  .services__col { flex: 0 0 auto; width: 100%; padding: 0 var(--gut); }
  .services__rail { display: none; }
  .services__visual { width: 100%; margin-left: 0; min-height: 0; aspect-ratio: 5 / 4; order: -1; }
  .sv__t { font-size: 22px; line-height: 30px; }
  .sv.is-on .sv__t { font-size: 26px; }
  .sv__d p { font-size: 15px; line-height: 26px; }
}
/* measuring pass: no transitions, so the reserved open height can be read in one
   frame instead of guessed from padding arithmetic */
.sv__list.is-snap .sv__d, .sv__list.is-snap .sv__t { transition: none; }
