/* ==========================================================================
   Sections — every value read from the published Framer build.
   Breakpoints: >=1280 desktop, 992–1279.98 tablet, <=991.98 phone.
   ========================================================================== */

/* Base Container: max-width 1450px, 40px gutters at desktop, 20px below.
   The max-width does NOT shrink at tablet — only the padding changes. */
.container {
  width: 100%;
  max-width: 1450px;
  margin-inline: auto;
  padding-inline: 40px;
}

@media (max-width: 1279.98px) {
  .container { padding-inline: 20px; }
}

/* Shared section H2 (preset 73t395): 50 / 46 / 38px, -2.5px */
.h2 {
  font-family: var(--f-display);
  font-size: 50px;
  font-weight: 400;
  line-height: 1.2em;
  letter-spacing: -2.5px;
  color: var(--c-text);
}

@media (max-width: 1279.98px) { .h2 { font-size: 46px; } }
@media (max-width: 991.98px)  { .h2 { font-size: 38px; } }

/* ==========================================================================
   Header
   ========================================================================== */

.header {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  z-index: 10;
}

.nav {
  background: var(--c-bg);
  width: 100%;
  padding: 20px 0;
  position: relative;
  /* padding-bottom is animated too: the bar opening downward IS the menu's
     animation, so it has to ease rather than snap. padding-top animates for
     the condense-on-scroll below. */
  transition:
    background-color var(--dur-base) var(--ease-site),
    padding-top 0.45s var(--ease-out-intro),
    padding-bottom var(--dur-base) var(--ease-site);
}

/* Condense once scrolled: the bar tightens and the logo eases down a touch,
   so the header acknowledges the scroll rather than only swapping colour. */
.header:not(.at-top) .nav {
  padding-top: 13px;
}

.header:not(.at-top) .nav__inner {
  --logo-scale: 0.92;
}

/* Hairline along the bottom edge, drawn only once the bar is solid. Scales
   from the centre so it draws outward rather than blinking on. */
.nav::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  height: 1px;
  background: linear-gradient(
    90deg,
    transparent,
    rgba(255, 255, 255, 0.16) 18%,
    rgba(255, 255, 255, 0.16) 82%,
    transparent
  );
  transform: scaleX(0);
  transition: transform 0.7s var(--ease-out-intro);
  pointer-events: none;
}

.header:not(.at-top) .nav::after {
  transform: scaleX(1);
}

/* While a menu is open the hairline would cut across the open panel. */
.nav:has(.nav__item:hover)::after,
.nav:has(.nav__item:focus-within)::after,
.nav.collective-open::after {
  transform: scaleX(0);
}

/* At the very top the bar is transparent so the hero runs under it; it goes
   solid once you scroll past 50px. The source ships a 1px sentinel at exactly
   that offset named "Header BG Animation" — this is the behaviour it drove. */
.header.at-top .nav {
  background: transparent;
}

/* ...except while the mobile drawer or the Collective menu is open, where the
   links need an opaque backing to stay legible over the hero. */
.header.at-top .nav.is-open,
.header.at-top .nav.collective-open {
  background: var(--c-bg);
}

.nav__inner {
  width: 100%;
  max-width: 1450px;
  margin-inline: auto;
  padding-inline: 40px;
  display: flex;
  align-items: center;
  gap: 40px;
}

@media (max-width: 1279.98px) {
  .nav__inner { padding-inline: 20px; }
}

.nav__logo { flex: none; display: block; }

/* Logo boxes: 166x31 desktop/tablet, 94x40 phone; art letterboxed inside */
.nav__logo picture,
.nav__logo img {
  display: block;
  width: 166px;
  height: 31px;
  object-fit: contain;
  /* --logo-scale is set to 0.92 on .nav__inner once scrolled (see the
     condense rule above); transform rather than width so it cannot reflow
     the row it sits in. */
  transform: scale(var(--logo-scale, 1));
  transform-origin: left center;
  transition: transform 0.45s var(--ease-out-intro);
}

@media (max-width: 991.98px) {
  .nav__logo picture,
  .nav__logo img {
    width: 94px;
    height: 40px;
  }
}

.nav__links {
  display: flex;
  align-items: center;
  gap: 40px;
  margin-inline: auto;
}

.nav__links a,
.nav__collective p {
  font-family: var(--f-display);
  font-size: 14px;
  font-weight: 500;
  line-height: 1.6em;
  text-transform: uppercase;
  color: var(--c-text);
}

/* Top-level links get the same wiping underline as the submenu items, so the
   whole bar shares one hover language. */
.nav__links a {
  position: relative;
}

.nav__links a::after {
  content: "";
  position: absolute;
  left: 0;
  bottom: -5px;
  width: 100%;
  height: 1px;
  background: currentColor;
  transform: scaleX(0);
  transform-origin: right center;
  transition: transform 0.42s var(--ease-out-intro);
}

.nav__links a:hover::after,
.nav__links a:focus-visible::after {
  transform: scaleX(1);
  transform-origin: left center;
}

.nav__links a:hover { color: var(--c-text-70); }

/* Superscript count on "Vacancies" — the number of new openings.

   Rendered from data-count rather than text content, so there is a single
   source per link and `data-count="0"` removes the badge without editing
   markup. The <sup> is aria-hidden; an .sr-only sibling carries the meaning
   for screen readers, since a bare floating numeral reads as noise. */
.nav__badge {
  font-size: 9px;
  font-weight: 600;
  line-height: 1;
  letter-spacing: 0;
  color: var(--c-accent);
  /* <sup> already raises it; this nudges it clear of the cap height and
     stops it adding to the line box and shifting the row. */
  top: -0.15em;
  margin-left: 3px;
  vertical-align: super;
  position: relative;
}

.nav__badge::after {
  content: attr(data-count);
}

/* Nothing new to announce. */
.nav__badge[data-count="0"],
.nav__badge:not([data-count]) {
  display: none;
}

/* The underline spans the label only — without this it runs under the
   numeral and looks like a typo. */
.nav__links a:has(.nav__badge)::after {
  right: 11px;
  width: auto;
  left: 0;
}

/* Dropdown parents (Group / Products / Services) — toggles, not links */
.nav__item {
  position: relative;
  cursor: pointer;
}

/* The trigger is a <button> for keyboard access, styled to match the links */
.nav__trigger {
  font-family: var(--f-display);
  font-size: 14px;
  font-weight: 500;
  line-height: 1.6em;
  text-transform: uppercase;
  color: var(--c-text);
  padding: 0;
  cursor: pointer;
  /* inline-flex so the chevron sits on the text baseline row */
  display: inline-flex;
  align-items: center;
  gap: 7px;
  position: relative;
  transition: color var(--dur-base) var(--ease-site);
}

/* Chevron — a rotated corner rather than a glyph, so it inherits colour and
   needs no icon font. Points down when closed, flips up when open. */
.nav__trigger::after {
  content: "";
  width: 5px;
  height: 5px;
  border-right: 1.5px solid currentColor;
  border-bottom: 1.5px solid currentColor;
  transform: translateY(-1px) rotate(45deg);
  transition: transform 0.42s var(--ease-out-intro);
}

.nav__item:hover .nav__trigger::after,
.nav__item:focus-within .nav__trigger::after,
.nav__item.is-open .nav__trigger::after {
  transform: translateY(1px) rotate(-135deg);
}

/* Underline on the label only — inset from the right so it stops short of
   the chevron instead of running under it. */
.nav__trigger::before {
  content: "";
  position: absolute;
  left: 0;
  right: 12px;
  bottom: -5px;
  height: 1px;
  background: currentColor;
  transform: scaleX(0);
  transform-origin: right center;
  transition: transform 0.42s var(--ease-out-intro);
}

.nav__item:hover .nav__trigger::before,
.nav__item:focus-within .nav__trigger::before,
.nav__item.is-open .nav__trigger::before {
  transform: scaleX(1);
  transform-origin: left center;
}

.nav__item.is-open .nav__trigger {
  color: var(--c-text-70);
}

/* No background of its own. The bar behind it grows to make room (see the
   open-state rules below) and supplies the black — giving the panel its own
   fill as well is what painted a second box over the expanded bar. */
.nav__submenu {
  position: absolute;
  top: 100%;
  left: 0;
  z-index: 5;
  /* Always laid out. `display:none` cannot be transitioned, which is why the
     panels used to snap open; visibility + opacity + transform can. */
  display: flex;
  flex-direction: column;
  gap: 14px;
  /* Padding rather than a `top` offset, so the panel's box touches the
     trigger. With a gap the pointer would leave .nav__item on the way down
     and the menu would shut under the cursor. */
  padding-top: 18px;
  padding-bottom: 20px;
  min-width: 160px;

  opacity: 0;
  visibility: hidden;
  transform: translateY(-8px);
  pointer-events: none;
  /* Visibility is delayed on the way out so the fade is visible before the
     panel is removed from the accessibility tree; on the way in it flips
     immediately (delay 0 in the open state below). */
  transition:
    opacity 0.34s var(--ease-site),
    transform 0.42s var(--ease-out-intro),
    visibility 0s linear 0.34s;
}

.nav__item:hover .nav__submenu,
.nav__item:focus-within .nav__submenu,
.nav__item.is-open .nav__submenu {
  opacity: 1;
  visibility: visible;
  transform: translateY(0);
  pointer-events: auto;
  transition-delay: 0s;
}

.nav__item:hover .nav__trigger,
.nav__item:focus-within .nav__trigger { color: var(--c-text-70); }

/* Services carries labels + five disciplines, so it needs more room */
.nav__submenu--wide { min-width: 200px; }

/* The panel carries its own backing.

   The bar growing (padding-bottom, below) is what makes the black space, but
   that value is a fixed number per panel while the panels size to their own
   content — so any panel taller than its allowance let the page show through
   behind the links. The Groep panel is ~280px against a 184px allowance, which
   is exactly that failure.

   This backdrop is the panel's own height by construction, so it cannot be
   out-measured when an item is added to a menu. It sits at z-index -1 inside
   the panel's own stacking context (.nav__submenu is z-index 5), so it covers
   the page beneath while staying behind the panel's own links.

   The 100vw bleed matches the bar it continues: the panel is ~200px wide but
   the black it sits on runs the full width of the viewport. */
.nav__submenu::before {
  content: "";
  position: absolute;
  z-index: -1;
  top: 0;
  bottom: 0;
  left: -100vw;
  right: -100vw;
  background: var(--c-bg);
}

/* --- Sectors mega panel ---------------------------------------------------
   Same idea as the other dropdowns, wider: three sectors shown as pictures
   and the rest as a list. Photographs answer "do you know my industry" faster
   than a column of six words does.

   The item goes position:static so this panel stops resolving against the
   trigger. .nav__item is relative, which is right for a 200px list but would
   centre a full-width panel on whichever word happens to sit above it. With
   the item static the nearest positioned ancestor is .header (fixed), so
   left/right:0 spans the header and an inner wrapper reuses the same 1450px
   / 40px column as .container. No magic offsets to re-tune when the nav
   changes.

   Everything else — the fade, the 100vw black backing, the hover intent — is
   inherited from .nav__submenu unchanged.
   -------------------------------------------------------------------------- */

.nav__item--mega { position: static; }

.nav__submenu--mega {
  left: 0;
  right: 0;
  min-width: 0;
  padding-bottom: 44px;
}

.megamenu {
  width: 100%;
  max-width: 1450px;
  margin-inline: auto;
  padding-inline: 40px;
}

.megamenu__title {
  font-family: var(--f-display);
  font-size: 26px;
  font-weight: 400;
  line-height: 1.2em;
  letter-spacing: -1px;
  color: var(--c-text);
  margin-bottom: 26px;
}

.megamenu__grid {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr)) 280px;
  gap: 20px;
  align-items: start;
}

/* Card ---------------------------------------------------------------------
   The boxed treatment the sectors index used to have, before that page became
   a row list. It earns its keep here: in a menu these are three things to
   choose between, not a list to read down. */
.sec-card {
  display: flex;
  flex-direction: column;
  gap: 14px;
  padding: 14px;
  /* .nav__submenu a sets `width: max-content` — right for a list of links,
     wrong for a card holding a 640px image: max-content took that image's
     intrinsic width, so each card sat 670px wide inside a 327px track and
     overlapped its neighbour. The override lives below, under a selector
     heavy enough to win — see the note there. */
  background: rgba(255, 255, 255, 0.04);
  border: 1px solid rgba(255, 255, 255, 0.12);
  text-decoration: none;
  transition:
    background-color var(--dur-base) var(--ease-site),
    border-color var(--dur-base) var(--ease-site);
}

.sec-card:hover {
  background: rgba(255, 255, 255, 0.08);
  border-color: rgba(255, 255, 255, 0.24);
}

/* Specificity, not cascade order. `.nav__submenu a` is (0,1,1) — one class
   plus a type — and `.sec-card` is only (0,1,0), so the plain class lost and
   the cards kept `width: max-content`. Setting it inline from the console
   worked, which is what gave it away. Two classes take it.

   Same shape as the bug in the mobile drawer: a broad `.nav__submenu a` /
   `.nav__drawer a` rule reaching into a component that happens to be a link. */
.nav__submenu--mega .sec-card {
  width: 100%;
  min-width: 0;
}

/* Same leak, different property: the submenu link rule also forces uppercase,
   which turned the card titles into INSTALLATIE & TECHNIEK. Headings on this
   site are sentence case; only eyebrows and small labels shout. */
.nav__submenu--mega .sec-card__name {
  text-transform: none;
  letter-spacing: -0.2px;
}

.sec-card__media {
  display: block;
  /* Fill the card rather than the image's intrinsic width — see min-width
     above; the two go together. */
  width: 100%;
  aspect-ratio: 16 / 9;
  overflow: hidden;
  background: var(--c-grey);
}

/* <picture> is an inline element with no box of its own, so the img's
   intrinsic 640px width propagated straight up through it and sized the card
   — 670px inside a 327px track. min-width:0 on the card was necessary but not
   sufficient; the chain has to be constrained at every level. */
.sec-card__media picture {
  display: block;
  width: 100%;
  height: 100%;
}

.sec-card__media img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  filter: grayscale(1);
  transition: filter var(--dur-base) var(--ease-site), transform 0.6s var(--ease-out-intro);
}

/* Colour on hover is the reward for pointing at it, and the same move the
   blog cards make. */
.sec-card:hover .sec-card__media img { filter: grayscale(0); transform: scale(1.04); }

.sec-card__name {
  font-family: var(--f-display);
  font-size: 18px;
  font-weight: 500;
  line-height: 1.3em;
  color: var(--c-text);
}

.sec-card__go {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  font-family: var(--f-display);
  font-size: 13px;
  font-weight: 500;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--c-accent);
}

.sec-card__go svg { transition: transform var(--dur-base) var(--ease-out-intro); }
.sec-card:hover .sec-card__go svg { transform: translateX(4px); }

/* The overflow column ------------------------------------------------------ */

.megamenu__more {
  display: flex;
  flex-direction: column;
  gap: 2px;
  padding-left: 30px;
  border-left: 1px solid var(--c-hairline, rgba(255, 255, 255, 0.18));
}

.megamenu__more-title {
  font-family: var(--f-display);
  font-size: 18px;
  font-weight: 500;
  color: var(--c-text);
  margin-bottom: 12px;
}

/* These are inside .nav__submenu, so they would otherwise inherit its link
   treatment — including the sliding underline, which reads wrong next to an
   arrow. Reset and restate. */
.nav__submenu--mega .megamenu__more a {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  padding: 7px 0;
  font-family: var(--f-display);
  font-size: 15px;
  font-weight: 400;
  text-transform: none;
  letter-spacing: normal;
  color: var(--c-text-70);
  transition: color var(--dur-base) var(--ease-site);
}

.nav__submenu--mega .megamenu__more a::after { display: none; }
.nav__submenu--mega .megamenu__more a:hover { color: var(--c-text); }

.nav__submenu--mega .megamenu__more a svg {
  opacity: 0.55;
  transition: transform var(--dur-base) var(--ease-out-intro), opacity var(--dur-base) var(--ease-site);
}

.nav__submenu--mega .megamenu__more a:hover svg { opacity: 1; transform: translate(2px, -2px); }

.nav__submenu--mega .megamenu__all {
  margin-top: 10px;
  padding-top: 14px !important;
  border-top: 1px solid var(--c-hairline, rgba(255, 255, 255, 0.18));
  color: var(--c-accent) !important;
  font-weight: 500 !important;
}

/* Below the desktop nav the whole panel is replaced by the drawer, so the
   grid only needs to survive the narrow end of the desktop range. */
@media (max-width: 1279.98px) {
  .megamenu__grid { grid-template-columns: repeat(3, minmax(0, 1fr)) 230px; gap: 16px; }
  .megamenu__title { font-size: 22px; }
  .megamenu__more { padding-left: 20px; }
}

/* Hairline separating the labels from the …8 disciplines */
.nav__submenu-rule {
  display: block;
  height: 1px;
  width: 100%;
  background: var(--c-hairline, rgba(255, 255, 255, 0.18));
  margin: 2px 0;
}

/* Open state — the black bar grows downward and the panel sits inside it,
   the way the source's "Collective" menu behaved (open-variant padding:
   0 40px 96px on the inner container).

   The submenus are absolutely positioned so the nav row itself never moves,
   which means the bar cannot size itself to the panel — the depth has to be
   stated. Two tiers, measured from the rendered panels:

     Group 152px · Products 115px · Services 280px

   plus 18px above the panel, ~13px to clear the row and ~20px of breathing
   room underneath. Services is the outlier, so it gets its own value keyed
   off `--wide` rather than nth-child, which would break if the menus were
   reordered. If a menu gains items, re-measure and bump the matching number.
   `:has()` is what lets a hovered child grow its ancestor.

   The growth goes on `.nav` (the black bar) rather than `.nav__inner`. The
   inner row is `align-items: center`, so padding it would re-centre the logo,
   links and CTA in a taller box and drag the whole row downward; padding the
   bar leaves the row where it is and opens black space beneath it. */
.nav:has(.nav__item:hover),
.nav:has(.nav__item:focus-within),
.nav.collective-open {
  padding-bottom: 184px;
}

.nav:has(.nav__item:hover .nav__submenu--wide),
.nav:has(.nav__item:focus-within .nav__submenu--wide),
.nav:has(.nav__item.is-open .nav__submenu--wide) {
  padding-bottom: 312px;
}

/* No matching rule for --mega, deliberately. The other panels hang off
   .nav__item, whose height never changes, so growing the bar under them is
   safe. The sectors panel hangs off .header (the item is position:static, so
   it can span the full column) and sits at top:100% of it — so padding the bar
   makes the header taller, which pushes the panel down, which needs more bar.
   Adding the rule sent it from 541px to 981px in one step.

   It does not need the bar anyway: .nav__submenu::before bleeds 100vw of
   background at the panel's own height, so the page is already covered. */

/* At the top of the page the bar is transparent; while a menu is open it needs
   the solid fill, or the links sit on the hero. */
.header.at-top .nav:has(.nav__item:hover),
.header.at-top .nav:has(.nav__item:focus-within) {
  background: var(--c-bg);
}

.nav__submenu a {
  font-family: var(--f-display);
  font-size: 14px;
  font-weight: 500;
  line-height: 1.6em;
  text-transform: uppercase;
  /* Periwinkle, the same accent the eyebrows and footer use — submenu items
     read as secondary to the nav row above them. */
  color: var(--c-accent);
  position: relative;
  width: max-content;

  /* Each item arrives just after the panel, so the menu cascades instead of
     appearing as one block. */
  opacity: 0;
  transform: translateY(-6px);
  transition:
    color var(--dur-base) var(--ease-site),
    opacity 0.3s var(--ease-site),
    transform 0.34s var(--ease-out-intro);
}

.nav__item:hover .nav__submenu a,
.nav__item:focus-within .nav__submenu a,
.nav__item.is-open .nav__submenu a {
  opacity: 1;
  transform: translateY(0);
}

/* 40ms apart. Seven items is the longest menu (Services). */
.nav__item:hover .nav__submenu a:nth-child(1),
.nav__item:focus-within .nav__submenu a:nth-child(1),
.nav__item.is-open .nav__submenu a:nth-child(1) { transition-delay: 0s, 0.05s, 0.05s; }
.nav__item:hover .nav__submenu a:nth-child(2),
.nav__item:focus-within .nav__submenu a:nth-child(2),
.nav__item.is-open .nav__submenu a:nth-child(2) { transition-delay: 0s, 0.09s, 0.09s; }
.nav__item:hover .nav__submenu a:nth-child(3),
.nav__item:focus-within .nav__submenu a:nth-child(3),
.nav__item.is-open .nav__submenu a:nth-child(3) { transition-delay: 0s, 0.13s, 0.13s; }
.nav__item:hover .nav__submenu a:nth-child(4),
.nav__item:focus-within .nav__submenu a:nth-child(4),
.nav__item.is-open .nav__submenu a:nth-child(4) { transition-delay: 0s, 0.17s, 0.17s; }
.nav__item:hover .nav__submenu a:nth-child(5),
.nav__item:focus-within .nav__submenu a:nth-child(5),
.nav__item.is-open .nav__submenu a:nth-child(5) { transition-delay: 0s, 0.21s, 0.21s; }
.nav__item:hover .nav__submenu a:nth-child(n + 6),
.nav__item:focus-within .nav__submenu a:nth-child(n + 6),
.nav__item.is-open .nav__submenu a:nth-child(n + 6) { transition-delay: 0s, 0.25s, 0.25s; }

/* Hover underline, wiping in from the left and out to the right. */
.nav__submenu a::after {
  content: "";
  position: absolute;
  left: 0;
  bottom: -3px;
  width: 100%;
  height: 1px;
  background: currentColor;
  transform: scaleX(0);
  transform-origin: right center;
  transition: transform 0.42s var(--ease-out-intro);
}

.nav__submenu a:hover::after,
.nav__submenu a:focus-visible::after {
  transform: scaleX(1);
  transform-origin: left center;
}

.nav__submenu a:hover { color: var(--c-text); }

.nav__cta { flex: none; }

/* Contact CTA: 10px 35px in the source (other buttons vary) */
.nav .nav__cta,
.nav__drawer .btn {
  padding: 10px 35px;
}

.nav__burger {
  display: none;
  width: 24px;
  height: 24px;
  /* overflow was hidden; the close cross is drawn with pseudo-elements that
     sit slightly proud of the 24px box once rotated, and clipping sheared
     their ends off. */
  overflow: visible;
  padding: 0;
  align-items: center;
  justify-content: center;
  position: relative;
}

/* Close cross. Drawn in CSS rather than added to the markup on purpose: the
   header is synced from index.html to 16 pages, so a pure-CSS control needs
   no re-sync and cannot drift out of step with the generated pages. */
.nav__burger::before,
.nav__burger::after {
  content: "";
  position: absolute;
  left: 50%;
  top: 50%;
  width: 19px;
  height: 1.5px;
  background: var(--c-text);
  border-radius: 1px;
  opacity: 0;
  transform: translate(-50%, -50%) rotate(0deg) scaleX(0.4);
  transition:
    opacity 0.22s var(--ease-site),
    transform 0.42s var(--ease-out-intro);
  pointer-events: none;
}

/* The two bars sweep out to opposite diagonals as they fade in. */
.nav.is-open .nav__burger::before {
  opacity: 1;
  transform: translate(-50%, -50%) rotate(45deg) scaleX(1);
}

.nav.is-open .nav__burger::after {
  opacity: 1;
  transform: translate(-50%, -50%) rotate(-45deg) scaleX(1);
}

/* Burger glyph is the site's three-bar mark svg (50x29), letterboxed */
.nav__burger img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: contain;
  transition:
    opacity 0.22s var(--ease-site),
    transform 0.42s var(--ease-out-intro);
}

/* The bars spin away as the cross arrives, so the two states trade places
   rather than one blinking out. */
.nav.is-open .nav__burger img {
  opacity: 0;
  transform: rotate(90deg) scale(0.7);
}

/* Phone drawer.

   Was a bar that grew downward to a fixed 520px max-height, which left the
   page showing underneath and kept the links at the desktop's 14px. It is now
   a full-screen panel: fixed to the viewport, opaque, with the links set at
   display scale so the menu is the only thing on screen. */
.nav__drawer {
  display: none;
  width: 100%;
  flex-direction: column;
  align-items: flex-start;
  gap: 40px;
  opacity: 0;
}

.nav__drawer ul {
  display: flex;
  flex-direction: column;
  gap: 20px;
}

/* Scoped to the list. Bare `.nav__drawer a` also caught the Contact button,
   which is an <a class="btn"> sitting outside the <ul> — see the note on the
   display-scale rule below. */
.nav__drawer ul a {
  font-family: var(--f-display);
  font-size: 14px;
  font-weight: 500;
  line-height: 1.6em;
  text-transform: uppercase;
  color: var(--c-text);
}

@media (max-width: 991.98px) {
  .nav .nav__links,
  .nav .nav__cta { display: none; }

  .nav__burger { display: flex; }

  /* row-gap 0: the closed bar is 20px pad + row + 20px pad in the source
     (gap:40px exists only in the OPEN variant, supplied by the drawer) */
  .nav__inner { justify-content: space-between; flex-wrap: wrap; row-gap: 0; }

  /* The panel is fixed to the viewport rather than sized inside the bar, so
     it covers the page whatever the content height. dvh rather than vh: on
     mobile Safari, vh is the tallest-toolbar height, which leaves the CTA
     pushed below the fold until the address bar collapses. */
  .nav__drawer {
    display: flex;
    position: fixed;
    inset: 0;
    height: 100vh;
    height: 100dvh;
    width: 100%;
    background: var(--c-bg);
    /* Clears the bar so the logo and the close cross stay visible above it. */
    padding: 92px 20px 40px;
    gap: 32px;
    /* Links centred in the space left over, CTA held at the bottom edge. */
    justify-content: space-between;
    overflow-y: auto;
    overscroll-behavior: contain;

    visibility: hidden;
    transform: translate3d(0, -12px, 0);
    transition:
      opacity var(--dur-base) var(--ease-site),
      transform var(--dur-base) var(--ease-out-intro),
      visibility 0s linear var(--dur-base);
  }

  .nav.is-open .nav__drawer {
    opacity: 1;
    visibility: visible;
    transform: translate3d(0, 0, 0);
    transition:
      opacity var(--dur-nav) var(--ease-site),
      transform 0.42s var(--ease-out-intro),
      visibility 0s linear 0s;
  }

  /* Takes the leftover height so the links sit optically centred rather than
     stacked under the bar. */
  .nav__drawer ul {
    flex: 1 1 auto;
    justify-content: center;
    gap: clamp(14px, 3.2vh, 28px);
    width: 100%;
  }

  /* The reason for the change: 14px uppercase was the desktop treatment
     borrowed at phone size. At display scale the uppercase preset stops
     working, so these take the .h2 treatment instead.

     `ul` matters. Unscoped, this also hit the Contact button at the foot of
     the drawer: it is an <a class="btn">, so it inherited both the display
     size and `display: block`. At 375px that is 9vw = 33.75px, which gave the
     button a 75px-tall line box and left its 14px label sitting against the
     35px padding instead of centred, because block killed the flex centring. */
  .nav__drawer ul a {
    font-size: clamp(32px, 9vw, 44px);
    font-weight: 400;
    line-height: 1.1;
    letter-spacing: -1.5px;
    text-transform: none;
    display: block;
  }

  /* The count badge is sized against 14px type; keep it proportional. */
  .nav__drawer .nav__badge {
    font-size: 13px;
    margin-left: 8px;
    top: -0.5em;
  }

  /* Items arrive in sequence, the same cascade the desktop submenu uses. */
  .nav__drawer li {
    opacity: 0;
    transform: translate3d(0, 12px, 0);
    transition:
      opacity 0.3s var(--ease-site),
      transform 0.34s var(--ease-out-intro);
  }

  .nav.is-open .nav__drawer li { opacity: 1; transform: none; }
  .nav.is-open .nav__drawer li:nth-child(1) { transition-delay: 0.06s; }
  .nav.is-open .nav__drawer li:nth-child(2) { transition-delay: 0.10s; }
  .nav.is-open .nav__drawer li:nth-child(3) { transition-delay: 0.14s; }
  .nav.is-open .nav__drawer li:nth-child(n + 4) { transition-delay: 0.18s; }

  .nav__drawer .btn {
    width: 100%;
    padding: 18px 35px;
    justify-content: center;
    flex: none;
  }

  /* The logo and the close cross must stay above the fixed panel; the drawer
     follows them in the DOM and would otherwise paint over both. */
  .nav__logo,
  .nav__burger { position: relative; z-index: 2; }

  /* Without this the page scrolls behind the open panel. The class is already
     toggled in js/motion.js; it simply had nothing attached to it.

     Scoped to this breakpoint deliberately: the drawer is display:none above
     it, so a phone opened and then rotated or resized to a wide layout would
     otherwise be left scroll-locked with no menu on screen to close. */
  body.nav-open {
    overflow: hidden;
  }
}

/* Reduced motion: the header still changes state, it just stops sliding,
   staggering and scaling. Menus open and close instantly, which is the point.
   Colour changes are kept — they carry meaning, not decoration. */
@media (prefers-reduced-motion: reduce) {
  .nav,
  .nav::after,
  .nav__logo picture,
  .nav__logo img,
  .nav__trigger,
  .nav__trigger::before,
  .nav__trigger::after,
  .nav__links a::after,
  .nav__submenu,
  .nav__submenu a,
  .nav__submenu a::after {
    transition-duration: 0.001ms !important;
    transition-delay: 0s !important;
  }

  .nav__submenu,
  .nav__submenu a {
    transform: none !important;
  }

  .header:not(.at-top) .nav__inner { --logo-scale: 1; }
}

/* ==========================================================================
   Hero — 100vh, content bottom-aligned, grayscale video under a 60% scrim
   ========================================================================== */

.hero {
  position: relative;
  min-height: 100vh;
  display: flex;
  align-items: flex-end;
  justify-content: center;
  padding: 200px 0 100px;
  /* Black, not the source's declared white fallback. This colour is what
     surrounds the clipped rectangle during the intro zoom, so white made the
     image appear to open out of a white page instead of out of the dark. */
  background: var(--c-bg);
  /* The source has this visible, but the intro zoom over-scales the hero
     image to 1.45 — at 1440px that is 2088px wide and pushed 324px of
     horizontal scroll onto the page mid-reveal. Nothing needs to escape
     the hero, so clip it. */
  overflow: hidden;
}

@media (max-width: 1279.98px) { .hero { padding: 200px 0 80px; } }
@media (max-width: 991.98px)  { .hero { padding: 200px 0 60px; } }

.hero__bg {
  position: absolute;
  inset: 0;
  display: flex;
}

.hero__video {
  width: 100%;
  height: 100%;
  object-fit: cover;
  filter: grayscale(1);
}

.hero__scrim {
  position: absolute;
  inset: 0;
  z-index: 2;
  background: var(--c-scrim);
}

.hero__inner {
  position: relative;
  z-index: 3;
  width: 100%;
  max-width: 1450px;
  margin-inline: auto;
  padding-inline: 40px;
}

@media (max-width: 1279.98px) { .hero__inner { padding-inline: 20px; } }

.hero__content { width: 100%; }

.hero__title {
  font-family: var(--f-display);
  font-size: var(--fs-h1);
  font-weight: 500;
  line-height: 1.2em;
  letter-spacing: -3px;
  color: var(--c-text);
  width: 70%;
}

/* Hero subline — names the four labels' domains under the H1. Deliberately
   set in the body face at a much lighter weight so it supports the display
   line rather than competing with it. Measure is capped near 60ch. */
.hero__sub {
  margin-top: 24px;
  font-family: var(--f-body);
  font-size: 18px;
  font-weight: 400;
  line-height: 1.55;
  letter-spacing: 0;
  color: var(--c-text-70);
  max-width: 56ch;
  width: 70%;
}

@media (max-width: 991.98px) {
  .hero__content { max-width: 540px; }
  .hero__title { width: 100%; }
  .hero__sub {
    width: 100%;
    margin-top: 20px;
    font-size: 16px;
  }
}

/* ==========================================================================
   About — "What we stand for"
   ========================================================================== */

.about { padding: 130px 0; }

@media (max-width: 1279.98px) { .about { padding: 100px 0; } }
@media (max-width: 991.98px)  { .about { padding: 80px 0; } }

/* Children of the Base Container sit 80px apart (60px on phone) */
.about__container {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 80px;
}

@media (max-width: 991.98px) { .about__container { gap: 60px; } }

.about__head {
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  gap: 10px;
  max-width: 930px;
  margin-inline: auto;
}

@media (max-width: 1279.98px) { .about__head { max-width: 845px; } }
@media (max-width: 991.98px)  { .about__head { max-width: 677px; } }

/* Stats: wrapping row, space-around, no gap; cards centered columns */
.stats {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-around;
  align-items: flex-start;
  width: 100%;
}

@media (max-width: 991.98px) {
  .stats { justify-content: center; gap: 30px 40px; }
}

.stat {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 18px;
  margin: 0;
}

/* ==========================================================================
   Fact card — the "thin glass" element

   Source: Figma file Zfth0yS35q8qaSgfno0GE4, page 67:2 ("styleguide"),
   nodes 76:386 / 76:387 / 76:398. The styleguide states the intent in its
   own words: "Thin glass elements are present to highlight the spots we're
   most proud of", alongside "light interfering in a way to create blue
   tints". So the edge is a sheet of glass catching light — white where it
   faces you, refracting to cyan and deep blue as it turns away at the
   corners.

   This replaces three flattened PNGs (stat-01/02/03.png) that had their
   figures baked into the artwork. Those could not be reused for any other
   number, could not be read by a screen reader, and went soft on retina.
   Everything below is derived from the Figma geometry as ratios of the
   card height, so one component serves every figure at any size.

     card    127.942 x 70.4901   ->  aspect-ratio below
     radius  4.07457             ->  5.78% of height
     edge    2                   ->  2.84% of height
   ========================================================================== */
.factcard {
  --fc-h: 140px;
  --fc-edge: max(1px, calc(var(--fc-h) * 0.009));
  --fc-bloom: calc(var(--fc-edge) + var(--fc-h) * 0.026);
  --fc-radius: calc(var(--fc-h) * 0.0578);

  position: relative;
  display: inline-grid;
  place-items: center;
  box-sizing: border-box;
  height: var(--fc-h);

  /* The Figma ratio is a floor, not a cage. A fixed aspect-ratio clipped
     "167.000" straight through the rim; this keeps the designed proportion
     for short figures and lets long ones push the card wider instead. */
  min-width: calc(var(--fc-h) * 1.81503);   /* 127.942 / 70.4901 */
  padding-inline: calc(var(--fc-h) * 0.16);

  border-radius: var(--fc-radius);
  background: #000;
  overflow: hidden;          /* keeps the bloom off the neighbouring card */
  isolation: isolate;
}

/* The refraction, sitting just inside the edge. A conic sweep is the cheap
   way to walk the perimeter: angle maps to position around the rim.

   The stops are not invented — they are sampled off the source artwork at a
   fixed depth inside the rim, every 10 degrees, then interpolated. Corner
   angle is atan(63.971 / 35.245) = 61.15deg; each corner burns out to a
   white plateau roughly six degrees wide.

   Three things about the measured profile are worth keeping, because they
   are what make it read as glass rather than as a neon outline:
     - the long runs (top and bottom) carry no colour at all in the middle
     - the short runs (left and right) stay lit end to end
     - the left rim runs cyan where the right rim runs deeper blue
   Symmetrising any of those flattens it.

   The bloom is drawn by subtracting the card's face from its own box. A
   browser that cannot do that subtraction would flood the whole card with
   the gradient and swallow the figure, so the paint lives behind @supports
   below; without it you still get the black card and the white glass edge. */
.factcard::before {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
  padding: var(--fc-bloom);
  pointer-events: none;
}

@supports (mask-composite: exclude) or (-webkit-mask-composite: xor) {
.factcard::before {
  background: conic-gradient(from 0deg at 50% 50%,
    #000              0deg,        /* top run, middle — dark */
    #000             33deg,
    rgb(2, 2, 23)    42deg,
    rgb(4, 5, 90)    48deg,
    rgb(3, 109, 237) 52deg,
    rgb(28, 202, 238) 56deg,
    rgb(242, 242, 242) 58.5deg,    /* top-right corner, burnt out */
    rgb(242, 242, 242) 64.5deg,
    rgb(28, 202, 238) 68deg,
    rgb(3, 48, 220)  73deg,
    rgb(4, 8, 147)   82deg,
    rgb(5, 6, 119)   90deg,        /* right run, middle — deep blue */
    rgb(4, 8, 147)   98deg,
    rgb(2, 67, 229) 106deg,
    rgb(28, 202, 238) 112deg,
    rgb(242, 242, 242) 115.5deg,   /* bottom-right corner */
    rgb(242, 242, 242) 121.5deg,
    rgb(62, 224, 239) 125deg,
    rgb(7, 145, 238) 130deg,
    rgb(4, 5, 79)   136deg,
    rgb(2, 3, 39)   142deg,
    #000            150deg,        /* bottom run, middle — dark */
    #000            210deg,
    rgb(2, 2, 23)   218deg,
    rgb(4, 5, 79)   224deg,
    rgb(3, 127, 238) 230deg,
    rgb(62, 224, 239) 236deg,
    rgb(242, 242, 242) 238.5deg,   /* bottom-left corner */
    rgb(242, 242, 242) 244.5deg,
    rgb(45, 212, 239) 248deg,
    rgb(7, 145, 238) 256deg,
    rgb(3, 109, 237) 264deg,
    rgb(3, 109, 237) 276deg,       /* left run — cyan-leaning throughout */
    rgb(7, 145, 238) 284deg,
    rgb(45, 212, 239) 292deg,
    rgb(242, 242, 242) 295.5deg,   /* top-left corner */
    rgb(242, 242, 242) 301.5deg,
    rgb(27, 190, 240) 305deg,
    rgb(3, 109, 237) 310deg,
    rgb(4, 5, 98)   316deg,
    rgb(2, 2, 23)   322deg,
    #000            328deg,
    #000            360deg);

  /* Punch out the middle so the sweep survives only as a band. */
  -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
          mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
  -webkit-mask-composite: xor;
          mask-composite: exclude;

  filter: blur(calc(var(--fc-h) * 0.006));
}
}

/* The glass edge itself, crisp and on top of its own bloom. */
.factcard::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
  border: var(--fc-edge) solid rgb(242, 242, 242);
  pointer-events: none;
}

.factcard__figure {
  position: relative;
  z-index: 1;
  font-family: var(--f-display);
  font-size: calc(var(--fc-h) * 0.5674); /* 40px on the 70.49 card */
  font-weight: 500;
  line-height: 1;
  color: var(--c-text);
  white-space: nowrap;
}

/* The bloom is decoration; it costs nothing to drop it for anyone who has
   asked the OS to calm things down, and the card still reads. */
@media (prefers-reduced-motion: reduce) {
  .factcard::before { filter: none; }
}

.stat__caption {
  font-family: var(--f-display);
  font-size: 16px;
  font-weight: 500;
  line-height: 1.6em;
  color: var(--c-accent);
}

/* Client grid: 80% wide, 3 / 2 / 1 columns, 20px gap */
.logos {
  display: grid;
  grid-template-columns: repeat(3, minmax(50px, 1fr));
  gap: 20px;
  justify-content: center;
  width: 80%;
  margin-inline: auto;
}

@media (max-width: 1279.98px) { .logos { grid-template-columns: repeat(2, minmax(50px, 1fr)); } }
@media (max-width: 991.98px)  { .logos { grid-template-columns: repeat(1, minmax(50px, 1fr)); max-width: 398px; } }

/* Cell: 12px padding around a 78px centered row holding a 200x64 logo box */
.logo-cell__row {
  display: flex;
  align-items: center;
  justify-content: center;
  height: 78px;
  width: 100%;
}

.logo-cell__box {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 200px;
  height: 64px;
}

.logo-cell__box img {
  display: block;
  max-width: 100%;
  max-height: 100%;
  width: auto;
  height: auto;
  object-fit: contain;
}

.about__cta,
.labels__cta,
.blog__cta {
  display: flex;
  justify-content: center;
}

/* ==========================================================================
   Mission ("Video Section") — eyebrow left, heading right, 70% scrim
   ========================================================================== */

.mission {
  position: relative;
  padding: 270px 0;
  overflow: hidden;
}

@media (max-width: 1279.98px) { .mission { padding: 198px 0; } }
@media (max-width: 991.98px)  { .mission { padding: 150px 0; } }

.mission__bg { position: absolute; inset: 0; display: flex; }

.mission__video { width: 100%; height: 100%; object-fit: cover; }

.mission__scrim {
  position: absolute;
  inset: 0;
  z-index: 2;
  background: rgba(0, 0, 0, 0.70);   /* #000000b3 — darker than the hero */
}

.mission__inner {
  position: relative;
  z-index: 3;
  display: flex;
  flex-direction: row;
  justify-content: space-between;
  align-items: flex-start;
  gap: 0;
}

.mission__title {
  font-family: var(--f-display);
  font-size: 50px;
  font-weight: 400;
  line-height: 1.2em;
  letter-spacing: -2.5px;
  color: var(--c-text);
  flex: 1 0 0;
  max-width: 900px;
}

@media (max-width: 1279.98px) {
  .mission__title { font-size: 46px; max-width: 610px; }
}

@media (max-width: 991.98px) {
  .mission__inner { flex-direction: column; gap: 16px; }
  .mission__title { font-size: 34px; flex: none; width: 100%; max-width: none; }
}

/* ==========================================================================
   Labels — "OUR EXPERTISE": head + three alternating rows + CTA
   ========================================================================== */

.labels {
  max-width: 1450px;
  margin-inline: auto;
  padding: 0 0 130px;
  overflow: hidden;
}

@media (max-width: 1279.98px) { .labels { padding-bottom: 100px; } }
@media (max-width: 991.98px)  { .labels { padding-bottom: 80px; } }

.labels__head {
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  gap: 10px;
  padding: 120px 0;
}

/* This heading stays 50px at every breakpoint (single render, no variants) */
.labels__h2 {
  font-family: var(--f-display);
  font-size: 50px;
  font-weight: 400;
  line-height: 1.2em;
  letter-spacing: -2.5px;
  color: var(--c-text);
}

.labels__h2 strong { font-weight: 600; }

/* Each row: quote column + 400px canvas panel, both flex:1, 1200px content */
.label-row {
  display: flex;
  flex-direction: row;
  justify-content: space-between;
  align-items: center;
  width: 100%;
  max-width: 1240px;
  margin-inline: auto;
  padding: 0 20px;
}

.label-row__text {
  flex: 1 0 0;
  width: 1px;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 40px;
}

.label-row__text--right {
  align-items: flex-end;
  text-align: right;
}

.label-row__panel {
  flex: 1 0 0;
  width: 1px;
  height: 400px;
  overflow: hidden;
  cursor: grab;
}

/* --- 3D logo panels ------------------------------------------------------
   The seven Framer "Logofy" panels (3 in this section, 4 in the footer).
   js/logo3d.js extrudes each label's SVG into a metallic 3D solid using the
   plugin's own parameters. The flat SVG underneath is the fallback: it shows
   until the canvas loads, and stays if WebGL is unavailable.
   ------------------------------------------------------------------------- */

.logo3d {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: grab;
  touch-action: pan-y;
}

.logo3d.is-grabbing { cursor: grabbing; }

.logo3d__canvas {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  opacity: 0;
  transition: opacity 0.5s ease;   /* the source's panel fade-in */
}

.logo3d.is-loaded .logo3d__canvas { opacity: 1; }

.logo3d__fallback {
  width: 70%;
  max-height: 60%;
  object-fit: contain;
  opacity: 0.85;
  transition: opacity 0.5s ease;
}

/* Once the 3D version is up, hide the flat one. */
.logo3d.is-loaded .logo3d__fallback { opacity: 0; }

/* No WebGL: keep the flat logo, drop the grab affordance. */
.logo3d.is-failed { cursor: default; }
.logo3d.is-failed .logo3d__fallback { opacity: 0.85; }

.label-row__panel:active { cursor: grabbing; }

@media (max-width: 1279.98px) {
  .label-row { justify-content: center; gap: 50px; }
  .label-row__text { max-width: 610px; }
}

@media (max-width: 991.98px) {
  .label-row { flex-direction: column; gap: 40px; align-items: stretch; }
  .label-row__text,
  .label-row__panel { flex: none; width: 100%; }
}

.label-quote {
  font-family: var(--f-accent);
  font-size: 30px;
  font-weight: 400;
  line-height: 1.2em;
  letter-spacing: -1.5px;
  color: var(--c-accent);
}

/* Label name renders white at regular weight; the period stays accent */
.label-quote__name {
  color: var(--c-text);
  font-weight: 400;
}

/* innov8 / communic8 / autom8 — Manrope semibold */
.label-quote strong { font-weight: 600; }

@media (max-width: 991.98px) {
  .label-quote { font-size: 25px; }
  .label-quote__name { font-size: 30px; }
}

.labels__cta { padding: 87px 0; }

/* ==========================================================================
   Awards — white section: heading column left, list right
   ========================================================================== */

.awards {
  background: var(--c-text);
  color: var(--c-bg);
  padding: 130px 0;
}

@media (max-width: 1279.98px) { .awards { padding: 130px 0 100px; } }
@media (max-width: 991.98px)  { .awards { padding: 130px 0 80px; } }

.awards__container {
  display: flex;
  flex-direction: row;
  justify-content: space-between;
  align-items: flex-start;
}

.awards__title {
  font-family: var(--f-display);
  font-size: 50px;
  font-weight: 400;
  line-height: 1.2em;
  letter-spacing: -2.5px;
  color: var(--c-bg);
  flex: 1;
  max-width: 460px;
}

@media (max-width: 1279.98px) { .awards__title { font-size: 46px; max-width: 360px; } }

.awards__list {
  flex: 1;
  display: flex;
  flex-direction: column;
  gap: 30px;
}

@media (max-width: 991.98px) {
  .awards__container { flex-direction: column; gap: 40px; }
  .awards__title { font-size: 38px; flex: none; width: 100%; max-width: none; }
  .awards__list { flex: none; width: 100%; }
}

.award {
  display: flex;
  align-items: flex-start;
  gap: 30px;
  padding: 0 0 30px;
  border-bottom: 1px solid var(--c-rule-dark);
}

.award__num {
  font-family: var(--f-display);
  font-size: 20px;
  font-weight: 500;
  line-height: 1.6em;
  color: var(--c-grey);
  flex: none;
}

/* Declared as Montserrat Alternates in the source, but the published site
   ships no @font-face for it — it renders in the sans-serif fallback there. */
.award__name {
  font-family: "Montserrat Alternates", sans-serif;
  font-size: 30px;
  font-weight: 400;
  line-height: 1.2em;
  letter-spacing: -1.5px;
  color: var(--c-bg);
}

@media (max-width: 991.98px) {
  .award__name { font-size: 25px; }
}

/* ==========================================================================
   Works — two-column head, two bottom-aligned card columns
   ========================================================================== */

.works { padding: 130px 0; }

@media (max-width: 1279.98px) { .works { padding: 130px 0 100px; } }
@media (max-width: 991.98px)  { .works { padding: 130px 0 80px; } }

.works__head {
  display: flex;
  flex-direction: row;
  justify-content: space-between;
  align-items: flex-start;
  width: 100%;
  margin-bottom: 50px;
}

@media (max-width: 1279.98px) { .works__head { margin-bottom: 40px; } }

.works__head-info {
  display: flex;
  flex-direction: column;
  flex: 1 0 0;
  gap: 24px;
  max-width: 600px;
}

@media (max-width: 991.98px) {
  .works__head { flex-direction: column; gap: 16px; }
  .works__head-info { flex: none; width: 100%; max-width: none; }
}

.works__sub {
  font-family: var(--f-display);
  font-size: 20px;
  font-weight: 500;
  line-height: 1.6em;
  color: var(--c-accent);
}

/* Two columns, bottom-aligned; col 1 holds the card + the All Works button */
.works__wrapper {
  display: flex;
  flex-direction: row;
  align-items: flex-end;
  gap: 165px;
}

@media (max-width: 1279.98px) { .works__wrapper { gap: 50px; } }

.works__col {
  flex: 1 0 0;
  display: flex;
  flex-direction: column;
  gap: 100px;
}

@media (max-width: 1279.98px) { .works__col { gap: 50px; } }
@media (max-width: 991.98px)  { .works__col { gap: 40px; } }

.works__cta {
  display: flex;
  justify-content: flex-start;
  width: 100%;
}

/* The COMTOO column disappears entirely on phone in the source */
@media (max-width: 991.98px) {
  .works__col--second { display: none; }
}

.work-card {
  display: flex;
  flex-direction: column;
  gap: 20px;
}

.work-card__media {
  height: 420px;
  border-radius: 0;
}

@media (max-width: 991.98px) {
  .work-card__media { height: 380px; }
}

.work-card__art { width: 100%; height: 100%; object-fit: cover; }

/* Body: title+date column left, Learn more right, bottom-aligned */
.work-card__body {
  display: flex;
  flex-direction: row;
  align-items: flex-end;
  gap: 20px;
  width: 100%;
}

.work-card__titles {
  display: flex;
  flex-direction: column;
  flex: 1 0 0;
  gap: 5px;
}

.work-card__title {
  font-family: var(--f-display);
  font-size: 24px;
  font-weight: 400;
  line-height: 1.2em;
  color: var(--c-text);
}

@media (max-width: 991.98px) {
  .work-card__title { font-size: 22px; }
}

.work-card__date {
  font-family: var(--f-display);
  font-size: 16px;
  font-weight: 500;
  line-height: 1.6em;
  color: var(--c-accent);
}

.learn-more__label {
  font-family: var(--f-display);
  font-size: 14px;
  font-weight: 500;
  line-height: 1.6em;
  text-transform: uppercase;
  color: var(--c-text);
}

/* ==========================================================================
   Blog
   ========================================================================== */

.blog { padding: 130px 0; overflow: hidden; }

@media (min-width: 992px) and (max-width: 1279.98px) { .blog { padding: 100px 0; } }
@media (max-width: 991.98px) { .blog { padding: 130px 0 80px; } }

.blog__container {
  display: flex;
  flex-direction: column;
  gap: 50px;
}

@media (max-width: 1279.98px) { .blog__container { gap: 40px; } }

.blog__head {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: 40px;
}

/* Fixed 500px at every breakpoint in the source (one rule, no overrides,
   flex:none so it never shrinks); the section's overflow:hidden clips it
   on very narrow viewports there too */
.blog__h2 {
  flex: none;
  width: 500px;
  max-width: 500px;
}

@media (max-width: 991.98px) {
  .blog__head-cta { display: none; }
}

.blog__cta { display: none; }

@media (max-width: 991.98px) {
  .blog__cta { display: flex; justify-content: flex-start; }
}

.blog__list {
  display: flex;
  flex-direction: column;
  gap: 50px;
}

@media (max-width: 1279.98px) { .blog__list { gap: 40px; } }

@media (max-width: 991.98px) {
  .blog__list { flex-direction: row; flex-wrap: wrap; gap: 40px 30px; }
}

/* Card: content column left (max 500px), fixed 360x220 thumbnail right */
.post {
  display: flex;
  flex-direction: row;
  justify-content: space-between;
  align-items: center;
}

/* Only the first card carries a bottom rule + padding */
.post--divided {
  padding: 0 0 50px;
  border-bottom: 1px solid var(--c-accent-70);
}

@media (max-width: 1279.98px) {
  .post--divided { padding: 0 0 40px; }
}

@media (max-width: 991.98px) {
  .post {
    flex: 1 0 0;
    min-width: 280px;
    flex-direction: column;
    align-items: stretch;
    gap: 40px;
  }
  .post--divided { padding: 0; border-bottom-width: 0; }
}

.post__body {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 30px;
  flex: 1 0 0;
  max-width: 500px;
}

@media (max-width: 1279.98px) { .post__body { max-width: 460px; } }
@media (max-width: 991.98px)  { .post__body { flex: none; width: 100%; max-width: 460px; } }

.post__titles {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 24px;
}

/* Date sits in a padded wrapper in the source */
.post__date {
  font-family: var(--f-display);
  font-size: 16px;
  font-weight: 500;
  line-height: 1.6em;
  color: var(--c-accent);
  padding: 4px 12px;
}

.post__title {
  font-family: var(--f-display);
  font-size: 30px;
  font-weight: 300;
  line-height: 1.2em;
  letter-spacing: -1.5px;
  color: var(--c-text);
}

@media (max-width: 1279.98px) {
  .post__title { font-size: 25px; }
}

.post__media {
  width: 360px;
  height: 220px;
  overflow: hidden;
  border-radius: 0;
  flex: none;
}

@media (max-width: 991.98px) {
  .post__media { width: 100%; flex: 1 0 0; }
}

.post__media .ph,
.post__media img { width: 100%; height: 100%; object-fit: cover; }

/* ==========================================================================
   Contact page

   Laid out to match transform8.framer.website/contact-us, measured at 1440px:

     banner      1440 x 400, full bleed, colour
     column      1200 wide (x 120..1320)
     left rail   520: eyebrow, 50px H2, office list
     office row  30x30 mark at x=120, text at x=164, Montserrat 18/500
     form        520 wide from x=770  ->  130px gutter
     field       250 x 52 boxed, label INSIDE the box above the control
     input       Manrope 16/300, 20px inset
     submit      520 x 62, white fill, black label

   The form's markup, endpoint and JS belong to the /api/contact work and are
   untouched — this only restyles the classes that markup already carries, so
   validation, inline errors, the honeypot and the status line keep working.
   ========================================================================== */

/* The banner is full bleed at the top of the page, so unlike the other
   subpages this one needs no clearance under the fixed header. */
.page-contact main { padding-top: 0; }

/* The 1200px column the source uses. Declared here as well as in pages.css
   because this page loads layout.css only. */
.container--narrow { max-width: 1280px; }

.contact-hero {
  width: 100%;
  height: 400px;
  overflow: hidden;
}

.contact-hero__img { width: 100%; height: 100%; object-fit: cover; }

/* --- Sector page hero photograph ----------------------------------------
   The same band as the contact hero. Desaturated in CSS rather than baked
   into the file, the way .hero__video is on the homepage: one line to change
   if colour is ever wanted, and the source images stay reusable elsewhere.

   The gradient does what the homepage scrim does. The page background is pure
   black, so a hard photo edge against it reads as a seam; the image is faded
   into the background at its lower edge instead of being cut off. */
.sector-hero {
  position: relative;
  width: 100%;
  height: 400px;
  overflow: hidden;
}

.sector-hero__img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  filter: grayscale(1);
}

.sector-hero::after {
  content: "";
  position: absolute;
  inset: auto 0 0 0;
  height: 45%;
  background: linear-gradient(to bottom, transparent, var(--c-bg));
  pointer-events: none;
}

/* The header is transparent at the top of the page and its links are white,
   so on a bright photograph they vanish. /sectors/handel opens on a lit
   monitor and the nav was white on near-white — unreadable, not merely low
   contrast.

   The homepage covers its whole hero with .hero__scrim; here only the header
   band needs protecting, so this fades out rather than flattening the picture.

   Note that it HOLDS at full strength across the header before it begins to
   fade. A plain top-to-bottom fade looked perfectly fine in a screenshot and
   measured 2.1:1 at the bottom of the nav — by y=104 a 200px gradient has
   almost nothing left. Holding to 110px and clearing by 230px measures 5.7:1
   at worst across all four photographs, against white 14px text that needs
   4.5:1.

   Any photograph dropped in later inherits the same guarantee. If you swap in
   something brighter still, measure it rather than trusting your eye — the
   first attempt here read as fine and was failing by a factor of two. */
.sector-hero::before {
  content: "";
  position: absolute;
  inset: 0 0 auto 0;
  height: 230px;
  background: linear-gradient(to bottom,
    var(--c-scrim) 0,
    var(--c-scrim) 110px,
    transparent 230px);
  pointer-events: none;
  z-index: 1;
}

/* Shorter header, so a shorter band — but not as short as it looks like it
   could be. Scaling this down in proportion to the header (an 84px hold) put
   the widest tablet case at 4.31:1, just under. 96px holds it. */
@media (max-width: 991.98px) {
  .sector-hero::before {
    height: 196px;
    background: linear-gradient(to bottom,
      var(--c-scrim) 0,
      var(--c-scrim) 96px,
      transparent 196px);
  }
}

/* With a photograph above it, the heading block no longer needs the full
   run-in space it uses when it is the first thing on the page. */
.sector-hero + .page-hero { padding-top: 60px; }

@media (max-width: 1279.98px) {
  .sector-hero { height: 320px; }
  .sector-hero + .page-hero { padding-top: 48px; }
}

@media (max-width: 991.98px) {
  .sector-hero { height: 240px; }
  .sector-hero + .page-hero { padding-top: 36px; }
}

/* 178px, not 90: measured from the bottom of the 400px banner to the top of
   the eyebrow on the source (400 -> 578). */
.contact { padding: 178px 0 0; }

.contact__grid {
  display: flex;
  align-items: flex-start;
  /* flex-start, not space-between: the source's form sits at x=770, i.e.
     rail + a 130px gutter, and stops 30px short of the column's right edge
     rather than stretching to meet it. */
  justify-content: flex-start;
  gap: 130px;
}

.contact__rail { flex: 0 0 520px; }

/* The source leaves 25px between the eyebrow and the headline (578 -> 625);
   the shared .h2 carries no top margin, so it is added here. */
.contact__rail .h2 { margin-top: 25px; }

/* 22/500 in the source, sitting 60px under the headline. */
.office-list__head {
  font-family: var(--f-display);
  font-size: 22px;
  font-weight: 500;
  line-height: 1.2em;
  color: var(--c-text);
  margin-top: 60px;
}

.office-list {
  display: flex;
  flex-direction: column;
  gap: 18px;
  margin-top: 26px;
  list-style: none;
  padding: 0;
}

.office { display: flex; align-items: flex-start; gap: 14px; }

.office__icon { flex: none; width: 30px; height: 30px; object-fit: contain; }

.office__link {
  font-family: var(--f-display);
  font-size: 18px;
  font-weight: 500;
  line-height: 1.6em;
  color: var(--c-text);
  transition: color var(--dur-base) var(--ease-site);
}

.office__link:hover { color: var(--c-accent); }

/* Form --------------------------------------------------------------------- */

.form {
  flex: 0 1 520px;
  display: flex;
  flex-direction: column;
  gap: 20px;
}

.form__row { display: flex; gap: 20px; width: 100%; }

/* Boxed field with the label inside it, which is what the source does — not a
   floating label and not a bare underline. */
.field {
  display: flex;
  flex-direction: column;
  flex: 1 0 0;
  min-width: 0;
  background: rgba(255, 255, 255, 0.06);
  border: 1px solid var(--c-accent-70);
  border-radius: 0;
  /* The source packs this into 52px: 22 label + 26 control + 1px padding + 1px
     border, with the label and control touching. That reads as cramped the
     moment a control actually has text in it — which is why the select looked
     wrong first: it is the only control that is never empty, so the empty
     inputs were hiding the same problem behind their own whitespace.

     12px vertical against the existing 20px horizontal, and 4px between label
     and control so they read as two lines rather than one block. 78px total. */
  padding: 12px 20px;
  gap: 4px;
  transition: border-color var(--dur-base) var(--ease-site);
}

.field:focus-within { border-color: var(--c-text); }

.field__label {
  font-family: var(--f-display);
  font-size: 14px;
  font-weight: 500;
  line-height: 1.6em;
  text-transform: uppercase;
  color: var(--c-text);
}

.field__label span { color: var(--c-accent); }

.field__input {
  font-family: var(--f-accent);
  font-size: 16px;
  font-weight: 300;
  line-height: 1.6em;
  color: var(--c-text);
  background: transparent;
  border: 0;
  border-radius: 0;
  padding: 0;
  width: 100%;
}

.field__input:focus,
.field__input:focus-visible { outline: none; }

.field__input::placeholder { color: rgba(255, 255, 255, 0.4); }

.field__textarea { resize: vertical; min-height: 100px; }

/* appearance:none strips the native arrow, so it is drawn back on. */
.field__select {
  appearance: none;
  -webkit-appearance: none;
  cursor: pointer;
  padding-right: 22px;
  background-image: linear-gradient(45deg, transparent 50%, var(--c-text) 50%),
                    linear-gradient(135deg, var(--c-text) 50%, transparent 50%);
  background-position: right 8px center, right 3px center;
  background-size: 5px 5px, 5px 5px;
  background-repeat: no-repeat;
}

.field__select option { background: var(--c-bg); color: var(--c-text); }

.field__input.is-invalid { color: #ff6b6b; }
.field:has(.is-invalid) { border-color: #ff6b6b; }

.field__error {
  font-family: var(--f-display);
  font-size: 13px;
  font-weight: 400;
  line-height: 1.5em;
  color: #ff6b6b;
  margin-top: 4px;
}

.field__error:empty { display: none; }

/* Off-screen rather than display:none, which some bots detect. */
.form__trap {
  position: absolute;
  left: -9999px;
  width: 1px;
  height: 1px;
  overflow: hidden;
}

/* Full-width white block, matching the source's 520x62 submit. The extra
   `.form` qualifier is load-bearing: motion.css comes after layout.css, so a
   bare .form__submit loses to .btn's own padding and the button stays 44px. */
.form .form__submit {
  width: 100%;
  /* 62px: 19 + 22 line + 19 + 2px of .btn border. */
  padding: 19px 40px;
  justify-content: center;
}

.form__status {
  font-family: var(--f-display);
  font-size: 14px;
  font-weight: 400;
  line-height: 1.6em;
  color: var(--c-text-70);
}

.form__status:empty { display: none; }
.form__status.is-success { color: var(--c-accent); }
.form__status.is-error { color: #ff6b6b; }

@media (max-width: 1279.98px) {
  .contact-hero { height: 320px; }
  .contact__grid { gap: 70px; }
  .contact__rail { flex-basis: 400px; }
  .office-list { margin-top: 70px; }
}

@media (max-width: 991.98px) {
  .contact-hero { height: 220px; }
  .contact { padding: 60px 0 0; }
  .contact__grid { flex-direction: column; gap: 50px; }
  .contact__rail { flex: none; width: 100%; }
  .office-list { margin-top: 40px; }
  .form { flex: none; width: 100%; }
  .form__row { flex-direction: column; gap: 20px; }
}

/* ==========================================================================
   Locations

   Used by the "Kantoren" section on the home page (index.html #contact).
   NB: this block was briefly deleted along with the old contact-page styles —
   the two lived under one header in this file, and only the contact half was
   being replaced. The home page then rendered the office list as raw unstyled
   markup. Keep it separate from the contact styles: /contact-us has its own
   .office-list and does not use these rules.
   ========================================================================== */

.locations { padding: 130px 0; }

@media (min-width: 992px) and (max-width: 1279.98px) { .locations { padding: 100px 0; } }
@media (max-width: 991.98px) { .locations { padding: 100px 0 80px; } }

.locations__head {
  display: flex;
  flex-direction: column;
  gap: 10px;
  margin-bottom: 50px;
}

.locations__grid {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 40px 20px;
}

@media (max-width: 991.98px) {
  .locations__grid { grid-template-columns: 1fr; gap: 50px; }
}

.location {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 12px;
}

.location__media {
  width: 100%;
  height: 260px;
  overflow: hidden;
  margin-bottom: 8px;
}

.location__media .ph { height: 100%; }

.location__label {
  font-family: var(--f-display);
  font-size: 24px;
  font-weight: 400;
  line-height: 1.2em;
  color: var(--c-text);
}

.location__city {
  font-family: var(--f-display);
  font-size: 16px;
  font-weight: 500;
  line-height: 1.6em;
  color: var(--c-accent);
}

.location__address {
  font-family: var(--f-display);
  font-size: 16px;
  font-weight: 400;
  line-height: 1.6em;
  font-style: normal;      /* <address> italicises by default */
  color: var(--c-text-70);
}

/* Phone sits between the address and the route link. A real <a href="tel:">
   so it dials on a phone rather than being text someone has to copy. */
.location__tel {
  font-family: var(--f-display);
  font-size: 16px;
  font-weight: 500;
  line-height: 1.6em;
  color: var(--c-text);
  transition: color var(--dur-base) var(--ease-site);
}

.location__tel:hover { color: var(--c-accent); }

.location__link {
  font-family: var(--f-display);
  font-size: 14px;
  font-weight: 500;
  line-height: 1.6em;
  text-transform: uppercase;
  color: var(--c-text);
}

/* --- Offices as alternating rows (/contact-us) ---------------------------
   The source lays these out as three wide rows rather than a card grid, and
   the geometry is regular enough to state exactly. Measured off
   transform8.framer.website/contact-us at a 1400px viewport, content column
   1200 wide:

     row          330 text + 870 photograph, no gutter  -> 1200
     photograph   870 x 315
     row pitch    421  ->  106 between rows
     text block   80px inset each side  ->  170 of content
     name         Montserrat 30/36, weight 400, -1.5px
     button       170 x 42

   Sides alternate, and the name always sits against the photograph: the text
   is right-aligned when it is on the left, left-aligned when it is on the
   right. That is what makes the zig-zag read as one object rather than three
   unrelated blocks, so it is the part not to "tidy up".

   Scoped to .locations__rows on purpose — the home page keeps its three-up
   .locations__grid, which is a different section with a different job.
   -------------------------------------------------------------------------- */

.locations__rows {
  display: flex;
  flex-direction: column;
  gap: 106px;
}

.locations__rows .location {
  display: grid;
  grid-template-columns: 330px 870px;
  align-items: center;
  gap: 0;
}

.locations__rows .location--flip { grid-template-columns: 870px 330px; }

/* Source order is photograph-then-text; the flip swaps them visually without
   moving the name away from its address in the reading order. */
.locations__rows .location__media {
  grid-column: 2;
  grid-row: 1;
  width: 870px;
  height: 315px;
  margin: 0;
}

/* Rows that have a photograph rather than a placeholder. Greyscale to match
   /about-us and the sector heroes. */
.locations__rows .location__media img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  filter: grayscale(1);
}

.locations__rows .location--flip .location__media { grid-column: 1; }

.locations__rows .location__body {
  grid-column: 1;
  grid-row: 1;
  padding: 0 80px;
  text-align: right;
}

.locations__rows .location--flip .location__body {
  grid-column: 2;
  text-align: left;
}

.locations__rows .location__name {
  font-family: var(--f-display);
  font-size: 30px;
  font-weight: 400;
  line-height: 1.2em;
  letter-spacing: -1.5px;
  color: var(--c-text);
}

/* The full stop and the city carry the accent; the label name stays white. */
.locations__rows .location__dot,
.locations__rows .location__city { color: var(--c-accent); }

/* The source's 170px column holds a two-word name and a button, nothing more —
   the addresses live up in the left rail beside the form. Ours carries them
   here too, and at 170px "5232 BC 's-Hertogenbosch" broke across three lines
   with a hyphen through the place name.

   Rather than widen the block and drag the name off its measured position,
   only the address reaches outwards, into its own free side. The edge that
   faces the photograph — the one the eye actually aligns on — stays exactly
   where the source puts it. */
.locations__rows .location__address {
  font-family: var(--f-display);
  font-size: 15px;
  font-weight: 300;
  line-height: 1.6em;
  font-style: normal;
  color: var(--c-text-70);
  margin-top: 18px;
  margin-left: -80px;   /* stops exactly on the container edge */
}

.locations__rows .location--flip .location__address {
  margin-left: 0;
  margin-right: -80px;
}

.locations__rows .location__tel {
  display: inline-block;
  font-family: var(--f-display);
  font-size: 15px;
  font-weight: 500;
  color: var(--c-text);
  margin-top: 6px;
}

.locations__rows .location__btn {
  display: inline-flex;
  width: 170px;
  height: 42px;
  margin-top: 40px;
}

/* Below the breakpoint the two fixed columns cannot both fit, so the row
   becomes a stack: photograph, then text, always left-aligned. */
@media (max-width: 1279.98px) {
  .locations__rows { gap: 70px; }
  .locations__rows .location,
  .locations__rows .location--flip {
    grid-template-columns: 1fr;
  }
  .locations__rows .location__media,
  .locations__rows .location--flip .location__media {
    grid-column: 1;
    grid-row: 1;
    width: 100%;
    height: auto;
    aspect-ratio: 870 / 315;
  }
  .locations__rows .location__body,
  .locations__rows .location--flip .location__body {
    grid-column: 1;
    grid-row: 2;
    padding: 28px 0 0;
    text-align: left;
  }
  /* Full width down here, so the address needs no reach-out. */
  .locations__rows .location__address,
  .locations__rows .location--flip .location__address {
    margin-left: 0;
    margin-right: 0;
  }
}

@media (max-width: 991.98px) {
  .locations__rows .location__name { font-size: 25px; letter-spacing: -1px; }
  /* The flip selector carries one more class than this one, so leaving it out
     left the middle row at the wide 870/315 ratio while its neighbours went to
     3/2 - 121px tall against 223px. Both listed, deliberately. */
  .locations__rows .location__media,
  .locations__rows .location--flip .location__media { aspect-ratio: 3 / 2; }
}

/* ==========================================================================
   Footer
   ========================================================================== */

.footer { padding: 96px 0 30px; }

.footer__container {
  display: flex;
  flex-direction: column;
  gap: 30px;
  max-width: 1435px;
}

/* Title + labels block: 80px vertical padding, right-aligned title */
.footer__top {
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: 10px;
  padding: 80px 0;
}

.footer__title {
  font-family: var(--f-accent);
  font-size: 50px;
  font-weight: 400;
  line-height: 1.2em;
  letter-spacing: 0;
  color: var(--c-accent);
  text-align: right;
  width: 100%;
  max-width: 710px;
  margin-left: auto;
}

@media (max-width: 991.98px) { .footer__title { font-size: 30px; } }

/* Four label panels side by side at every breakpoint, no gap */
.footer__labels {
  display: flex;
  flex-direction: row;
  gap: 0;
  width: 100%;
}

.footer-label {
  flex: 1 0 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 10px;
}

.footer-label__panel {
  width: 100%;
  height: 250px;
  overflow: hidden;
  cursor: grab;
}

.footer-label__panel:active { cursor: grabbing; }

.footer-label__text {
  font-family: var(--f-display);
  font-size: 14px;
  font-weight: 500;
  line-height: 1.6em;
  text-transform: uppercase;
  color: var(--c-text);
  width: auto;
  max-width: 700px;
  text-align: center;
}

.footer-label__text strong { font-weight: 600; }

.footer__rule {
  height: 1px;
  border: 0;
  background: var(--c-accent-70);
  margin: 0;
  width: 100%;
}

/* Contact: eyebrow left, pitch block right */
.footer__contact {
  display: flex;
  flex-direction: row;
  justify-content: space-between;
  align-items: flex-start;
  padding: 0 0 30px;
}

.footer__contact-block {
  flex: 1 0 0;
  max-width: 810px;
  padding: 0 0 30px;
}

@media (max-width: 1279.98px) {
  .footer__contact-block { max-width: 720px; padding: 0 0 20px; }
}

@media (max-width: 991.98px) {
  .footer__contact { flex-wrap: wrap; gap: 20px 60px; padding: 0; }
  .footer__contact-block { min-width: 280px; padding: 0 0 10px; }
}

.footer__pitch {
  font-family: var(--f-accent);
  font-size: 50px;
  font-weight: 400;
  line-height: 1.2em;
  color: var(--c-accent);
  width: 100%;
  max-width: 710px;
}

@media (max-width: 991.98px) { .footer__pitch { font-size: 30px; } }

/* Mail link flows inline at the end of the pitch: white, underlined */
.footer__mail {
  color: var(--c-text);
  text-decoration: underline;
  text-underline-offset: 3px;
  text-decoration-thickness: 1px;
  transition: color var(--dur-base) var(--ease-site);
}

.footer__mail:hover { color: var(--c-text-70); }

/* --- Copy-to-clipboard on the mail address -------------------------------
   No pill, no tooltip, no floating chrome: the address itself becomes the
   confirmation. Both words share one grid cell, so the wrapper is always as
   wide as the wider of the two and the 50px pitch paragraph never reflows —
   the sentence around it does not move.

   The word swaps in the same place, at the same size, in the same face. The
   only thing that changes is which word is there. */
.mailcopy {
  display: inline-grid;
  vertical-align: baseline;
}

.mailcopy > * {
  grid-area: 1 / 1;
  /* Both children sit on the same baseline row; the address stays the one that
     defines the box, so the confirmation cannot shift the line. */
  justify-self: start;
}

.mailcopy .footer__mail {
  cursor: pointer;
}

/* The confirmation. White and un-underlined against the periwinkle pitch, so
   it reads as the link's own state rather than as new text in the sentence.
   `nowrap` keeps "Kopieer met ⌘C" — the fallback string — on one line. */
.mailcopy__done {
  color: var(--c-text);
  white-space: nowrap;
  pointer-events: none;
  opacity: 0;
  transform: translate3d(0, 4px, 0);
  transition:
    opacity var(--dur-base) var(--ease-site),
    transform var(--dur-base) var(--ease-site);
}

/* Out on --dur-base (0.4s) as a considered recede; in on --dur-nav (0.2s) so
   the acknowledgement lands immediately. Same easing as every other transition
   on the site. */
.mailcopy.is-copied .footer__mail {
  opacity: 0;
  transform: translate3d(0, -4px, 0);
  transition:
    opacity var(--dur-nav) var(--ease-site),
    transform var(--dur-nav) var(--ease-site);
}

.mailcopy.is-copied .mailcopy__done {
  opacity: 1;
  transform: translate3d(0, 0, 0);
  transition:
    opacity var(--dur-nav) var(--ease-site),
    transform var(--dur-nav) var(--ease-site);
}

/* The address needs the transform property declared in its rest state too,
   or the first swap has nothing to animate from. */
.mailcopy .footer__mail {
  transform: translate3d(0, 0, 0);
  transition:
    color var(--dur-base) var(--ease-site),
    opacity var(--dur-base) var(--ease-site),
    transform var(--dur-base) var(--ease-site);
}

/* Centre row: 200x150 logo left; nav column + social icons right */
.footer__center {
  display: flex;
  flex-direction: row;
  justify-content: space-between;
  align-items: flex-start;
}

.footer__logo {
  display: block;
  width: 200px;
  height: 150px;
}

.footer__logo img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: contain;
}

.footer__center-right {
  flex: 1 0 0;
  max-width: 810px;
  padding: 0 0 20px;
  display: flex;
  flex-direction: row;
  justify-content: space-between;
  align-items: flex-start;
}

@media (max-width: 1279.98px) {
  .footer__center-right { max-width: 720px; padding: 0 0 10px; }
}

@media (max-width: 991.98px) {
  .footer__center { flex-direction: column; gap: 30px; }
  .footer__center-right { flex: none; width: 100%; }
}

.footer__nav {
  display: flex;
  flex-direction: column;
  gap: 4px;
  width: min-content;
}

.footer__nav a {
  font-family: var(--f-display);
  font-size: 14px;
  font-weight: 500;
  line-height: 1.6em;
  text-transform: uppercase;
  color: var(--c-accent);
  transition: color var(--dur-base) var(--ease-site);
}

.footer__nav a:hover { color: var(--c-text); }

.footer__social {
  display: flex;
  gap: 25px;
  justify-content: flex-end;
}

.footer__social img {
  display: block;
  width: 18px;
  height: 18px;
}

@media (max-width: 991.98px) {
  .footer__social img { width: 30px; height: 30px; }
}

/* Copyright row: powered-by column left, copyright right */
.footer__bottom {
  display: flex;
  flex-direction: row;
  justify-content: space-between;
  align-items: center;
}

@media (max-width: 991.98px) {
  .footer__bottom { flex-direction: column; align-items: flex-start; gap: 0; }
}

.footer__powered {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 5px;
  padding: 29px 0 50px;
  flex: 1;
}

.footer__powered-label {
  font-family: var(--f-display);
  font-size: 14px;
  font-weight: 500;
  line-height: 1.6em;
  text-transform: uppercase;
  color: var(--c-text);
}

.footer__powered-mark {
  display: block;
  width: 243px;
  height: 60px;
}

.footer__copy {
  font-family: var(--f-display);
  font-size: 16px;
  font-weight: 500;
  line-height: 1.6em;
  color: var(--c-accent);
}


/* Footer mark — the ring turns ------------------------------------------------
   Three layers reproducing the Figma construction (node 173:2):

     1. the ring
     2. the 8, over it
     3. the ring AGAIN, clipped to a small ellipse, over the 8

   Layer 3 is the "inlet": it is what makes the two shapes read as woven rather
   than merely stacked. Figma builds the weave the same way — a masked patch
   where the z-order is reversed.

   Percentages come from the Figma frame (400.5253 x 304):
     ring   0,0        303.605 x 303.605
     eight  164.83,1.05  237.647 x 304.909   (export carries ~1.955u of bleed)
     inlet  ellipse r(54,48) centred (210,256)

   Rotating is only safe because the ring is a true annulus: its outline does
   not change as it turns, so the crossing points — and therefore the inlet —
   stay valid at every angle. Both copies share one animation name and the same
   duration, so they cannot drift out of sync.
   -------------------------------------------------------------------------- */

.t8mark {
  display: block;
  position: relative;
  /* Height-led inside the 200x150 box: the mark is 1.3175:1 against the box's
     1.3333:1, so matching height keeps the proportions and fits the width. */
  height: 100%;
  width: auto;
  aspect-ratio: 400.5253 / 304;
  margin-inline: auto;
}

/* `.footer__logo img` stretches the old single-image logo to fill its box.
   These layers size themselves, so they carry an `img` qualifier of their own
   to out-specify both it and the reset below. */
.footer__logo .t8mark img {
  object-fit: fill;
}

.t8mark__ring,
.t8mark__eight {
  position: absolute;
  display: block;
}

.footer__logo .t8mark img.t8mark__ring {
  left: 0;
  top: 0;
  width: 75.802%;
  height: 99.870%;
  /* The image box is exactly the annulus, so its own centre is the ring's
     centre — no origin offset needed. */
  transform-origin: 50% 50%;
  animation: t8-spin 48s linear infinite;
  will-change: transform;
}

.footer__logo .t8mark img.t8mark__eight {
  left: 41.154%;
  top: 0.344%;
  width: 59.334%;
  height: 100.299%;
}

/* The patch that puts the ring back on top of the 8 at the lower crossing. */
.t8mark__inlet {
  position: absolute;
  inset: 0;
  clip-path: ellipse(13.482% 15.789% at 52.431% 84.211%);
}

@keyframes t8-spin {
  from { transform: rotate(0deg); }
  to   { transform: rotate(360deg); }
}

/* A slowly turning logo is decorative motion with no informational value, so
   it stops entirely rather than merely slowing down. */
@media (prefers-reduced-motion: reduce) {
  .t8mark__ring { animation: none; }
}

/* ==========================================================================
   Specialismen — need first, label second
   ========================================================================== */

.specialismen { padding: 130px 0; }

@media (min-width: 992px) and (max-width: 1279.98px) { .specialismen { padding: 100px 0; } }
@media (max-width: 991.98px) { .specialismen { padding: 80px 0; } }

.specialismen__head {
  display: flex;
  flex-direction: column;
  gap: 16px;
  max-width: 760px;
  margin-bottom: 60px;
}

.specialismen__lead,
.waarom__lead {
  font-family: var(--f-display);
  font-size: 20px;
  font-weight: 300;
  line-height: 1.6em;
  color: var(--c-text-70);
}

.specialismen__grid {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 20px;
}

@media (max-width: 1279.98px) { .specialismen__grid { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 599.98px)  { .specialismen__grid { grid-template-columns: 1fr; } }

.spec {
  display: flex;
  flex-direction: column;
  gap: 10px;
  padding: 34px 30px 28px;
  background: rgba(255, 255, 255, 0.04);
  border: 1px solid var(--c-hairline, rgba(255, 255, 255, 0.12));
  transition:
    background-color var(--dur-base) var(--ease-site),
    border-color var(--dur-base) var(--ease-site),
    transform var(--dur-base) var(--ease-out-intro);
}

.spec:hover {
  background: rgba(255, 255, 255, 0.07);
  border-color: rgba(255, 255, 255, 0.24);
  transform: translateY(-4px);
}

/* The visitor's problem, in their words — deliberately the first thing read. */
.spec__need {
  font-family: var(--f-display);
  font-size: 13px;
  font-weight: 500;
  line-height: 1.5em;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--c-accent);
}

.spec__label {
  font-family: var(--f-display);
  font-size: 26px;
  font-weight: 400;
  line-height: 1.2em;
  letter-spacing: -0.8px;
  color: var(--c-text);
}

.spec__text {
  font-family: var(--f-display);
  font-size: 15px;
  font-weight: 300;
  line-height: 1.6em;
  color: var(--c-text-70);
  flex: 1;
}

.spec__go {
  font-family: var(--f-display);
  font-size: 13px;
  font-weight: 500;
  text-transform: uppercase;
  color: var(--c-text);
  margin-top: 8px;
}

/* ==========================================================================
   Waarom Transform8
   ========================================================================== */

.waarom { padding: 130px 0 110px; }

@media (max-width: 991.98px) { .waarom { padding: 80px 0 70px; } }

/* Head and reasons sit side by side so the section is two tiers, not three.
   The 5fr/7fr split gives the heading enough width to break where it wants
   while leaving the three reasons a workable measure each. */
.waarom__band {
  display: grid;
  grid-template-columns: 4.5fr 7.5fr;
  gap: 20px 64px;
  align-items: start;
  margin-bottom: 70px;
}

.waarom__head {
  display: flex;
  flex-direction: column;
  gap: 16px;
  max-width: 760px;
}

.waarom__grid {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 20px;
}

/* Below the desktop breakpoint the reasons have no room to be three columns
   next to a heading, so the band collapses back to stacked — one tier of
   heading, one of reasons — which is the correct shape on a narrow screen. */
@media (max-width: 1279.98px) {
  .waarom__band {
    grid-template-columns: 1fr;
    gap: 48px;
  }
}

@media (max-width: 991.98px) {
  .waarom__grid { grid-template-columns: 1fr; }
  .waarom__band { gap: 36px; margin-bottom: 50px; }
}

.reason {
  display: flex;
  flex-direction: column;
  gap: 12px;
  padding-top: 24px;
  border-top: 1px solid var(--c-accent-70);
}

.reason__title {
  font-family: var(--f-display);
  font-size: 22px;
  font-weight: 400;
  line-height: 1.25em;
  letter-spacing: -0.5px;
  color: var(--c-text);
  /* Three columns beside the heading leaves each title a narrow measure, where
     Dutch compounds strand single short words on their own line ("…je sector /
     al"). Let the browser even the lines out instead. Purely a refinement —
     unsupported browsers just get the default ragged break. */
  text-wrap: balance;
}

.reason__text {
  font-family: var(--f-display);
  font-size: 16px;
  font-weight: 300;
  line-height: 1.6em;
  color: var(--c-text-70);
}

/* Figures are attributed per label, so each needs room for a full sentence
   rather than the usual bare stat-strip caption. */
.proof {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 30px 20px;
}

@media (max-width: 991.98px) { .proof { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 479.98px) { .proof { grid-template-columns: 1fr; } }

.proof__item { display: flex; flex-direction: column; align-items: flex-start; gap: 14px; }

/* Same glass card as the stat strip, sized down. "167.000" is wider than the
   Figma ratio allows, which is why the card grows on min-width rather than
   locking to aspect-ratio. */
.proof .factcard { --fc-h: 58px; }

.proof__label {
  font-family: var(--f-display);
  font-size: 14px;
  font-weight: 300;
  line-height: 1.5em;
  color: var(--c-text-70);
}

/* ==========================================================================
   FAQ — native <details>, so it works without JavaScript
   ========================================================================== */

/* --- FAQ: a light band ---------------------------------------------------
   Answers to questions are reference material, not brand voice, and they read
   better out of the dark. This follows .awards and .quotes--light, which
   already invert the same way: background var(--c-text), text var(--c-bg).

   Both FAQ sections are listed together — the home page's .faq and the
   generated .sector-faq — because they share every child class below and a
   light home FAQ with a dark sector FAQ would just look like a bug. The rules
   live in layout.css rather than pages.css since index.html does not load
   pages.css but does load this file.

   On white, --c-accent (#bfcfff) all but disappears and --c-accent-70 makes an
   invisible hairline, so the two tokens already reserved for light sections
   take over: --c-grey for secondary text, --c-rule-dark for rules.

   The +/- marker needs no override: it is drawn from currentColor.
   -------------------------------------------------------------------------- */

.faq,
.sector-faq {
  background: var(--c-text);
  color: var(--c-bg);
}

/* Spacing around a light band.

   Every dark section pads 130px top and bottom, so a dark-to-dark seam is
   260px of black. Invisible, and fine. Turn one side white and that same
   260px becomes something you can see: a slab of empty black, then a slab of
   empty white, before anything is said. Measured 260px on the home page and
   220px on a sector page.

   So the band takes the gap itself and its neighbours give theirs up. 40px
   outside plus 90px inside is 130px either side, which is the rhythm the rest
   of the page already keeps — the seam just stops being additive.

   :has() is the right tool because the section before the FAQ is not always
   the same one: a sector with no related cases has .sector-labels there
   instead. Where it is unsupported the neighbours keep their padding and the
   gap is merely large, which is what it was a moment ago. */
.faq,
.sector-faq { padding: 90px 0; }

section:has(+ .faq),
section:has(+ .sector-faq) { padding-bottom: 40px; }

.faq + section,
.sector-faq + section { padding-top: 40px; }

.faq .h2,
.faq .faq__q,
.sector-faq .h2,
.sector-faq .faq__q { color: var(--c-bg); }

/* The eyebrow keeps --c-grey, the role .award__num already uses on white.
   The answers do not: at #757575 they measured 4.61:1, which clears AA by
   0.11 and is thin for something people actually read. --c-bg-70 mirrors the
   --c-text-70 the dark version uses, and lands at 8.9:1. */
.faq .eyebrow,
.sector-faq .eyebrow { color: var(--c-grey); }

.faq .faq__a,
.sector-faq .faq__a { color: var(--c-bg-70); }

.faq .faq__item,
.sector-faq .faq__item { border-bottom-color: var(--c-rule-dark); }

.faq .faq__q:hover,
.sector-faq .faq__q:hover { color: var(--c-grey); }

@media (max-width: 991.98px) {
  .faq,
  .sector-faq { padding: 60px 0; }
  section:has(+ .faq),
  section:has(+ .sector-faq) { padding-bottom: 30px; }
  .faq + section,
  .sector-faq + section { padding-top: 30px; }
}

.faq__head {
  display: flex;
  flex-direction: column;
  gap: 14px;
  margin-bottom: 50px;
}

.faq__list { display: flex; flex-direction: column; }

.faq__item { border-bottom: 1px solid var(--c-accent-70); }

.faq__q {
  font-family: var(--f-display);
  font-size: 20px;
  font-weight: 400;
  line-height: 1.4em;
  color: var(--c-text);
  padding: 26px 44px 26px 0;
  cursor: pointer;
  list-style: none;
  position: relative;
  transition: color var(--dur-base) var(--ease-site);
}

.faq__q::-webkit-details-marker { display: none; }

.faq__q:hover { color: var(--c-accent); }

/* Plus that becomes a minus. Drawn rather than a glyph so it inherits colour. */
.faq__q::before,
.faq__q::after {
  content: "";
  position: absolute;
  right: 4px;
  top: 50%;
  width: 15px;
  height: 1.5px;
  background: currentColor;
  transition: transform 0.42s var(--ease-out-intro);
}

.faq__q::after { transform: translateY(-50%) rotate(90deg); }
.faq__q::before { transform: translateY(-50%); }

.faq__item[open] .faq__q::after { transform: translateY(-50%) rotate(0deg); }

.faq__a {
  padding: 0 60px 30px 0;
  font-family: var(--f-display);
  font-size: 16px;
  font-weight: 300;
  line-height: 1.7em;
  color: var(--c-text-70);
}

@media (max-width: 991.98px) {
  .faq__q { font-size: 17px; padding-right: 36px; }
  .faq__a { padding-right: 0; }
}
