/*
 * Interactive KVK hero: "zoek je bedrijf → zie je zaak online komen".
 * Search the KVK register, pick your business, and a themed builder-site
 * preview + a paid invoice + a mailbox on your own domain assemble live.
 *
 * The hero chrome uses --kvk-* tokens (dual-theme). The mini "site" inside the
 * browser frame is themed at runtime from the /kvk/preview endpoint's design
 * tokens via --sp-* custom properties set by kvk-hero.js.
 */
:root {
  --kvk-surface: #ffffff;
  --kvk-ground-2: #f2f0fb;
  --kvk-ink: #17131f;
  --kvk-ink-soft: #4b4459;
  --kvk-ink-faint: #837c92;
  --kvk-line: #e7e3f2;
  --kvk-line-strong: #d9d3ea;
  --kvk-violet: #7c3aed;
  --kvk-violet-deep: #6d28d9;
  --kvk-green: #059669;
  --kvk-amber: #f59e0b;
  --kvk-shadow-soft: 0 1px 2px rgba(23, 19, 31, 0.06), 0 8px 24px rgba(23, 19, 31, 0.06);
  --kvk-shadow-lift: 0 2px 4px rgba(23, 19, 31, 0.05), 0 1.75rem 4rem rgba(109, 40, 217, 0.18);
  --kvk-shadow-pop: 0 0.625rem 1.875rem rgba(23, 19, 31, 0.12), 0 2.5rem 5.6rem rgba(109, 40, 217, 0.22);
  --kvk-num: ui-monospace, "SF Mono", "Geist Mono", Menlo, monospace;
  --kvk-serif: "Iowan Old Style", "Palatino Linotype", Palatino, "Book Antiqua", Georgia, serif;
}
[data-theme="dark"] {
  --kvk-surface: #191423;
  --kvk-ground-2: #14101f;
  --kvk-ink: #f4f1fb;
  --kvk-ink-soft: #bab3cd;
  --kvk-ink-faint: #857e97;
  --kvk-line: #292337;
  --kvk-line-strong: #372f4a;
  --kvk-shadow-soft: 0 1px 2px rgba(0, 0, 0, 0.4), 0 8px 24px rgba(0, 0, 0, 0.45);
  --kvk-shadow-lift: 0 2px 4px rgba(0, 0, 0, 0.3), 0 1.9rem 4.4rem rgba(124, 58, 237, 0.3);
  --kvk-shadow-pop: 0 0.625rem 1.875rem rgba(0, 0, 0, 0.5), 0 2.75rem 6.25rem rgba(124, 58, 237, 0.4);
}

/* ---- layout: reuse .landing-hero shell, tune the inner grid ----
   Three grid cells (copy, cta, visual). Desktop: copy + cta stacked in the
   left column, the preview spanning the right. Mobile: copy, then the preview,
   then the CTA below it (so people see the payoff before the button). */
.kvk-hero-inner {
  grid-template-columns: 0.92fr 1.08fr;
  grid-template-areas: "copy visual" "cta visual";
  align-items: start;
  row-gap: var(--landing-hero-stack-gap);
}
.kvk-hero-copy {
  grid-area: copy;
  position: relative;
  z-index: 2;
}
.kvk-hero-cta-block {
  grid-area: cta;
}
/* The preview is a picture of the product: three cards whose every dimension is
   in rem, so at the desktop scale it is a fixed ~682px tall no matter how much
   room the viewport has. That single number is what used to push the home hero
   past the fold on a laptop.

   `zoom` scales it as one artifact — unlike `transform: scale()` it shrinks the
   LAYOUT box too, so the hero above it actually gets shorter, and unlike
   `transform` it leaves `.kvk-canvas`'s inline transform (the mouse parallax in
   kvk-hero.js) alone. Browsers without `zoom` simply ignore it and get today's
   behaviour. The factor is stepped by the (max-height) queries in
   landing-modern.css. */
.kvk-hero-visual {
  grid-area: visual;
  align-self: center;
  /* The tighter of the height fit and the width fit -- see the block at the
     bottom of landing-modern.css. Whichever constraint bites harder wins,
     without depending on which media query happens to come last. */
  zoom: min(var(--landing-hero-fit, 1), var(--landing-hero-fit-w, 1));
}
@media (max-width: 980px) {
  .kvk-hero-inner {
    grid-template-columns: 1fr;
    grid-template-areas: "copy" "visual" "cta";
  }
}

/* ---- KVK search combobox ---- */
.kvk-search {
  position: relative;
  max-width: 30rem;
  margin: var(--landing-hero-search-gap) 0 0.25rem;
}
.page-home .kvk-search {
  margin-right: auto;
}
.kvk-search-label {
  display: block;
  font-size: 0.82rem;
  font-weight: 600;
  color: var(--kvk-ink-faint);
  margin: 0 0 0.5rem;
}
.kvk-field {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  background: var(--kvk-surface);
  border: 1.5px solid var(--kvk-line-strong);
  border-radius: 0.9rem;
  padding: 0.35rem 0.6rem 0.35rem 1rem;
  box-shadow: var(--kvk-shadow-soft);
  transition: border-color 0.15s ease, box-shadow 0.15s ease;
}
.kvk-field:focus-within {
  border-color: var(--kvk-violet);
  box-shadow: 0 0 0 4px color-mix(in srgb, var(--kvk-violet) 16%, transparent);
}
.kvk-field-icon {
  color: var(--kvk-ink-faint);
  flex: none;
  display: flex;
}
.kvk-field input {
  flex: 1;
  min-width: 0;
  border: 0;
  background: transparent;
  font-family: inherit;
  font-size: 1.05rem;
  font-weight: 600;
  color: var(--kvk-ink);
  padding: 0.6rem 0;
}
.kvk-field input::placeholder {
  color: var(--kvk-ink-faint);
  font-weight: 500;
}
.kvk-field input:focus {
  outline: none;
}
.kvk-field-spinner {
  flex: none;
  width: 1.1rem;
  height: 1.1rem;
  border: 2px solid var(--kvk-line-strong);
  border-top-color: var(--kvk-violet);
  border-radius: 50%;
  animation: kvk-spin 0.7s linear infinite;
}
@keyframes kvk-spin {
  to {
    transform: rotate(360deg);
  }
}

.kvk-pop {
  position: absolute;
  left: 0;
  right: 0;
  top: calc(100% + 0.5rem);
  z-index: 30;
  background: var(--kvk-surface);
  border: 1px solid var(--kvk-line);
  border-radius: 0.9rem;
  box-shadow: var(--kvk-shadow-pop);
  overflow: hidden;
  animation: kvk-pop 0.16s ease-out both;
}
@keyframes kvk-pop {
  from {
    opacity: 0;
    transform: translateY(-0.375rem);
  }
  to {
    opacity: 1;
    transform: none;
  }
}
.kvk-pop-src {
  display: flex;
  align-items: center;
  gap: 0.45rem;
  padding: 0.55rem 0.9rem;
  border-bottom: 1px solid var(--kvk-line);
  font-size: 0.72rem;
  color: var(--kvk-ink-faint);
  font-weight: 600;
}
.kvk-pop-src .kvk-badge {
  font-weight: 800;
  color: #fff;
  background: #003d82;
  border-radius: 0.3rem;
  padding: 0.1rem 0.35rem;
  font-size: 0.68rem;
}
.kvk-row {
  display: flex;
  align-items: center;
  gap: 0.8rem;
  width: 100%;
  text-align: left;
  padding: 0.7rem 0.9rem;
  border: 0;
  border-bottom: 1px solid var(--kvk-line);
  background: transparent;
  cursor: pointer;
  font-family: inherit;
}
.kvk-row:last-child {
  border-bottom: 0;
}
.kvk-row:hover,
.kvk-row.is-active {
  background: color-mix(in srgb, var(--kvk-violet) 7%, transparent);
}
.kvk-row-avatar {
  width: 2.2rem;
  height: 2.2rem;
  border-radius: 0.55rem;
  flex: none;
  display: grid;
  place-items: center;
  color: #fff;
  font-weight: 800;
  font-size: 0.95rem;
  background: linear-gradient(135deg, var(--kvk-violet-deep), var(--kvk-violet));
}
.kvk-row-info {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 0.1rem;
}
.kvk-row-name {
  font-weight: 700;
  font-size: 0.92rem;
  color: var(--kvk-ink);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.kvk-row-meta {
  font-size: 0.78rem;
  color: var(--kvk-ink-faint);
}
.kvk-row-num {
  font-family: var(--kvk-num);
  font-size: 0.74rem;
  color: var(--kvk-ink-soft);
  flex: none;
}
.kvk-pop-empty {
  padding: 0.9rem;
  font-size: 0.85rem;
  color: var(--kvk-ink-faint);
}

.kvk-found {
  display: flex;
  align-items: center;
  gap: 0.45rem;
  margin-top: 0.7rem;
  font-size: 0.82rem;
  color: var(--kvk-green);
  font-weight: 600;
}
.kvk-hero-hint {
  display: none;
  align-items: center;
  gap: 0.4rem;
  margin-top: 1rem;
  font-size: 0.8rem;
  color: var(--kvk-ink-faint);
  font-weight: 500;
}
.kvk-hero-hint svg {
  color: var(--kvk-violet);
  animation: kvk-nudge 1.6s ease-in-out infinite;
}
@keyframes kvk-nudge {
  0%,
  100% {
    transform: translateY(0);
  }
  50% {
    transform: translateY(3px);
  }
}

/* vak-picker (shown when trade not confident) */
.kvk-picker {
  margin-top: 0.85rem;
}
.kvk-picker-label {
  font-size: 0.8rem;
  color: var(--kvk-ink-soft);
  font-weight: 600;
  margin: 0 0 0.5rem;
}
.kvk-picker-grid {
  display: flex;
  flex-wrap: wrap;
  gap: 0.4rem;
}
.kvk-chip {
  font-family: inherit;
  font-size: 0.8rem;
  font-weight: 600;
  color: var(--kvk-ink-soft);
  background: var(--kvk-surface);
  border: 1px solid var(--kvk-line-strong);
  border-radius: 999px;
  padding: 0.35rem 0.75rem;
  cursor: pointer;
  transition: border-color 0.12s ease, color 0.12s ease;
}
.kvk-chip:hover {
  border-color: var(--kvk-violet);
  color: var(--kvk-ink);
}

/* ---- the assembly canvas ---- */
.kvk-canvas {
  position: relative;
  display: grid;
  gap: 1rem;
  transform-style: preserve-3d;
  transition: transform 0.25s ease-out;
}
.kvk-canvas.is-building::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 6;
  border-radius: 1rem;
  pointer-events: none;
  background: linear-gradient(
    105deg,
    transparent 30%,
    color-mix(in srgb, var(--kvk-violet) 22%, transparent) 50%,
    transparent 70%
  );
  background-size: 220% 100%;
  animation: kvk-sweep 0.5s ease-out forwards;
}
@keyframes kvk-sweep {
  from {
    background-position: 130% 0;
  }
  to {
    background-position: -60% 0;
  }
}
.kvk-canvas.is-assembling .kvk-card-wrap {
  animation: kvk-rise 0.55s cubic-bezier(0.2, 0.75, 0.2, 1) both;
}
.kvk-canvas.is-assembling .kvk-card-wrap.wrap-2 {
  animation-delay: 0.12s;
}
.kvk-canvas.is-assembling .kvk-card-wrap.wrap-3 {
  animation-delay: 0.2s;
}
@keyframes kvk-rise {
  from {
    opacity: 0;
    transform: translateY(1.1rem) scale(0.96);
    filter: blur(6px);
  }
  to {
    opacity: 1;
    transform: none;
    filter: none;
  }
}

.kvk-card-wrap {
  position: relative;
}
.kvk-card {
  position: relative;
  background: var(--kvk-surface);
  border: 1px solid var(--kvk-line);
  border-radius: 1rem;
  box-shadow: var(--kvk-shadow-lift);
  overflow: hidden;
}
.kvk-card-tag {
  position: absolute;
  left: -0.4rem;
  top: -0.5rem;
  z-index: 4;
  font-size: 0.68rem;
  font-weight: 700;
  color: #fff;
  background: var(--kvk-violet);
  padding: 0.22rem 0.5rem;
  border-radius: 0.45rem;
  box-shadow: 0 4px 10px rgba(124, 58, 237, 0.35);
}

/* browser chrome */
.kvk-chrome {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  padding: 0.55rem 0.8rem;
  border-bottom: 1px solid var(--kvk-line);
  background: var(--kvk-ground-2);
}
.kvk-dots {
  display: flex;
  gap: 0.35rem;
}
.kvk-dots i {
  width: 0.6rem;
  height: 0.6rem;
  border-radius: 50%;
  background: var(--kvk-line-strong);
}
.kvk-urlbar {
  flex: 1;
  /* the domain is the company name too -- see .kvk-swordmark */
  min-width: 0;
  max-width: 17rem;
  font-family: var(--kvk-num);
  font-size: 0.74rem;
  color: var(--kvk-ink-soft);
  background: var(--kvk-surface);
  border: 1px solid var(--kvk-line);
  border-radius: 0.5rem;
  padding: 0.22rem 0.6rem;
  display: flex;
  align-items: center;
  gap: 0.4rem;
  overflow: hidden;
  white-space: nowrap;
}
.kvk-urlbar .kvk-lock {
  color: var(--kvk-green);
  flex: none;
  display: flex;
}
.kvk-urlbar [data-kvk-url] {
  overflow: hidden;
  text-overflow: ellipsis;
  min-width: 0;
}
.kvk-dom-badge {
  margin-left: auto;
  flex: none;
  display: inline-flex;
  align-items: center;
  gap: 0.2rem;
  font-family: inherit;
  font-size: 0.64rem;
  font-weight: 700;
  color: var(--kvk-green);
  background: color-mix(in srgb, var(--kvk-green) 14%, transparent);
  border-radius: 999px;
  padding: 0.1rem 0.4rem;
  opacity: 0;
  transform: scale(0.8);
  transition: opacity 0.25s ease, transform 0.25s cubic-bezier(0.2, 1.4, 0.4, 1);
}
.kvk-dom-badge.is-show {
  opacity: 1;
  transform: scale(1);
}

/* the themed mini "site" (vars set by JS from preset tokens) */
.kvk-site {
  --sp-paper: #f4efe6;
  --sp-ink: #2b2119;
  --sp-brand: #9a5b2a;
  --sp-on: #ffffff;
  --sp-muted: rgba(43, 33, 25, 0.62);
  --sp-line: rgba(43, 33, 25, 0.1);
  --sp-head: var(--kvk-serif);
  background: var(--sp-paper);
  color: var(--sp-ink);
}
.kvk-snav {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.5rem;
  padding: 0.6rem 0.85rem;
}
.kvk-swordmark {
  font-family: var(--sp-head);
  font-weight: 700;
  /* explicit, so the nav's height doesn't move when --sp-head swaps stacks */
  line-height: 1.5;
  letter-spacing: -0.01em;
  /*
   * This is the VISITOR'S company name, and a nowrap string contributes its
   * full max-content to a content-sized card, so an unbounded one dragged the
   * preview off the side of the screen. The tight bound is the BASE and the
   * roomy one at the bottom of this file is the override, so that a width
   * falling between media queries keeps the bound rather than losing it.
   *
   * --sp-head swaps between a serif and a sans stack per preset and the demo
   * wordmark measures 110px in one against 123px in the other, so the size and
   * the cap are set for the wider of the two rather than for whichever preset
   * the demo happens to draw today.
   */
  font-size: 0.8rem;
  max-width: 7rem;
  color: var(--sp-ink);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.kvk-slinks {
  display: flex;
  gap: 0.75rem;
  font-size: 0.72rem;
  color: var(--sp-muted);
}
.kvk-snav-cta {
  flex: none;
  font-size: 0.68rem;
  font-weight: 700;
  color: var(--sp-on);
  background: var(--sp-brand);
  border-radius: 999px;
  padding: 0.28rem 0.6rem;
  white-space: nowrap;
}
.kvk-shero {
  position: relative;
  margin: 0 0.55rem;
  border-radius: 0.7rem;
  overflow: hidden;
  /*
   * The band takes its height from its contents, as before -- but every line
   * of those contents is now RESERVED (see the eyebrow, title and sub rules
   * below), so the height is the same for the baked demo and for every payload
   * without a magic number here that has to be re-derived whenever the copy
   * moves. min-height stays as the floor it always was.
   */
  min-height: 9.5rem;
  display: flex;
  align-items: center;
}
.kvk-shero-photo {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
}
.kvk-shero-fallback {
  position: absolute;
  inset: 0;
  background: linear-gradient(135deg, var(--sp-brand), color-mix(in srgb, var(--sp-brand) 55%, #000));
}
.kvk-shero-scrim {
  position: absolute;
  inset: 0;
  background: linear-gradient(90deg, rgba(0, 0, 0, 0.6) 0%, rgba(0, 0, 0, 0.34) 55%, rgba(0, 0, 0, 0.12) 100%);
}
.kvk-shero-in {
  position: relative;
  z-index: 2;
  padding: 1.1rem 1.2rem;
  max-width: 82%;
}
.kvk-shero-eyebrow {
  font-size: 0.6rem;
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.82);
  margin-bottom: 0.35rem;
  /*
   * Two reserved lines is the BASE, relaxed to one only in the bands measured
   * to be roomy enough (see the bottom of this file). Deliberately this way
   * round: a media-query gap -- and browser zoom plus fractional display
   * scaling produce layout widths like 1199.33px all the time -- then costs an
   * empty line, not a cut-off city.
   */
  line-height: 1.6;
  height: 3.2em;
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 2;
  overflow: hidden;
}
.kvk-shero-title {
  font-family: var(--sp-head);
  color: #fff;
  font-size: 1.35rem;
  line-height: 1.08;
  letter-spacing: -0.01em;
  margin: 0 0 0.35rem;
  /*
   * Clamped, NOT `white-space: nowrap`. The headline is "{vak} in {plaats}.",
   * which wraps to two or three lines on a narrow card and would outgrow the
   * band. Suppressing the wrap instead makes the title's max-content the floor
   * for the whole hero visual, and the card grew SIDEWAYS: 408px -> 518px at a
   * 360px viewport, right edge off-screen. -webkit-line-clamp keeps the text
   * wrapping for intrinsic sizing and only limits what is painted.
   *
   * TWO reserved lines is the base; the roomy bands relax it to one (see the
   * bottom of this file). That way round on purpose -- a width that falls
   * between media queries then costs an empty line rather than the city.
   */
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 2;
  overflow: hidden;
  /*
   * The reserved lines plus 0.12em. A 1.08 line-height is tighter than this
   * font's content area, so the tails of j/g/p/q hang ~1px below the line box
   * and `overflow: hidden` shaved them. The extra goes in the HEIGHT, not in
   * padding: base.css sets `* { box-sizing: border-box }` globally, so padding
   * would shrink the content box and clip at exactly the same place.
   */
  height: calc(2.16em + 0.12em);
}
.kvk-shero-sub {
  color: rgba(255, 255, 255, 0.85);
  font-size: 0.76rem;
  line-height: 1.6;
  margin: 0 0 0.7rem;
  /*
   * ~34 characters of measure, in rem rather than ch: `ch` is resolved against
   * the font actually in use, so this box -- and with it the whole card, whose
   * width it sets -- grew 13px the moment the webfont swapped in.
   */
  max-width: 16.35rem;
  /*
   * Reserve three lines and clamp to three. Trade intros run 75-113 characters,
   * which is two or three lines at this measure, while the baked demo line is
   * one — so without a reserved box the text block jumped inside the band on
   * every render. The clamp is the guard for the longest intros.
   */
  height: 4.8em;
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 3;
  overflow: hidden;
}
.kvk-shero-cta {
  display: flex;
  gap: 0.45rem;
  flex-wrap: wrap;
}
.kvk-spill {
  font-size: 0.7rem;
  font-weight: 600;
  border-radius: 999px;
  padding: 0.4rem 0.75rem;
  white-space: nowrap;
}
.kvk-spill.is-solid {
  background: var(--sp-brand);
  color: var(--sp-on);
}
.kvk-spill.is-ghost {
  background: rgba(255, 255, 255, 0.14);
  color: #fff;
  border: 1px solid rgba(255, 255, 255, 0.55);
}
.kvk-sservices {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 0.5rem;
  padding: 0.7rem 0.85rem 1rem;
}
.kvk-sservice {
  border-radius: 0.55rem;
  overflow: hidden;
  background: color-mix(in srgb, var(--sp-ink) 5%, transparent);
  border: 1px solid var(--sp-line);
}
.kvk-sthumb {
  position: relative;
  height: 3.1rem;
  background: color-mix(in srgb, var(--sp-brand) 20%, var(--sp-paper));
}
.kvk-sthumb img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
}
.kvk-sthumb .kvk-sthumb-ph {
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  font-size: 0.55rem;
  font-weight: 600;
  color: var(--sp-muted);
  text-align: center;
  padding: 0 0.3rem;
}
.kvk-slabel {
  font-family: var(--sp-head);
  font-size: 0.68rem;
  font-weight: 600;
  color: var(--sp-ink);
  padding: 0.35rem 0.5rem;
  /* One line always: a two-line label made its tile taller than the other two
     and stretched the whole services row. The explicit line-height (and the
     min-height that reserves it) also holds the tile steady when a label is
     empty, and when applyTheme() swaps --sp-head between the serif and sans
     stacks -- `normal` resolves per font, so the row twitched a pixel.

     The cost is an ellipsis on 3 of the 108 service titles at 430px and below
     (none of them the three baked into home.html, so no default pageload shows
     one). Reserving two lines instead would keep every word, at 14px of card
     height on every phone -- not worth it for a caption in a mock, and the
     ellipsis at least says the word was cut. */
  line-height: 1.6;
  min-height: calc(1.6em + 0.7rem);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* invoice + mail row */
.kvk-row-cards {
  display: grid;
  grid-template-columns: 1.35fr 1fr;
  gap: 1rem;
}
/* The invoice is the product's core promise, so it must read as a real, premium
   document and lift off the dark canvas instead of sinking into it. */
.kvk-inv {
  padding: 0.95rem 1.05rem 1.05rem;
  border-color: var(--kvk-line-strong);
  box-shadow: var(--kvk-shadow-pop);
}
.kvk-inv-head {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  margin-bottom: 0.6rem;
}
.kvk-inv-badge {
  font-size: 0.6rem;
  font-weight: 800;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--kvk-violet);
  background: color-mix(in srgb, var(--kvk-violet) 14%, transparent);
  border: 1px solid color-mix(in srgb, var(--kvk-violet) 30%, transparent);
  padding: 0.14rem 0.4rem;
  border-radius: 0.35rem;
}
.kvk-inv-meta {
  font-family: var(--kvk-num);
  font-size: 0.68rem;
  color: var(--kvk-ink-faint);
  letter-spacing: -0.01em;
}
.kvk-inv-head .kvk-inv-status {
  margin-left: auto;
}
.kvk-inv-who {
  font-weight: 700;
  font-size: 0.95rem;
  letter-spacing: -0.01em;
  margin-bottom: 0.6rem;
  /* bounded -- see .kvk-swordmark */
  max-width: 14rem;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
/* Inset "sheet" so the amounts read as the body of a document. */
.kvk-inv-sheet {
  background: var(--kvk-ground-2);
  border: 1px solid var(--kvk-line);
  border-radius: 0.7rem;
  padding: 0.55rem 0.75rem 0.7rem;
}
.kvk-inv-status {
  flex: none;
  font-size: 0.64rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.03em;
  padding: 0.12rem 0.45rem;
  border-radius: 999px;
  color: var(--kvk-ink-faint);
  background: var(--kvk-ground-2);
  border: 1px solid var(--kvk-line);
  transition: all 0.3s ease;
}
.kvk-inv-status.is-paid {
  color: #fff;
  background: var(--kvk-green);
  border-color: transparent;
}
.kvk-inv-line {
  display: flex;
  justify-content: space-between;
  font-size: 0.8rem;
  color: var(--kvk-ink-soft);
  padding: 0.28rem 0;
  border-bottom: 1px dashed var(--kvk-line);
}
.kvk-inv-sheet .kvk-inv-line:last-of-type {
  border-bottom: none;
}
.kvk-inv-line .kvk-amt {
  font-family: var(--kvk-num);
  font-variant-numeric: tabular-nums;
  color: var(--kvk-ink);
}
.kvk-inv-total {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  margin-top: 0.6rem;
  padding-top: 0.55rem;
  border-top: 1.5px solid var(--kvk-line-strong);
}
.kvk-inv-total .kvk-lbl {
  font-size: 0.72rem;
  font-weight: 600;
  color: var(--kvk-ink-faint);
  text-transform: uppercase;
  letter-spacing: 0.03em;
}
.kvk-inv-total .kvk-big {
  font-family: var(--kvk-num);
  font-variant-numeric: tabular-nums;
  font-weight: 800;
  font-size: 1.5rem;
  letter-spacing: -0.02em;
  color: var(--kvk-ink);
}
.kvk-ideal {
  margin-top: 0.8rem;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 0.45rem;
  font-size: 0.82rem;
  font-weight: 700;
  color: #fff;
  background: var(--kvk-green);
  border-radius: 0.6rem;
  padding: 0.6rem;
  box-shadow: 0 6px 16px rgba(5, 150, 105, 0.32);
  transition: background 0.3s ease;
}
.kvk-ideal-mark {
  font-size: 0.66rem;
  font-weight: 800;
  font-style: italic;
  letter-spacing: -0.02em;
  color: #fff;
  background: rgba(255, 255, 255, 0.22);
  padding: 0.08rem 0.3rem;
  border-radius: 0.28rem;
}
.kvk-inv-note {
  margin-top: 0.6rem;
  display: flex;
  align-items: center;
  gap: 0.35rem;
  font-size: 0.68rem;
  font-weight: 500;
  color: var(--kvk-ink-faint);
}
.kvk-inv-note svg {
  flex: none;
  color: var(--kvk-green);
}
.kvk-ideal .kvk-chk {
  display: none;
}
.kvk-ideal.is-paid .kvk-chk {
  display: flex;
  animation: kvk-pop 0.3s ease-out both;
}
.kvk-money-toast {
  position: absolute;
  right: 0.7rem;
  top: 2.4rem;
  z-index: 8;
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
  font-size: 0.74rem;
  font-weight: 700;
  color: #fff;
  background: linear-gradient(135deg, var(--kvk-green), #10b981);
  padding: 0.35rem 0.6rem;
  border-radius: 0.5rem;
  box-shadow: 0 8px 20px rgba(5, 150, 105, 0.4);
  opacity: 0;
  pointer-events: none;
}
.kvk-money-toast.is-fly {
  animation: kvk-fly 1.9s ease-out forwards;
}
@keyframes kvk-fly {
  0% {
    opacity: 0;
    transform: translateY(0.375rem) scale(0.9);
  }
  15% {
    opacity: 1;
    transform: translateY(0) scale(1);
  }
  70% {
    opacity: 1;
    transform: translateY(-0.25rem);
  }
  100% {
    opacity: 0;
    transform: translateY(-1rem);
  }
}

.kvk-mail {
  padding: 1rem 1.1rem;
  display: flex;
  flex-direction: column;
  gap: 0.65rem;
}
.kvk-mail-head {
  display: flex;
  align-items: center;
  gap: 0.45rem;
  font-size: 0.72rem;
  font-weight: 600;
  color: var(--kvk-ink-faint);
  text-transform: uppercase;
  letter-spacing: 0.03em;
}
.kvk-mail-addr-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.5rem;
}
.kvk-mail-addr {
  font-family: var(--kvk-num);
  font-size: 0.8rem;
  font-weight: 600;
  color: var(--kvk-violet);
  /*
   * hallo@{slug}.nl, and the slug is the company name -- see .kvk-swordmark.
   * The floor matters as much as the cap here: once the card stopped growing
   * to fit its content, this row was the first thing squeezed, and the demo's
   * own address started rendering as "hallo@houtwerkkessel...". A bounded
   * min-width buys back just enough width without handing the card back to
   * its content.
   */
  min-width: 11.75rem;
  max-width: 13rem;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.kvk-mail-verified {
  flex: none;
  display: inline-flex;
  align-items: center;
  gap: 0.22rem;
  font-size: 0.6rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.03em;
  color: var(--kvk-green);
  background: color-mix(in srgb, var(--kvk-green) 12%, transparent);
  border: 1px solid color-mix(in srgb, var(--kvk-green) 28%, transparent);
  padding: 0.12rem 0.35rem;
  border-radius: 999px;
}
.kvk-mail-item {
  border-top: 1px solid var(--kvk-line);
  padding-top: 0.55rem;
  transition: opacity 0.4s ease, transform 0.4s ease;
}
.kvk-mail-item.is-incoming {
  opacity: 0;
  transform: translateY(0.375rem);
}
.kvk-mail-item.is-read {
  opacity: 0.72;
}
.kvk-mail-from {
  font-size: 0.78rem;
  font-weight: 600;
  display: flex;
  align-items: center;
}
.kvk-mail-dot {
  display: inline-block;
  width: 0.45rem;
  height: 0.45rem;
  border-radius: 50%;
  background: var(--kvk-line-strong);
  margin-right: 0.4rem;
}
.kvk-mail-sub {
  font-size: 0.74rem;
  color: var(--kvk-ink-soft);
}
.kvk-mail-snip {
  font-size: 0.72rem;
  color: var(--kvk-ink-faint);
}
.kvk-unread {
  display: inline-block;
  width: 0.45rem;
  height: 0.45rem;
  border-radius: 50%;
  background: var(--kvk-violet);
  margin-right: 0.4rem;
}
.kvk-unread.is-ping {
  animation: kvk-ping 1.4s ease-out 2;
}
@keyframes kvk-ping {
  0% {
    box-shadow: 0 0 0 0 rgba(124, 58, 237, 0.6);
  }
  70% {
    box-shadow: 0 0 0 0.45rem rgba(124, 58, 237, 0);
  }
  100% {
    box-shadow: 0 0 0 0 rgba(124, 58, 237, 0);
  }
}

/* ---- responsive ---- */
@media (max-width: 980px) {
  .kvk-hero-copy .kvk-hero-hint {
    display: flex;
  }
  .kvk-canvas {
    scroll-margin-top: 1rem;
    transform: none !important;
  }
  /* The card is narrower here, so the longer service names would sit on the
     ellipsis. A notch smaller keeps the common ones whole. */
  .kvk-slabel {
    font-size: 0.62rem;
  }
}

/*
 * Two reserved headline lines, in the two bands that need them -- NOT simply
 * "narrow". The headline is "{vak} in {plaats}." and the card's width does not
 * fall off monotonically with the viewport: the two-column hero gives the
 * visual its smallest share just above the 980px breakpoint (542px at 981,
 * against 824px at 1440), while the single-column layout at 700-980px is the
 * roomiest of all. Counted against all 42 trade labels with a long city
 * (Nieuwerkerk aan den IJssel -- a real municipality, and picked over
 * 's-Hertogenbosch precisely because sizing against a short city is what put
 * this rule in the wrong place twice), the number needing a second line runs
 * 36 at 360px, 11 at 521, 0 from ~680 to 980, 9 again at 1024, 9 at 1200,
 * 1 at 1280, 0 from 1300 up.
 *
 * So the reserve covers 680px-and-below and 981-1299px, and stays out of the
 * roomy middle -- reserving there is a whole empty line in the band on the
 * state every visitor sees first. A one-line clamp in the bands that DO need
 * it dropped the city and the full stop, which is the half of the headline
 * that makes the preview feel like the visitor's own. 1280x800 is a common
 * laptop, so the old 1199 ceiling was cutting it on real screens.
 */
/*
 * The four places render() writes the visitor's company name into, all of them
 * `white-space: nowrap`. A nowrap string sets the card's max-content width and
 * the card is content-sized, so an unbounded company name pushed the preview's
 * right edge 147px off a 360px screen, where `overflow-x: clip` ate it without
 * a scrollbar to show for it.
 *
 * Bounded at EVERY width, in two tiers. "The card has room up the top end" was
 * measured against a 45-character name and is not true: with a realistic
 * 69-character one out of the handelsregister ("Coöperatieve Vereniging van
 * Eigenaren Nieuwerkerk aan den IJssel U.A.") an unbounded card runs 214px off
 * a 1200px window, 126px off 1300 and still 12px off 1512. A company name has
 * no length ceiling, so neither a breakpoint nor a bigger sample fixes this --
 * only a bound does.
 *
 * The wide tier is loose enough that the objection to capping on desktop (a
 * URL bar pinned to 255px inside an 824px card, with 570px of empty browser
 * chrome beside it) does not apply: at 1440 the domain gets 26rem before the
 * ellipsis, which no real domain reaches.
 *
 * The tight values are the BASE rules on each selector, and the block below is
 * the only media query -- so there is no width at which the bound disappears.
 * Writing it as two mutually exclusive tiers left 1199-1200px uncovered, which
 * is exactly the kind of width browser zoom and fractional display scaling
 * produce, and every cap blinked off there at once.
 */
@media (min-width: 1200px) {
  .kvk-swordmark {
    font-size: 0.95rem;
    max-width: 16rem;
  }
  .kvk-inv-who {
    max-width: 20rem;
  }
  .kvk-mail-addr {
    max-width: 18rem;
  }
  .kvk-urlbar {
    max-width: 26rem;
  }
}

/*
 * Relax to ONE reserved headline and eyebrow line in the two bands with room
 * for it. Written as a relaxation of a safe base rather than as a reserve
 * bolted onto a narrow one, so a width falling between the queries -- browser
 * zoom and fractional display scaling produce layout widths like 1199.33px
 * routinely -- costs an empty line rather than a cut-off city.
 *
 * Which bands: the card's width does not fall off monotonically with the
 * viewport. The single-column layout at 681-980px is the roomiest of all, and
 * from 1300px up the two-column layout has caught back up. Counted against all
 * 42 trade labels with a real long city (Nieuwerkerk aan den IJssel), the
 * number needing a second headline line runs 36 at 360px, 11 at 521, 0 from
 * ~680 to 980, 9 at 1024, 9 at 1200, 1 at 1280, 0 from 1300 up; the eyebrow
 * needs its second on 8 at 981 and 4 at 521, none at 700 or 1199.
 */
@media (min-width: 681px) and (max-width: 980px), (min-width: 1300px) {
  .kvk-shero-title {
    -webkit-line-clamp: 1;
    height: calc(1.08em + 0.12em);
  }
  .kvk-shero-eyebrow {
    -webkit-line-clamp: 1;
    height: 1.6em;
  }
}
@media (max-width: 520px) {
  .kvk-row-cards {
    grid-template-columns: 1fr;
  }
  /* A notch down so the two reserved headline lines are enough here too. At
     1.35rem the longest label ("Kunst, illustratie & handgemaakt") needs three
     lines against a 319px text block and lost the city; at 1.25rem it fits in
     two, which is cheaper than reserving a third line for all 42 trades. The
     reserved height is in em, so it follows this automatically. */
  .kvk-shero-title {
    font-size: 1.25rem;
  }
  /* Money-climax on mobile: the canvas stacks and the CTA sits right below it,
     so end the scroll on the PAID invoice instead of the mailbox. Reordering
     the invoice last makes the story read site live -> lead in je mailbox ->
     factuur betaald -> "Gratis beginnen", with the money moment adjacent to
     the button. (Desktop keeps invoice-left / mail-right, unaffected.) */
  .kvk-row-cards .wrap-2 {
    order: 1;
  }
}

@media (prefers-reduced-motion: reduce) {
  .kvk-canvas.is-assembling .kvk-card-wrap,
  .kvk-money-toast,
  .kvk-unread.is-ping,
  .kvk-hero-hint svg,
  .kvk-field-spinner {
    animation: none !important;
  }
  .kvk-canvas.is-building::after {
    display: none;
  }
}
