/* Rouby 3.0 componenten. Consumeert uitsluitend tokens uit tokens.css. */

/* Snellere taps op mobiel (geen 300ms dubbel-tik-vertraging) */
a, button, input, textarea, select { touch-action: manipulation; }

/* Knoppen */
.btn {
  display: inline-flex; align-items: center; gap: 0.5rem;
  font: 600 1rem/1 var(--font-text);
  padding: 0.95rem 1.7rem; border-radius: var(--radius-pill);
  text-decoration: none; border: 1px solid transparent;
  transition: background var(--dur) var(--ease-out),
              color var(--dur) var(--ease-out),
              border-color var(--dur) var(--ease-out),
              transform var(--dur) var(--ease-out);
}
.btn:hover { transform: translateY(-1px); }
.btn:active { transform: translateY(0) scale(0.985); }
/* Focus-ring werkt op elke canvas (nacht/licht/paars): een donkere binnenring
   plus een lila buitenring, zodat er altijd minstens één met >=3:1 zichtbaar is
   (WCAG 2.4.7/2.4.11). Niet op kleur alleen leunen. */
.btn:focus-visible { outline: none; box-shadow: 0 0 0 2px var(--canvas-nacht), 0 0 0 4px var(--accent-lila); }
.btn-primary { background: var(--accent-paars); color: var(--paper); }
.btn-primary:hover { background: var(--accent-lila); color: var(--canvas-nacht); }
.btn-ghost { border-color: currentColor; color: inherit; }
.btn-ghost:hover { border-color: var(--accent-lila); color: var(--accent-lila); }

/* Nav */
.nav {
  position: sticky; top: 0; z-index: 90;
  display: flex; align-items: center; justify-content: space-between; gap: 1rem;
  padding: 0.8rem var(--space-inner);
  background: color-mix(in srgb, var(--canvas-nacht) 88%, transparent);
  backdrop-filter: blur(12px); color: var(--paper);
}
.nav-logo { display: inline-flex; align-items: center; min-height: 44px; font: 600 1.25rem/1 var(--font-display); color: inherit; text-decoration: none; }
.nav-dot { color: var(--accent-lila); }
.nav-actions { display: flex; align-items: center; gap: 0.9rem; }
/* Inline sectie-nav: maakt de site glanceable op desktop; het kinetische menu
   blijft de signatuur voor het volledige overzicht. Verborgen onder 900px. */
.nav-inline { display: none; }
@media (min-width: 900px) {
  .nav-inline { display: flex; gap: 1.8rem; margin-left: auto; margin-right: 0.4rem; }
  .nav-inline a { display: inline-flex; align-items: center; min-height: 44px; color: var(--paper-dim); font: 500 0.95rem/1 var(--font-text); text-decoration: none; transition: color var(--dur) var(--ease-out); }
  .nav-inline a:hover, .nav-inline a:focus-visible { color: var(--paper); }
  .nav-inline a:focus-visible { outline: 2px solid var(--accent-lila); outline-offset: 4px; border-radius: 4px; }
}
.cta-bar { display: none; }
@media (max-width: 560px) {
  .nav-cta { display: none; }
}
@media (max-width: 719px) {
  .cta-bar { display: inline-flex; position: fixed; left: 1rem; right: 1rem; bottom: 1rem; z-index: 40; justify-content: center; }
}

/* Zwevende berichtenknop met keuze uit WhatsApp, Signal en Telegram. Op
   mobiel staat hij rechts naast de cta-bar, die daarvoor smaller wordt: zo
   kiest een bezoeker op de telefoon, waar die apps juist zitten, zelf zijn
   app in plaats van alleen WhatsApp. */
.visueel-verborgen {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip-path: inset(50%); white-space: nowrap; border: 0;
}
.chat-float { display: block; position: fixed; right: 1.6rem; bottom: 1.6rem; z-index: 50; }
.chat-knop {
  display: grid; place-items: center; position: relative;
  width: 68px; height: 68px; padding: 0; border: 0; cursor: pointer;
  border-radius: var(--radius-pill); background: var(--accent-paars); color: var(--paper);
  box-shadow: 0 18px 40px -12px rgba(109, 40, 217, 0.7), 0 0 0 1px rgba(167, 139, 250, 0.55) inset;
  transition: background var(--dur) var(--ease-out), box-shadow var(--dur) var(--ease-out);
}
/* GSAP stuurt transform aan (magnetisch, indrukken), dus die staat bewust niet
   in de transition: anders vechten de tween en de CSS-overgang om dezelfde
   eigenschap en gaat de beweging schokken. */
.chat-knop:hover { background: var(--accent-lila); }
.chat-knop:hover .chat-icoon { fill: var(--canvas-nacht); }
/* Pulserende ring die de aandacht trekt. GSAP animeert scale en opacity; los
   element omdat box-shadow-spread niet op de compositor draait. */
.chat-ring {
  position: absolute; inset: 0; border-radius: var(--radius-pill);
  border: 2px solid var(--accent-lila); opacity: 0; pointer-events: none;
}
/* Het icoon is bewust neutraal: de knop is geen WhatsApp-knop meer maar een
   keuze uit drie apps, dus het merk hoort in het paneel en niet op de knop. */
.chat-icoon { width: 31px; height: 31px; fill: var(--paper); transition: fill var(--dur) var(--ease-out); }
.chat-knop:focus-visible { outline: none; box-shadow: 0 0 0 3px var(--canvas-nacht), 0 0 0 6px var(--accent-lila); }
/* Open: het icoon draait naar een kruis-gevoel en de knop blijft opgetild. */
.chat-float[data-open] .chat-knop { background: var(--accent-lila); }
.chat-float[data-open] .chat-icoon { fill: var(--canvas-nacht); }

/* Label absoluut ernaast, niet in de flow: zo groeit de knop niet en blijft de
   beweging op transform en opacity (geen layout). Verdwijnt zodra het paneel
   openstaat, want dan vertelt het paneel zelf al waar het over gaat. */
.chat-label {
  position: absolute; right: calc(100% + 0.7rem); top: 50%;
  transform: translate(6px, -50%); opacity: 0; pointer-events: none; white-space: nowrap;
  padding: 0.5rem 0.85rem; border-radius: var(--radius-pill);
  background: var(--canvas-paars); color: var(--paper);
  font: 500 0.85rem/1 var(--font-text);
  box-shadow: 0 12px 28px -14px rgba(11, 10, 16, 0.7), 0 0 0 1px rgba(167, 139, 250, 0.2) inset;
  transition: opacity var(--dur) var(--ease-out), transform var(--dur) var(--ease-out);
}
.chat-knop:hover .chat-label, .chat-knop:focus-visible .chat-label { opacity: 1; transform: translate(0, -50%); }
.chat-float[data-open] .chat-label { opacity: 0; }

/* Keuzepaneel boven de knop */
.chat-panel {
  position: absolute; right: 0; bottom: calc(100% + 0.8rem);
  min-width: 250px; padding: 0.9rem;
  border-radius: calc(var(--radius) + 2px);
  background: var(--canvas-paars); color: var(--paper);
  box-shadow: 0 26px 60px -22px rgba(11, 10, 16, 0.8), 0 0 0 1px rgba(167, 139, 250, 0.24) inset;
  transform-origin: 100% 100%;
}
.chat-panel[hidden] { display: none; }
.chat-panel-kop {
  margin: 0 0 0.7rem; padding: 0 0.35rem; max-width: none;
  font: 600 0.72rem/1.3 var(--font-text); letter-spacing: 0.09em;
  text-transform: uppercase; color: var(--accent-lila);
}
.chat-optie {
  display: flex; align-items: center; gap: 0.75rem;
  padding: 0.6rem 0.6rem; border-radius: var(--radius-sm);
  color: var(--paper); text-decoration: none; font: 500 0.98rem/1 var(--font-text);
  transition: background var(--dur) var(--ease-out), transform var(--dur) var(--ease-out);
}
.chat-optie svg { width: 22px; height: 22px; flex: none; }
.chat-optie[data-net="whatsapp"] svg { fill: #25D366; }
.chat-optie[data-net="signal"] svg { fill: #3A76F0; }
.chat-optie[data-net="telegram"] svg { fill: #29A9EB; }
.chat-optie:hover { background: rgba(167, 139, 250, 0.14); transform: translateX(2px); }
.chat-optie:focus-visible { outline: none; background: rgba(167, 139, 250, 0.14); box-shadow: 0 0 0 2px var(--accent-lila) inset; }

/* Instapanimatie van het paneel en de rijen. Alleen transform en opacity. */

/* Hero: editorial manifest, geen video, geen media */
.hero { position: relative; min-height: 88svh; display: grid; align-items: center; overflow: hidden; }
/* Hero-achtergrond: geanimeerd isometrisch diorama (video; poster = still).
   Het beeld staat rechts, links loopt het via een scrim donker weg zodat de
   witte kop scherp leesbaar blijft. De losse lijn-geometrie vervalt hier. */
.hero-media { position: absolute; inset: 0; z-index: 0; overflow: hidden; background: var(--canvas-nacht); }
.hero-media video, .hero-media img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; object-position: right center; }
.hero-media-scrim {
  position: absolute; inset: 0; pointer-events: none;
  background:
    linear-gradient(100deg, rgba(11, 10, 16, 0.98) 0%, rgba(11, 10, 16, 0.9) 32%, rgba(11, 10, 16, 0.55) 50%, rgba(11, 10, 16, 0.14) 74%, rgba(11, 10, 16, 0) 100%),
    linear-gradient(0deg, rgba(11, 10, 16, 0.5), rgba(11, 10, 16, 0) 40%);
}
.hero-ambient { display: none; }
@media (max-width: 719px) {
  /* Smal scherm: tekst staat over het hele beeld, dus verticaal donkeren en het
     diorama iets naar het midden schuiven zodat het onder de tekst blijft leven. */
  .hero-media video, .hero-media img { object-position: 70% center; }
  .hero-media-scrim {
    background: linear-gradient(180deg, rgba(11, 10, 16, 0.92) 0%, rgba(11, 10, 16, 0.62) 42%, rgba(11, 10, 16, 0.42) 68%, rgba(11, 10, 16, 0.72) 100%);
  }
}
/* Fijne film-grain over de hero: haalt de "digitale platheid" eraf. Statisch,
   pointer-events uit, subtiel. */
.hero::after {
  content: ""; position: absolute; inset: 0; z-index: 2; pointer-events: none;
  opacity: 0.05; mix-blend-mode: overlay;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='160' height='160'%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");
  background-size: 160px 160px;
}
/* Kinetische ambient-vormen: lila geometrie op nacht, zweeft + parallax op de cursor.
   Geen multicolor blobs; on-brand vertaling van het kinetic-navigation-effect. */
.hero-ambient { position: absolute; inset: 0; z-index: 0; overflow: hidden; pointer-events: none; color: var(--accent-lila); }
.hero-shape { position: absolute; display: block; will-change: transform; transition: transform 0.5s var(--ease-out); }
.hero-shape svg { display: block; width: 100%; height: auto; animation: heroFloat var(--float, 10s) ease-in-out infinite; animation-delay: var(--delay, 0s); }
.hero-shape-1 { top: 12%; left: 56%; width: clamp(120px, 15vw, 230px); opacity: 0.12; --float: 13s; }
.hero-shape-2 { top: 20%; left: 84%; width: clamp(78px, 8vw, 128px); opacity: 0.16; --float: 12s; --delay: -3s; }
.hero-shape-3 { top: 58%; left: 50%; width: clamp(150px, 20vw, 300px); opacity: 0.16; --float: 11s; --delay: -1.5s; }
.hero-shape-4 { top: 52%; left: 80%; width: clamp(88px, 10vw, 158px); opacity: 0.18; --float: 9s; --delay: -4s; }
.hero-shape-5 { top: 74%; left: 38%; width: clamp(22px, 3vw, 44px); opacity: 0.24; --float: 8s; --delay: -2s; }
@keyframes heroFloat { 0%, 100% { transform: translateY(0); } 50% { transform: translateY(-16px); } }
.hero-grid { position: relative; z-index: 1; display: grid; justify-items: start; gap: 1.4rem; padding-block: clamp(2rem, 5vh, 4rem); }
.hero-kicker { font: 500 0.85rem/1 var(--font-text); letter-spacing: 0.14em; text-transform: uppercase; color: var(--paper-dim); margin: 0; }
.hero-statement { margin: 0; max-width: 24ch; font-size: clamp(2.7rem, 0.6rem + 5.4vw, 5.75rem); font-weight: 660; letter-spacing: -0.028em; line-height: 1.04; }
/* SplitText-regels: transform + filter worden geanimeerd (blur focus-in). */
.hero-statement .hero-line { will-change: transform, filter; }
.hero-sub { max-width: 34ch; color: var(--paper-dim); margin: 0.3rem 0 0.7rem; line-height: 1.55; }
.hero-cta { display: flex; flex-wrap: wrap; gap: 0.8rem; }
@media (max-width: 719px) {
  /* Vormen die de kop kunnen kruisen weglaten op smalle schermen */
  .hero-shape-3, .hero-shape-5 { display: none; }
}
@media (prefers-reduced-motion: reduce) {
  .hero-shape svg { animation: none; }
  .hero-shape { transition: none; }
}

/* Werk-galerij: de OG-kaart van elk project, allemaal even groot, met eronder
   de opdracht, het doel en waarom het werkt.

   Het beeld wordt nooit bijgesneden. Een OG-kaart draagt zijn kop in het beeld,
   en een uitsnede van een paar procent haalt al een regel weg (bij de oude brede
   kaarten sneuvelde zo de onderregel van Mediozorg). Kader en bron hebben dus
   exact dezelfde verhouding. De diepte komt niet uit een overmaat in het beeld
   maar uit lagen eromheen, net als in de Over KMLR-hero:
     achter  de volledige projectnaam, groot, die trager scrollt;
     midden  de kaart zelf;
     voor    het branchelabel op de onderrand, dat iets sneller gaat.
   De snelheden staan in motion.js. */
#werk { overflow-x: clip; }
.bento {
  --rij-ruimte: clamp(4rem, 3rem + 4vw, 6.5rem);
  display: grid; grid-template-columns: repeat(2, minmax(0, 1fr));
  column-gap: clamp(1.25rem, 3vw, 2.5rem); row-gap: 0;
  margin-block: clamp(2.5rem, 5vw, 4rem) calc(-1 * var(--rij-ruimte));
}
/* Subgrid: de beelden in een rij staan op dezelfde lijn, ook als de naam erboven
   bij de een één regel is en bij de ander twee, en de links onderaan ook. De ruimte tussen de rijen zit als
   padding onder elke kaart, niet als row-gap: een row-gap erft het subgrid mee en
   zet dan ook een gat tussen beeld en tekst. De negatieve marge onderaan het
   raster haalt de laatste padding weer weg. */
.case-card { display: grid; grid-row: span 3; grid-template-rows: subgrid; padding-bottom: var(--rij-ruimte); color: var(--paper); }

.case-podium { position: relative; align-self: end; container-type: inline-size; }
/* De naam is de echte kop van de kaart, dus hij moet te lezen zijn: het beeld
   schuift er maar een klein stuk overheen (de onderkant van de laatste regel),
   net genoeg om de naam erachter te laten staan. Twee regels mag, zoals ARIK /
   NATIV; de afbreking staat in de HTML. */
.case-naam {
  position: relative; margin: 0 0 -0.06em -0.045em;
  font: 800 12.5cqi/0.88 var(--font-display); letter-spacing: -0.04em; text-wrap: nowrap;
  color: color-mix(in srgb, var(--accent-lila) 80%, var(--canvas-nacht));
  pointer-events: none;
}
.case-naam span { display: block; }
.case-beeld {
  position: relative; z-index: 1; aspect-ratio: 1200 / 630; overflow: hidden;
  border-radius: var(--radius); background: #14121d;
  box-shadow: 0 0 0 1px rgba(246, 244, 249, 0.06), 0 -18px 40px -24px rgba(0, 0, 0, 0.7), 0 28px 60px -30px rgba(0, 0, 0, 0.95);
  transition: box-shadow var(--dur) var(--ease-out);
}
.case-beeld > img { display: block; width: 100%; height: 100%; object-fit: cover; }
.case-card:hover .case-beeld { box-shadow: 0 0 0 1px rgba(167, 139, 250, 0.35), 0 -18px 40px -24px rgba(0, 0, 0, 0.7), 0 30px 60px -28px rgba(0, 0, 0, 0.95); }
/* Rechtsonder, half over de rand. Boven zou het de naam afdekken; links onder
   staan op de meeste kaarten de onderregels. */
.case-tag {
  position: absolute; z-index: 2; right: clamp(0.75rem, 3cqi, 1.25rem); bottom: -0.95rem;
  padding: 0.6rem 0.95rem; border-radius: var(--radius-pill);
  background: var(--paper); color: var(--ink);
  font: 600 0.75rem/1.1 var(--font-text); letter-spacing: 0.1em; text-transform: uppercase;
  box-shadow: 0 14px 30px -14px rgba(0, 0, 0, 0.9);
}

.case-feiten { display: grid; align-content: start; gap: 1rem; margin: 2.1rem 0 0; }
.case-feiten > div { display: grid; grid-template-columns: 2.25rem minmax(0, 1fr); column-gap: 0.9rem; row-gap: 0.3rem; align-items: start; }
/* Eén icoon per tekstblok, links in een getint vlak: zo scant het oog de drie
   blokken zonder de labels te hoeven lezen. Lijnicoontjes (Lucide, ISC) als
   achtergrond, dus geen extra HTML in elke kaart. */
.case-feiten > div::before {
  content: ""; grid-row: 1 / span 2; width: 2.25rem; height: 2.25rem; margin-top: 0.1rem;
  border-radius: var(--radius-sm);
  background: rgba(167, 139, 250, 0.1) var(--feit-icoon) center / 1.15rem no-repeat;
  box-shadow: inset 0 0 0 1px rgba(167, 139, 250, 0.22);
}
.case-feiten dt, .case-feiten dd { grid-column: 2; }
.feit-opdracht { --feit-icoon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23A78BFA' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'%3E%3Crect width='8' height='4' x='8' y='2' rx='1'/%3E%3Cpath d='M16 4h2a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2h2'/%3E%3Cpath d='M12 11h4M12 16h4M8 11h.01M8 16h.01'/%3E%3C/svg%3E"); }
.feit-doel { --feit-icoon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23A78BFA' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='12' cy='12' r='10'/%3E%3Ccircle cx='12' cy='12' r='6'/%3E%3Ccircle cx='12' cy='12' r='2'/%3E%3C/svg%3E"); }
.feit-waarom { --feit-icoon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23A78BFA' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M4 14a1 1 0 0 1-.78-1.63l9.9-10.2a.5.5 0 0 1 .86.46l-1.92 6.02A1 1 0 0 0 13 10h7a1 1 0 0 1 .78 1.63l-9.9 10.2a.5.5 0 0 1-.86-.46l1.92-6.02A1 1 0 0 0 11 14z'/%3E%3C/svg%3E"); }
.case-feiten dt { font: 600 0.75rem/1.2 var(--font-text); letter-spacing: 0.12em; text-transform: uppercase; color: var(--accent-lila); }
.case-feiten dd { margin: 0; max-width: 52ch; color: var(--paper-dim); line-height: 1.55; }
/* Gewone, volgbare links naar de klant: dat is wat ze als verwijzing waard maakt.
   Sites die nog niet live staan krijgen geen link, anders wijst die naar de oude
   site of naar niets. */
.case-link { margin: 1.4rem 0 0; font: 600 0.95rem/1.3 var(--font-text); }
.case-link a {
  color: var(--paper); text-decoration: underline; text-decoration-color: color-mix(in srgb, var(--accent-lila) 55%, transparent);
  text-underline-offset: 0.3em; text-decoration-thickness: 1px; transition: color var(--dur) var(--ease-out), text-decoration-color var(--dur) var(--ease-out);
}
.case-link a:hover { color: var(--accent-lila); text-decoration-color: currentColor; }
.case-link a:focus-visible { outline: 2px solid var(--accent-lila); outline-offset: 4px; border-radius: 2px; }
.case-link--wacht { color: var(--paper-dim); font-weight: 500; }

@media (prefers-reduced-motion: no-preference) {
  .case-beeld > img { transition: scale 0.9s var(--ease-out); }
  .case-card:hover .case-beeld > img { scale: 1.03; }
}
@media (max-width: 900px) {
  .bento { grid-template-columns: minmax(0, 1fr); }
}
/* Op een telefoon besloeg "Sport & zelfverdediging" de halve kaart. Kleiner
   maken kan niet (onder 12px wordt het onleesbaar), dus minder lucht eromheen. */
@media (max-width: 560px) {
  .case-tag { padding: 0.5rem 0.75rem; letter-spacing: 0.05em; bottom: -0.85rem; }
}

/* Prijsfases */
/* Deze sectie stond op de volle 1200px van .wrap met een kop op de globale
   --text-h2 (tot 3.4rem). Op een breed scherm werd dat een kop van bijna een
   halve meter boven drie brede kaarten, en dan leest het als een poster in
   plaats van als een prijslijst. Eén smallere kolom voor de hele sectie, zodat
   kop, intro en kaarten op dezelfde lijn staan. */
#tarieven .wrap { width: min(1060px, 100% - 2 * var(--space-inner)); }
#tarieven > .wrap > h2 { font-size: clamp(1.7rem, 1.05rem + 2vw, 2.7rem); max-width: 22ch; }
#tarieven > .wrap > p { max-width: 56ch; }
.fases { display: grid; gap: 1rem; grid-template-columns: 1fr 1.12fr 1fr; align-items: stretch; margin-top: 2.2rem; }
.fase-card {
  display: flex; flex-direction: column;
  border: 1px solid rgba(22, 18, 31, 0.09); border-radius: var(--radius); padding: 1.5rem; background: #fcfbfe;
  box-shadow: 0 2px 4px -2px rgba(36, 22, 64, 0.06), 0 12px 28px -18px rgba(36, 22, 64, 0.18);
  transition: transform var(--dur) var(--ease-out), box-shadow var(--dur) var(--ease-out);
}
.fase-card:not(.gekozen):hover { transform: translateY(-4px); box-shadow: 0 22px 46px -24px rgba(36, 22, 64, 0.28); }
/* Uitlijning over de drie kaarten heen. Alleen de middelste heeft een badge, en
   alleen de derde titel breekt over twee regels; zonder correctie staan de drie
   prijzen daardoor op drie verschillende hoogtes en leest de rij als scheef.
   Het lege blokje reserveert de badgeruimte in de andere twee kaarten, de
   min-heights reserveren de tweede regel die soms wel en soms niet komt. */
.fase-card:not(.gekozen)::before { content: ""; display: block; height: 1.52rem; }
.fase-card h3 { min-height: 2.1em; }
.fase-beheer { min-height: calc(2.9em + 0.8rem); }   /* twee regels plus de padding-top; box-sizing rekent die mee */
.fase-card.gekozen { border: none; background: var(--canvas-paars); box-shadow: 0 24px 60px -24px rgba(36, 22, 64, 0.45); }
.fase-badge { font: 600 0.72rem/1 var(--font-text); letter-spacing: 0.1em; text-transform: uppercase; color: var(--accent-lila); margin: 0 0 0.8rem; }
.fase-prijs { font-family: var(--font-display); font-size: 1.6rem; font-variant-numeric: tabular-nums; letter-spacing: -0.015em; }
.fase-prijs span { font-family: var(--font-text); font-size: 0.85rem; color: inherit; opacity: 0.7; }
.fase-card ul { list-style: none; padding-left: 0; margin-block: 1.2rem 1.6rem; display: grid; gap: 0.5rem; align-content: start; flex: 1; }
.fase-card li { position: relative; padding-left: 1.4rem; margin: 0; }
.fase-card li::before { content: ""; position: absolute; left: 0; top: 0.6em; width: 12px; height: 2px; border-radius: 2px; background: var(--accent-paars); }
.fase-card.gekozen li::before { background: var(--accent-lila); }
.fase-card .btn { align-self: start; }
.fase-beheer {
  margin: 0.7rem 0 0; padding-top: 0.8rem; border-top: 1px solid rgba(22, 18, 31, 0.09);
  font-size: 0.85rem; line-height: 1.45; color: var(--ink-dim);
}
.fase-beheer b { font-weight: 620; color: var(--accent-paars); }
.fase-card.gekozen .fase-beheer { border-top-color: rgba(167, 139, 250, 0.26); color: var(--paper-dim); }
.fase-card.gekozen .fase-beheer b { color: var(--accent-lila); }
@media (max-width: 900px) {
  .fases { grid-template-columns: 1fr; }
  /* Eén kolom lijnt zichzelf uit, dus de gereserveerde badge- en regelruimte
     is hier alleen maar gat. */
  .fase-card:not(.gekozen)::before { display: none; }
  .fase-card h3, .fase-beheer { min-height: 0; }
}

/* Losse regel onder de kaarten in plaats van een eigen paneel: de drie bedragen
   staan al op de kaarten zelf, dus alles wat het paneel nog toevoegde was de
   inhoud van beheer. Dat is een zin, geen blok met een eigen kop en knop. */
.fases-noot {
  margin: 1.6rem 0 0; max-width: 62ch;
  font-size: 0.92rem; line-height: 1.6; color: var(--ink-dim);
}

/* Scroll-scrub embed (alleen desktop; js/scrollworld.js zet dit aan) */
.scrollworld--active .wrap { display: none; }
/* De sectie zelf levert de scroll-afstand (1 viewport beeld + 4 viewports reis);
   native CSS sticky pint het beeld. Geen GSAP-pin/pin-spacer meer nodig, dus
   geen kans dat de pagina korter is dan de reis (scroll-vastloper). */
/* Padding weg: de sticky moet exact op de sectierand starten en loslaten,
   anders begint de reis met een zwarte band en schuift hij aan het einde
   te vroeg weg (padding telt binnen de 300svh). */
/* De reis binnenin is 4.25 viewports lang (embed.html). Hoeveel scroll je
   daarvoor nodig hebt, bepaalt het tempo.
   Mobiel: 525svh, dus 425svh scroll op 4.25 viewports reis, precies 1:1. Op een
   telefoon is meer scrollen geen rust maar werk.
   Desktop: 700svh, dus 600svh scroll op diezelfde 4.25 viewports. Een verhouding
   van ongeveer 1.4:1, waardoor de camera trager beweegt dan je wiel en de vlucht
   kalm blijft in plaats van langs te schieten. */
.scrollworld--active { height: 525svh; padding-block: 0; }
@media (min-width: 900px) { .scrollworld--active { height: 700svh; } }
/* Reis afgerond: sectie klapt in tot een scherm, eindbeeld blijft staan. */
.scrollworld--active.scrollworld--done { height: 100svh; }

/* GEEN scroll-snap op deze sectie. Safari trekt bij een snap-area van 525svh
   terug naar de startrand tijdens een wheel-gesture, waardoor de reis naar
   frame 0 terugspoelt en opnieuw begint. In Chromium en in headless WebKit is
   dat niet te zien, want programmatisch scrollen omzeilt snap.

   De reden dat snap er ooit in kwam (het beeld begon halverwege) zat ergens
   anders: de generieke `section { scroll-margin-top: 4.5rem }` parkeerde de
   sectie 72px onder de bovenrand. Die staat hieronder op nul en dat lost het op,
   want de sticky pint daarna vanzelf op top: 0. */
.scrollworld--active { scroll-margin-top: 0; }
.scrollworld-sticky { position: sticky; top: 0; height: 100svh; overflow: hidden; background: var(--canvas-nacht); }
.scrollworld-frame { position: absolute; inset: 0; width: 100%; height: 100%; border: 0; display: block; pointer-events: none; }
/* Vangt de wheel af in de parent zodat de iframe niet zelf gaat scrollen.
   Moet pointer-events houden (dus geen `none`) en boven de iframe liggen. */
.scrollworld-catch { position: absolute; inset: 0; z-index: 2; }

/* Contact */
/* Hier stonden drie routekaarten naast het formulier: WhatsApp, bellen, mailen.
   Diezelfde drie staan inmiddels ook in de footer eronder, in het schermvullende
   menu en in de zwevende knop. Vier keer dezelfde vraag in een pagina.
   Wat deze sectie als enige kan is een briefing aannemen, dus dat blijft over,
   met de snelle route als een regel erboven. */
/* Het formulier stond in zijn eentje links op de volle sectiebreedte, waardoor
   de rechterhelft leeg bleef. Tekst links, formulier rechts: dezelfde inhoud in
   ongeveer de halve hoogte, en het vlak wordt gebruikt. */
.contact-grid { display: grid; grid-template-columns: 1fr 1fr; gap: clamp(2rem, 1rem + 4vw, 5rem); align-items: start; }
.contact-tekst { max-width: 46ch; }
@media (max-width: 860px) { .contact-grid { grid-template-columns: 1fr; } }
.contact-direct { margin: 1.3rem 0 0; color: var(--paper-dim); }
.contact-direct a { color: var(--accent-lila); }
.contact-mail { color: var(--accent-lila); }
#contact form { display: grid; gap: 0.7rem; }
/* Naam en e-mail naast elkaar: scheelt een veldhoogte, en het zijn twee korte
   velden dus het formulier wordt er niet drukker van. */
.form-rij { display: grid; grid-template-columns: 1fr 1fr; gap: 0.7rem; }
@media (max-width: 560px) { .form-rij { grid-template-columns: 1fr; } }
#contact label { display: grid; gap: 0.25rem; font: 500 0.88rem/1.3 var(--font-text); }
#contact input, #contact textarea, #contact select { padding: 0.6rem 0.7rem; font-size: 0.95rem; border-radius: var(--radius-sm); border: 1px solid rgba(246, 244, 249, 0.14); background: rgba(246, 244, 249, 0.06); color: var(--paper); font: inherit; transition: border-color var(--dur) var(--ease-out), box-shadow var(--dur) var(--ease-out); }
#contact input:hover, #contact textarea:hover, #contact select:hover { border-color: rgba(246, 244, 249, 0.28); }
#contact input:focus-visible, #contact textarea:focus-visible, #contact select:focus-visible { outline: none; border-color: var(--accent-lila); box-shadow: 0 0 0 3px rgba(167, 139, 250, 0.28); }
#contact input::placeholder, #contact textarea::placeholder { color: var(--paper-dim); }
#contact button { justify-self: start; }
#contact select option { color: var(--canvas-nacht); }
#contact .form-optioneel { font-weight: 400; color: var(--paper-dim); }
.form-hp { position: absolute; left: -9999px; width: 1px; height: 1px; overflow: hidden; }
#contact .form-consent { display: flex; align-items: flex-start; gap: 0.6rem; margin-top: 0.2rem; font: 400 0.85rem/1.45 var(--font-text); color: var(--paper-dim); }
#contact .form-consent input { flex: none; width: 1.2rem; height: 1.2rem; margin-top: 0.05rem; accent-color: var(--accent-lila); }
#contact .form-consent a, .form-fallback a { color: var(--accent-lila); }
.form-fallback { margin: 0; font-size: 0.9rem; color: var(--paper-dim); }
.form-status[data-state="ok"] { color: var(--accent-lila); }
.form-status[data-state="error"] { color: #ff9aa8; }

/* Footer */
/* Footer. Was een dunne regel met het merk, twee links en een copyright: de
   laatste zes centimeter van de pagina deden niets. Nu sluit hij de pagina af
   met wat er hoort te staan, en wat er ontbrak: het bezoekadres en het
   telefoonnummer stonden nergens op de site.
   Geen tweede CTA hier. De contactsectie staat er direct boven en de zwevende
   knop zweeft mee; nog een "plan een gesprek" zou dezelfde vraag drie keer
   stellen. */
.footer { padding-block: clamp(3rem, 2rem + 3vw, 5rem) 1.6rem; font-size: 0.92rem; color: var(--paper-dim); }
.footer a { color: var(--paper-dim); text-decoration: none; transition: color var(--dur) var(--ease-out); }
.footer a:hover { color: var(--accent-lila); }
.footer a:focus-visible { outline: 2px solid var(--accent-lila); outline-offset: 3px; border-radius: 3px; }

.footer-top {
  display: grid; grid-template-columns: 1.15fr 0.85fr 0.95fr 1.05fr;
  gap: clamp(1.8rem, 1rem + 2.5vw, 3.5rem); align-items: start;
}
/* Het woordmerk is de signatuur aan het eind, niet een logo'tje in een hoek.
   Op deze maat draagt het de hele rij en hoeft er niets omheen. */
.footer .footer-merk {
  font: 660 clamp(2.4rem, 1.4rem + 3.4vw, 4.2rem)/0.9 var(--font-display);
  letter-spacing: -0.04em; color: var(--paper); align-self: start; margin-top: -0.14em;
}
.footer .footer-merk:hover { color: var(--paper); }
.footer-merk .nav-dot { color: var(--accent-lila); }

.footer-kolom { display: grid; gap: 0.55rem; align-content: start; }
/* Kolomkoppen in gewone schrijfwijze, niet als versperde kapitalen: die vorm
   is op deze site al de badge en de case-tag, en een derde variant maakt er
   een tic van. */
.footer-kop { margin: 0 0 0.35rem; font: 600 0.92rem/1.2 var(--font-text); color: var(--paper); letter-spacing: 0; }
.footer-kolom a { display: inline-flex; align-items: center; min-height: 30px; }
.footer-adres { margin: 0; max-width: none; line-height: 1.65; }

.footer-onder {
  display: flex; flex-wrap: wrap; gap: 0.6rem 1.6rem;
  margin-top: clamp(2.5rem, 1.5rem + 3vw, 4rem); padding-top: 1.2rem;
  border-top: 1px solid rgba(246, 244, 249, 0.1);
  font-size: 0.85rem;
}
.footer-onder p { margin: 0; max-width: none; }
.footer-onder a { margin-left: auto; }

@media (max-width: 860px) {
  .footer-top { grid-template-columns: repeat(2, 1fr); }
  .footer-merk { grid-column: 1 / -1; margin-bottom: 0.6rem; }
}
@media (max-width: 480px) {
  .footer-top { grid-template-columns: 1fr; }
  .footer-onder a { margin-left: 0; }
}

/* Juridische pagina's (privacy) */
.legal { padding-block: clamp(3rem, 8vh, 6rem); }
.legal-back { display: inline-block; margin-bottom: 2rem; color: var(--accent-paars); font-weight: 500; }
.legal h1 { font-size: clamp(2rem, 1rem + 3vw, 3.2rem); margin-bottom: 0.8rem; }
.legal h2 { font-size: 1.3rem; margin-top: 2.2rem; }
.legal p, .legal li { color: var(--ink); max-width: 68ch; line-height: 1.6; }
.legal ul { margin: 0.5rem 0 0 1.1rem; }
.legal a { color: var(--accent-paars); }
.legal-updated { color: var(--ink-soft, #555); font-size: 0.9rem; }

/* Over. Hier stond nooit een basisregel voor .over-grid, alleen een mobiele
   override. Zonder grid viel de foto terug op zijn eigen 818px en duwde hij de
   sectie een heel scherm open. Nu een echte tweekolom met een portret op maat.
   Het portret krijgt de rand- en schaduwtaal van de werkkaarten, zodat de pagina
   één materiaal spreekt in plaats van een losse foto op zwart. */
.over-grid {
  display: grid; grid-template-columns: minmax(0, 0.72fr) minmax(0, 1fr);
  gap: clamp(2rem, 1rem + 4vw, 4.5rem); align-items: center;
}
.over-portret {
  margin: 0; position: relative; overflow: hidden;
  border-radius: calc(var(--radius) + 2px);
  max-width: 380px; aspect-ratio: 818 / 1024;
  box-shadow: 0 0 0 1px rgba(246, 244, 249, 0.08), 0 34px 70px -34px rgba(0, 0, 0, 0.95);
}
.over-portret img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
.over-tekst { max-width: 56ch; }
/* Een naamregel sluit het blok af zoals een brief: het maakt de belofte
   "gewoon de maker" concreet met de persoon die hem doet. */
.over-signatuur {
  margin-top: 1.6rem; padding-top: 1.1rem;
  border-top: 1px solid rgba(246, 244, 249, 0.12);
  font: 600 1rem/1.4 var(--font-text); color: var(--paper);
}
.over-signatuur span { display: block; font-weight: 400; font-size: 0.9rem; color: var(--paper-dim); }

@media (max-width: 900px) {
  .stappen { grid-template-columns: 1fr 1fr; }
  .over-grid { grid-template-columns: 1fr; }
  .over-portret { max-width: 300px; }
}

/* Scrollgestuurde hero-overgang */
.motion-ready .hero-grid {
  will-change: transform, opacity;
}
@media (max-width: 719px) {
  .hero { min-height: 84svh; }
}

@media (prefers-reduced-motion: reduce) {
  .motion-ready .hero-grid {
    will-change: auto;
  }
}

/* Toegankelijkheid en mobiele contactruimte */
.skip-link {
  position: fixed;
  top: 0.75rem;
  left: 0.75rem;
  z-index: 100;
  padding: 0.75rem 1rem;
  border-radius: var(--radius-pill);
  background: var(--accent-lila);
  color: var(--canvas-nacht);
  font-weight: 600;
  text-decoration: none;
  transform: translateY(-160%);
}

.skip-link:focus { transform: translateY(0); }
section { scroll-margin-top: 4.5rem; }
#contact { padding-block: var(--space-section) clamp(3rem, 2rem + 2.5vw, 4.5rem); }


.form-status { color: var(--paper-dim); font-size: 0.9rem; }
.form-status { min-height: 1.5em; margin: 0; }

@media (max-width: 719px) {
  body { padding-bottom: calc(5.5rem + env(safe-area-inset-bottom)); }
  /* Balk en berichtenknop op één lijn: zelfde hoogte, zelfde onderkant. */
  .cta-bar { bottom: calc(1rem + env(safe-area-inset-bottom)); right: calc(1rem + 52px + 0.6rem); min-height: 52px; }
  .chat-float { right: 1rem; bottom: calc(1rem + env(safe-area-inset-bottom)); }
  .chat-knop { width: 52px; height: 52px; }
  .chat-icoon { width: 25px; height: 25px; }
}

/* Dienstpagina /website-laten-maken/: hergebruikt legal (tekst), fases (kaarten)
   en de bestaande canvassen; hieronder alleen wat die pagina extra nodig heeft. */
.dienst-intro { padding-bottom: 1rem; }
.dienst-lead { font-size: 1.15rem; }
.dienst-cta { display: flex; flex-wrap: wrap; gap: 0.75rem; margin-top: 1.6rem; }
.dienst-tarieven { padding-block: clamp(2.5rem, 6vh, 4.5rem); }
.dienst-tarieven .wrap { width: min(1060px, 100% - 2 * var(--space-inner)); }
.dienst-tarieven h2 { font-size: clamp(1.6rem, 1rem + 1.8vw, 2.4rem); }
.dienst-tarieven > .wrap > p { max-width: 56ch; }
.dienst-tekst { padding-top: 1rem; }
.dienst-stappen { margin: 0.5rem 0 0 1.2rem; display: grid; gap: 0.6rem; }
.dienst-stappen li { max-width: 68ch; line-height: 1.6; }
.dienst-faq { display: grid; gap: 0.6rem; margin-top: 1rem; max-width: 68ch; }
.dienst-faq details { border: 1px solid rgba(36, 22, 64, 0.14); border-radius: 12px; padding: 0.9rem 1.1rem; }
.dienst-faq summary { cursor: pointer; font-weight: 600; }
.dienst-faq details p { margin: 0.6rem 0 0; }
.dienst-slot { padding-block: clamp(3rem, 8vh, 5rem); }
.dienst-slot p { max-width: 56ch; color: var(--paper-dim); }
/* .legal a kleurt links paars; knoppen houden hun eigen tekstkleur. */
.legal .btn-primary { color: var(--paper); }
.legal .btn-primary:hover { color: var(--canvas-nacht); }
/* Geen vaste cta-bar op de dienstpagina, dus ook geen gereserveerde ruimte. */
@media (max-width: 719px) { body.dienst-pagina { padding-bottom: 0; } }
/* Casepagina's /werk/<klant>/ */
.case-kicker { margin: 0 0 0.4rem; font-size: 0.85rem; letter-spacing: 0.12em; text-transform: uppercase; color: var(--accent-paars); font-weight: 600; }
.case-hero { margin: 1.6rem 0 0.4rem; max-width: 760px; }
.case-hero img { display: block; width: 100%; height: auto; border-radius: 14px; }
/* Overzicht /werk/ en de link ernaartoe vanaf de homepage */
.werk-kop { font-size: clamp(2rem, 1.1rem + 3vw, 3.4rem); margin-top: clamp(2rem, 6vh, 4rem); max-width: 18ch; }
.werk-intro { color: var(--paper-dim); max-width: 56ch; margin-bottom: 2rem; }
.werk-alles { margin-top: 2.4rem; }
/* Kennisartikelen /kennis/ */
.kennis-meta { color: var(--ink-soft, #555); font-size: 0.9rem; margin: -0.2rem 0 1.2rem; }
.kennis-artikel h3 { font-size: 1.05rem; margin: 1.4rem 0 0.3rem; }
.kennis-artikel code { font-family: "JetBrains Mono", ui-monospace, monospace; font-size: 0.9em; background: rgba(36, 22, 64, 0.06); padding: 0.1em 0.35em; border-radius: 4px; }
.legal .kennis-lijst { list-style: none; margin: 2rem 0 0; padding: 0; display: grid; gap: 1rem; max-width: 68ch; }
.kennis-lijst li { border: 1px solid rgba(36, 22, 64, 0.14); border-radius: 12px; padding: 1.1rem 1.2rem; }
.kennis-lijst a { font-weight: 600; font-size: 1.1rem; }
.kennis-lijst p { margin: 0.4rem 0 0; }
