/*
Theme Name: Vertex Digital Groep
Theme URI: https://vertexdigital.nl
Author: Vertex Digital Groep
Description: Custom theme for vertexdigital.nl - "wow" launch v2, Isadora-inspired structure reskinned in Vertex brand.
Version: 2.38.0
Text Domain: vertex-digital
*/

/* Self-hosted (not loaded live from Google's CDN, so no per-visitor request
   leaves this origin) - a single variable-font file covering weight 400-800,
   used for headings/eyebrows/nav/buttons only. Body copy stays on the fast
   system font stack for readability and payload. This is the typeface the
   brand plan (business-plan.md §11) specified but the first "wow" pass
   never actually shipped - still on system fonts until now, which read as
   generic rather than distinctive. */
@font-face{
  font-family:'Sora';font-style:normal;font-weight:400 800;font-display:swap;
  src:url('assets/img/sora-var.woff2') format('woff2');
  unicode-range:U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215;
}

/* =========================================================================
   DESIGN-SYSTEM CONSOLIDATION PASS - 2026-09-10
   =========================================================================
   Canonical palette re-derived from the REAL logo asset (assets/img/
   logo-icon-512.png), pixel-sampled programmatically (not eyeballed) along
   the mark's own navy(bottom-left)->blue(mid)->teal(top-right) gradient.
   Real drift was found and corrected: the values below are measurably
   darker/more saturated than the hand-picked "clean" hex this file
   previously carried (old --navy:#0A2540, --blue:#3B82F6, --teal:#14B8A6 -
   recognizable Tailwind-style swatches, but NOT what the shipped logo PNG
   actually contains). See vertex-digital/CLAUDE.md for the full before/
   after report. --navy-mid/--navy-deep/--navy-black are a proportional
   dark-navy shade family (same relative brightness spacing as the old
   #0d3155/#071A2E/#050f1c trio, recalculated against the new --navy so the
   footer/preloader gradients keep their original "shape") - these replace
   raw one-off hex that used to live directly in footer/preloader rules.
   --*-rgb tokens exist ONLY so rgba(var(--x-rgb),alpha) can reuse the same
   channel values for shadow/border/glow tints without a second hardcoded
   number needing to be kept in sync by hand - this is the structural fix
   for the "one color, N slightly-different hardcoded copies" drift class.

   EXPLICIT COLOR-USAGE RULES (see also klantplan-style audit in the task
   report - this is the enforced contract, not just documentation):
   - Headings (h1-h4): var(--navy) on white/--tint backgrounds (default
     rule below); #fff on dark sections (.section.bg-navy h2/h3,
     .final-cta h2) - no other heading color exists anywhere on the site.
   - Body text (p): var(--muted) on light backgrounds (default rule);
     var(--muted-dark) on dark sections (.section.bg-navy p, .final-cta p,
     .service-block-body p) - never plain gray, always one of these two.
   - Primary CTA (.btn-primary): background var(--blue), color #fff;
     hover background var(--teal). No exceptions site-wide.
   - Secondary/outline CTA: TWO variants, chosen by background context so
     the "invisible outline button on light background" bug class cannot
     recur structurally: .btn-outline (default, for plain light sections)
     is navy border+text, hover blue; .btn-outline-light (for genuinely
     dark sections/.bg-navy/.final-cta/footer) is white-ish border+text,
     hover teal. Both .hero and .page-hero are LIGHT backgrounds (2026-09-10
     light-rebalance), so `.hero .btn-outline-light,.page-hero
     .btn-outline-light` is force-overridden back to the dark-on-light
     variant - meaning even if a future component reuses the
     .btn-outline-light class inside a hero/page-hero by mistake, the
     scoped override still saves it from disappearing. Don't add a THIRD
     outline-button variant; recolor via this existing pair.
   - Section backgrounds: #fff (default/plain), var(--tint) (soft
     alternating light sections - the homepage/interior "never quite pure
     white" pattern), var(--navy) (.section.bg-navy - deliberate dark
     accent sections only, never a large default). var(--gray) remains
     defined for tag/pill chip backgrounds (.case-tags), not used as a
     section background anymore post light-rebalance.
   - Icon badges AND card-header/gradient panels: ONE standardized gradient
     formula, see VERTEX-GRADIENT below - no more separate/drifted formulas
     between these two component families.
   - Tags/badge pills: .tag-voorbeeld (var(--teal) bg, #fff text),
     .tag-portfolio (var(--navy) bg, #fff text), .case-tags span
     (var(--gray) bg, var(--navy) text) - exactly these three, everywhere.
   - Neutral UI grays that are NOT part of the 3-color brand system
     (#dbe3ea form-input borders, #c7d2dc the "old/before" comparison bar
     in .roi-compare-fill--old) are a deliberate, documented exception:
     these represent "neutral/inactive" states that should NOT be tinted
     navy/blue/teal, matching standard form/comparison-UI convention.

   VERTEX-GRADIENT (the one standardized decorative gradient formula):
     linear-gradient(45deg, var(--navy) 0%, var(--blue) 50%, var(--teal) 100%)
   45deg (not the old 135deg) because the real logo's gradient runs from
   its bottom-left navy node to its top-right teal arrowhead - CSS 45deg
   points "to top right," which is the correct direction for that same
   navy(start)->teal(end) travel. The 50% blue stop matches the logo's own
   measured node position (52% along the navy->teal axis). Checked for a
   muddy midpoint: navy->blue and blue->teal are both dark-to-bright steps
   within the same blue/cyan hue family (no orange/red inserted), so
   neither half-blend produces a gray/brown "mud" tone. Applied to both the
   icon-badge family (.card .icon, .step .num, .service-block-icon,
   .process-step-num, .cookie-banner-icon, .pledge-icon) and the card-panel
   family (.case-visual, .case-visual--portfolio, .article-card-media) -
   previously these were two different gradients (2-stop blue/teal only vs
   3-stop navy/blue/teal, and .case-visual--portfolio was even running the
   opposite direction from its own sibling .case-visual - a real bug, fixed
   here, not just a style choice).
   ========================================================================= */
:root{
  --font-display:'Sora',-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,sans-serif;
  --navy:#001C33;
  --navy-mid:#002543;
  --navy-deep:#001424;
  --navy-black:#000C16;
  --blue:#2483E4;
  --teal:#12A898;
  --navy-rgb:0,28,51;
  --blue-rgb:36,131,228;
  --teal-rgb:18,168,152;
  --gray:#F3F4F6;
  /* Pale navy/blue tint (not a neutral gray) used for "light" alternating
     sections on the homepage - matches the "never quite pure white" section
     background pattern from doitdigital.nl/gibby.it, mixed from the brand's
     own navy/blue rather than reusing --gray (kept untouched so other pages
     that already rely on --gray/.bg-gray are unaffected by this pass). */
  --tint:#EEF3F8;
  --ink:#1C2B3A;
  --muted:#5B6B7B;
  --muted-dark:#9FB1C4;
  --radius:20px;
  --shadow:0 10px 30px rgba(var(--navy-rgb),0.08);
  --shadow-hover:0 20px 48px rgba(var(--navy-rgb),0.16);
  --maxw:1200px;
}

*{box-sizing:border-box;}
html{scroll-behavior:smooth;}
body{
  margin:0;
  font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Helvetica,Arial,sans-serif;
  color:var(--ink);
  background:#fff;
  line-height:1.6;
  font-size:17px;
  -webkit-font-smoothing:antialiased;
}
img{max-width:100%;display:block;}
a{color:var(--blue);text-decoration:none;}
a:hover{color:var(--teal);}
h1,h2,h3,h4{font-family:var(--font-display);font-weight:800;color:var(--navy);line-height:1.12;letter-spacing:-0.02em;margin:0 0 .5em;}
h1{font-size:clamp(2rem,4.5vw,3.5rem);letter-spacing:-0.03em;}
/* Reduced 2026-09-10 (Zawar: heading "too rushy" vs the calmer hero-mockup
   card next to it) - was clamp(2.25rem,5vw,4.5rem)/max 72px, rendering as a
   3-4 line block whose height nearly matched the 331.6px mockup card at
   1440/1920px (measured 322.5px, a 0.97 ratio - visually as heavy as the
   image, not balanced with it). Reduced again to clamp(2rem,4vw,3.6rem)/
   max 57.6px (measured 193.5px, a 0.58 ratio) - still not enough per
   Zawar's next round of feedback ("font weight is still very huge"): at
   800 weight (inherited from the generic h1,h2,h3,h4 rule) this still
   wrapped to 3 lines at 1440/1920px and read as heavy regardless of the
   numeric size cut. Real cause was two-fold, both fixed here: (1) 800 is
   a genuinely bold weight that reads as "shouty" at any size: dropped to
   700, scoped to .hero h1 only (not the generic h1 rule, which still
   correctly serves every other heading site-wide); (2) the 700-weight
   glyphs are narrower, which alone drops the wrap from 3 lines to 2 even
   at the old 57.6px max - combined with a further clamp cut (max
   3rem/48px, min 1.75rem/28px, 3.4vw mid-factor) measured live via CDP at
   1280/1440/1920px: font resolves to 43.5-48px, height 97-108px, a
   consistent 2-line wrap, ratio 0.29-0.32 against the (also re-measured)
   331.6px mockup card - clearly reads as a calm, secondary element next
   to the card at every desktop width, not a 3-line block competing with
   it. (Matching the card's height 1:1, as literally read from this
   round's brief, would mean enlarging the heading back toward ~300px+ -
   the opposite of "still too huge"; treated that literal instruction as
   describing the earlier failure mode, not a target to hit exactly.) */
.hero h1{font-size:clamp(1.75rem,3.4vw,3rem);font-weight:700;}
h2{font-size:clamp(1.9rem,4vw,2.9rem);}
h3{font-size:1.3rem;letter-spacing:-0.01em;}
p{margin:0 0 1em;color:var(--muted);}
.container{max-width:var(--maxw);margin:0 auto;padding:0 24px;}
.section{padding:100px 0;}
.section.tight{padding:64px 0;}
.section.bg-gray{background:var(--gray);}
/* New homepage-only "light" alternating background, see --tint above. */
.section.bg-tint{background:var(--tint);}
.section.bg-navy{background:var(--navy);color:#fff;}
.section.bg-navy h2,.section.bg-navy h3{color:#fff;}
.section.bg-navy p{color:var(--muted-dark);}
.center{text-align:center;}
.eyebrow{
  display:inline-block;color:var(--teal);font-weight:700;letter-spacing:.08em;
  text-transform:uppercase;font-size:.8rem;margin-bottom:.9em;font-family:var(--font-display);
}

/* Scroll reveal - direction variants (default is an upward fade; cards in
   a row can alternate left/right instead, matching the inspiration site's
   pattern of alternating entrance directions rather than one uniform fade). */
/* No CSS transition here on purpose - GSAP now owns the reveal animation
   timing/easing directly (see reveal.js). A CSS transition on the same
   properties would fight GSAP's own easing on every inline-style update,
   producing double-eased, mushy motion instead of clean GSAP motion. This
   opacity/transform pair is just the pre-JS hidden state. */
.reveal{opacity:0;transform:translateY(28px);}
.reveal.is-visible{opacity:1;transform:none;}
.reveal-up{transform:translateY(28px);}
.reveal-left{transform:translateX(-36px);}
.reveal-right{transform:translateX(36px);}
.reveal-1{transition-delay:.05s;}
.reveal-2{transition-delay:.15s;}
.reveal-3{transition-delay:.25s;}
.reveal-4{transition-delay:.35s;}
.reveal-5{transition-delay:.45s;}
.reveal-6{transition-delay:.55s;}
@media (max-width:900px){
  /* Left/right entrance reads oddly once grids stack to one column on
     mobile - fall back to a plain upward fade there. */
  .reveal-left,.reveal-right{transform:translateY(28px);}
}

/* Header */
.site-header{
  position:sticky;top:0;z-index:100;background:rgba(255,255,255,0);
  border-bottom:1px solid transparent;transition:background-color .18s ease, border-color .18s ease, box-shadow .18s ease;
}
.site-header.is-scrolled{
  background:rgba(255,255,255,.97);backdrop-filter:saturate(180%) blur(10px);
  border-bottom:1px solid rgba(var(--navy-rgb),0.08);box-shadow:0 4px 24px rgba(var(--navy-rgb),.08);
}
.hero-page .site-header{background:rgba(7,26,46,0);position:absolute;top:0;left:0;right:0;}
/* Was color:#fff here when every .hero/.page-hero was dark navy - now that
   both are light (2026-09-10 light-rebalance pass), the transparent-header
   state needs to read against a light background instead, so it just keeps
   the same navy already set by .logo/.main-nav a - no override needed. */
/* Specificity fix: on hero pages (almost every page in this theme), the
   ".hero-page .site-header" transparent-background rule above tied in
   specificity with ".site-header.is-scrolled" and (per source order) won,
   leaving dark navy nav text over a still-dark, only-blurred header once
   scrolled - illegible. This rule is more specific (3 classes) so the
   opaque scrolled background always wins once .is-scrolled is added,
   regardless of hero-page context. */
.hero-page .site-header.is-scrolled{background:rgba(255,255,255,.97);position:fixed;}
.site-header .container{
  display:flex;align-items:center;justify-content:space-between;
  padding-top:18px;padding-bottom:18px;
}
/* white-space:nowrap added 2026-09-10 - real bug fix (not a blanket
   overflow-hiding hack): root cause was that with 8 nav items + a mega
   dropdown + CTA button all needing ~1184px of space against the header's
   ~1117-1152px real available width (measured live via CDP, deficit
   19-347px depending on viewport), the default flex-shrink algorithm's
   automatic min-width:auto let the two MULTI-WORD text items ("Vertex
   Digital", "Over ons") shrink down to their min-content (single-word)
   width and wrap - while every single-word item (Cases/Blog/Contact/etc.)
   has no such break opportunity and stayed full width, unaffected. Nowrap
   here removes that one specific escape hatch; the real space deficit is
   closed below via tighter gaps + a raised hamburger breakpoint, so nothing
   is forced to overflow once wrapping is no longer possible. */
.logo{font-family:var(--font-display);font-size:1.2rem;font-weight:800;color:var(--navy);letter-spacing:-.01em;display:flex;align-items:center;gap:10px;transition:color .25s ease;white-space:nowrap;}
.logo .vertex-mark{flex:none;}
.main-nav ul{list-style:none;display:flex;gap:22px;margin:0;padding:0;align-items:center;}
.main-nav{display:flex;align-items:center;gap:24px;}
.main-nav a{color:var(--navy);font-weight:600;font-size:.95rem;transition:color .25s ease;font-family:var(--font-display);white-space:nowrap;}
.main-nav a:hover{color:var(--blue);}
.header-cta{
  background:var(--navy);color:#fff !important;padding:12px 20px;border-radius:999px;
  font-weight:700;font-size:.9rem;white-space:nowrap;
}
.header-cta:hover{background:var(--blue);color:#fff !important;}
.nav-toggle{display:none;background:none;border:0;font-size:1.7rem;color:inherit;cursor:pointer;}

/* Mega-menu (Diensten nav item) - categorized dropdown instead of a flat
   link list, matching the categorized service-menu pattern used by rich
   Dutch IT-agency sites. Desktop only: reveals on hover/focus of the
   parent <li>; collapses away entirely on mobile, where tapping "Diensten"
   just navigates straight to the Diensten page (which carries this same
   content as page sections, so nothing is lost). */
.nav-has-mega{position:relative;}
/* Real bug fix (2026-09-11): this was display:flex;align-items:center;gap:5px
   so the "▾" arrow could sit next to the text with a small gap - but that
   switches the <a> from normal inline layout (matching every plain sibling
   link) to a flex container, which resolves its own box height from flex
   layout (24.3px) instead of the inline text/line-height metrics (19px)
   every other nav link uses - shifting "Diensten" ~3.5px higher than
   "Home"/"Cases"/etc. Confirmed via getBoundingClientRect: siblings all
   centered at y=43 with top=33.5, "Diensten" (flex) was top=30/center=42.16.
   Reverted to plain inline (byte-identical box model to every sibling link,
   confirmed all 8 items now share top=33.5/center=43 exactly) and moved the
   text-to-arrow gap onto the ::after pseudo-element's margin instead. */
.nav-has-mega > a{display:inline;}
.nav-has-mega > a::after{content:"▾";font-size:.65em;opacity:.65;margin-left:5px;}
/* .mega-menu is the invisible hoverable "bridge": it starts flush against
   the trigger link (top:100%, no gap) and uses padding-top - not a top
   offset or margin - to push the visible card down. Padding is still part
   of the same hoverable box, so the mouse never crosses dead space on its
   way from "Diensten" to the panel below (the classic dropdown bug where
   the panel vanishes before the pointer arrives). All visible chrome lives
   on the nested .mega-menu-panel instead. */
.mega-menu{
  position:absolute;top:100%;left:50%;transform:translateX(-50%);
  width:min(760px,88vw);padding-top:16px;
  opacity:0;visibility:hidden;pointer-events:none;
  transition:opacity .15s ease, transform .15s ease, visibility 0s linear .15s;
  z-index:150;
}
.mega-menu-panel{
  background:#fff;border-radius:16px;
  box-shadow:0 24px 48px rgba(var(--navy-rgb),.18);border:1px solid rgba(var(--navy-rgb),.06);
  padding:28px;display:grid;grid-template-columns:repeat(3,1fr);gap:24px;
}
/* Wider 4-category variant (Diensten mega-menu) - covers the full real
   service line-up (bouwen / koppelen & automatiseren / marketing &
   zichtbaarheid / beheren & hosten) instead of only the 3 core systems,
   matching how dense a rich Dutch IT-agency's services menu actually is. */
.mega-menu--4col{width:min(880px,92vw);}
.mega-menu--4col .mega-menu-panel{grid-template-columns:repeat(4,1fr);gap:22px;}
/* Real bug fix (2026-09-11): "no opaque background" bleed-through was never
   actually a transparency/z-index problem - .mega-menu-panel's z-index:150
   inside .site-header's own stacking context (z-index:100) already painted
   correctly above the hero's root-level content (confirmed via
   elementFromPoint hit-testing, and the hero's z-index values top out at 3,
   confined to .hero-grid's own local z:2 stacking context). The REAL bug:
   grid items default to min-width:auto, so with .mega-menu a.mega-link
   inheriting white-space:nowrap from the site-wide .main-nav a rule (a few
   lines up, added for the logo/"Over ons" wrap fix - never meant to reach
   nested .mega-link text), each unwrappable link line forced its own
   1fr column to grow to that full unwrapped width instead of sharing the
   panel's 880px evenly - measured live: computed grid-template-columns was
   "369px 252px 237px 284px" (summing to 1209px+gaps) inside an 880px panel,
   so the last column rendered ~360px outside the panel's own white
   background/box-shadow box, with nothing behind it - that uncovered
   overflow is exactly what let the hero's dashboard-mockup card and
   €1,5M+ badge show through "the panel" in the screenshot. Fixed at the
   root: allow the mega-link text to wrap again, and let each column
   actually shrink to its fair 1fr share. Verified live: grid-template-
   columns now resolves to "189px 189px 189px 189px" (fits exactly inside
   the panel), zero elements found with scrollWidth > clientWidth. */
.mega-col{min-width:0;}
.mega-menu a.mega-link,.mega-menu a.mega-link span{white-space:normal;}
@media (max-width:1180px){
  .mega-menu--4col{width:min(560px,90vw);}
  .mega-menu--4col .mega-menu-panel{grid-template-columns:repeat(2,1fr);}
}
.nav-has-mega:hover .mega-menu,.nav-has-mega:focus-within .mega-menu{
  opacity:1;visibility:visible;pointer-events:auto;transition:opacity .15s ease, transform .15s ease;
}
.mega-col-label{
  display:flex;align-items:center;gap:8px;font-size:.72rem;font-weight:800;
  letter-spacing:.06em;text-transform:uppercase;color:var(--teal);margin-bottom:14px;
}
.mega-col-label svg{width:16px;height:16px;flex:none;}
.mega-menu a.mega-link{display:block;padding:9px 0;color:var(--navy) !important;font-weight:700;font-size:.92rem;border-bottom:1px solid rgba(var(--navy-rgb),.06);}
.mega-menu a.mega-link:last-child{border-bottom:0;}
.mega-menu a.mega-link:hover{color:var(--blue) !important;}
.mega-menu a.mega-link span{display:block;font-weight:500;font-size:.8rem;color:var(--muted);margin-top:2px;}
.mega-foot{
  grid-column:1/-1;border-top:1px solid rgba(var(--navy-rgb),.08);padding-top:18px;margin-top:2px;
  display:flex;align-items:center;justify-content:space-between;gap:16px;flex-wrap:wrap;
}
.mega-foot span{color:var(--muted);font-size:.88rem;font-weight:600;}
@media (max-width:1080px){.mega-menu-panel{padding:22px;gap:18px;}}

/* Mobile toggle button - hover doesn't exist on touch, so "Diensten" alone
   navigating away meant mobile visitors never saw the mega-menu content at
   all. This separate button expands/collapses the panel in place inside
   the mobile nav stack, while the "Diensten" link itself keeps navigating
   straight to the Diensten page as before. */
.mega-toggle{
  display:none;background:none;border:0;color:inherit;font-size:.75rem;
  padding:10px 4px;margin-left:auto;cursor:pointer;
}
/* Raised from max-width:860px to 1200px on 2026-09-10 - real measurement
   (live CDP getBoundingClientRect against vertexdigital.nl, not a guess)
   showed the desktop nav's genuine content demand (logo + 8 nav items +
   mega-menu trigger + CTA button, ~1184px unwrapped) exceeds the header's
   real available width (~1117-1152px, container capped at --maxw:1200px
   minus its own 48px padding) at EVERY viewport from just above the old
   860px mobile breakpoint up to ~1160px - by as much as 347px at 900px
   wide, not just at one narrow width. That's a genuine "too much nav for
   the space" situation with 8 top-level items + a mega-dropdown + a CTA
   button, not fixable by trimming a few px of padding - the mobile
   hamburger nav (unaffected, since .main-nav is display:none there) is the
   correct fix for that whole range, matching this file's own documented
   pattern for "genuinely needed" cases. Both this block and the following
   .main-nav block below must stay in lockstep (same breakpoint) since they
   jointly define the mobile-vs-desktop nav behavior. */
@media (max-width:1200px){
  .nav-has-mega{display:flex;flex-wrap:wrap;align-items:center;}
  .nav-has-mega > a::after{display:none;}
  .mega-toggle{display:inline-flex;align-items:center;color:var(--navy) !important;}
  .mega-menu{
    order:3;flex-basis:100%;
    position:static;display:none;width:auto;padding-top:0;
    opacity:1;visibility:visible;pointer-events:auto;transform:none;transition:none;
  }
  .nav-has-mega.is-open .mega-menu{display:block;}
  .mega-menu-panel{
    display:block;background:transparent;box-shadow:none;border:0;border-radius:0;
    padding:4px 0 14px 14px;
  }
  .mega-col{margin-bottom:16px;}
  .mega-col:last-child{margin-bottom:0;}
  .mega-menu a.mega-link{padding:8px 0;}
  .mega-foot{display:none;}
}

@media (max-width:1200px){
  .main-nav{
    display:none;position:absolute;top:100%;left:0;right:0;background:#fff;
    border-bottom:1px solid rgba(var(--navy-rgb),0.08);box-shadow:var(--shadow);
  }
  /* The panel is position:absolute, so it's out of normal document flow -
     the page behind it can scroll, but that never moves this panel, and
     with no max-height/overflow of its own, content taller than the
     viewport (easily the case now the Diensten mega-menu can expand to
     13+ links) was simply unreachable below the screen edge. Give it its
     own bounded, scrollable height instead. */
  .main-nav.open{
    display:block;max-height:calc(100vh - 76px);overflow-y:auto;
    -webkit-overflow-scrolling:touch;
  }
  .main-nav ul{flex-direction:column;align-items:stretch;gap:0;padding:8px 24px 20px;}
  .main-nav li{border-top:1px solid rgba(var(--navy-rgb),0.06);}
  .main-nav li:first-child{border-top:0;}
  .main-nav a{display:block;padding:14px 0;color:var(--navy) !important;}
  .header-cta{display:inline-block;margin-top:10px;text-align:center;}
  .nav-toggle{display:block;}
  /* Was color:#fff - hero/page-hero are light now, .nav-toggle{color:inherit}
     already resolves to the surrounding navy text color correctly. */
}

/* Buttons */
.btn{
  display:inline-block;padding:15px 30px;border-radius:999px;font-weight:700;
  font-size:1rem;border:2px solid transparent;transition:.15s ease;font-family:var(--font-display);
}
.btn-primary{background:var(--blue);color:#fff;}
.btn-primary:hover{background:var(--teal);color:#fff;}
.btn-outline{border-color:var(--navy);color:var(--navy);}
.btn-outline:hover{border-color:var(--blue);color:var(--blue);}
.btn-outline-light{border-color:rgba(255,255,255,.5);color:#fff;}
.btn-outline-light:hover{border-color:var(--teal);color:var(--teal);}
/* .btn-outline-light was designed for a dark hero backdrop (white border,
   white text) - .hero and .page-hero are both light now (2026-09-10
   light-rebalance), so every hero's secondary CTA needs a dark-on-light
   variant instead, without touching .btn-outline-light itself (it's still
   correctly used as-is on the site's remaining legitimately-dark bg-navy
   sections further down various pages). */
.hero .btn-outline-light,.page-hero .btn-outline-light{border-color:rgba(var(--navy-rgb),.28);color:var(--navy);}
.hero .btn-outline-light:hover,.page-hero .btn-outline-light:hover{border-color:var(--blue);color:var(--blue);}
.btn-white{background:#fff;color:var(--navy);}
.btn-white:hover{background:var(--teal);color:#fff;}
.btn-row{display:flex;gap:16px;flex-wrap:wrap;}

/* Hero - light background (2026-09-10 light-rebalance: Zawar reviewed
   do-it's real pages directly and confirmed they're almost entirely
   light/white, with the brand blue only ever appearing as an accent -
   buttons, small eyebrow bars, hover states, chart highlights - never as a
   large solid-color block background. This was previously a dark navy
   full-bleed hero; now light/tint with the same dot-grid texture and the
   canvas network/glow blobs recolored as the animated brand accent instead
   of the block color itself). */
.hero{
  position:relative;overflow:hidden;padding:170px 0 120px;
  background-image:
    radial-gradient(rgba(var(--blue-rgb),.14) 1px, transparent 1.6px),
    radial-gradient(ellipse at top,#fff 0%, var(--tint) 75%, var(--tint) 100%);
  background-size:26px 26px, 100% 100%;
  background-position:0 0, 0 0;
  color:var(--ink);
}
/* Was #vertex-network (one id per page) - renamed to a class 2026-09-10 so
   the same canvas element/behaviour can appear more than once on a page
   (dark bg-navy sections, footer) via reveal.js's initNetworkCanvas
   factory, not just the single hero/page-hero instance. */
.vertex-canvas{position:absolute;inset:0;z-index:1;pointer-events:none;}

/* Two-column hero layout (copy left, dashboard-mockup visual right) -
   matches the doitdigital.nl/gibby.it hero split instead of the previous
   single centered column. Stacks to one column on mobile. */
.hero-grid{
  position:relative;z-index:2;display:grid;grid-template-columns:1.05fr .95fr;
  gap:56px;align-items:center;text-align:left;
}
/* Grid items default to min-width:auto, which lets their intrinsic content
   width (here, the large H1) refuse to shrink below its own natural size,
   overflowing the assigned track instead of wrapping - a classic CSS Grid
   trap. min-width:0 lets them shrink to fit their column like normal block
   content would (real bug, caught via computed-width inspection on a
   390px viewport: h1 rendered at 420px and got clipped by .hero's own
   overflow:hidden instead of wrapping). */
.hero-grid > *{min-width:0;}
.hero-copy{max-width:560px;}
.hero-copy .lead{margin:0 0 1.8em;max-width:480px;}
.hero-copy .btn-row{justify-content:flex-start;}
@media (max-width:960px){
  .hero-grid{grid-template-columns:1fr;text-align:center;gap:48px;}
  .hero-copy{max-width:100%;margin:0 auto;}
  .hero-copy .lead{margin:0 auto 1.8em;}
  .hero-copy .btn-row{justify-content:center;}
  .hero-visual{max-width:420px;width:100%;margin:0 auto;}
}

/* Dashboard-mockup hero visual: a rounded card with a small illustrative
   bar chart (one bar highlighted in the accent color) plus two floating
   badge pills anchored to its corners - same structural pattern as
   doitdigital.nl's hero mockup, honestly labeled "Illustratief" since this
   is not real client data. */
/* Was a translucent glass card (rgba(255,255,255,.06) + blur) designed to
   sit on the old dark hero backdrop - now that .hero is light, rewritten as
   a real opaque white dashboard card (matching .card/.contact-form-card's
   shadow language), which is also closer to how doitdigital.nl's own hero
   mockup actually looks (a real white UI card on a light page). */
.hero-mockup{
  position:relative;background:#fff;border:1px solid rgba(var(--navy-rgb),.06);
  border-radius:24px;padding:28px 26px 40px;box-shadow:var(--shadow-hover);
}
.hero-mockup-header{display:flex;align-items:center;gap:10px;margin-bottom:18px;}
.hero-mockup-title{font-family:var(--font-display);font-weight:700;color:var(--navy);font-size:.95rem;}
.hero-mockup-tag{
  margin-left:auto;background:var(--tint);color:var(--muted);
  font-size:.68rem;font-weight:700;letter-spacing:.05em;text-transform:uppercase;
  padding:4px 10px;border-radius:999px;
}
.mockup-chart{
  display:flex;align-items:flex-end;gap:10px;height:184px;
  padding:0 4px 4px;border-bottom:1px solid rgba(var(--navy-rgb),.08);
}
.mockup-bar{
  flex:1;height:var(--h,40%);border-radius:6px 6px 0 0;
  background:var(--tint);
}
.mockup-bar--highlight{background:linear-gradient(180deg,var(--blue),var(--teal));}
.mockup-chart-labels{display:flex;gap:10px;padding:8px 4px 0;}
.mockup-chart-labels span{flex:1;text-align:center;font-size:.65rem;color:var(--muted);letter-spacing:.02em;}

.hero-badge{
  position:absolute;display:flex;align-items:center;gap:8px;
  background:#fff;color:var(--navy);border-radius:18px;padding:10px 14px;
  border:1px solid rgba(var(--navy-rgb),.06);
  box-shadow:0 16px 32px rgba(var(--navy-rgb),.32);z-index:3;
}
.hero-badge--stat{top:-46px;right:-10px;flex-direction:column;align-items:flex-start;gap:2px;border-radius:20px;}
.hero-badge-num{font-family:var(--font-display);font-weight:800;color:var(--navy);font-size:1.15rem;line-height:1;}
.hero-badge-label{font-size:.72rem;color:var(--muted);line-height:1.3;}
.hero-badge--stat .hero-badge-label{max-width:150px;}
.hero-badge--live{bottom:-18px;left:-14px;max-width:230px;}
.hero-badge--live .hero-badge-label{max-width:170px;}
.hero-badge--live em{color:var(--muted);font-style:italic;}
.live-dot{
  width:9px;height:9px;border-radius:50%;background:var(--teal);flex:none;
  box-shadow:0 0 0 0 rgba(var(--teal-rgb),.6);animation:vertexLiveDot 1.8s ease-out infinite;
}
@keyframes vertexLiveDot{
  0%{box-shadow:0 0 0 0 rgba(var(--teal-rgb),.55);}
  70%{box-shadow:0 0 0 9px rgba(var(--teal-rgb),0);}
  100%{box-shadow:0 0 0 0 rgba(var(--teal-rgb),0);}
}
@media (prefers-reduced-motion: reduce){.live-dot{animation:none;}}
@media (max-width:960px){
  .hero-badge--stat{top:-38px;right:6px;}
  .hero-badge--live{bottom:-14px;left:6px;}
}
@media (max-width:520px){
  .hero-badge{position:static;margin-top:14px;box-shadow:none;border:1px solid rgba(var(--navy-rgb),.08);width:100%;}
  .hero-mockup{overflow:visible;}
}
/* On very narrow phones "Vertex Dashboard" (wrapped to 2 lines) leaves no
   room for the "Illustratief" tag on the same row, pushing it past the
   card edge - let it wrap to its own row there instead of overflowing. */
@media (max-width:400px){
  .hero-mockup-header{flex-wrap:wrap;row-gap:6px;}
  .hero-mockup-tag{margin-left:0;}
}

/* Small variant of the hero centerpiece mark, relocated into the mockup
   card header - keeps the existing mouse-parallax/scroll-fade effect
   (reveal.js targets the same #js-hero-mark id regardless of where it
   lives in the DOM) instead of removing it. */
.hero-mark.hero-mark--card{width:34px;height:35px;margin:0;flex:none;transform:none;opacity:1;}
.hero-mark--card .hero-mark-glow{inset:-10px;filter:blur(12px);animation:none;opacity:.55;}
/* Opacity brought down from .35/.28 (tuned for a dark backdrop, where a
   glow needs to be strong to read at all) since the same glow over a light
   background reads as color at a much lower opacity - kept as a soft
   animated brand-color wash behind the hero content, not a colored block. */
.hero::before{
  content:"";position:absolute;inset:-6%;
  background:
    radial-gradient(600px 420px at 22% 15%, rgba(var(--blue-rgb),.16), transparent 60%),
    radial-gradient(700px 460px at 82% 30%, rgba(var(--teal-rgb),.14), transparent 60%);
  filter:blur(10px);pointer-events:none;
  transform:translate(var(--px,0),var(--py,0));
  transition:transform .4s cubic-bezier(.2,.7,.2,1);
  will-change:transform;
}
/* Subtle grain texture for depth on dark sections, matching the premium
   reference site rather than a flat gradient. Cheap CSS-only noise via an
   embedded SVG feTurbulence filter, no image asset needed. Scoped to
   .section.bg-navy only now (2026-09-10) - .hero/.page-hero are light
   backgrounds since the light-rebalance pass, and this dark-tuned overlay
   blend mode isn't intended for them any more. */
.section.bg-navy::after{
  content:"";position:absolute;inset:0;pointer-events:none;z-index:1;opacity:.05;mix-blend-mode:overlay;
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='120' height='120'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='2' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
}
.section.bg-navy,.page-hero{position:relative;overflow:hidden;}
/* bg-navy sections now optionally carry a .vertex-canvas (Fix 3, 2026-09-10)
   as a direct child before .container - the canvas itself is z-index:1, so
   the actual content column needs to sit above it explicitly, same pattern
   already used for .hero/.page-hero's own .container. */
.section.bg-navy>.container{position:relative;z-index:2;}
/* Widened from the old single-column max-width:860px/text-align:center to
   fit the new two-column .hero-grid (copy + dashboard-mockup visual). The
   stat-strip below stays centered via its own explicit rule further down. */
.hero .container{position:relative;max-width:1120px;text-align:center;z-index:2;}
.hero .eyebrow{color:var(--teal);}
.hero h1{color:var(--navy);}
.hero p.lead{font-size:1.25rem;max-width:660px;margin:0 auto 2.2em;color:var(--muted);}
.hero-mark{
  position:relative;margin:0 auto 32px;width:200px;height:204px;
  display:flex;align-items:center;justify-content:center;
  will-change:transform,opacity;
  transform:
    translate(var(--mx,0px), calc(var(--my,0px) - (var(--heroScroll,0) * 40px)))
    scale(calc(1 - (var(--heroScroll,0) * 0.12)));
  opacity:calc(1 - (var(--heroScroll,0) * 0.85));
}
@media (prefers-reduced-motion: reduce){ .hero-mark{transform:none !important;opacity:1 !important;} }
.hero-mark .vertex-mark{width:100%;height:auto;position:relative;z-index:2;}
.hero-mark-glow{
  position:absolute;inset:-70px;z-index:1;pointer-events:none;
  background:radial-gradient(circle, rgba(var(--blue-rgb),.45) 0%, rgba(var(--teal-rgb),.28) 45%, transparent 72%);
  filter:blur(28px);animation:vertexGlowPulse 4.5s ease-in-out infinite;
}
@keyframes vertexGlowPulse{
  0%,100%{opacity:.7;transform:scale(1);}
  50%{opacity:1;transform:scale(1.12);}
}
.trust-line{margin-top:32px;font-size:.9rem;color:var(--muted);}
.trust-line strong{color:var(--navy);}

@keyframes vertexPulse{
  0%,100%{filter:drop-shadow(0 0 14px rgba(var(--blue-rgb),.55)) drop-shadow(0 0 4px rgba(var(--teal-rgb),.4));}
  50%{filter:drop-shadow(0 0 34px rgba(var(--teal-rgb),.8)) drop-shadow(0 0 10px rgba(var(--blue-rgb),.65));}
}
.vertex-mark--glow{animation:vertexPulse 3.2s ease-in-out infinite;}
@media (prefers-reduced-motion: reduce){
  .hero-mark-glow, .vertex-mark--glow{animation:none;}
}

/* Stat strip */
.stat-strip{display:grid;grid-template-columns:repeat(3,1fr);gap:24px;margin-top:64px;position:relative;z-index:2;}
@media (max-width:700px){.stat-strip{grid-template-columns:1fr;}}
.stat-strip .stat{
  background:#fff;border:1px solid rgba(var(--navy-rgb),.06);border-radius:var(--radius);
  padding:28px 20px;box-shadow:var(--shadow);
}
.stat .num{font-size:2.3rem;font-weight:800;letter-spacing:-0.02em;font-family:var(--font-display);
  background:linear-gradient(45deg,var(--navy) 0%,var(--blue) 50%,var(--teal) 100%);-webkit-background-clip:text;background-clip:text;color:transparent;}
.stat .label{font-size:.88rem;color:var(--muted);margin-top:4px;}

/* Horizontal marquee ticker (matches the repeated-keyword strip pattern on
   webelephant.nl / isadoradigitalagency.com) - CSS-only infinite scroll,
   content duplicated once so translateX(-50%) loops seamlessly.
   margin-top added 2026-09-10 (Zawar: it sat flush against the stat-card
   row above with zero gap, reading as attached/cramped) - a clear gap
   before its own top border now separates it from .stat-strip. */
.marquee{
  overflow:hidden;white-space:nowrap;position:relative;margin-top:56px;
  -webkit-mask-image:linear-gradient(90deg,transparent,#000 6%,#000 94%,transparent);
  mask-image:linear-gradient(90deg,transparent,#000 6%,#000 94%,transparent);
  padding:22px 0;border-top:1px solid rgba(var(--navy-rgb),.08);border-bottom:1px solid rgba(var(--navy-rgb),.08);
}
.marquee-track{display:inline-flex;width:max-content;animation:vertexMarquee 32s linear infinite;}
.marquee:hover .marquee-track{animation-play-state:paused;}
.marquee-track span{
  font-family:var(--font-display);font-weight:800;font-size:1.3rem;letter-spacing:.02em;
  white-space:nowrap;color:var(--navy);opacity:.55;padding:0 28px;display:inline-flex;align-items:center;gap:28px;
}
.marquee-track span::after{content:"◆";font-size:.7rem;color:var(--teal);opacity:.8;}
@keyframes vertexMarquee{from{transform:translateX(0);}to{transform:translateX(-50%);}}
@media (prefers-reduced-motion: reduce){.marquee-track{animation:none;}}

/* Needs-based navigator cards (matches the "wat heeft je bedrijf nodig"
   pattern on wauw.nl) - each card leads with the client's own goal, not
   our service name, and points straight at the matching dedicated page. */
.need-card{
  display:block;background:#fff;border-radius:var(--radius);padding:30px 28px;box-shadow:var(--shadow);
  border:1px solid rgba(var(--navy-rgb),0.06);text-decoration:none;height:100%;
  transition:transform .3s cubic-bezier(.2,.7,.2,1), box-shadow .3s ease, border-color .3s ease;
}
.need-card:hover{box-shadow:var(--shadow-hover);transform:translateY(-6px);border-color:rgba(var(--blue-rgb),.25);}
.need-card .need-label{display:block;color:var(--muted);font-size:.95rem;margin-bottom:2px;}
.need-card h3{margin:0 0 10px;font-size:1.3rem;background:linear-gradient(45deg,var(--navy) 0%,var(--blue) 50%,var(--teal) 100%);-webkit-background-clip:text;background-clip:text;color:transparent;}
.need-card .need-arrow{display:inline-flex;align-items:center;gap:6px;color:var(--blue);font-weight:700;font-size:.92rem;margin-top:6px;}
.need-card:hover .need-arrow{color:var(--teal);}

/* Cards grid */
.grid{display:grid;gap:28px;}
.grid-2{grid-template-columns:repeat(2,1fr);}
.grid-3{grid-template-columns:repeat(3,1fr);}
.grid-4{grid-template-columns:repeat(4,1fr);}
@media (max-width:900px){.grid-2,.grid-3,.grid-4{grid-template-columns:1fr;}}

.card{
  display:block;background:#fff;border-radius:var(--radius);padding:36px 30px;box-shadow:var(--shadow);
  border:1px solid rgba(var(--navy-rgb),0.06);transition:transform .3s cubic-bezier(.2,.7,.2,1), box-shadow .3s ease, border-color .3s ease;
}
.card h3{color:var(--navy);}
.card:hover{box-shadow:var(--shadow-hover);transform:translateY(-6px);border-color:rgba(var(--blue-rgb),0.25);}
.card .icon{
  width:58px;height:58px;border-radius:16px;display:flex;align-items:center;justify-content:center;
  background:linear-gradient(45deg,var(--navy) 0%,var(--blue) 50%,var(--teal) 100%);
  box-shadow:inset 0 1px 0 rgba(255,255,255,.35), inset 0 -6px 10px rgba(var(--navy-rgb),.18), 0 8px 18px rgba(var(--blue-rgb),.25);
  color:#fff;font-size:1.5rem;margin-bottom:22px;transition:transform .3s cubic-bezier(.2,.7,.2,1);
}
.vicon{display:block;}
.case-visual .case-icon{display:flex;transition:transform .3s cubic-bezier(.2,.7,.2,1);}
.case-card:hover .case-icon{transform:scale(1.1) rotate(-4deg);}
.card:hover .icon{transform:scale(1.08) rotate(-4deg);}
.card h3{margin-bottom:.5em;font-size:1.35rem;}

/* Steps */
.steps{display:grid;grid-template-columns:repeat(4,1fr);gap:24px;}
@media (max-width:900px){.steps{grid-template-columns:1fr;}}

/* Used where a 5-item capability grid needs a 3+2 layout instead of the
   default 4-column .steps (which would wrap 4-then-1, looking unbalanced). */
.steps.steps-3col{grid-template-columns:repeat(3,1fr);}
@media (max-width:900px){.steps.steps-3col{grid-template-columns:1fr;}}
.step{
  /* Was a translucent glass card tuned for a dark bg-navy backdrop -
     .step only appears on the homepage's "Drie systemen" and the Cases
     page's "Onze expertise" grid, both converted to a light background in
     the 2026-09-10 light-rebalance, so this is now a plain light card
     matching .card's shadow language. */
  position:relative;background:#fff;border-radius:var(--radius);padding:32px 26px;
  border:1px solid rgba(var(--navy-rgb),.06);box-shadow:var(--shadow);
  transition:transform .3s cubic-bezier(.2,.7,.2,1), box-shadow .3s ease, border-color .3s ease;
}
.step:hover{
  transform:translateY(-6px);box-shadow:var(--shadow-hover);
  border-color:rgba(var(--teal-rgb),.35);
}
.step .num{
  width:46px;height:46px;border-radius:50%;
  background:linear-gradient(45deg,var(--navy) 0%,var(--blue) 50%,var(--teal) 100%);color:#fff;
  box-shadow:inset 0 1px 0 rgba(255,255,255,.35), inset 0 -6px 10px rgba(var(--navy-rgb),.25), 0 8px 18px rgba(var(--blue-rgb),.3);
  display:flex;align-items:center;justify-content:center;font-weight:800;margin-bottom:18px;font-size:1.2rem;
  transition:transform .3s cubic-bezier(.2,.7,.2,1);
}
.step:hover .num{transform:scale(1.1) rotate(-4deg);}

/* Service deep-dive blocks (Diensten page) - icon + heading + body laid
   out side by side, for a much longer, more explanatory page than a plain
   card grid allows. */
.service-block{
  display:flex;gap:28px;align-items:flex-start;
  padding:36px 0;border-bottom:1px solid rgba(255,255,255,.08);
}
.service-block:last-of-type{border-bottom:0;}
.service-block-icon{
  flex:none;width:64px;height:64px;border-radius:18px;display:flex;align-items:center;justify-content:center;
  background:linear-gradient(45deg,var(--navy) 0%,var(--blue) 50%,var(--teal) 100%);color:#fff;
  box-shadow:inset 0 1px 0 rgba(255,255,255,.35), inset 0 -6px 10px rgba(var(--navy-rgb),.2), 0 8px 20px rgba(var(--blue-rgb),.3);
}
.service-block-body{flex:1;min-width:0;}
.service-block-body p{color:var(--muted-dark);}
.service-block-body strong{color:#fff;}
.service-block-body .list-check li{color:var(--muted-dark);}
@media (max-width:700px){.service-block{flex-direction:column;gap:16px;}}

/* Process steps (Werkwijze page) - numbered badge + explanatory body,
   same layout family as service-block but on light sections. */
.process-step{
  display:flex;gap:28px;align-items:flex-start;
  padding:32px 0;border-bottom:1px solid rgba(var(--navy-rgb),.08);
}
.process-step:last-of-type{border-bottom:0;}
.process-step-num{
  flex:none;width:56px;height:56px;border-radius:50%;display:flex;align-items:center;justify-content:center;
  background:linear-gradient(45deg,var(--navy) 0%,var(--blue) 50%,var(--teal) 100%);color:#fff;font-weight:800;font-size:1.4rem;
  box-shadow:inset 0 1px 0 rgba(255,255,255,.35), inset 0 -6px 10px rgba(var(--navy-rgb),.18), 0 8px 18px rgba(var(--blue-rgb),.25);
}
.process-step-body{flex:1;min-width:0;}
.process-step-body h2{margin-top:2px;}
@media (max-width:700px){.process-step{flex-direction:column;gap:16px;}}

/* FAQ list - deliberately plain expanded Q&A (not an accordion) so every
   answer is present in the DOM without JS, which also keeps it crawlable
   for search engines. */
.faq-list{max-width:820px;margin:0 auto;}
.faq-item{padding:26px 0;border-bottom:1px solid rgba(var(--navy-rgb),.1);}
.faq-item:last-child{border-bottom:0;}
.faq-item h3{margin-bottom:.4em;font-size:1.15rem;}
.faq-item p{margin:0;}

/* Technology/partner badges (Cases page) - plain text chips rather than
   official trademarked logos, since we don't hold logo-usage rights for
   these brands and a text badge conveys the same information without a
   trademark question. */
.tech-group{max-width:900px;margin:0 auto 32px;}
.tech-group:last-child{margin-bottom:0;}
.tech-group h3{font-size:.95rem;text-transform:uppercase;letter-spacing:.04em;color:var(--muted);margin-bottom:14px;}
.tech-badges{display:flex;flex-wrap:wrap;gap:10px;}
.tech-badges span{
  background:#fff;border:1.5px solid rgba(var(--navy-rgb),.1);color:var(--navy);
  font-weight:700;font-size:.9rem;padding:9px 18px;border-radius:999px;
  transition:border-color .2s ease, transform .2s ease;
}
.tech-badges span:hover{border-color:var(--blue);transform:translateY(-2px);}

/* Partner/technology logo grid (Cases page) - bordered cells on a dark
   section, real logo + name in each, matching the reference site's
   "Partners" section pattern rather than plain text pills. */
.partner-grid{
  display:grid;grid-template-columns:repeat(4,1fr);
  border:1px solid rgba(255,255,255,.12);border-radius:var(--radius);overflow:hidden;
}
@media (max-width:900px){.partner-grid{grid-template-columns:repeat(2,1fr);}}
@media (max-width:520px){.partner-grid{grid-template-columns:1fr;}}
.partner-card{
  display:flex;flex-direction:column;align-items:center;justify-content:center;gap:12px;
  padding:32px 20px;border-right:1px solid rgba(255,255,255,.12);border-bottom:1px solid rgba(255,255,255,.12);
  color:#fff;transition:background-color .2s ease;
}
.partner-card:hover{background:rgba(255,255,255,.04);}
.partner-card svg{opacity:.92;}
.partner-card span{font-size:.85rem;font-weight:600;color:var(--muted-dark);text-align:center;}
.partner-card--text span{font-size:1rem;font-weight:700;color:#fff;}
/* Trim the trailing border on the last card of each visual row so the grid
   reads as clean cells, not a stray line past the final item. */
.partner-grid .partner-card:nth-child(4n){border-right:0;}
@media (max-width:900px){.partner-grid .partner-card:nth-child(4n){border-right:1px solid rgba(255,255,255,.12);} .partner-grid .partner-card:nth-child(2n){border-right:0;}}
@media (max-width:520px){.partner-grid .partner-card{border-right:0 !important;}}

/* Light variant (2026-09-10 light-rebalance) - added as a modifier rather
   than changing .partner-grid/.partner-card themselves, since those are
   still correctly used as-is on several other pages' remaining dark
   bg-navy sections outside this pass's scope (out of scope for this round:
   Diensten, Lead/Business Systeem, and the other individual service
   pages). Used on the homepage, Cases, and Automatisering Systeem's
   partner sections once those were converted to a light background. */
.partner-grid--light{border-color:rgba(var(--navy-rgb),.1);}
.partner-grid--light .partner-card{color:var(--navy);border-right-color:rgba(var(--navy-rgb),.08);border-bottom-color:rgba(var(--navy-rgb),.08);}
.partner-grid--light .partner-card:hover{background:rgba(var(--navy-rgb),.03);}
.partner-grid--light .partner-card span{color:var(--muted);}
.partner-grid--light .partner-card--text span{color:var(--navy);}
@media (max-width:900px){.partner-grid--light .partner-card:nth-child(4n){border-right-color:rgba(var(--navy-rgb),.08);}}
/* Real contrast bug caught via screenshot QA (2026-09-10): OpenClaw's own
   logo asset is a pale/white mascot, correctly invisible-proof on the old
   dark partner cards but nearly invisible against this new light variant.
   Rather than recolor the actual asset (it has real internal color detail,
   not a flat white silhouette - inverting risks distorting it), give it
   the same small dark-chip backdrop already used elsewhere on this exact
   page for a light-card-with-a-dark-widget-inside pattern (.mini-mockup). */
.partner-grid--light .partner-card img[alt="OpenClaw"]{background:var(--navy);padding:6px;}

/* Placeholder / notice boxes */
.notice{
  border:2px dashed var(--teal);background:rgba(var(--teal-rgb),.06);border-radius:var(--radius);
  padding:30px;color:var(--ink);
}
.tag-voorbeeld{
  display:inline-block;background:var(--teal);color:#fff;font-size:.72rem;font-weight:800;
  letter-spacing:.05em;text-transform:uppercase;padding:5px 12px;border-radius:999px;margin-bottom:12px;
}
.tag-portfolio{
  display:inline-block;background:var(--navy);color:#fff;font-size:.72rem;font-weight:800;
  letter-spacing:.05em;text-transform:uppercase;padding:5px 12px;border-radius:999px;margin-bottom:12px;
}
.case-visual--portfolio{background:linear-gradient(45deg,var(--navy) 0%,var(--blue) 50%,var(--teal) 100%);}

/* Full case-study narrative blocks (Cases page portfolio section) - a
   bigger, story-format layout (situatie/aanpak/resultaat) instead of the
   compact card+bullet-list version used as a teaser on Home. */
.case-story{
  display:flex;gap:32px;align-items:flex-start;
  padding:36px 0;border-bottom:1px solid rgba(var(--navy-rgb),.08);
}
.case-story:last-of-type{border-bottom:0;}
.case-story-visual{
  flex:none;width:96px;height:96px;border-radius:22px;display:flex;align-items:center;justify-content:center;
  color:#fff;box-shadow:0 12px 28px rgba(var(--navy-rgb),.18);
}
.case-story-body{flex:1;min-width:0;}
.case-story-body p strong{color:var(--navy);}
@media (max-width:700px){.case-story{flex-direction:column;gap:18px;}}

/* Image-forward case cards */
.case-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:26px;}
@media (max-width:900px){.case-grid{grid-template-columns:1fr;}}
.case-card{
  border-radius:var(--radius);overflow:hidden;background:#fff;box-shadow:var(--shadow);
  border:1px solid rgba(var(--navy-rgb),0.06);transition:.25s ease;
}
.case-card:hover{box-shadow:var(--shadow-hover);transform:translateY(-4px);}
.case-visual{
  height:180px;display:flex;align-items:center;justify-content:center;position:relative;overflow:hidden;
  background:linear-gradient(45deg,var(--navy) 0%,var(--blue) 50%,var(--teal) 100%);
  transition:transform .8s cubic-bezier(.2,.7,.2,1);
}
/* Bug fix: .case-peek sits at bottom:0 then translateY(100%) to hide below
   the visual - but without overflow:hidden HERE (not just on the parent
   .case-card), that translated position lands exactly where .case-body's
   content starts, overlapping the tag-voorbeeld/tag-portfolio badge. */
/* Slow (0.8s) zoom-in on hover, matching the reference site's image-hover
   treatment - .case-card (the overflow:hidden parent) keeps this cropped
   to the rounded corners instead of spilling out. */
.case-card:hover .case-visual{transform:scale(1.08);}
.case-visual .case-index{position:absolute;top:14px;left:16px;color:#fff;font-weight:800;font-size:.85rem;opacity:.85;letter-spacing:.05em;}
.case-visual .case-icon{font-size:2.4rem;color:#fff;opacity:.9;}
/* Label that slides up from below on hover, matching the reference site's
   card-reveal pattern instead of a static caption. */
.case-peek{
  position:absolute;left:0;right:0;bottom:0;padding:11px 16px;
  background:rgba(5,15,26,.62);backdrop-filter:blur(4px);
  color:#fff;font-weight:700;font-size:.82rem;text-align:center;letter-spacing:.01em;
  transform:translateY(100%);transition:transform .35s cubic-bezier(.2,.7,.2,1);
}
.case-card:hover .case-peek{transform:translateY(0);}
@media (prefers-reduced-motion: reduce){
  .case-visual,.case-peek{transition:none;}
}
.case-body{padding:26px 24px;}
.case-tags{display:flex;flex-wrap:wrap;gap:8px;margin-top:14px;}
.case-tags span{background:var(--gray);color:var(--navy);font-size:.78rem;font-weight:700;padding:5px 11px;border-radius:999px;}

/* Team */
.team-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:24px;}
@media (max-width:900px){.team-grid{grid-template-columns:1fr;}}
.avatar{
  width:64px;height:64px;border-radius:50%;background:linear-gradient(45deg,var(--navy) 0%,var(--blue) 50%,var(--teal) 100%);
  color:#fff;display:flex;align-items:center;justify-content:center;font-weight:800;font-size:1.3rem;margin-bottom:16px;
}

/* Final CTA */
.final-cta{
  position:relative;overflow:hidden;background:var(--navy);border-radius:28px;padding:72px 40px;text-align:center;color:#fff;
}
.final-cta::before{
  content:"";position:absolute;inset:0;
  background:radial-gradient(500px 300px at 50% 0%, rgba(var(--blue-rgb),.35), transparent 70%);
}
.final-cta > *{position:relative;z-index:1;}
.final-cta h2{color:#fff;}
.final-cta p{color:var(--muted-dark);}
.final-cta .list-check li{color:var(--muted-dark);}
.final-cta .list-check li::before{color:var(--teal);}

/* Footer (Fix 4, 2026-09-10: Zawar wanted the footer's own flat solid color
   changed - was a plain var(--navy-deep) block, visually just "the dark
   navy continuing forever" with no differentiation from the rest of the
   site's dark sections - plus the same particle-network canvas treatment
   as Fix 3. Reworked to a subtle angled gradient using shades already
   established elsewhere in the design system (the same --navy-mid/--navy-deep/
   --navy-black tokens already used by the homepage clock-preloader background -
   recalculated 2026-09-10 from raw #0d3155/#050f1c hex to real logo-derived
   values, see the :root comment block above),
   not an arbitrary new color, so it reads as a deliberate variation on the
   existing palette rather than an unrelated new block. position:relative
   +overflow:hidden added so its own .vertex-canvas (inserted as the first
   child in footer.php) can sit inset:0 behind the real content, same
   pattern as .section.bg-navy above. */
.site-footer{
  position:relative;overflow:hidden;
  background:linear-gradient(165deg,var(--navy-mid) 0%, var(--navy-deep) 55%, var(--navy-black) 100%);
  color:var(--muted-dark);padding:60px 0 30px;font-size:.92rem;
}
.site-footer>.container{position:relative;z-index:2;}

/* Scroll-to-top button - fixed bottom-right, hidden until scrolled down a
   bit (toggled in reveal.js), always above everything else. */
.scroll-top-btn{
  position:fixed;right:24px;bottom:24px;z-index:200;
  width:48px;height:48px;border-radius:50%;border:0;cursor:pointer;
  background:var(--navy);color:#fff;
  display:flex;align-items:center;justify-content:center;
  box-shadow:0 8px 22px rgba(var(--navy-rgb),.28);
  opacity:0;transform:translateY(14px);pointer-events:none;
  transition:opacity .25s ease, transform .25s ease, background-color .2s ease;
}
.scroll-top-btn.is-visible{opacity:1;transform:none;pointer-events:auto;}
.scroll-top-btn:hover{background:var(--blue);}
@media (max-width:600px){.scroll-top-btn{right:16px;bottom:16px;width:44px;height:44px;}}
@media (prefers-reduced-motion: reduce){.scroll-top-btn{transition:opacity .15s ease;}}

/* Scroll-progress ring (doitdigital.nl pattern) - a thin ring around the
   existing scroll-to-top button that fills as the visitor scrolls down the
   page, driven by reveal.js setting stroke-dashoffset on .scroll-progress-
   ring-fill. Static fallback values below (a fully-empty ring) apply if JS
   fails, so the button never shows a misleadingly-full/solid ring. */
.scroll-progress-ring{position:absolute;inset:0;width:100%;height:100%;transform:rotate(-90deg);pointer-events:none;}
.scroll-progress-ring-track{fill:none;stroke:rgba(255,255,255,.2);stroke-width:3;}
.scroll-progress-ring-fill{
  fill:none;stroke:var(--teal);stroke-width:3;stroke-linecap:round;
  stroke-dasharray:132;stroke-dashoffset:132;
  transition:stroke-dashoffset .1s linear;
}
@media (prefers-reduced-motion: reduce){.scroll-progress-ring-fill{transition:none;}}
.site-footer a{color:#fff;}
.site-footer a:hover{color:var(--teal);}
.footer-grid{display:grid;grid-template-columns:2fr 1fr 1fr;gap:32px;margin-bottom:36px;}
@media (max-width:700px){.footer-grid{grid-template-columns:1fr;}}
.footer-grid h4{color:#fff;font-size:.85rem;text-transform:uppercase;letter-spacing:.05em;margin-bottom:14px;}
.footer-grid ul{list-style:none;margin:0;padding:0;}
.footer-grid li{margin-bottom:8px;}
.footer-bottom{border-top:1px solid rgba(255,255,255,.1);padding-top:20px;font-size:.82rem;color:var(--muted-dark);}

/* Page hero (interior pages, ~15 templates share this one component) -
   converted from a dark navy full-bleed background to light (2026-09-10,
   Zawar's explicit direction after reviewing do-it's real pages directly:
   light background everywhere, brand blue/teal only ever as an accent -
   never as the section's own block color). The particle-network canvas
   and centerpiece glow keep the brand colors as the animated accent this
   component is built around; only the flat block color underneath and the
   text contrast change. */
.page-hero{
  padding:150px 0 70px;position:relative;overflow:hidden;color:var(--ink);
  background:radial-gradient(ellipse at top,#fff 0%, var(--tint) 70%, var(--tint) 100%);
}
.page-hero::before{
  content:"";position:absolute;inset:0;
  background:radial-gradient(600px 380px at 50% 0%, rgba(var(--blue-rgb),.12), transparent 65%);
  pointer-events:none;
}
.page-hero .container{position:relative;max-width:780px;text-align:center;z-index:2;}
.page-hero .eyebrow{color:var(--teal);}
/* Explicit override added 2026-09-10 (was previously just inheriting the
   generic h1{clamp(2rem,4.5vw,3.5rem)} rule, max 56px) - reduced by the same
   proportion as the homepage .hero h1 cut just above (~20%) so every
   page-hero across the ~15 interior pages reads calmer too, without
   touching the unrelated generic h1 rule (still used by e.g. blog posts). */
.page-hero h1{color:var(--navy);font-size:clamp(1.75rem,4vw,2.75rem);}
.page-hero p{color:var(--muted);}
/* A single real, confirmed trust stat (not a fabricated one) shown prominently
   in a page-hero, matching the reference site's "leading brands" stat
   pattern - kept honest by only ever holding numbers Zawar has confirmed. */
.hero-stat{margin-top:40px;display:inline-block;}
.hero-stat-num{
  font-family:var(--font-display);font-weight:800;font-size:clamp(2.4rem,5vw,3.4rem);
  background:linear-gradient(45deg,var(--navy) 0%,var(--blue) 50%,var(--teal) 100%);-webkit-background-clip:text;background-clip:text;color:transparent;
  letter-spacing:-0.02em;line-height:1;
}
.hero-stat-label{color:var(--muted);font-size:.95rem;max-width:360px;margin:8px auto 0;}

/* Inline stat within a case-story write-up (e.g. the IntercomDirect
   order/quote value) - distinct from the aggregate hero stat above. */
.case-stat{
  font-family:var(--font-display);font-weight:800;color:var(--navy);font-size:1.3rem;
  margin:14px 0 4px;
}
.case-stat span{display:block;font-family:inherit;font-weight:600;font-size:.85rem;color:var(--muted);margin-top:4px;}
/* Small centerpiece mark on interior-page heroes, so they carry the same
   glowing focal point as the homepage instead of feeling like a flatter,
   lower-effort version of it. */
.page-hero-mark{
  position:relative;margin:0 auto 22px;width:90px;height:92px;
  display:flex;align-items:center;justify-content:center;
}
.page-hero-mark::before{
  content:"";position:absolute;inset:-36px;z-index:0;pointer-events:none;
  background:radial-gradient(circle, rgba(var(--blue-rgb),.4) 0%, rgba(var(--teal-rgb),.24) 45%, transparent 72%);
  filter:blur(20px);animation:vertexGlowPulse 4.5s ease-in-out infinite;
}
.page-hero-mark .vertex-mark{position:relative;z-index:1;}
@media (prefers-reduced-motion: reduce){ .page-hero-mark::before{animation:none;} }

/* Contact */
.contact-wrap{display:grid;grid-template-columns:1fr 1.3fr;gap:48px;align-items:start;}
@media (max-width:900px){.contact-wrap{grid-template-columns:1fr;}}
.contact-form-card{background:#fff;border-radius:var(--radius);padding:36px;box-shadow:var(--shadow);border:1px solid rgba(var(--navy-rgb),0.06);}
.wpcf7-form p{margin-bottom:16px;}
.wpcf7-form label{display:block;font-weight:700;color:var(--navy);margin-bottom:6px;font-size:.9rem;}
.form-row{display:grid;grid-template-columns:1fr 1fr;gap:16px;}
@media (max-width:560px){.form-row{grid-template-columns:1fr;}}
.wpcf7-form input[type=text],.wpcf7-form input[type=email],.wpcf7-form input[type=tel],.wpcf7-form textarea,.wpcf7-form select{
  width:100%;padding:13px 14px;border:1.5px solid #dbe3ea;border-radius:10px;font-size:1rem;font-family:inherit;background:#fff;color:var(--ink);
}
.wpcf7-form input:focus,.wpcf7-form textarea:focus,.wpcf7-form select:focus{outline:none;border-color:var(--blue);}
.wpcf7-form input[type=submit]{
  background:var(--blue);color:#fff;border:0;padding:15px 32px;border-radius:999px;font-weight:700;
  font-size:1rem;cursor:pointer;width:100%;
}
.wpcf7-form input[type=submit]:hover{background:var(--teal);}
.wpcf7-response-output{border-radius:10px !important;padding:12px 16px !important;margin-top:14px !important;}

/* "Who we are" intro (Home, replaces the earlier needs-based nav cards) -
   two-column layout: a short numbered headline on the left, an intro
   paragraph + link on the right, matching the reference site's team-intro
   section structure. */
.who-we-are{display:grid;grid-template-columns:1fr 1.3fr;gap:48px;align-items:start;}
.who-we-are-lead .eyebrow{display:block;}
.who-we-are-lead h2{font-size:clamp(1.7rem,3vw,2.3rem);margin-top:6px;}
@media (max-width:760px){.who-we-are{grid-template-columns:1fr;gap:20px;}}
.link-arrow{display:inline-flex;align-items:center;gap:6px;color:var(--teal);font-weight:700;font-size:.95rem;margin-top:14px;}
.link-arrow:hover{color:var(--blue);}

.list-check{list-style:none;margin:0;padding:0;}
.list-check li{padding-left:32px;position:relative;margin-bottom:14px;color:var(--ink);}
.list-check li::before{content:"✓";position:absolute;left:0;color:var(--teal);font-weight:800;}
.list-check.on-dark li{color:var(--muted-dark);}

/* Muted "x" variant (Home "Passen we bij elkaar?" section) - deliberately
   muted gray rather than alarming red, matching the "less direct" tone
   established for this site rather than reading as a harsh rejection. */
.list-x{list-style:none;margin:0;padding:0;}
.list-x li{padding-left:32px;position:relative;margin-bottom:14px;color:var(--muted);}
.list-x li::before{content:"✕";position:absolute;left:0;top:1px;color:var(--muted);font-weight:700;font-size:.82em;}

/* Small "Gratis" badge on the first Werkwijze step (Home) */
.step-badge{
  display:inline-block;background:var(--teal);color:#fff;font-size:.7rem;font-weight:800;
  letter-spacing:.05em;text-transform:uppercase;padding:4px 10px;border-radius:999px;margin:10px 0 -2px;
}

/* Micro-stat under each "Onze denkwijze" process step (Home) - a small
   real fact per step, reusing the connected-step visual below rather than
   a separate component (doitdigital.nl/gibby.it pattern: a numbered
   process strip where each step also carries a short stat). */
.micro-stat{
  display:inline-block;margin-top:12px;font-family:var(--font-display);font-weight:800;
  font-size:.8rem;color:var(--blue);letter-spacing:.01em;
}

/* Pledge/promise row (Home, "Onze belofte") - icon + stat + one-liner
   columns, doitdigital.nl's 5-pledge pattern. Some columns are real,
   already-published facts; unconfirmed ones use .is-placeholder styling
   so they read as visibly provisional, matching the HTML-comment markers
   next to them in front-page.php. */
.pledge-grid{display:grid;grid-template-columns:repeat(5,1fr);gap:20px;}
@media (max-width:960px){.pledge-grid{grid-template-columns:repeat(2,1fr);}}
@media (max-width:560px){.pledge-grid{grid-template-columns:1fr;}}
.pledge-card{
  background:#fff;border-radius:16px;padding:26px 18px;text-align:center;
  border:1px solid rgba(var(--navy-rgb),.07);box-shadow:var(--shadow);
}
.pledge-icon{
  width:40px;height:40px;margin:0 auto 14px;border-radius:12px;display:flex;
  align-items:center;justify-content:center;
  background:linear-gradient(45deg,var(--navy) 0%,var(--blue) 50%,var(--teal) 100%);color:#fff;
}
.pledge-stat{font-family:var(--font-display);font-weight:800;color:var(--navy);font-size:1.1rem;margin-bottom:6px;line-height:1.25;}
.pledge-stat.is-placeholder{color:var(--muted);font-weight:700;font-size:.82rem;font-style:italic;}
.pledge-label{font-size:.82rem;color:var(--muted);line-height:1.4;margin:0;}

/* Illustrative mini-mockup cards ("Zo ziet het eruit", Home) - a tiny
   dark dashboard preview inside a regular white .card, one bar highlighted
   per system, explicitly labeled illustrative (do-it/gibby pattern). */
.mock-badge{
  display:inline-block;background:rgba(var(--navy-rgb),.06);color:var(--muted);
  font-size:.68rem;font-weight:800;letter-spacing:.05em;text-transform:uppercase;
  padding:4px 10px;border-radius:999px;margin-bottom:16px;
}
.mini-mockup{background:var(--navy);border-radius:12px;padding:16px;margin-bottom:20px;}
.mini-mockup-bar{height:8px;border-radius:999px;background:rgba(255,255,255,.18);margin-bottom:8px;}
.mini-mockup-bar:last-child{margin-bottom:0;}
.mini-mockup-bar--accent{background:linear-gradient(90deg,var(--blue),var(--teal));}

/* Per-sector example grid (Home) - deliberately framed as illustrative
   examples across many sectors, not a niche list (Vertex's explicit
   positioning is all-sectors mkb, not a single-industry specialist).
   Same bordered-cell pattern as .partner-grid for visual consistency. */
.sector-grid{
  display:grid;grid-template-columns:repeat(4,1fr);
  border:1px solid rgba(var(--navy-rgb),.08);border-radius:var(--radius);overflow:hidden;background:#fff;
}
@media (max-width:900px){.sector-grid{grid-template-columns:repeat(2,1fr);}}
@media (max-width:560px){.sector-grid{grid-template-columns:1fr;}}
.sector-card{
  position:relative;display:block;padding:28px 24px;text-decoration:none;color:inherit;
  border-right:1px solid rgba(var(--navy-rgb),.08);border-bottom:1px solid rgba(var(--navy-rgb),.08);
  transition:background-color .2s ease;
}
.sector-card:hover{background:var(--gray);}
.sector-grid .sector-card:nth-child(4n){border-right:0;}
@media (max-width:900px){.sector-grid .sector-card:nth-child(4n){border-right:1px solid rgba(var(--navy-rgb),.08);} .sector-grid .sector-card:nth-child(2n){border-right:0;}}
@media (max-width:560px){.sector-grid .sector-card{border-right:0!important;}}
.sector-arrow{position:absolute;top:24px;right:24px;color:var(--muted);font-size:1.1rem;transition:transform .2s ease, color .2s ease;}
.sector-card:hover .sector-arrow{color:var(--blue);transform:translateX(3px);}
.sector-card h3{font-size:1.05rem;margin-bottom:8px;padding-right:24px;color:var(--navy);}
.sector-card p{font-size:.9rem;margin-bottom:14px;}
.sector-tags{display:block;font-size:.72rem;font-weight:700;letter-spacing:.04em;text-transform:uppercase;color:var(--muted);}

/* "Vaste afspraken" promise strip (Werkwijze hero) - concrete, checkable
   promises laid out as a horizontal wrapped row instead of a vertical list,
   matching the reference site's "wat je van ons mag verwachten" pattern.
   Scoped to .page-hero so it inherits readable colors on the dark hero bg. */
.list-check--row{display:flex;flex-wrap:wrap;justify-content:center;gap:10px 30px;text-align:left;}
.list-check--row li{margin-bottom:0;font-weight:600;font-size:.95rem;}
.page-hero .list-check li{color:var(--muted);}
.page-hero .list-check li::before{color:var(--teal);}
.promise-strip{margin-top:36px;}

/* "Partner of leverancier?" contrast block (Home) - two columns side by
   side so the difference in approach reads at a glance instead of as a
   paragraph of self-praise. */
.compare-grid{
  display:grid;grid-template-columns:1fr 1fr;border-radius:var(--radius);overflow:hidden;box-shadow:var(--shadow);
}
@media (max-width:760px){.compare-grid{grid-template-columns:1fr;}}
.compare-col{background:#fff;padding:40px 36px;border:1px solid rgba(var(--navy-rgb),.06);}
.compare-col--highlight{background:var(--navy);border-color:var(--navy);}
.compare-label{
  display:block;font-family:var(--font-display);font-weight:800;font-size:1.05rem;
  color:var(--navy);margin-bottom:20px;
}
.compare-col--highlight .compare-label{color:#fff;}
.compare-col:not(.compare-col--highlight) .list-check li::before{color:var(--muted);}
.compare-col:not(.compare-col--highlight) .list-check li{color:var(--muted);}
.compare-col--highlight .list-check li{color:var(--muted-dark);}
.compare-col--highlight .list-check li::before{color:var(--teal);}

/* Gibby-style "voor -> nu" transformation stat, led with the change itself
   rather than a wall of prose - used at the top of each case-story before
   the situatie/aanpak/resultaat narrative. Text-based (not invented numbers)
   since we only show transformations we can actually stand behind. */
.stat-transform{
  display:flex;align-items:center;gap:18px;flex-wrap:wrap;
  margin:6px 0 26px;padding:22px 24px;border-radius:16px;
  background:linear-gradient(120deg,rgba(var(--blue-rgb),.06),rgba(var(--teal-rgb),.06));
  border:1px solid rgba(var(--navy-rgb),.08);
}
.stat-transform-col{display:flex;flex-direction:column;gap:4px;}
.stat-transform-label{font-size:.72rem;font-weight:800;letter-spacing:.08em;text-transform:uppercase;color:var(--muted);}
.stat-transform-val{font-family:var(--font-display);font-weight:800;font-size:1.15rem;color:var(--navy);line-height:1.2;}
.stat-transform-col--after .stat-transform-label{color:var(--teal);}
.stat-transform-col--after .stat-transform-val{
  background:linear-gradient(45deg,var(--navy) 0%,var(--blue) 50%,var(--teal) 100%);-webkit-background-clip:text;background-clip:text;color:transparent;
}
.stat-transform-arrow{
  color:var(--teal);font-size:1.4rem;font-weight:800;flex:none;
  animation:vertexArrowPulse 1.8s ease-in-out infinite;
}
@keyframes vertexArrowPulse{0%,100%{transform:translateX(0);opacity:.65;}50%{transform:translateX(6px);opacity:1;}}
@media (prefers-reduced-motion: reduce){.stat-transform-arrow{animation:none;}}
@media (max-width:560px){.stat-transform{flex-direction:column;align-items:flex-start;}.stat-transform-arrow{transform:rotate(90deg);}}

/* Connected-step visual for numbered "Aanpak" process cards - a small line
   bridges each icon to the next, echoing the reference site's stepper
   instead of four disconnected numbered cards. Anchored to each icon's own
   right edge (not a container-width percentage), so it stays correctly
   aligned regardless of card width. */
.step-grid .card .icon{position:relative;}
.step-grid .card:not(:last-child) .icon::after{
  content:"";position:absolute;top:50%;left:100%;transform:translateY(-50%);
  width:58px;height:2px;background:linear-gradient(90deg,var(--blue),var(--teal));
  z-index:1;
}
@media (max-width:900px){.step-grid .card:not(:last-child) .icon::after{display:none;}}

/* Homepage preloader - an animated SVG analog clock showing the visitor's
   own local time (real SVG/CSS/JS, no image asset). Boom-in entrance,
   holds while ticking, zooms out to reveal the homepage underneath. Shown
   once per browser session (see preloader.js) and skipped entirely for
   prefers-reduced-motion. pointer-events:none so a slow/failed cleanup
   can never actually block the page underneath. */
html.vertex-preloading{overflow:hidden;}
#vertex-preloader{
  position:fixed;inset:0;z-index:9999;display:flex;align-items:center;justify-content:center;
  background:radial-gradient(ellipse at center,var(--navy-mid) 0%, var(--navy-deep) 60%, var(--navy-black) 100%);
  pointer-events:none;
}
.preloader-clock{
  position:relative;width:min(280px,60vw);display:flex;flex-direction:column;align-items:center;gap:20px;
  opacity:0;transform:scale(.15);
}
/* Boom-in/zoom-out durations trimmed alongside the JS hold/exit timers -
   same total-time complaint (felt like a slow page load, not a fast
   flourish). .6s in, .4s out instead of .9s/.6s. */
#vertex-preloader.is-visible .preloader-clock{animation:vertexPreloaderBoomIn .6s cubic-bezier(.2,1.4,.4,1) forwards;}
#vertex-preloader.is-leaving .preloader-clock{animation:vertexPreloaderZoomOut .4s cubic-bezier(.3,0,.7,1) forwards;}
#vertex-preloader.is-leaving{animation:vertexPreloaderFadeOut .45s ease forwards;}
@keyframes vertexPreloaderBoomIn{
  0%{opacity:0;transform:scale(.15);}
  55%{opacity:1;transform:scale(1.12);}
  75%{transform:scale(.96);}
  100%{opacity:1;transform:scale(1);}
}
@keyframes vertexPreloaderZoomOut{
  0%{opacity:1;transform:scale(1);}
  100%{opacity:0;transform:scale(2.6);}
}
@keyframes vertexPreloaderFadeOut{
  0%{opacity:1;}
  45%{opacity:1;}
  100%{opacity:0;}
}
.preloader-clock-face{width:100%;height:auto;overflow:visible;filter:drop-shadow(0 0 24px rgba(var(--blue-rgb),.45));}
.preloader-clock-ring{fill:rgba(255,255,255,.03);stroke:url(#preloaderRing);stroke-width:2.5;}
.preloader-tick{stroke:rgba(255,255,255,.35);stroke-width:1.5;stroke-linecap:round;}
.preloader-tick--major{stroke:#fff;stroke-width:2.5;}
/* Distinct color per hand (not all white) - the hour/minute hands were
   originally plain white, the same color as the major tick marks, and
   blended into them at this size. Teal/blue/white are each visually
   distinct from the white ticks and from each other.
   No transform-origin here on purpose - the hands are positioned by
   recomputing their endpoint coordinates directly in JS (see
   setHandEndpoint in preloader.js), not via an SVG transform="rotate()"
   attribute. That combination previously sent the hands flying off
   outside the clock face entirely (a real SVG/CSS transform-origin
   interop bug, not just a contrast issue). */
.preloader-hand{stroke-linecap:round;}
.preloader-hand--hour{stroke:var(--teal);stroke-width:7;}
.preloader-hand--minute{stroke:var(--blue);stroke-width:5;}
.preloader-hand--second{stroke:#fff;stroke-width:2;opacity:.95;}
.preloader-clock-pivot{fill:var(--teal);}
.preloader-digital{text-align:center;font-family:var(--font-display);color:#fff;}
.preloader-digital #preloader-time{display:block;font-size:1.6rem;font-weight:800;letter-spacing:.04em;}
.preloader-tz{display:block;font-size:.78rem;color:var(--muted-dark);text-transform:uppercase;letter-spacing:.08em;margin-top:4px;}
@media (prefers-reduced-motion: reduce){
  #vertex-preloader{display:none;}
}

/* Cookie consent banner - a slim, attractive bottom bar rather than a
   blocking full-screen modal (deliberately "not annoying" per Zawar's
   ask). Slides up from below on a delay-free entrance once JS confirms
   no prior choice is stored; pointer-events stays off until then so it
   can never intercept a click while off-screen. */
.cookie-banner{
  position:fixed;left:0;right:0;bottom:0;z-index:500;
  background:var(--navy-deep);border-top:1px solid rgba(255,255,255,.08);
  box-shadow:0 -8px 30px rgba(0,0,0,.25);
  transform:translateY(120%);opacity:0;pointer-events:none;
  transition:transform .5s cubic-bezier(.2,.8,.3,1), opacity .5s ease;
}
.cookie-banner.is-visible{transform:translateY(0);opacity:1;pointer-events:auto;}
.cookie-banner-inner{
  max-width:1200px;margin:0 auto;padding:18px 24px;
  display:flex;align-items:center;gap:22px;flex-wrap:wrap;
}
.cookie-banner-icon{
  flex:none;width:40px;height:40px;border-radius:12px;
  background:linear-gradient(45deg,var(--navy) 0%,var(--blue) 50%,var(--teal) 100%);
  display:flex;align-items:center;justify-content:center;color:#fff;
}
.cookie-banner-text{flex:1;min-width:240px;}
.cookie-banner-text p{margin:0;color:var(--muted-dark);font-size:.92rem;}
.cookie-banner-text a{color:var(--teal);font-weight:600;}
.cookie-banner-actions{display:flex;gap:10px;flex:none;}
.cookie-banner-actions .btn{padding:11px 22px;font-size:.9rem;white-space:nowrap;}
/* "Weigeren" was a near-invisible ghost outline against the dark banner
   (Zawar's live look: "hardly seen, not user friendly") - a faint border
   alone doesn't read as a real, clickable button next to a solid primary
   one. Give it an actual visible fill instead of just an outline. */
.cookie-banner-actions #cookie-decline{
  background:rgba(255,255,255,.1);border-color:rgba(255,255,255,.35);color:#fff;
}
.cookie-banner-actions #cookie-decline:hover{
  background:rgba(255,255,255,.18);border-color:#fff;color:#fff;
}
@media (max-width:640px){
  .cookie-banner-inner{padding:16px 20px;}
  .cookie-banner-actions{width:100%;}
  .cookie-banner-actions .btn{flex:1;text-align:center;}
}
@media (prefers-reduced-motion: reduce){.cookie-banner{transition:opacity .2s ease;}}

/* Cursor-follow Vertex mark - a small version of the logo that eases
   toward the pointer site-wide (desktop only, see reveal.js). Fixed +
   pointer-events:none so it never intercepts clicks; fades in on first
   movement and dims while hovering interactive elements so it stays a
   background touch rather than competing with the real cursor. */
.cursor-follow{
  position:fixed;top:0;left:0;width:26px;height:26px;pointer-events:none;z-index:40;
  opacity:0;transition:opacity .35s ease;
  filter:drop-shadow(0 4px 12px rgba(var(--blue-rgb),.4));
  will-change:transform;
}
.cursor-follow.is-active{opacity:.5;}
.cursor-follow.is-active.is-hidden-hover{opacity:.15;}
.cursor-follow .vertex-mark{width:100%;height:100%;}
@media (hover:none), (pointer:coarse){.cursor-follow{display:none;}}
@media (prefers-reduced-motion:reduce){.cursor-follow{display:none;}}

/* Blog index - article card grid, matching the reference site's "Laatste
   artikelen" pattern. */
.article-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:26px;}
@media (max-width:900px){.article-grid{grid-template-columns:1fr;}}
.article-card{
  display:block;background:#fff;border-radius:var(--radius);overflow:hidden;box-shadow:var(--shadow);
  border:1px solid rgba(var(--navy-rgb),0.06);text-decoration:none;color:inherit;transition:.25s ease;
}
.article-card:hover{box-shadow:var(--shadow-hover);transform:translateY(-4px);}
.article-card-media{
  height:170px;display:flex;align-items:center;justify-content:center;overflow:hidden;
  background:linear-gradient(45deg,var(--navy) 0%,var(--blue) 50%,var(--teal) 100%);color:#fff;
}
.article-card-media img{width:100%;height:100%;object-fit:cover;}
.article-card-body{padding:24px;}
.article-meta{display:block;color:var(--muted);font-size:.8rem;font-weight:700;text-transform:uppercase;letter-spacing:.04em;margin-bottom:8px;}
.article-card h3{font-size:1.15rem;margin-bottom:.4em;color:var(--navy);}
.article-card p{font-size:.95rem;}

/* Single post - prose styling for raw the_content() HTML, since posts
   don't use the hand-built section classes the rest of the site does. */
.entry-content{font-size:1.05rem;line-height:1.75;color:var(--ink);}
.entry-content h2{margin-top:1.6em;margin-bottom:.5em;font-size:1.6rem;}
.entry-content h3{margin-top:1.3em;margin-bottom:.4em;font-size:1.25rem;}
.entry-content p{margin-bottom:1.2em;}
.entry-content ul, .entry-content ol{margin:0 0 1.2em;padding-left:1.4em;}
.entry-content li{margin-bottom:.5em;}
.entry-content a{color:var(--blue);text-decoration:underline;}
.entry-content strong{color:var(--navy);}
.entry-content img{border-radius:var(--radius);margin:1.5em 0;max-width:100%;height:auto;}
.entry-content blockquote{
  border-left:3px solid var(--teal);padding-left:20px;margin:1.5em 0;font-style:italic;color:var(--muted);
}

/* Pagination (blog index) */
.pagination, .nav-links{display:flex;gap:12px;justify-content:center;flex-wrap:wrap;}
.pagination .page-numbers, .nav-links .page-numbers{
  display:inline-flex;align-items:center;justify-content:center;min-width:40px;height:40px;padding:0 12px;
  border-radius:999px;background:#fff;border:1px solid rgba(var(--navy-rgb),.1);color:var(--navy);font-weight:700;
  text-decoration:none;transition:border-color .2s ease, color .2s ease;
}
.pagination .page-numbers.current, .nav-links .page-numbers.current{background:var(--navy);color:#fff;border-color:var(--navy);}
.pagination .page-numbers:hover, .nav-links .page-numbers:hover{border-color:var(--blue);color:var(--blue);}
.pagination .page-numbers.dots{border:0;background:transparent;}

/* "In het kort" quick-facts strip (individual service pages) - a compact
   commercial-terms summary right under the hero, matching the reference
   site's "in het kort" box. Real, standing facts only (a fixed-price quote
   before building starts, cancel-anytime maintenance) - no invented
   pricing numbers. */
.fact-strip{display:flex;flex-wrap:wrap;gap:0;border:1px solid rgba(var(--navy-rgb),.08);border-radius:16px;overflow:hidden;max-width:900px;margin:0 auto;}
.fact-strip .fact{flex:1;min-width:200px;padding:22px 20px;text-align:center;border-right:1px solid rgba(var(--navy-rgb),.08);}
.fact-strip .fact:last-child{border-right:0;}
.fact-strip .fact-val{font-family:var(--font-display);font-weight:800;font-size:1.1rem;color:var(--navy);}
.fact-strip .fact-label{font-size:.85rem;color:var(--muted);margin-top:4px;}
@media (max-width:700px){
  .fact-strip{flex-direction:column;}
  .fact-strip .fact{border-right:0;border-bottom:1px solid rgba(var(--navy-rgb),.08);}
  .fact-strip .fact:last-child{border-bottom:0;}
}

/* Breadcrumb (individual service pages) - small trail above the page-hero
   eyebrow, matching the reference site's Home / Diensten / [service] path. */
.breadcrumb{font-size:.82rem;color:var(--muted);margin-bottom:18px;}
.breadcrumb a{color:var(--muted);}
.breadcrumb a:hover{color:var(--teal);}
.breadcrumb .sep{margin:0 6px;opacity:.5;}

/* "Op deze pagina" table of contents - anchor links into a long, rich
   service page so a visitor can jump straight to what they need. */
.page-toc{display:flex;flex-wrap:wrap;gap:10px 26px;justify-content:center;list-style:none;margin:0;padding:0;}
.page-toc li a{color:var(--muted);font-weight:600;font-size:.9rem;display:inline-flex;align-items:center;gap:6px;}
.page-toc li a:hover{color:var(--blue);}
.page-toc li a::before{content:"→";color:var(--teal);}

/* Numbered "concrete voorbeelden" rows - situation-based, not sector-based
   (Vertex serves all sectors), echoing the reference site's numbered
   example format without the per-industry framing. */
.example-num{display:flex;gap:20px;align-items:flex-start;padding:20px 0;border-bottom:1px solid rgba(var(--navy-rgb),.08);}
.example-num:last-child{border-bottom:0;}
.example-num .num{flex:none;width:44px;font-family:var(--font-display);font-weight:800;font-size:1.3rem;color:var(--teal);}
.example-num p{margin:0;font-size:1.02rem;color:var(--ink);}

/* Small numbered index badge on each case-story icon, echoing the
   reference site's numbered-case pattern (01, 02 ...). */
.case-story-visual{position:relative;}
.case-story-visual .case-index{
  position:absolute;top:-10px;left:-10px;width:28px;height:28px;border-radius:50%;
  background:var(--navy);color:#fff;font-weight:800;font-size:.78rem;
  display:flex;align-items:center;justify-content:center;box-shadow:0 4px 10px rgba(var(--navy-rgb),.3);
}

/* ROI / savings illustration section (homepage, "Voorbeeldberekening") -
   deliberately illustrative, never tied to a named real company. Rewritten
   2026-09-10 from a dark-glass card pattern (matching the old dark .step)
   to a plain light dashboard-style card - do-it's own "chart highlight"
   pattern is real bar/number data on a light card, with color reserved for
   the highlighted bar/fill only, not the card's own background. Bars are
   plain CSS width percentages, no chart library - keeps with the site's
   "no heavy JS" rule (see business-plan.md §12). */
.roi-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:24px;}
@media (max-width:900px){.roi-grid{grid-template-columns:1fr;}}

.roi-card{
  background:#fff;border-radius:var(--radius);padding:32px 28px;
  border:1px solid rgba(var(--navy-rgb),.06);box-shadow:var(--shadow);
  transition:transform .3s cubic-bezier(.2,.7,.2,1), box-shadow .3s ease, border-color .3s ease;
}
.roi-card:hover{
  transform:translateY(-6px);box-shadow:var(--shadow-hover);
  border-color:rgba(var(--teal-rgb),.35);
}
.roi-label{
  display:block;color:var(--teal);font-size:.8rem;font-weight:700;letter-spacing:.06em;text-transform:uppercase;margin-bottom:14px;
}
.roi-bigstat{
  font-family:var(--font-display);font-weight:800;font-size:2.4rem;color:var(--navy);line-height:1;margin-bottom:16px;
}
.roi-bigstat .roi-unit{font-size:1.1rem;font-weight:600;color:var(--muted);}
.roi-bar-track{
  height:8px;border-radius:999px;background:var(--tint);overflow:hidden;margin-bottom:18px;
}
.roi-bar-fill{
  height:100%;border-radius:999px;background:linear-gradient(90deg,var(--blue),var(--teal));
}
.roi-caption{color:var(--muted);font-size:.86rem;margin:0;line-height:1.5;}

/* Cost-comparison mini bar chart (old vs. new, within one card) */
.roi-compare{margin-bottom:18px;}
.roi-compare-row{margin-bottom:16px;}
.roi-compare-row:last-child{margin-bottom:0;}
.roi-compare-name{display:block;color:var(--navy);font-size:.85rem;font-weight:700;margin-bottom:6px;}
.roi-compare-name small{display:block;color:var(--muted);font-size:.78rem;font-weight:400;margin-top:1px;}
.roi-compare-track{height:10px;border-radius:999px;background:var(--tint);overflow:hidden;margin-bottom:4px;}
.roi-compare-fill{height:100%;border-radius:999px;}
.roi-compare-fill--old{background:#c7d2dc;}
.roi-compare-fill--new{background:linear-gradient(90deg,var(--blue),var(--teal));}
.roi-compare-value{display:block;color:var(--navy);font-weight:800;font-size:1rem;font-family:var(--font-display);}
