/*
Theme Name:   agencyCompare
Theme URI:    https://marketingagencyvergelijker.nl/
Author:       Misha Yazdi
Author URI:   https://essentialswordpress.com/
Description:  Design system and templates for marketingagencyvergelijker.nl — an independent comparison site for Dutch online marketing agencies. Vanilla JS only (no jQuery), animations via a self-hosted Motion build, self-hosted variable fonts.
Version:      1.0.0
Requires at least: 6.5
Requires PHP: 8.3
License:      Proprietary
Text Domain:  agencyCompare
*/

/* ==========================================================================
   1. DESIGN TOKENS
   --------------------------------------------------------------------------
   Light is the default palette and lives on bare :root. Dark redefines only
   the tokens, never the rules, in two places: the prefers-color-scheme query
   (guarded so an explicit light choice still wins) and the [data-theme="dark"]
   attribute the header toggle sets. Never give a colour its only definition
   inside one of those blocks.
   ========================================================================== */

:root {
    /* --- Surfaces ------------------------------------------------------- */
    --colorPaper: #fcfcfa;
    --colorSurface: #ffffff;
    --colorSurfaceRaised: #f4f4ef;
    --colorSurfaceSunken: #efefe8;
    --colorInverse: #101016;
    --colorInverseInk: #f6f6f2;

    /* --- Text ----------------------------------------------------------- */
    --colorInk: #14141a;
    --colorInkMuted: #56565f;
    --colorInkSubtle: #85858f;

    /* --- Lines ---------------------------------------------------------- */
    --colorBorder: #e5e5df;
    --colorBorderStrong: #cdcdc4;

    /* --- Brand ---------------------------------------------------------- */
    --colorBrand: #5b3bef;
    --colorBrandHover: #4b2ed6;
    --colorBrandInk: #ffffff;
    --colorBrandSoft: #eeeaff;
    --colorBrandBorder: #cfc4ff;

    /* --- Highlight -------------------------------------------------------
       Used sparingly: the #1 ranking, a key stat, one CTA per screen. It
       loses all its force the moment it is on more than a few elements. */
    --colorHighlight: #c8f751;
    --colorHighlightInk: #1b2a05;
    --colorHighlightSoft: #f2fdd4;

    /* --- Semantic --------------------------------------------------------
       Deliberately outside the brand hue so a score colour can never be
       mistaken for a brand accent. */
    --colorPositive: #14804f;
    --colorPositiveSoft: #e2f5ec;
    --colorCaution: #a76a05;
    --colorCautionSoft: #fdf1dc;
    --colorNegative: #bf3b2e;
    --colorNegativeSoft: #fce9e7;

    /* --- Focus ---------------------------------------------------------- */
    --colorFocus: #5b3bef;

    /* --- Type ------------------------------------------------------------
       Instrument Serif carries the display sizes, Geist the interface, Geist
       Mono every figure that has to line up in a column (scores, prices). */
    /* Clash Grotesk (Fontshare) — the register opklopper.nl leads with. */
    --fontDisplay: "Clash Grotesk", "Space Grotesk", "Helvetica Neue", Arial, sans-serif;
    --fontBody: "Geist", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
    --fontMono: "Geist Mono", ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace;

    /* Fluid scale, 320px -> 1440px viewport. */
    --textXs: clamp(0.75rem, 0.73rem + 0.09vw, 0.8125rem);
    --textSm: clamp(0.875rem, 0.85rem + 0.11vw, 0.9375rem);
    --textBase: clamp(1rem, 0.97rem + 0.14vw, 1.0625rem);
    --textMd: clamp(1.125rem, 1.08rem + 0.22vw, 1.25rem);
    --textLg: clamp(1.375rem, 1.28rem + 0.45vw, 1.625rem);
    --textXl: clamp(1.75rem, 1.55rem + 0.98vw, 2.375rem);
    --text2xl: clamp(2.25rem, 1.87rem + 1.87vw, 3.375rem);
    --text3xl: clamp(2.875rem, 2.16rem + 3.48vw, 4.875rem);
    --text4xl: clamp(3.5rem, 2.29rem + 5.98vw, 6.875rem);

    --leadingTight: 1.05;
    --leadingSnug: 1.2;
    --leadingNormal: 1.5;
    --leadingRelaxed: 1.65;

    --trackingTight: -0.02em;
    --trackingSnug: -0.01em;
    --trackingWide: 0.02em;
    --trackingWider: 0.08em;

    --weightRegular: 400;
    --weightMedium: 500;
    --weightSemibold: 600;
    --weightBold: 700;

    /* --- Space -----------------------------------------------------------
       8px rhythm; the two sub-8 steps exist for icon and badge padding. */
    --space1: 0.25rem;
    --space2: 0.5rem;
    --space3: 0.75rem;
    --space4: 1rem;
    --space5: 1.5rem;
    --space6: 2rem;
    --space7: 2.5rem;
    --space8: 3rem;
    --space9: 4rem;
    --space10: 5rem;
    --space11: 6.5rem;
    --space12: 8rem;

    /* Section rhythm scales with the viewport. */
    --sectionSpace: clamp(3.5rem, 2.4rem + 5.5vw, 7.5rem);

    /* --- Radius --------------------------------------------------------- */
    --radiusXs: 4px;
    --radiusSm: 8px;
    --radiusMd: 12px;
    --radiusLg: 18px;
    --radiusXl: 28px;
    --radiusFull: 999px;

    /* --- Elevation -------------------------------------------------------
       Tinted with the brand hue rather than pure black, so cards sit on the
       warm paper instead of looking cut out of it. */
    --shadowSm: 0 1px 2px rgba(20, 20, 26, 0.05), 0 1px 3px rgba(20, 20, 26, 0.04);
    --shadowMd: 0 4px 12px rgba(20, 20, 26, 0.06), 0 2px 4px rgba(20, 20, 26, 0.04);
    --shadowLg: 0 18px 40px rgba(28, 22, 60, 0.1), 0 4px 12px rgba(28, 22, 60, 0.06);
    --shadowXl: 0 32px 64px rgba(28, 22, 60, 0.14), 0 8px 20px rgba(28, 22, 60, 0.08);

    /* --- Layout --------------------------------------------------------- */
    --shellWidth: 74rem;
    --shellWidthNarrow: 46rem;
    --shellWidthWide: 88rem;
    --shellGutter: clamp(1.25rem, 0.9rem + 1.7vw, 2.5rem);

    /* --- Motion ----------------------------------------------------------
       Durations are read by inc/js/app.js as well; keep the two in step. */
    --durationFast: 160ms;
    --durationBase: 240ms;
    --durationSlow: 420ms;
    --easeOut: cubic-bezier(0.22, 1, 0.36, 1);
    --easeInOut: cubic-bezier(0.65, 0, 0.35, 1);
}

@media (prefers-color-scheme: dark) {
    :root:not([data-theme="light"]) {
        --colorPaper: #0b0b0f;
        --colorSurface: #131319;
        --colorSurfaceRaised: #1b1b23;
        --colorSurfaceSunken: #08080b;
        --colorInverse: #f6f6f2;
        --colorInverseInk: #101016;

        --colorInk: #f2f2ee;
        --colorInkMuted: #a2a2ae;
        --colorInkSubtle: #71717e;

        --colorBorder: #262630;
        --colorBorderStrong: #3a3a46;

        --colorBrand: #927bff;
        --colorBrandHover: #a794ff;
        --colorBrandInk: #12101f;
        --colorBrandSoft: #1d1834;
        --colorBrandBorder: #34294f;

        --colorHighlight: #c8f751;
        --colorHighlightInk: #1b2a05;
        --colorHighlightSoft: #202b0d;

        --colorPositive: #4ac489;
        --colorPositiveSoft: #10281e;
        --colorCaution: #e0a640;
        --colorCautionSoft: #2b2110;
        --colorNegative: #f2786a;
        --colorNegativeSoft: #2d1614;

        --colorFocus: #927bff;

        --shadowSm: 0 1px 2px rgba(0, 0, 0, 0.5);
        --shadowMd: 0 4px 12px rgba(0, 0, 0, 0.45);
        --shadowLg: 0 18px 40px rgba(0, 0, 0, 0.55);
        --shadowXl: 0 32px 64px rgba(0, 0, 0, 0.6);
    }
}

:root[data-theme="dark"] {
    --colorPaper: #0b0b0f;
    --colorSurface: #131319;
    --colorSurfaceRaised: #1b1b23;
    --colorSurfaceSunken: #08080b;
    --colorInverse: #f6f6f2;
    --colorInverseInk: #101016;

    --colorInk: #f2f2ee;
    --colorInkMuted: #a2a2ae;
    --colorInkSubtle: #71717e;

    --colorBorder: #262630;
    --colorBorderStrong: #3a3a46;

    --colorBrand: #927bff;
    --colorBrandHover: #a794ff;
    --colorBrandInk: #12101f;
    --colorBrandSoft: #1d1834;
    --colorBrandBorder: #34294f;

    --colorHighlight: #c8f751;
    --colorHighlightInk: #1b2a05;
    --colorHighlightSoft: #202b0d;

    --colorPositive: #4ac489;
    --colorPositiveSoft: #10281e;
    --colorCaution: #e0a640;
    --colorCautionSoft: #2b2110;
    --colorNegative: #f2786a;
    --colorNegativeSoft: #2d1614;

    --colorFocus: #927bff;

    --shadowSm: 0 1px 2px rgba(0, 0, 0, 0.5);
    --shadowMd: 0 4px 12px rgba(0, 0, 0, 0.45);
    --shadowLg: 0 18px 40px rgba(0, 0, 0, 0.55);
    --shadowXl: 0 32px 64px rgba(0, 0, 0, 0.6);
}

/* ==========================================================================
   2. RESET + BASE
   ========================================================================== */

*,
*::before,
*::after {
    box-sizing: border-box;
}

html {
    -webkit-text-size-adjust: 100%;
    scroll-behavior: smooth;
    scroll-padding-top: 6rem;
}

body {
    margin: 0;
    background-color: var(--colorPaper);
    color: var(--colorInk);
    font-family: var(--fontBody);
    font-size: var(--textBase);
    line-height: var(--leadingRelaxed);
    font-weight: var(--weightRegular);
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
    text-rendering: optimizeLegibility;
    font-synthesis-weight: none;

    /* This site's own name is a 29-character unbreakable token, and so are the
       agency URLs and several Dutch compounds in the copy. Without this, one
       of them pushes the whole page sideways on a narrow phone. */
    overflow-wrap: break-word;
}

h1, h2, h3, h4, h5, h6, p, figure, blockquote, dl, dd {
    margin: 0;
}

ul, ol {
    margin: 0;
    padding: 0;
}

img, picture, video, canvas, svg {
    display: block;
    max-width: 100%;
    height: auto;
}

input, button, textarea, select {
    font: inherit;
    color: inherit;
}

button {
    background: none;
    border: 0;
    cursor: pointer;
}

a {
    color: var(--colorBrand);
    text-decoration-thickness: 1px;
    text-underline-offset: 0.18em;
}

a:hover {
    color: var(--colorBrandHover);
}

:focus-visible {
    outline: 2px solid var(--colorFocus);
    outline-offset: 3px;
    border-radius: var(--radiusXs);
}

::selection {
    background-color: var(--colorHighlight);
    color: var(--colorHighlightInk);
}

hr {
    height: 1px;
    border: 0;
    margin: var(--space7) 0;
    background-color: var(--colorBorder);
}

/* Skip link — visible only once focused. */
.skipLink {
    position: absolute;
    left: var(--space4);
    top: var(--space4);
    z-index: 999;
    padding: var(--space3) var(--space4);
    border-radius: var(--radiusSm);
    background-color: var(--colorInk);
    color: var(--colorPaper);
    font-weight: var(--weightMedium);
    text-decoration: none;
    transform: translateY(-150%);
    transition: transform var(--durationFast) var(--easeOut);
}

.skipLink:focus-visible {
    transform: translateY(0);
}

.visuallyHidden {
    position: absolute;
    width: 1px;
    height: 1px;
    margin: -1px;
    padding: 0;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
    border: 0;
}

/* ==========================================================================
   3. TYPOGRAPHY
   ========================================================================== */

.displayHuge,
.displayLarge,
.displayMedium,
.displaySmall {
    font-family: var(--fontDisplay);
    font-weight: var(--weightMedium);
    line-height: var(--leadingTight);
    letter-spacing: var(--trackingTight);
    text-wrap: balance;
}

.displayHuge { font-size: var(--text4xl); }
.displayLarge { font-size: var(--text3xl); }
.displayMedium { font-size: var(--text2xl); }
.displaySmall { font-size: var(--textXl); line-height: var(--leadingSnug); }

/* Emphasis inside a headline. Clash Grotesk ships no italic, so the accent is
   carried by weight and colour rather than a synthesised slant. */
.displayHuge em,
.displayLarge em,
.displayMedium em,
.displaySmall em {
    font-style: normal;
    font-weight: var(--weightSemibold);
    color: var(--colorBrand);
}

.headingLarge,
.headingMedium,
.headingSmall {
    font-family: var(--fontBody);
    font-weight: var(--weightSemibold);
    letter-spacing: var(--trackingSnug);
    line-height: var(--leadingSnug);
    text-wrap: balance;
}

.headingLarge { font-size: var(--textLg); }
.headingMedium { font-size: var(--textMd); }
.headingSmall { font-size: var(--textBase); }

.leadText {
    font-size: var(--textMd);
    line-height: var(--leadingRelaxed);
    color: var(--colorInkMuted);
    text-wrap: pretty;
}

.bodyText {
    text-wrap: pretty;
}

.smallText {
    font-size: var(--textSm);
    color: var(--colorInkMuted);
}

.microText {
    font-size: var(--textXs);
    color: var(--colorInkSubtle);
}

/* Section eyebrow: small, tracked-out, mono. */
.eyebrow {
    display: inline-flex;
    align-items: center;
    gap: var(--space2);
    font-family: var(--fontMono);
    font-size: var(--textXs);
    font-weight: var(--weightMedium);
    letter-spacing: var(--trackingWider);
    text-transform: uppercase;
    color: var(--colorInkSubtle);
}

.eyebrow::before {
    content: "";
    width: 1.5rem;
    height: 1px;
    background-color: var(--colorBorderStrong);
}

/* Every figure that sits in a column — scores, prices, review counts — so the
   digits line up regardless of value. */
.numeric {
    font-family: var(--fontMono);
    font-variant-numeric: tabular-nums;
    font-feature-settings: "tnum" 1;
    letter-spacing: var(--trackingSnug);
}

/* Long-form prose: the only place where bare tag selectors are allowed. */
.prose > * + * {
    margin-top: var(--space4);
}

.prose h2 {
    font-family: var(--fontDisplay);
    font-weight: var(--weightMedium);
    font-size: var(--textXl);
    line-height: var(--leadingSnug);
    letter-spacing: var(--trackingTight);
    margin-top: var(--space8);
}

.prose h3 {
    font-size: var(--textMd);
    font-weight: var(--weightSemibold);
    margin-top: var(--space6);
}

.prose ul,
.prose ol {
    padding-left: var(--space5);
}

.prose li + li {
    margin-top: var(--space2);
}

.prose blockquote {
    margin: var(--space6) 0;
    padding: var(--space4) var(--space5);
    border-left: 3px solid var(--colorBrand);
    background-color: var(--colorBrandSoft);
    border-radius: 0 var(--radiusMd) var(--radiusMd) 0;
    font-family: var(--fontDisplay);
    font-size: var(--textMd);
    line-height: var(--leadingNormal);
}

.prose code {
    font-family: var(--fontMono);
    font-size: 0.9em;
    padding: 0.15em 0.4em;
    border-radius: var(--radiusXs);
    background-color: var(--colorSurfaceRaised);
}

/* ==========================================================================
   4. LAYOUT
   ========================================================================== */

.shell {
    width: 100%;
    max-width: var(--shellWidth);
    margin-inline: auto;
    padding-inline: var(--shellGutter);
}

.shellNarrow { max-width: var(--shellWidthNarrow); }
.shellWide { max-width: var(--shellWidthWide); }

.section {
    padding-block: var(--sectionSpace);
}

.sectionTight {
    padding-block: calc(var(--sectionSpace) * 0.55);
}

/* For a section that directly follows a hero: two stacked section paddings
   read as a gap where something failed to render. */
.sectionFlushTop {
    padding-block-start: 0;
}

.sectionSurface { background-color: var(--colorSurface); }
.sectionRaised { background-color: var(--colorSurfaceRaised); }

.sectionInverse {
    background-color: var(--colorInverse);
    color: var(--colorInverseInk);
}

.sectionHeader {
    display: flex;
    flex-direction: column;
    gap: var(--space3);
    max-width: var(--shellWidthNarrow);
    margin-bottom: var(--space7);
}

.stack {
    display: flex;
    flex-direction: column;
    gap: var(--space4);
}

.stackTight { gap: var(--space2); }
.stackLoose { gap: var(--space6); }

.cluster {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--space3);
}

.grid {
    display: grid;
    gap: var(--space5);
}

/* Auto-fit cards without a media query per breakpoint. */
.gridCards {
    display: grid;
    gap: var(--space5);
    grid-template-columns: repeat(auto-fit, minmax(min(18rem, 100%), 1fr));
}

.gridHalves {
    display: grid;
    gap: var(--space6);
    grid-template-columns: repeat(auto-fit, minmax(min(22rem, 100%), 1fr));
}

/* ==========================================================================
   5. COMPONENTS
   ========================================================================== */

/* --- Buttons ------------------------------------------------------------ */

.buttonPrimary,
.buttonSecondary,
.buttonGhost,
.buttonHighlight {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: var(--space2);
    padding: var(--space3) var(--space5);
    border-radius: var(--radiusFull);
    border: 1px solid transparent;
    font-size: var(--textSm);
    font-weight: var(--weightSemibold);
    letter-spacing: var(--trackingSnug);
    line-height: 1.2;
    text-decoration: none;
    white-space: nowrap;
    cursor: pointer;
    transition:
        background-color var(--durationFast) var(--easeOut),
        border-color var(--durationFast) var(--easeOut),
        color var(--durationFast) var(--easeOut),
        transform var(--durationFast) var(--easeOut),
        box-shadow var(--durationFast) var(--easeOut);
}

.buttonPrimary {
    background-color: var(--colorBrand);
    color: var(--colorBrandInk);
    box-shadow: var(--shadowSm);
}

.buttonPrimary:hover {
    background-color: var(--colorBrandHover);
    color: var(--colorBrandInk);
    transform: translateY(-1px);
    box-shadow: var(--shadowMd);
}

.buttonSecondary {
    background-color: var(--colorSurface);
    border-color: var(--colorBorderStrong);
    color: var(--colorInk);
}

.buttonSecondary:hover {
    border-color: var(--colorInk);
    color: var(--colorInk);
    transform: translateY(-1px);
}

.buttonGhost {
    background-color: transparent;
    color: var(--colorInkMuted);
    padding-inline: var(--space3);
}

.buttonGhost:hover {
    background-color: var(--colorSurfaceRaised);
    color: var(--colorInk);
}

/* On the inverse band the page ink is the background colour, so the ghost
   button has to borrow the inverse ink instead. */
.sectionInverse .buttonGhost {
    color: var(--colorInverseInk);
    border-color: color-mix(in srgb, var(--colorInverseInk) 24%, transparent);
    opacity: 0.85;
}

.sectionInverse .buttonGhost:hover {
    background-color: color-mix(in srgb, var(--colorInverseInk) 12%, transparent);
    color: var(--colorInverseInk);
    opacity: 1;
}

.buttonHighlight {
    background-color: var(--colorHighlight);
    color: var(--colorHighlightInk);
}

.buttonHighlight:hover {
    color: var(--colorHighlightInk);
    transform: translateY(-1px);
    box-shadow: var(--shadowMd);
}

.buttonLarge {
    padding: var(--space4) var(--space6);
    font-size: var(--textBase);
}

.buttonSmall {
    padding: var(--space2) var(--space3);
    font-size: var(--textXs);
}

.buttonPrimary:active,
.buttonSecondary:active,
.buttonHighlight:active {
    transform: translateY(0);
}

.buttonPrimary[disabled],
.buttonSecondary[disabled] {
    opacity: 0.5;
    pointer-events: none;
}

/* --- Card --------------------------------------------------------------- */

.card {
    display: flex;
    flex-direction: column;
    gap: var(--space3);
    padding: var(--space5);
    border: 1px solid var(--colorBorder);
    border-radius: var(--radiusLg);
    background-color: var(--colorSurface);
    transition:
        border-color var(--durationBase) var(--easeOut),
        box-shadow var(--durationBase) var(--easeOut),
        transform var(--durationBase) var(--easeOut);
}

.cardInteractive:hover {
    border-color: var(--colorBrandBorder);
    box-shadow: var(--shadowLg);
    transform: translateY(-2px);
}

.cardFeatured {
    border-color: var(--colorBrandBorder);
    box-shadow: var(--shadowLg);
}

.cardPadded { padding: var(--space6); }

/* --- Pill / badge ------------------------------------------------------- */

.pill {
    display: inline-flex;
    align-items: center;
    gap: var(--space1);
    padding: 0.3rem var(--space3);
    border-radius: var(--radiusFull);
    border: 1px solid var(--colorBorder);
    background-color: var(--colorSurfaceRaised);
    color: var(--colorInkMuted);
    font-size: var(--textXs);
    font-weight: var(--weightMedium);
    letter-spacing: var(--trackingSnug);
    white-space: nowrap;
}

.pillBrand {
    background-color: var(--colorBrandSoft);
    border-color: var(--colorBrandBorder);
    color: var(--colorBrand);
}

.pillHighlight {
    background-color: var(--colorHighlight);
    border-color: transparent;
    color: var(--colorHighlightInk);
    font-weight: var(--weightSemibold);
}

.pillPositive {
    background-color: var(--colorPositiveSoft);
    border-color: transparent;
    color: var(--colorPositive);
}

.pillCaution {
    background-color: var(--colorCautionSoft);
    border-color: transparent;
    color: var(--colorCaution);
}

.pillNegative {
    background-color: var(--colorNegativeSoft);
    border-color: transparent;
    color: var(--colorNegative);
}

/* --- Rank badge ---------------------------------------------------------
   The position marker in the agency ranking. rankBadgeTop is reserved for
   #1 and is the single loudest element on the page. */

.rankBadge {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    inline-size: 2.75rem;
    block-size: 2.75rem;
    border-radius: var(--radiusMd);
    background-color: var(--colorSurfaceRaised);
    border: 1px solid var(--colorBorder);
    color: var(--colorInkMuted);
    font-family: var(--fontMono);
    font-size: var(--textMd);
    font-weight: var(--weightSemibold);
    font-variant-numeric: tabular-nums;
    flex-shrink: 0;
}

.rankBadgeTop {
    background-color: var(--colorHighlight);
    border-color: transparent;
    color: var(--colorHighlightInk);
    box-shadow: var(--shadowMd);
}

.rankBadgeRunnerUp {
    background-color: var(--colorBrandSoft);
    border-color: var(--colorBrandBorder);
    color: var(--colorBrand);
}

/* --- Score meter --------------------------------------------------------
   A numeric score plus a proportional bar. --scoreValue (0-10) is set inline
   per instance; the bar width is derived from it so markup carries the number
   exactly once. */

.scoreMeter {
    display: flex;
    flex-direction: column;
    gap: var(--space2);
    min-inline-size: 7rem;
}

.scoreMeterValue {
    display: flex;
    align-items: baseline;
    gap: var(--space1);
    font-family: var(--fontMono);
    font-variant-numeric: tabular-nums;
    font-size: var(--textLg);
    font-weight: var(--weightSemibold);
    line-height: 1;
    color: var(--colorInk);
}

.scoreMeterMax {
    font-size: var(--textXs);
    font-weight: var(--weightRegular);
    color: var(--colorInkSubtle);
}

.scoreMeterTrack {
    position: relative;
    block-size: 6px;
    border-radius: var(--radiusFull);
    background-color: var(--colorSurfaceSunken);
    overflow: hidden;
}

.scoreMeterFill {
    display: block;
    block-size: 100%;
    border-radius: inherit;
    background-color: var(--colorPositive);
    inline-size: calc(var(--scoreValue, 0) * 10%);
    transform-origin: left center;
}

.scoreMeterCaution .scoreMeterFill { background-color: var(--colorCaution); }
.scoreMeterNegative .scoreMeterFill { background-color: var(--colorNegative); }
.scoreMeterBrand .scoreMeterFill { background-color: var(--colorBrand); }

/* --- Star rating -------------------------------------------------------- */

.starRating {
    display: inline-flex;
    align-items: center;
    gap: var(--space1);
    color: var(--colorCaution);
}

.starRatingCount {
    color: var(--colorInkSubtle);
    font-size: var(--textXs);
    font-family: var(--fontMono);
}

/* --- Stat ---------------------------------------------------------------- */

.statList {
    display: grid;
    gap: var(--space5);
    grid-template-columns: repeat(auto-fit, minmax(min(11rem, 100%), 1fr));
}

.stat {
    display: flex;
    flex-direction: column;
    gap: var(--space1);
}

.statValue {
    font-family: var(--fontDisplay);
    font-weight: var(--weightSemibold);
    font-size: var(--text2xl);
    line-height: 1;
    letter-spacing: var(--trackingTight);
    font-variant-numeric: tabular-nums;
}

.statLabel {
    font-size: var(--textSm);
    color: var(--colorInkMuted);
    text-wrap: pretty;
}

/* --- Table --------------------------------------------------------------
   Wide tables must scroll inside their own container, never the page. */

.tableScroll {
    overflow-x: auto;
    border: 1px solid var(--colorBorder);
    border-radius: var(--radiusLg);
    background-color: var(--colorSurface);
}

.comparisonTable {
    inline-size: 100%;
    border-collapse: collapse;
    font-size: var(--textSm);
}

.comparisonTable th,
.comparisonTable td {
    padding: var(--space3) var(--space4);
    text-align: left;
    vertical-align: middle;
    border-bottom: 1px solid var(--colorBorder);
    white-space: nowrap;
}

.comparisonTable thead th {
    position: sticky;
    top: 0;
    z-index: 1;
    background-color: var(--colorSurfaceRaised);
    font-size: var(--textXs);
    font-weight: var(--weightSemibold);
    letter-spacing: var(--trackingWide);
    text-transform: uppercase;
    color: var(--colorInkMuted);
}

.comparisonTable tbody tr:last-child th,
.comparisonTable tbody tr:last-child td {
    border-bottom: 0;
}

.comparisonTable tbody tr:hover {
    background-color: var(--colorSurfaceRaised);
}

.comparisonTable .numeric {
    text-align: right;
}

/* --- Accordion ----------------------------------------------------------
   Built on <details>, so it works with JS disabled and stays keyboard
   accessible without any ARIA wiring. */

.accordion {
    display: flex;
    flex-direction: column;
    border: 1px solid var(--colorBorder);
    border-radius: var(--radiusLg);
    background-color: var(--colorSurface);
    overflow: hidden;
}

.accordionItem + .accordionItem {
    border-top: 1px solid var(--colorBorder);
}

.accordionSummary {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--space4);
    padding: var(--space4) var(--space5);
    cursor: pointer;
    font-weight: var(--weightMedium);
    list-style: none;
    transition: background-color var(--durationFast) var(--easeOut);
}

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

.accordionSummary:hover {
    background-color: var(--colorSurfaceRaised);
}

.accordionIcon {
    flex-shrink: 0;
    inline-size: 1.25rem;
    block-size: 1.25rem;
    color: var(--colorInkSubtle);
    transition: transform var(--durationBase) var(--easeOut);
}

.accordionItem[open] .accordionIcon {
    transform: rotate(45deg);
}

.accordionPanel {
    padding: 0 var(--space5) var(--space5);
    color: var(--colorInkMuted);
    text-wrap: pretty;
}

/* --- Breadcrumb ---------------------------------------------------------- */

.breadcrumb {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--space2);
    font-size: var(--textXs);
    color: var(--colorInkSubtle);
    list-style: none;
}

.breadcrumb li {
    display: flex;
    align-items: center;
    gap: var(--space2);
}

.breadcrumb li + li::before {
    content: "/";
    color: var(--colorBorderStrong);
}

.breadcrumb a {
    color: var(--colorInkMuted);
    text-decoration: none;
}

.breadcrumb a:hover {
    color: var(--colorInk);
    text-decoration: underline;
}

/* --- Forms --------------------------------------------------------------- */

.fieldLabel {
    display: block;
    margin-bottom: var(--space2);
    font-size: var(--textSm);
    font-weight: var(--weightMedium);
}

.fieldInput,
.fieldSelect,
.fieldTextarea {
    inline-size: 100%;
    padding: var(--space3) var(--space4);
    border: 1px solid var(--colorBorderStrong);
    border-radius: var(--radiusMd);
    background-color: var(--colorSurface);
    color: var(--colorInk);
    font-size: var(--textSm);
    transition:
        border-color var(--durationFast) var(--easeOut),
        box-shadow var(--durationFast) var(--easeOut);
}

.fieldInput::placeholder,
.fieldTextarea::placeholder {
    color: var(--colorInkSubtle);
}

.fieldInput:focus,
.fieldSelect:focus,
.fieldTextarea:focus {
    outline: none;
    border-color: var(--colorBrand);
    box-shadow: 0 0 0 3px var(--colorBrandSoft);
}

.fieldTextarea {
    min-block-size: 8rem;
    resize: vertical;
}

.fieldHint {
    margin-top: var(--space2);
    font-size: var(--textXs);
    color: var(--colorInkSubtle);
}

/* --- Site header --------------------------------------------------------- */

.siteHeader {
    position: sticky;
    top: 0;
    z-index: 50;
    background-color: color-mix(in srgb, var(--colorPaper) 85%, transparent);
    backdrop-filter: blur(12px);
    border-bottom: 1px solid transparent;
    transition:
        border-color var(--durationBase) var(--easeOut),
        background-color var(--durationBase) var(--easeOut);
}

/* Set by app.js once the page is scrolled past the header. */
.siteHeaderScrolled {
    border-bottom-color: var(--colorBorder);
}

.siteHeaderInner {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--space5);
    min-block-size: 4.5rem;
}

.siteLogo {
    display: inline-flex;
    align-items: baseline;
    gap: 0.1em;
    font-family: var(--fontDisplay);
    font-weight: var(--weightSemibold);
    font-size: var(--textLg);
    letter-spacing: var(--trackingTight);
    color: var(--colorInk);
    text-decoration: none;
    white-space: nowrap;
}

.siteLogoAccent {
    color: var(--colorBrand);
    font-weight: var(--weightMedium);
}

.primaryNav {
    display: flex;
    align-items: center;
    gap: var(--space5);
    list-style: none;
}

.primaryNav a {
    color: var(--colorInkMuted);
    font-size: var(--textSm);
    font-weight: var(--weightMedium);
    text-decoration: none;
    transition: color var(--durationFast) var(--easeOut);
}

.primaryNav a:hover,
.primaryNav .current-menu-item > a {
    color: var(--colorInk);
}

.headerActions {
    display: flex;
    align-items: center;
    gap: var(--space3);
    flex-shrink: 0;
}

/* "Marketingagencyvergelijker" is a long word that cannot wrap, so on the
   narrowest phones it pushes the theme and menu buttons off the right edge.
   Shrinking the wordmark and tightening the row keeps everything inside 320px
   without truncating the brand name. */
@media (max-width: 26rem) {
    .siteHeaderInner {
        gap: var(--space3);
    }

    .siteLogo {
        font-size: var(--textBase);
    }
}

.themeToggle {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    inline-size: 2.25rem;
    block-size: 2.25rem;
    border-radius: var(--radiusFull);
    border: 1px solid var(--colorBorder);
    color: var(--colorInkMuted);
    transition:
        color var(--durationFast) var(--easeOut),
        border-color var(--durationFast) var(--easeOut);
}

.themeToggle:hover {
    color: var(--colorInk);
    border-color: var(--colorBorderStrong);
}

.themeToggleSun { display: none; }
.themeToggleMoon { display: block; }

@media (prefers-color-scheme: dark) {
    :root:not([data-theme="light"]) .themeToggleSun { display: block; }
    :root:not([data-theme="light"]) .themeToggleMoon { display: none; }
}

:root[data-theme="dark"] .themeToggleSun { display: block; }
:root[data-theme="dark"] .themeToggleMoon { display: none; }

.navToggle {
    display: none;
    align-items: center;
    justify-content: center;
    inline-size: 2.25rem;
    block-size: 2.25rem;
    border-radius: var(--radiusFull);
    border: 1px solid var(--colorBorder);
    color: var(--colorInk);
}

@media (max-width: 60rem) {
    .navToggle { display: inline-flex; }

    .primaryNav {
        position: absolute;
        inset-inline: var(--shellGutter);
        top: calc(100% + var(--space2));
        flex-direction: column;
        align-items: stretch;
        gap: var(--space1);
        padding: var(--space4);
        border: 1px solid var(--colorBorder);
        border-radius: var(--radiusLg);
        background-color: var(--colorSurface);
        box-shadow: var(--shadowLg);
    }

    .primaryNav[hidden] { display: none; }

    .primaryNav a {
        display: block;
        padding: var(--space2) var(--space3);
        border-radius: var(--radiusSm);
    }

    .primaryNav a:hover {
        background-color: var(--colorSurfaceRaised);
    }
}

@media (min-width: 60.0625rem) {
    /* [hidden] is how the mobile menu closes; it must not hide the desktop nav. */
    .primaryNav[hidden] { display: flex; }
}

/* --- Site footer ---------------------------------------------------------
   Four columns built from real content, a chip row carrying every specialism,
   and a bottom bar. The columns are not a nav menu on purpose: specialismen
   and onderwerpen get added over time and a hand-kept menu falls behind. */

.siteFooter {
    padding-block: var(--space10) var(--space6);
    border-top: 1px solid var(--colorBorder);
    background-color: var(--colorSurfaceRaised);
    color: var(--colorInkMuted);
    font-size: var(--textSm);
}

.siteFooterGrid {
    display: grid;
    gap: var(--space7);
    grid-template-columns: repeat(auto-fit, minmax(min(13rem, 100%), 1fr));
    margin-bottom: var(--space8);
}

/* The identity column carries the logo, the line and the figures, so it needs
   more room than a list of links. */
@media (min-width: 62rem) {
    .siteFooterGrid {
        grid-template-columns: minmax(0, 1.6fr) repeat(3, minmax(0, 1fr));
        gap: var(--space8);
    }
}

.siteFooter a {
    color: var(--colorInkMuted);
    text-decoration: none;
    transition: color var(--durationFast) var(--easeOut);
}

.siteFooter a:hover {
    color: var(--colorInk);
}

.siteFooterBrand {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: var(--space4);
}

.siteFooterBrand .siteLogo:hover {
    color: inherit;
}

.siteFooterTagline {
    max-inline-size: 26rem;
    line-height: var(--leadingRelaxed);
    text-wrap: pretty;
}

/* --- The three figures ----------------------------------------------------- */

.siteFooterStats {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space6);
    margin-block-start: var(--space1);
}

.siteFooterStats > div {
    display: flex;
    flex-direction: column-reverse;
    gap: var(--space1);
}

.siteFooterStats dt {
    font-size: var(--textXs);
    letter-spacing: var(--trackingWide);
    text-transform: uppercase;
    color: var(--colorInkSubtle);
}

.siteFooterStats dd {
    font-family: var(--fontDisplay);
    font-weight: var(--weightSemibold);
    font-size: var(--textLg);
    line-height: 1;
    letter-spacing: var(--trackingTight);
    color: var(--colorInk);
}

/* --- Link columns ----------------------------------------------------------- */

.siteFooterHeading {
    margin-bottom: var(--space4);
    color: var(--colorInk);
    font-family: var(--fontMono);
    font-size: var(--textXs);
    font-weight: var(--weightMedium);
    letter-spacing: var(--trackingWider);
    text-transform: uppercase;
}

.siteFooterList {
    display: flex;
    flex-direction: column;
    gap: var(--space3);
    list-style: none;
}

/* A hairline that grows from the link on hover — enough of a signal without
   the underline shifting the baseline. */
.siteFooterList a {
    display: inline-block;
    position: relative;
}

.siteFooterList a::after {
    content: "";
    position: absolute;
    inset-inline-start: 0;
    inset-block-end: -2px;
    inline-size: 0;
    block-size: 1px;
    background-color: var(--colorBrand);
    transition: inline-size var(--durationBase) var(--easeOut);
}

.siteFooterList a:hover::after {
    inline-size: 100%;
}

/* --- Specialism chips -------------------------------------------------------- */

.siteFooterChips {
    padding-block: var(--space6);
    border-block-start: 1px solid var(--colorBorder);
}

.siteFooterChipsLabel {
    margin-block-end: var(--space4);
    font-family: var(--fontMono);
    font-size: var(--textXs);
    letter-spacing: var(--trackingWider);
    text-transform: uppercase;
    color: var(--colorInkSubtle);
}

.siteFooterChips ul {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space2);
    list-style: none;
}

.siteFooterChips .pill {
    gap: var(--space2);
    background-color: var(--colorSurface);
}

.siteFooterChips .pill:hover {
    border-color: var(--colorBrandBorder);
    color: var(--colorBrand);
}

.siteFooterChipCount {
    font-size: var(--textXs);
    color: var(--colorInkSubtle);
}

/* --- Bottom bar ---------------------------------------------------------------- */

.siteFooterBottom {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--space3) var(--space5);
    padding-top: var(--space5);
    border-top: 1px solid var(--colorBorder);
    font-size: var(--textXs);
    color: var(--colorInkSubtle);
}

.siteFooterLegal {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--space2) var(--space4);
    list-style: none;
}

.siteFooterTop {
    display: inline-flex;
    align-items: center;
    gap: var(--space2);
    margin-inline-start: auto;
    padding: var(--space2) var(--space4);
    border: 1px solid var(--colorBorder);
    border-radius: var(--radiusFull);
    background-color: var(--colorSurface);
    transition:
        border-color var(--durationFast) var(--easeOut),
        transform var(--durationFast) var(--easeOut);
}

.siteFooterTop:hover {
    border-color: var(--colorBrandBorder);
    color: var(--colorBrand);
    transform: translateY(-1px);
}

/* One arrow asset, pointed up. */
.siteFooterTopIcon {
    transform: rotate(-90deg);
}


/* ==========================================================================
   6. MOTION BASELINE
   --------------------------------------------------------------------------
   MUST STAY IN SYNC WITH THE SELECTORS IN inc/js/app.js. This rule hides the
   animation targets; app.js is the only thing that reveals them. If the two
   drift apart, content silently stays at opacity 0 — so the no-JS and
   reduced-motion escape hatches below are not optional.
   ========================================================================== */

@media (prefers-reduced-motion: no-preference) {
    .js [data-motion] {
        opacity: 0;
        will-change: opacity, transform;
    }
}

/* No JS: .js is never added, so nothing is ever hidden. */
.js [data-motion].isRevealed {
    opacity: 1;
}

/* Belt and braces: honour the OS setting in CSS as well as in app.js. */
@media (prefers-reduced-motion: reduce) {
    .js [data-motion] {
        opacity: 1 !important;
        transform: none !important;
    }

    html {
        scroll-behavior: auto;
    }

    *,
    *::before,
    *::after {
        animation-duration: 0.01ms !important;
        animation-iteration-count: 1 !important;
        transition-duration: 0.01ms !important;
    }
}

/* Per-page opt-out, set through the Page behaviour meta box. */
.motionOff [data-motion] {
    opacity: 1 !important;
    transform: none !important;
}

/* ==========================================================================
   7. UTILITIES
   ========================================================================== */

.textCenter { text-align: center; }
.textMuted { color: var(--colorInkMuted); }
.textSubtle { color: var(--colorInkSubtle); }
.textBrand { color: var(--colorBrand); }
.textPositive { color: var(--colorPositive); }
.textNegative { color: var(--colorNegative); }

.marginAuto { margin-inline: auto; }
.fullWidth { inline-size: 100%; }

.dividerLine {
    block-size: 1px;
    inline-size: 100%;
    background-color: var(--colorBorder);
}

/* ==========================================================================
   8. AGENCY COMPONENTS
   --------------------------------------------------------------------------
   Shared by the ranking (template-comparison) and the single agency profile.
   Page layout for each of those lives in its own stylesheet; what is here is
   the vocabulary both pages are built from.
   ========================================================================== */
/* --- Identity side -------------------------------------------------------- */

.agencyLogo {
    display: flex;
    align-items: center;
    justify-content: center;
    inline-size: 4rem;
    block-size: 4rem;
    padding: var(--space2);
    border: 1px solid var(--colorBorder);
    border-radius: var(--radiusMd);
    background-color: var(--colorSurfaceRaised);
    flex-shrink: 0;
}

.agencyLogoImage {
    inline-size: auto;
    max-block-size: 100%;
    object-fit: contain;
}

.agencyLogoFallback {
    font-family: var(--fontDisplay);
    font-size: var(--textLg);
    letter-spacing: var(--trackingTight);
    color: var(--colorInkSubtle);
}

.agencyName {
    font-family: var(--fontDisplay);
    font-weight: var(--weightSemibold);
    font-size: var(--textLg);
    line-height: var(--leadingSnug);
    letter-spacing: var(--trackingTight);
}

.agencyName a {
    color: inherit;
    text-decoration: none;
}

.agencyName a:hover {
    color: var(--colorBrand);
}

.agencyMeta {
    margin-top: var(--space1);
    font-size: var(--textSm);
    color: var(--colorInkMuted);
}

.agencySummary {
    color: var(--colorInkMuted);
    text-wrap: pretty;
}

.agencyUspList {
    display: grid;
    gap: var(--space2);
    list-style: none;
}

@media (min-width: 40rem) {
    .agencyUspList {
        grid-template-columns: repeat(auto-fit, minmax(min(15rem, 100%), 1fr));
        gap: var(--space2) var(--space5);
    }
}

.agencyUspList li {
    display: flex;
    align-items: flex-start;
    gap: var(--space2);
    font-size: var(--textSm);
}

.agencyUspIcon {
    flex-shrink: 0;
    margin-top: 0.15em;
    color: var(--colorPositive);
}

.agencyTags {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space2);
}

/* --- Verdict side --------------------------------------------------------- */

.verdictSplit {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: var(--space3);
    padding-block: var(--space3);
    border-block: 1px solid var(--colorBorder);
}

.verdictSplit dt {
    font-size: var(--textXs);
    color: var(--colorInkSubtle);
}

.verdictSplit dd {
    margin: 0;
    font-size: var(--textMd);
    font-weight: var(--weightSemibold);
}

.agencyPrice {
    display: flex;
    flex-direction: column;
    gap: 0.1rem;
    font-size: var(--textMd);
    font-weight: var(--weightSemibold);
}

.agencyPriceUnit {
    font-family: var(--fontBody);
    font-size: var(--textXs);
    font-weight: var(--weightRegular);
    color: var(--colorInkSubtle);
}

.agencyActions {
    display: flex;
    flex-direction: column;
    gap: var(--space2);
    margin-top: var(--space1);
}

.agencyDisclosure {
    text-align: center;
}

/* --- Criterion bars -------------------------------------------------------- */

.criterionList {
    display: flex;
    flex-direction: column;
    gap: var(--space3);
}

.criterionRow {
    display: grid;
    grid-template-columns: minmax(0, 1fr) 6rem 2.5rem;
    align-items: center;
    gap: var(--space3);
}

.criterionLabel {
    font-size: var(--textSm);
    color: var(--colorInkMuted);
    text-wrap: pretty;
}

.criterionTrack {
    block-size: 6px;
    border-radius: var(--radiusFull);
    background-color: var(--colorSurfaceSunken);
    overflow: hidden;
}

.criterionFill {
    display: block;
    block-size: 100%;
    inline-size: calc(var(--scoreValue, 0) * 10%);
    border-radius: inherit;
    background-color: var(--colorBrand);
}

.criterionValue {
    font-size: var(--textSm);
    font-weight: var(--weightSemibold);
    text-align: right;
}

@media (max-width: 40rem) {
    .criterionRow {
        grid-template-columns: minmax(0, 1fr) 4rem 2.5rem;
    }
}

/* --- Pros / cons ----------------------------------------------------------- */

.prosConsGrid {
    display: grid;
    gap: var(--space6);
    grid-template-columns: repeat(auto-fit, minmax(min(18rem, 100%), 1fr));
}

.verdictList {
    display: flex;
    flex-direction: column;
    gap: var(--space2);
    list-style: none;
}

.verdictList li {
    display: flex;
    align-items: flex-start;
    gap: var(--space2);
    font-size: var(--textSm);
}

.verdictIcon {
    flex-shrink: 0;
    margin-top: 0.15em;
}

.verdictListPros .verdictIcon { color: var(--colorPositive); }
.verdictListCons .verdictIcon { color: var(--colorNegative); }

/* --- Fact grid ------------------------------------------------------------- */

.factGrid {
    display: grid;
    gap: var(--space4) var(--space6);
    grid-template-columns: repeat(auto-fit, minmax(min(14rem, 100%), 1fr));
    padding-top: var(--space5);
    border-top: 1px solid var(--colorBorder);
}

.factGrid dt {
    font-size: var(--textXs);
    font-weight: var(--weightSemibold);
    letter-spacing: var(--trackingWide);
    text-transform: uppercase;
    color: var(--colorInkSubtle);
}

.factGrid dd {
    margin: var(--space1) 0 0;
    font-size: var(--textSm);
    text-wrap: pretty;
}


/* Section headings inside an agency dossier or profile block. */
.dossierHeading {
    margin-bottom: var(--space3);
    font-size: var(--textXs);
    font-weight: var(--weightSemibold);
    letter-spacing: var(--trackingWider);
    text-transform: uppercase;
    color: var(--colorInkSubtle);
}

.dossierNote {
    margin-top: var(--space3);
    color: var(--colorInkSubtle);
}

/* An agency with no published review figures. Deliberately not a zero score:
   nothing was measured and failed, there is simply nothing to measure yet. */
.scoreMissing {
    display: flex;
    flex-direction: column;
    gap: var(--space1);
    padding-block: var(--space2);
}

.scoreMissingLabel {
    font-family: var(--fontDisplay);
    font-size: var(--textLg);
    line-height: 1.1;
    color: var(--colorInkMuted);
}

.rankBadgeUnranked {
    color: var(--colorInkSubtle);
    background-color: transparent;
    border-style: dashed;
}

/* --- The agency record ----------------------------------------------------
   Moved here from inc/css/template-comparison.css: the record is used by the
   ranking, by the dienstpagina's and by anything else that lists agencies, so
   it belongs with the other shared agency components rather than with one
   template's layout. template-comparison.css keeps only what is unique to the
   ranking page — hero, filter bar and the "show the rest" control. */

/* --- The list ------------------------------------------------------------ */

.agencyList {
    display: flex;
    flex-direction: column;
    gap: var(--space5);
}

.agencyListEmpty {
    padding: var(--space8) var(--space5);
    border: 1px dashed var(--colorBorderStrong);
    border-radius: var(--radiusLg);
    text-align: center;
    color: var(--colorInkMuted);
}

/* --- One agency ----------------------------------------------------------
   A record, not a card: identity on the left, verdict on the right, and the
   full assessment in a drawer underneath. */

.agencyRow {
    border: 1px solid var(--colorBorder);
    border-radius: var(--radiusXl);
    background-color: var(--colorSurface);
    overflow: hidden;
    transition:
        border-color var(--durationBase) var(--easeOut),
        box-shadow var(--durationBase) var(--easeOut);
}

.agencyRow:hover {
    border-color: var(--colorBorderStrong);
    box-shadow: var(--shadowMd);
}

/* Number one is the loudest thing on the page, and only number one. */
.agencyRowTop {
    border-color: var(--colorHighlight);
    box-shadow: var(--shadowLg);
}

.agencyRowTop::before {
    content: "";
    display: block;
    block-size: 4px;
    background: linear-gradient(90deg, var(--colorHighlight), var(--colorBrand));
}

.agencyRowBody {
    display: grid;
    gap: var(--space6);
    padding: var(--space6);
    grid-template-columns: 1fr;
}

@media (min-width: 62rem) {
    .agencyRowBody {
        grid-template-columns: minmax(0, 1fr) 17rem;
    }
}

/* --- Dossier drawer -------------------------------------------------------
   Built on <details>, so it opens without JavaScript. */

.agencyDossier {
    border-top: 1px solid var(--colorBorder);
}

.agencyDossierSummary {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--space4);
    padding: var(--space4) var(--space6);
    cursor: pointer;
    list-style: none;
    font-size: var(--textSm);
    font-weight: var(--weightMedium);
    color: var(--colorInkMuted);
    transition: background-color var(--durationFast) var(--easeOut);
}

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

.agencyDossierSummary:hover {
    background-color: var(--colorSurfaceRaised);
    color: var(--colorInk);
}

.agencyDossier[open] .accordionIcon {
    transform: rotate(45deg);
}

.agencyDossierPanel {
    display: grid;
    gap: var(--space6);
    padding: 0 var(--space6) var(--space6);
    border-top: 1px solid var(--colorBorder);
    padding-top: var(--space6);
}

@media (min-width: 62rem) {
    .agencyDossierPanel {
        grid-template-columns: 1fr 1fr;
    }

    .dossierBlockWide {
        grid-column: 1 / -1;
    }
}

.agencyRowIdentity {
    display: flex;
    flex-direction: column;
    gap: var(--space4);
    min-inline-size: 0;
}

.agencyRowHeading {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: var(--space4);
}

.agencyRowTitles {
    min-inline-size: 0;
    flex: 1 1 12rem;
}

.agencyRowFlags {
    display: flex;
    flex-wrap: wrap;
    gap: var(--space2);
    margin-inline-start: auto;
}

.agencyRowVerdict {
    display: flex;
    flex-direction: column;
    gap: var(--space3);
    padding: var(--space5);
    border-radius: var(--radiusLg);
    background-color: var(--colorSurfaceRaised);
    align-self: start;
}

.agencyRowVerdict .scoreMeterValue {
    font-size: var(--text2xl);
}


/* --- Stat strip -----------------------------------------------------------
   The figures under a hero, counted from the data rather than typed: on a
   dienstpagina the bureaus and the price band for that discipline, on the
   specialismen hub the totals across all of them. Lives here because both
   templates use it and a per-template stylesheet cannot be shared. */

.serviceStats {
    display: grid;
    gap: 1px;
    margin-block-start: var(--space8);
    border: 1px solid var(--colorBorder);
    border-radius: var(--radiusLg);
    background-color: var(--colorBorder);
    overflow: hidden;
    grid-template-columns: repeat(auto-fit, minmax(min(11rem, 100%), 1fr));
}

.serviceStat {
    display: flex;
    flex-direction: column-reverse;
    gap: var(--space1);
    padding: var(--space5);
    background-color: var(--colorSurface);
}

.serviceStat dt {
    font-size: var(--textXs);
    letter-spacing: var(--trackingWide);
    text-transform: uppercase;
    color: var(--colorInkSubtle);
}

.serviceStat dd {
    font-family: var(--fontDisplay);
    font-weight: var(--weightSemibold);
    font-size: var(--textXl);
    line-height: 1.1;
    letter-spacing: var(--trackingTight);
}

/* A price range or a lead time is a phrase, not a figure — it must not be set
   at headline size or it wraps into three lines on a phone. */
.serviceStat .serviceStatSmall {
    font-family: var(--fontBody);
    font-size: var(--textMd);
    font-weight: var(--weightMedium);
    letter-spacing: var(--trackingSnug);
}


/* ==========================================================================
   9. ARTICLES
   --------------------------------------------------------------------------
   Shared by the blog, the kennisbank and the teasers on the homepage.
   ========================================================================== */

/* auto-fill, not auto-fit: with auto-fit an empty track collapses, so a group
   holding a single article stretched that card across the full width and gave
   it a hero-sized image. Keeping the empty tracks keeps every card the same
   size however many there are. */
.articleGrid {
    display: grid;
    gap: var(--space5);
    grid-template-columns: repeat(auto-fill, minmax(min(19rem, 100%), 1fr));
}

.articleCard {
    display: flex;
    flex-direction: column;
    border: 1px solid var(--colorBorder);
    border-radius: var(--radiusLg);
    background-color: var(--colorSurface);
    overflow: hidden;
    transition:
        border-color var(--durationBase) var(--easeOut),
        transform var(--durationBase) var(--easeOut),
        box-shadow var(--durationBase) var(--easeOut);
}

.articleCard:hover {
    border-color: var(--colorBrandBorder);
    transform: translateY(-2px);
    box-shadow: var(--shadowLg);
}

.articleCardImage {
    position: relative;
    display: block;
    aspect-ratio: 3 / 2;
    overflow: hidden;
    background-color: var(--colorSurfaceRaised);
}

.articleCardImageLink {
    display: block;
    block-size: 100%;
}

.articleCardImage img {
    inline-size: 100%;
    block-size: 100%;
    object-fit: cover;
}

.articleCardBody {
    display: flex;
    flex-direction: column;
    gap: var(--space2);
    padding: var(--space5);
}

.articleCardMeta {
    font-family: var(--fontMono);
    font-size: var(--textXs);
    letter-spacing: var(--trackingSnug);
    color: var(--colorInkSubtle);
}

.articleCardTitle {
    font-family: var(--fontDisplay);
    font-weight: var(--weightSemibold);
    font-size: var(--textMd);
    line-height: var(--leadingSnug);
    letter-spacing: var(--trackingSnug);
    text-wrap: balance;
}

.articleCardTitle a {
    color: inherit;
    text-decoration: none;
}

.articleCardTitle a:hover {
    color: var(--colorBrand);
}

.articleHeader {
    display: flex;
    flex-direction: column;
    gap: var(--space3);
    margin-top: var(--space6);
    margin-bottom: var(--space7);
}

.articleHero {
    margin: 0 0 var(--space7);
    border-radius: var(--radiusLg);
    overflow: hidden;
}

/* ==========================================================================
   10. DECOR
   --------------------------------------------------------------------------
   Atmosphere, not decoration for its own sake: every primitive here exists to
   give a section depth without adding an image request. They are all built
   from the tokens, so they follow the theme into dark mode by themselves.

   All of them are decorative in the accessibility sense — they live behind
   `aria-hidden` wrappers and never carry meaning that is not also in text.
   ========================================================================== */

/* The positioning context a decorated section needs. Everything inside .shell
   is lifted above the decor by .shellRaised. */
.hasDecor {
    position: relative;
    isolation: isolate;
    overflow: hidden;
}

.decorLayer {
    position: absolute;
    inset: 0;
    z-index: -1;
    pointer-events: none;
    overflow: hidden;
}

/* --- Orbs ---------------------------------------------------------------
   Two or three soft colour fields behind a hero. Kept at low opacity so the
   paper still reads as paper; in dark mode they are the only thing keeping
   the top of the page from being flat black. */

/* Opacity comes from a custom property rather than a plain declaration. The
   dark-mode value has to live on :root, and a variant like .decorOrbFooter
   that wants to be dimmer could never out-specify `:root:not(...) .decorOrb`.
   A property set on the element itself always beats an inherited one, so the
   variants below win in both themes without a specificity fight. */
.decorOrb {
    position: absolute;
    border-radius: 50%;
    filter: blur(70px);
    opacity: var(--decorOrbOpacity, 0.5);
}

@media (prefers-color-scheme: dark) {
    :root:not([data-theme="light"]) { --decorOrbOpacity: 0.34; }
}

:root[data-theme="dark"] { --decorOrbOpacity: 0.34; }

.decorOrbBrand {
    background: radial-gradient(circle at 50% 50%, var(--colorBrand), transparent 68%);
}

.decorOrbHighlight {
    background: radial-gradient(circle at 50% 50%, var(--colorHighlight), transparent 68%);
}

.decorOrbA { inline-size: 34rem; block-size: 34rem; inset-block-start: -14rem; inset-inline-end: -10rem; }
@media (max-width: 48rem) {
    /* A 34rem orb covers most of a phone screen and washes out the text under
       it. Half the size keeps the colour and gives the copy its contrast back. */
    .decorOrbA { inline-size: 18rem; block-size: 18rem; inset-block-start: -8rem; inset-inline-end: -6rem; }
}
.decorOrbB { inline-size: 26rem; block-size: 26rem; inset-block-end: -16rem; inset-inline-start: -8rem; }
.decorOrbC { inline-size: 18rem; block-size: 18rem; inset-block-start: 30%; inset-inline-start: 42%; --decorOrbOpacity: 0.28; }

/* The footer closes the page rather than opening it, so its decor is softer
   than a hero's: a low orb below the fold and a grid that fades in and out
   instead of starting on the footer's top border, which would read as a box. */
.decorOrbFooter {
    inline-size: 32rem;
    block-size: 32rem;
    inset-block-end: -20rem;
    inset-inline-end: -8rem;
    --decorOrbOpacity: 0.3;
}

@media (max-width: 48rem) {
    .decorOrbFooter { inline-size: 18rem; block-size: 18rem; inset-block-end: -12rem; }
}

/* --- Grids and dots -----------------------------------------------------
   Masked so they fade out rather than stopping at an edge, which is what
   makes them read as texture instead of as a table. */

.decorGrid {
    position: absolute;
    inset: 0;
    background-image:
        linear-gradient(to right, var(--colorBorder) 1px, transparent 1px),
        linear-gradient(to bottom, var(--colorBorder) 1px, transparent 1px);
    background-size: 4.5rem 4.5rem;
    opacity: 0.55;
    -webkit-mask-image: radial-gradient(ellipse 80% 60% at 50% 0%, #000 20%, transparent 78%);
    mask-image: radial-gradient(ellipse 80% 60% at 50% 0%, #000 20%, transparent 78%);
}

.decorGridFooter {
    -webkit-mask-image: linear-gradient(to bottom, transparent, #000 40%, #000 70%, transparent);
    mask-image: linear-gradient(to bottom, transparent, #000 40%, #000 70%, transparent);
    opacity: 0.4;
}

.decorDots {
    position: absolute;
    inset: 0;
    background-image: radial-gradient(var(--colorBorderStrong) 1px, transparent 1px);
    background-size: 1.5rem 1.5rem;
    opacity: 0.4;
    -webkit-mask-image: linear-gradient(to bottom, #000, transparent 70%);
    mask-image: linear-gradient(to bottom, #000, transparent 70%);
}

/* Fine film grain. Inline SVG so it costs no request and scales with the
   element; at 3.5% it is felt rather than seen. */
.decorNoise {
    position: absolute;
    inset: 0;
    opacity: 0.035;
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='140' height='140'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='3'/%3E%3C/filter%3E%3Crect width='140' height='140' filter='url(%23n)'/%3E%3C/svg%3E");
}

/* --- Rules and edges ----------------------------------------------------- */

.decorRule {
    block-size: 1px;
    border: 0;
    background: linear-gradient(to right, transparent, var(--colorBorderStrong) 18%, var(--colorBorderStrong) 82%, transparent);
}

.decorRuleBrand {
    background: linear-gradient(to right, transparent, var(--colorBrand), var(--colorHighlight), transparent);
    opacity: 0.7;
}

/* --- Type accents --------------------------------------------------------- */

.gradientText {
    background: linear-gradient(105deg, var(--colorInk) 12%, var(--colorBrand) 58%, var(--colorInk) 96%);
    -webkit-background-clip: text;
    background-clip: text;
    color: transparent;
    /* The gradient clips the descenders on some faces without this. */
    padding-block-end: 0.06em;
}

/* An oversized ghost numeral behind a step or a stat. */
.numberMark {
    font-family: var(--fontDisplay);
    font-weight: var(--weightBold);
    font-size: clamp(3rem, 2rem + 4vw, 4.75rem);
    line-height: 0.8;
    letter-spacing: var(--trackingTight);
    color: transparent;
    -webkit-text-stroke: 1.5px var(--colorBorderStrong);
    font-variant-numeric: tabular-nums;
}

.numberMarkBrand {
    -webkit-text-stroke-color: var(--colorBrandBorder);
}

/* --- Icon tile -----------------------------------------------------------
   The recurring "this is the subject" mark: a rounded plate with an icon in
   it, used on service heroes, deliverable cards and checklist rows. */

.iconTile {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
    inline-size: 2.75rem;
    block-size: 2.75rem;
    border-radius: var(--radiusMd);
    border: 1px solid var(--colorBorder);
    background-color: var(--colorSurfaceRaised);
    color: var(--colorInkMuted);
}

.iconTileBrand {
    border-color: var(--colorBrandBorder);
    background-color: var(--colorBrandSoft);
    color: var(--colorBrand);
}

.iconTilePositive {
    border-color: transparent;
    background-color: var(--colorPositiveSoft);
    color: var(--colorPositive);
}

.iconTileLarge {
    inline-size: 4rem;
    block-size: 4rem;
    border-radius: var(--radiusLg);
}

.iconTileSmall {
    inline-size: 2rem;
    block-size: 2rem;
    border-radius: var(--radiusSm);
}

/* --- Marquee -------------------------------------------------------------
   One continuous strip of terms under a hero. The track is duplicated in the
   markup and translated by exactly half, which is what makes the loop
   seamless without measuring anything in JavaScript. */

.marquee {
    position: relative;
    overflow: hidden;
    -webkit-mask-image: linear-gradient(to right, transparent, #000 8%, #000 92%, transparent);
    mask-image: linear-gradient(to right, transparent, #000 8%, #000 92%, transparent);
}

.marqueeTrack {
    display: flex;
    inline-size: max-content;
    gap: var(--space3);
    animation: acMarquee 48s linear infinite;
}

.marquee:hover .marqueeTrack {
    animation-play-state: paused;
}

@keyframes acMarquee {
    from { transform: translateX(0); }
    to   { transform: translateX(-50%); }
}

@media (prefers-reduced-motion: reduce) {
    .marqueeTrack { animation: none; }
}

/* --- Hover glow -----------------------------------------------------------
   A brand-tinted wash that appears under the pointer. The coordinates come
   from inc/js/app.js; without JS the custom properties stay at their centre
   defaults and the card simply lights up evenly. */

.glowHover {
    position: relative;
    --glowX: 50%;
    --glowY: 50%;
}

.glowHover::after {
    content: "";
    position: absolute;
    inset: 0;
    border-radius: inherit;
    pointer-events: none;
    opacity: 0;
    background: radial-gradient(18rem circle at var(--glowX) var(--glowY), color-mix(in srgb, var(--colorBrand) 14%, transparent), transparent 62%);
    transition: opacity var(--durationBase) var(--easeOut);
}

.glowHover:hover::after,
.glowHover:focus-within::after {
    opacity: 1;
}

/* ==========================================================================
   11. EDITORIAL
   --------------------------------------------------------------------------
   Everything the blog, the kennisbank and the dienstpagina's share: the
   article shell, the reading furniture around it and the richer article card.
   ========================================================================== */

/* --- Reading progress ------------------------------------------------------
   Fixed under the header. The width comes from --acProgress, set by app.js;
   at 0 it is invisible, so nothing shows before the script runs. */

.readingProgress {
    position: fixed;
    inset-block-start: 0;
    inset-inline: 0;
    block-size: 3px;
    z-index: 60;
    pointer-events: none;
    background: linear-gradient(to right, var(--colorBrand), var(--colorHighlight));
    transform-origin: 0 50%;
    transform: scaleX(var(--acProgress, 0));
    transition: transform 90ms linear;
}

/* --- Article hero --------------------------------------------------------- */

.articleShell {
    position: relative;
}

.articleTopline {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--space3);
    margin-block-end: var(--space4);
}

.articleHeroFigure {
    position: relative;
    margin: 0;
    border-radius: var(--radiusXl);
    overflow: hidden;
    border: 1px solid var(--colorBorder);
    background-color: var(--colorSurfaceRaised);
}

.articleHeroFigure img {
    display: block;
    inline-size: 100%;
    block-size: 100%;
    object-fit: cover;
    aspect-ratio: 16 / 9;
}

/* A soft ink wash at the foot of every photograph, so a caption or a badge
   sitting on it stays legible whatever the image happens to contain. */
.articleHeroFigure::after {
    content: "";
    position: absolute;
    inset-inline: 0;
    inset-block-end: 0;
    block-size: 45%;
    pointer-events: none;
    background: linear-gradient(to top, rgba(8, 8, 12, 0.55), transparent);
}

.figureCredit {
    position: absolute;
    inset-block-end: var(--space2);
    inset-inline-end: var(--space3);
    z-index: 1;
    font-family: var(--fontMono);
    font-size: 0.6875rem;
    letter-spacing: var(--trackingSnug);
    color: rgba(255, 255, 255, 0.6);
    text-shadow: 0 1px 3px rgba(0, 0, 0, 0.5);
}

.figureCredit a {
    color: inherit;
    text-decoration: none;
    border-block-end: 1px solid transparent;
}

.figureCredit a:focus-visible,
.articleHeroFigure:hover .figureCredit a,
.serviceHeroFigure:hover .figureCredit a {
    border-block-end-color: rgba(255, 255, 255, 0.35);
}

.figureCredit a:hover {
    color: #fff;
}

/* --- Meta row ------------------------------------------------------------- */

.articleMetaRow {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--space2) var(--space4);
    padding-block: var(--space4);
    border-block: 1px solid var(--colorBorder);
    font-size: var(--textSm);
    color: var(--colorInkMuted);
}

.articleMetaItem {
    display: inline-flex;
    align-items: center;
    gap: var(--space2);
}

.articleMetaItem svg {
    inline-size: 1rem;
    block-size: 1rem;
    color: var(--colorInkSubtle);
}

.articleMetaSpacer { margin-inline-start: auto; }

/* --- Takeaways ------------------------------------------------------------
   The "in het kort" panel above the body. Deliberately the only brand-tinted
   block in the article, so it reads as a summary and not as a callout among
   callouts. */

.takeaways {
    position: relative;
    padding: var(--space5) var(--space5) var(--space5) var(--space6);
    border: 1px solid var(--colorBrandBorder);
    border-radius: var(--radiusLg);
    background-color: var(--colorBrandSoft);
    overflow: hidden;
}

.takeaways::before {
    content: "";
    position: absolute;
    inset-block: 0;
    inset-inline-start: 0;
    inline-size: 3px;
    background: linear-gradient(to bottom, var(--colorBrand), var(--colorHighlight));
}

.takeawaysTitle {
    display: inline-flex;
    align-items: center;
    gap: var(--space2);
    font-family: var(--fontMono);
    font-size: var(--textXs);
    font-weight: var(--weightMedium);
    letter-spacing: var(--trackingWider);
    text-transform: uppercase;
    color: var(--colorBrand);
    margin-block-end: var(--space3);
}

.takeawaysList {
    display: grid;
    gap: var(--space3);
    list-style: none;
    font-size: var(--textSm);
    line-height: var(--leadingRelaxed);
    text-wrap: pretty;
}

.takeawaysList li {
    display: grid;
    grid-template-columns: 1.1rem 1fr;
    gap: var(--space3);
    align-items: start;
}

.takeawaysList svg {
    margin-block-start: 0.2em;
    color: var(--colorBrand);
}

/* --- Table of contents -----------------------------------------------------
   Built from the h2s by app.js and only rendered when there are at least
   three of them; a two-item list of contents is furniture, not navigation. */

.tocPanel {
    border: 1px solid var(--colorBorder);
    border-radius: var(--radiusLg);
    background-color: var(--colorSurface);
    padding: var(--space5);
}

.tocTitle {
    font-family: var(--fontMono);
    font-size: var(--textXs);
    letter-spacing: var(--trackingWider);
    text-transform: uppercase;
    color: var(--colorInkSubtle);
    margin-block-end: var(--space3);
}

.tocList {
    display: grid;
    gap: var(--space1);
    list-style: none;
    counter-reset: toc;
}

.tocList a {
    display: grid;
    grid-template-columns: 1.75rem 1fr;
    gap: var(--space2);
    padding: var(--space2) var(--space2) var(--space2) 0;
    border-radius: var(--radiusSm);
    font-size: var(--textSm);
    line-height: var(--leadingSnug);
    color: var(--colorInkMuted);
    text-decoration: none;
    text-wrap: pretty;
    transition: color var(--durationFast) var(--easeOut);
}

.tocList a::before {
    counter-increment: toc;
    content: counter(toc, decimal-leading-zero);
    font-family: var(--fontMono);
    font-size: var(--textXs);
    color: var(--colorInkSubtle);
}

.tocList a:hover {
    color: var(--colorInk);
}

.tocList a[aria-current="true"] {
    color: var(--colorBrand);
    font-weight: var(--weightMedium);
}

.tocList a[aria-current="true"]::before {
    color: var(--colorBrand);
}

/* --- Share ---------------------------------------------------------------- */

.shareRow {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--space2);
}

.shareLabel {
    font-family: var(--fontMono);
    font-size: var(--textXs);
    letter-spacing: var(--trackingWider);
    text-transform: uppercase;
    color: var(--colorInkSubtle);
    margin-inline-end: var(--space1);
}

.shareButton {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    inline-size: 2.25rem;
    block-size: 2.25rem;
    border-radius: var(--radiusFull);
    border: 1px solid var(--colorBorder);
    background-color: var(--colorSurface);
    color: var(--colorInkMuted);
    cursor: pointer;
    transition:
        color var(--durationFast) var(--easeOut),
        border-color var(--durationFast) var(--easeOut),
        transform var(--durationFast) var(--easeOut);
}

.shareButton:hover {
    color: var(--colorBrand);
    border-color: var(--colorBrandBorder);
    transform: translateY(-1px);
}

/* --- Prose, extended ------------------------------------------------------ */

/* An accent tick in the margin of every h2, so the eye can find the structure
   while scanning. Hidden below the breakpoint where there is no margin left. */
.prose h2 {
    position: relative;
}

@media (min-width: 60rem) {
    .prose h2::before {
        content: "";
        position: absolute;
        inset-inline-start: -1.75rem;
        inset-block-start: 0.55em;
        inline-size: 0.75rem;
        block-size: 2px;
        border-radius: 2px;
        background: linear-gradient(to right, var(--colorBrand), var(--colorHighlight));
    }
}

/* The opening paragraph carries the article. */
.proseLede > p:first-of-type {
    font-size: var(--textMd);
    line-height: var(--leadingRelaxed);
    color: var(--colorInk);
}

.prose strong {
    font-weight: var(--weightSemibold);
    color: var(--colorInk);
}

.prose ul {
    list-style: none;
    padding-left: 0;
}

.prose ul li {
    position: relative;
    padding-left: var(--space5);
}

.prose ul li::before {
    content: "";
    position: absolute;
    inset-inline-start: 0.35rem;
    inset-block-start: 0.6em;
    inline-size: 0.4rem;
    block-size: 0.4rem;
    border-radius: 50%;
    background-color: var(--colorBrand);
}

.prose ol {
    list-style: none;
    padding-left: 0;
    counter-reset: prose;
}

.prose ol li {
    position: relative;
    padding-left: var(--space6);
    counter-increment: prose;
}

.prose ol li::before {
    content: counter(prose);
    position: absolute;
    inset-inline-start: 0;
    inset-block-start: 0.05em;
    inline-size: 1.5rem;
    block-size: 1.5rem;
    display: grid;
    place-items: center;
    border-radius: var(--radiusSm);
    background-color: var(--colorBrandSoft);
    color: var(--colorBrand);
    font-family: var(--fontMono);
    font-size: var(--textXs);
    font-weight: var(--weightSemibold);
}

.prose blockquote {
    position: relative;
    padding-left: var(--space7);
}

.prose blockquote::before {
    content: "\201C";
    position: absolute;
    inset-inline-start: var(--space3);
    inset-block-start: 0.05em;
    font-family: var(--fontDisplay);
    font-size: 2.75rem;
    line-height: 1;
    color: var(--colorBrand);
    opacity: 0.5;
}

.prose a {
    color: var(--colorBrand);
    text-underline-offset: 0.2em;
    text-decoration-thickness: 1px;
}

.prose img {
    border-radius: var(--radiusLg);
}

/* --- Article cards, extended ---------------------------------------------- */

/* The card image needs a hover of its own; the zoom is on the image so the
   card border stays exactly where it was. */
.articleCardImage img {
    transition: transform var(--durationSlow) var(--easeOut);
}

.articleCard:hover .articleCardImage img {
    transform: scale(1.04);
}

.articleCardTopic {
    position: absolute;
    inset-block-start: var(--space3);
    inset-inline-start: var(--space3);
    z-index: 1;
}

/* Placeholder for an article that has no image yet: a designed empty state
   rather than a card that is simply shorter than the two beside it. */
.articleCardImageEmpty {
    display: grid;
    place-items: center;
    block-size: 100%;
    background:
        radial-gradient(circle at 30% 25%, var(--colorBrandSoft), transparent 60%),
        var(--colorSurfaceRaised);
    color: var(--colorInkSubtle);
}

.articleCardBody {
    flex: 1;
}

.articleCardFooter {
    display: flex;
    align-items: center;
    gap: var(--space2);
    margin-block-start: auto;
    padding-block-start: var(--space3);
    font-size: var(--textSm);
    font-weight: var(--weightMedium);
    color: var(--colorBrand);
}

.articleCard:hover .articleCardFooter svg {
    transform: translateX(3px);
}

.articleCardFooter svg {
    transition: transform var(--durationBase) var(--easeOut);
}

/* --- Feature card ---------------------------------------------------------
   One article per index gets the full width: image on one side, everything
   else on the other. Below 52rem it collapses into an ordinary card. */

.articleFeature {
    display: grid;
    gap: 0;
    border: 1px solid var(--colorBorder);
    border-radius: var(--radiusXl);
    background-color: var(--colorSurface);
    overflow: hidden;
    transition:
        border-color var(--durationBase) var(--easeOut),
        box-shadow var(--durationBase) var(--easeOut);
}

.articleFeature:hover {
    border-color: var(--colorBrandBorder);
    box-shadow: var(--shadowLg);
}

.articleFeatureImage {
    position: relative;
    overflow: hidden;
    background-color: var(--colorSurfaceRaised);
    min-block-size: 15rem;
}

.articleFeatureImage img {
    inline-size: 100%;
    block-size: 100%;
    object-fit: cover;
    transition: transform var(--durationSlow) var(--easeOut);
}

.articleFeature:hover .articleFeatureImage img {
    transform: scale(1.03);
}

.articleFeatureBody {
    display: flex;
    flex-direction: column;
    gap: var(--space3);
    padding: var(--space6);
}

.articleFeatureTitle {
    font-family: var(--fontDisplay);
    font-weight: var(--weightMedium);
    font-size: var(--textXl);
    line-height: var(--leadingSnug);
    letter-spacing: var(--trackingTight);
    text-wrap: balance;
}

.articleFeatureTitle a {
    color: inherit;
    text-decoration: none;
}

.articleFeatureTitle a:hover {
    color: var(--colorBrand);
}

@media (min-width: 52rem) {
    .articleFeature {
        grid-template-columns: 1.05fr 1fr;
        align-items: stretch;
    }

    .articleFeatureBody {
        padding: var(--space7);
        justify-content: center;
    }
}

/* --- The article layout ----------------------------------------------------
   Shared by single.php and single-kennisbank.php, which both render
   template-parts/article.php. It lives here rather than in a per-template
   stylesheet for the same reason the agency record does: two templates use it,
   so it is a component and not one page's layout. */

/* --- Header ----------------------------------------------------------------- */

.articleHead {
    padding-block-start: var(--space7);
}

.articleHead .articleHeader {
    margin-block-start: var(--space6);
    margin-block-end: var(--space5);
}

.articleHead .leadText {
    max-inline-size: 40rem;
}

/* --- Hero image --------------------------------------------------------------
   Sits between two sections rather than inside one, so the picture spans the
   full content width while the text above it stays in the narrow column. */

.articleHeroShell {
    margin-block-start: var(--space7);
}

/* --- Body --------------------------------------------------------------------- */

.articleBody {
    padding-block-start: var(--space8);
}

.articleBodyGrid {
    display: grid;
    gap: var(--space8);
    align-items: start;
}

/* The rail follows the article in the markup, so a screen reader and a phone
   both get the text first; on a wide screen it moves to the right-hand
   column and sticks. */
.articleRail {
    display: flex;
    flex-direction: column;
    gap: var(--space5);
}

@media (min-width: 66rem) {
    .articleBodyGrid {
        grid-template-columns: minmax(0, 1fr) 17rem;
        gap: var(--space9);
    }

    .articleRail {
        position: sticky;
        /* Clears the sticky site header plus a little breathing room. */
        inset-block-start: 6rem;
    }
}

.articleColumn {
    display: flex;
    flex-direction: column;
    gap: var(--space6);
    min-inline-size: 0;
    /* Long-form measure. Wider than this and the eye loses the line. */
    max-inline-size: 42rem;
}

/* --- Rail CTA -------------------------------------------------------------------- */

.articleRailCta {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: var(--space3);
    padding: var(--space5);
    border: 1px solid var(--colorBorder);
    border-radius: var(--radiusLg);
    background-color: var(--colorSurfaceRaised);
}

/* --- Footer ------------------------------------------------------------------------ */

.articleFooter {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: var(--space4);
    padding-block-start: var(--space5);
    border-block-start: 1px solid var(--colorBorder);
}

/* --- Previous / next ----------------------------------------------------------------- */

/* One arrow asset, pointed the other way for "vorige". */
.postNavIconBack {
    transform: rotate(180deg);
}

/* --- Closing CTA ------------------------------------------------------------------------ */

.articleCtaLead {
    margin-block-start: var(--space3);
    max-inline-size: 34rem;
    color: inherit;
    opacity: 0.78;
}

.articleCtaActions {
    justify-content: center;
    margin-block-start: var(--space6);
}

/* --- Next / previous ------------------------------------------------------ */

.postNav {
    display: grid;
    gap: var(--space4);
    grid-template-columns: repeat(auto-fit, minmax(min(18rem, 100%), 1fr));
}

.postNavLink {
    display: flex;
    flex-direction: column;
    gap: var(--space2);
    padding: var(--space5);
    border: 1px solid var(--colorBorder);
    border-radius: var(--radiusLg);
    background-color: var(--colorSurface);
    text-decoration: none;
    color: inherit;
    transition:
        border-color var(--durationBase) var(--easeOut),
        transform var(--durationBase) var(--easeOut);
}

.postNavLink:hover {
    border-color: var(--colorBrandBorder);
    transform: translateY(-2px);
}

.postNavLabel {
    display: inline-flex;
    align-items: center;
    gap: var(--space2);
    font-family: var(--fontMono);
    font-size: var(--textXs);
    letter-spacing: var(--trackingWider);
    text-transform: uppercase;
    color: var(--colorInkSubtle);
}

.postNavNext { text-align: right; }
.postNavNext .postNavLabel { justify-content: flex-end; }

/* --- Section header, centred variant -------------------------------------- */

.sectionHeaderCentered {
    margin-inline: auto;
    align-items: center;
    text-align: center;
}

/* ==========================================================================
   12. ZOEKWOORDPAGINA'S
   --------------------------------------------------------------------------
   Everything the keyword pages and the blog articles share: the top five
   table, the checkmark list inside prose, and the internal-link grid. The
   layout that arranges them on one template lives in
   inc/css/template-keyword.css, per the rule at the top of section 11.
   ========================================================================== */

/* --- The top five, as a table ---------------------------------------------
   The same five bureaus, in the same order, on every page that carries this
   block. The first row is the only one that gets the highlight colour — it
   loses its force the moment a second row borrows it. */

.topFiveHeader {
    display: flex;
    /* .sectionHeader is a column; without this the "align-items: flex-end"
       below pushes the heading to the right instead of the button. */
    flex-direction: row;
    flex-wrap: wrap;
    align-items: flex-end;
    justify-content: space-between;
    gap: var(--space5);
    /* .sectionHeader caps itself at the narrow shell; a two-column header
       needs the full width or the button lands under the heading. */
    max-width: none;
}

.topFiveHeader > div {
    max-width: 46rem;
}

.topFiveScroll {
    box-shadow: var(--shadowMd);
}

.topFiveTable th,
.topFiveTable td {
    padding: var(--space4);
    vertical-align: middle;
}

.topFiveTable tbody th {
    inline-size: 3.5rem;
    text-align: center;
}

/* The number one. A tinted row, a gradient rule along the top and the
   highlight button — nothing else on the page does all three. */
.topFiveTable tbody tr.topFiveRowLead {
    background-image: linear-gradient(
        to right,
        color-mix(in srgb, var(--colorBrandSoft) 70%, transparent),
        transparent 55%
    );
    box-shadow: inset 3px 0 0 var(--colorBrand);
}

.topFiveTable tbody tr.topFiveRowLead:hover {
    background-color: transparent;
}

.topFiveName {
    display: inline-flex;
    align-items: center;
    gap: var(--space3);
    text-decoration: none;
    color: inherit;
}

.topFiveName > span {
    display: flex;
    flex-direction: column;
    gap: 2px;
}

.topFiveName strong {
    font-weight: var(--weightSemibold);
}

.topFiveName:hover strong {
    color: var(--colorBrand);
}

.topFiveName .agencyLogo {
    flex-shrink: 0;
    inline-size: 2.75rem;
    block-size: 2.75rem;
    padding: var(--space2);
}

.topFiveFlag {
    margin-inline-start: var(--space3);
    vertical-align: middle;
}

/* The tags live in their own flex box rather than loose in the cell: a
   max-inline-size on a <td> is ignored under table-layout: auto, so the pills
   ran straight through the score column beside them. */
.topFiveTagList {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--space1);
    max-inline-size: 17rem;
    white-space: normal;
}

.topFiveScore {
    font-family: var(--fontMono);
    font-size: var(--textMd);
    font-weight: var(--weightSemibold);
    color: var(--colorInk);
}

.topFiveRowLead .topFiveScore {
    color: var(--colorBrand);
}

.topFiveNote {
    display: flex;
    align-items: flex-start;
    gap: var(--space2);
    margin-block-start: var(--space4);
    max-inline-size: 54rem;
    color: var(--colorInkSubtle);
}

.topFiveNote .icon {
    flex-shrink: 0;
    margin-block-start: 0.15em;
}

/* --- Checkmark list inside prose -------------------------------------------
   The briefing asks for the benefits as ticks. Drawn in CSS rather than with
   an icon, so it costs no request and follows the theme by itself. */

.prose .checkList {
    display: grid;
    gap: var(--space3);
    margin-block: var(--space5);
}

.prose .checkList li {
    padding-left: var(--space7);
    text-wrap: pretty;
}

.prose .checkList li::before {
    content: "";
    position: absolute;
    inset-inline-start: 0;
    inset-block-start: 0.2em;
    inline-size: 1.35rem;
    block-size: 1.35rem;
    border-radius: 50%;
    background-color: var(--colorPositiveSoft);
}

.prose .checkList li::after {
    content: "";
    position: absolute;
    inset-inline-start: 0.42rem;
    inset-block-start: 0.55em;
    inline-size: 0.5rem;
    block-size: 0.26rem;
    border-inline-start: 2px solid var(--colorPositive);
    border-block-end: 2px solid var(--colorPositive);
    border-end-start-radius: 1px;
    transform: rotate(-45deg);
}

/* --- Internal links ---------------------------------------------------------
   Six per page, as the briefing prescribes. A grid rather than a sentence full
   of anchors: the set has to be complete and scannable, and a visitor who has
   read the text is looking for where to go next, not for a link buried in a
   paragraph they already passed. */

.linkGrid {
    display: grid;
    gap: var(--space4);
    grid-template-columns: repeat(auto-fit, minmax(min(19rem, 100%), 1fr));
}

.linkCard {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: var(--space4);
    padding: var(--space5);
    border: 1px solid var(--colorBorder);
    border-radius: var(--radiusLg);
    background-color: var(--colorSurface);
    text-decoration: none;
    color: inherit;
    transition:
        border-color var(--durationBase) var(--easeOut),
        transform var(--durationBase) var(--easeOut),
        box-shadow var(--durationBase) var(--easeOut);
}

.linkCard:hover {
    border-color: var(--colorBrandBorder);
    transform: translateY(-2px);
    box-shadow: var(--shadowMd);
}

.linkCardBody {
    display: flex;
    flex-direction: column;
    gap: var(--space2);
}

.linkCardBody .smallText {
    color: var(--colorInkMuted);
    text-wrap: pretty;
}

.linkCardPath {
    font-family: var(--fontMono);
    font-size: var(--textXs);
    color: var(--colorInkSubtle);
    word-break: break-all;
}

.linkCardArrow {
    flex-shrink: 0;
    display: grid;
    place-items: center;
    inline-size: 2rem;
    block-size: 2rem;
    border-radius: var(--radiusFull);
    background-color: var(--colorSurfaceRaised);
    color: var(--colorInkMuted);
    transition:
        background-color var(--durationBase) var(--easeOut),
        color var(--durationBase) var(--easeOut);
}

.linkCard:hover .linkCardArrow {
    background-color: var(--colorBrand);
    color: var(--colorBrandInk);
}

/* --- The top five on an article ---------------------------------------------
   A blog post carries the same table, one step quieter: it sits between the
   body and the related articles rather than under the hero. */

.articleTopFive {
    padding-block-start: 0;
}

@media (max-width: 47.99rem) {
    .topFiveHeader {
        align-items: flex-start;
    }

    .topFiveTagList {
        max-inline-size: 12rem;
    }
}
