/**
 * Kind Recards — Components
 * ----------------------------------------------------------------------------
 * Reusable UI built from the tokens: buttons, filter pills, cards, badges,
 * form fields. These mirror the elements in the home-page mockup.
 */

/* ========================================================================
 * Buttons — navy pill, "Drawing Doodle", uppercase, +20 tracking
 * ======================================================================== */
.kr-btn,
.button {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: var(--kr-space-2);
    font-family: var(--kr-font-button);
    font-weight: var(--kr-weight-regular);
    font-size: calc(var(--kr-text-base) + 2px); /* a touch larger label */
    letter-spacing: var(--kr-tracking-button);
    text-transform: uppercase;
    /* Tight, not 1: a label that wraps at 390px needs leading between its two
       lines. A single-line button is unaffected — nothing to space away. */
    line-height: var(--kr-leading-tight);
    text-align: center;
    color: var(--kr-btn-primary-text);
    background: var(--kr-primary);
    border: 2px solid var(--kr-primary);
    border-radius: var(--kr-btn-radius);
    padding: 0.6em 1.8em; /* less top/bottom → shorter button */
    cursor: pointer;
    transition:
        transform var(--kr-transition-fast),
        background var(--kr-transition),
        color var(--kr-transition),
        box-shadow var(--kr-transition);
}

.kr-btn:hover,
.button:hover,
.kr-btn:focus-visible {
    /* navy → light-pink flip keeps text readable (pink text on pink fails) */
    color: var(--kr-primary);
    background: var(--kr-btn-soft-bg);
    border-color: var(--kr-btn-soft-bg);
    box-shadow: var(--kr-shadow-pink);
    transform: translateY(-2px);
}

.kr-btn:active {
    transform: translateY(0);
}

/* Variants */

/* Soft — light-pink fill, navy text (the "INLOGGEN" choice button). */
.kr-btn--soft {
    background: var(--kr-btn-soft-bg);
    border-color: var(--kr-btn-soft-bg);
    color: var(--kr-primary);
}
.kr-btn--soft:hover,
.kr-btn--soft:focus-visible {
    background: var(--kr-primary);
    border-color: var(--kr-primary);
    color: var(--kr-btn-primary-text);
}

.kr-btn--accent {
    background: var(--kr-accent);
    border-color: var(--kr-accent);
    color: var(--kr-accent-contrast);
}
.kr-btn--accent:hover {
    background: var(--kr-primary);
    border-color: var(--kr-primary);
    color: var(--kr-btn-primary-text);
}

.kr-btn--outline {
    background: transparent;
    color: var(--kr-primary);
}
.kr-btn--outline:hover {
    background: var(--kr-primary);
    color: var(--kr-btn-primary-text);
    border-color: var(--kr-primary);
}

.kr-btn--ghost {
    background: transparent;
    border-color: transparent;
    color: var(--kr-primary);
}
.kr-btn--ghost:hover {
    background: var(--kr-section-pink);
    color: var(--kr-primary);
    border-color: transparent;
    box-shadow: none;
}

/* Sizes */
.kr-btn--sm {
    font-size: var(--kr-text-sm);
    padding: 0.6em 1.3em;
    /* At ~35px tall the default 16px corner reads as a pill; scale it down so a
       small button is still recognisably the same rounded rectangle. */
    border-radius: var(--kr-btn-radius-sm);
}
.kr-btn--lg {
    font-size: calc(var(--kr-text-md) + 2px);
    padding: 0.7em 2.4em; /* less top/bottom → shorter button */
}
/* ---- Width: one rule, everywhere ---------------------------------------
 * A button is shrink-to-fit and centres inside its container. Full-bleed is
 * NEVER implicit — it is opted into with `.kr-btn--block`, and nothing else.
 *
 * The two ways a button used to go full-bleed by accident, both neutralised
 * here so a screen can't drift on its own:
 *   1. woocommerce.css sets `width: 100%` on `.button` at small widths;
 *   2. a button that is the only child of a `display: block` / stretch
 *      container inherits that container's width.
 * `max-inline-size: 100%` is the mobile guard: a long Drawing Doodle label at
 * 390px wraps inside the button instead of pushing the page sideways.
 *
 * Centring a lone button is the container's job, not the button's — put it in
 * a `.kr-btn-row.kr-btn-row--center`, or give the parent `text-align: center`.
 * ------------------------------------------------------------------------ */
.kr-btn:not(.kr-btn--block),
.button:not(.kr-btn--block) {
    inline-size: auto;
    max-inline-size: 100%;
}

.kr-btn--block,
.button.kr-btn--block {
    display: flex;
    inline-size: 100%;
    max-inline-size: 100%;
}

/* Disclosure (DA8) — native <details>; the summary is a button-styled toggle.
 * Markup: woocommerce/taxonomy-product_cat.php. */
.kr-disclosure {
    margin-block-start: var(--kr-space-4);
}

.kr-disclosure__summary {
    min-block-size: var(--kr-tap-target);
    list-style: none;
    cursor: pointer;
}

.kr-disclosure__summary::-webkit-details-marker {
    display: none;
}

.kr-disclosure__summary::marker {
    content: '';
}

.kr-disclosure[open] > .kr-disclosure__summary {
    margin-block-end: var(--kr-space-4);
}

.kr-disclosure > p:first-of-type {
    margin-block-start: 0;
}

.kr-btn[disabled],
.kr-btn:disabled {
    opacity: 0.5;
    cursor: not-allowed;
    transform: none;
    box-shadow: none;
}

/* ========================================================================
 * Close / remove control (.kr-close) — the one "×" in the system
 *
 * Every dismiss and every remove is the same control: a navy multiplication
 * sign in a transparent circle whose HIT AREA is --kr-tap-target (44px) even
 * though the glyph is much smaller. The client's report was that these were
 * "veel te klein" — the glyph is bigger now, but the target is the real fix.
 *
 * `.kr-close` is the canonical class for new markup. The four existing close /
 * remove controls are listed alongside it so the fix reaches cart, kalender,
 * modals, quick-view and toasts without touching their templates; each keeps
 * its own positioning below, nudged so the bigger box centres the glyph where
 * the small one used to sit.
 *
 * Always give it a real accessible name ("Melding sluiten", "Sluiten",
 * "<product> uit je winkelmand verwijderen") — the glyph alone is not a label.
 * ======================================================================== */
.kr-close,
.kr-toast__close,
.kr-quickview__close,
.kr-modal__close,
.kr-cart-item__remove {
    display: inline-flex;
    flex: none;
    align-items: center;
    justify-content: center;
    inline-size: var(--kr-tap-target);
    block-size: var(--kr-tap-target);
    padding: 0;
    font-family: var(--kr-font-body);
    font-size: var(--kr-text-xl);
    font-weight: var(--kr-weight-bold);
    line-height: 1;
    text-decoration: none;
    color: var(--kr-primary);
    background: transparent;
    border: 0;
    border-radius: var(--kr-radius-circle);
    cursor: pointer;
    transition:
        color var(--kr-transition-fast),
        background var(--kr-transition-fast);
}

.kr-close:hover,
.kr-close:focus-visible,
.kr-toast__close:hover,
.kr-toast__close:focus-visible,
.kr-quickview__close:hover,
.kr-quickview__close:focus-visible,
.kr-modal__close:hover,
.kr-modal__close:focus-visible,
.kr-cart-item__remove:hover,
.kr-cart-item__remove:focus-visible {
    /* Navy on pink-pale is 12.4:1 — the glyph stays navy, the disc does the
       state change. Pink text on a pink disc would drop to ~2.6:1. */
    color: var(--kr-primary);
    background: var(--kr-section-pink);
}

.kr-close:focus-visible,
.kr-toast__close:focus-visible,
.kr-quickview__close:focus-visible,
.kr-modal__close:focus-visible,
.kr-cart-item__remove:focus-visible {
    outline: 2px solid var(--kr-focus-ring);
    outline-offset: 2px;
}

/* On a light-pink surface (the reworked toast) the pink-pale hover disc is
   nearly invisible — deepen it to the accent tint at 20% instead. */
.kr-toast__close:hover,
.kr-toast__close:focus-visible {
    background: color-mix(in srgb, var(--kr-accent) 20%, transparent);
}

/* ========================================================================
 * Busy / loading states — one convention for every async action
 *
 * Driven by `aria-busy="true"`, so the semantics and the visuals are the same
 * thing: assistive tech announces the wait, CSS draws the spinner.
 *
 *   .kr-btn[aria-busy="true"]   a spinner grows in front of the button label
 *                               (the base .kr-btn is inline-flex with a gap, so
 *                               the pseudo-element just becomes its first item)
 *                               and pointer events stop — no double submits.
 *   .kr-busy[aria-busy="true"]  a whole region (a card, a form) dims and gets a
 *                               centred spinner on top.
 *   .kr-spinner                 the standalone element, for markup that wants a
 *                               spinner of its own.
 *
 * Deliberately NOT `disabled`: a disabled button loses keyboard focus mid-flow.
 * `aria-disabled` + `pointer-events: none` keeps focus where the user put it.
 * The `kr-spin` keyframes live with .kr-product-loading further down this file —
 * keyframe rules are document-global, so this reuses them rather than adding a
 * second spin animation.
 * ======================================================================== */
.kr-spinner {
    display: inline-block;
    flex: none;
    width: 1em;
    height: 1em;
    border: 2px solid currentColor;
    border-top-color: transparent;
    border-radius: var(--kr-radius-circle);
    animation: kr-spin 0.8s linear infinite;
}

/* The standalone "the site is thinking" indicator. Sized from
   --kr-loader-size so every large spinner in the theme scales together (the
   client asked for the loading indicator at 140% of its previous size). */
.kr-spinner--lg {
    width: var(--kr-loader-size);
    height: var(--kr-loader-size);
    border-width: var(--kr-loader-ring);
    border-color: var(--kr-color-pink-light);
    border-top-color: var(--kr-primary);
}

.kr-btn[aria-busy="true"] {
    cursor: progress;
    pointer-events: none;
}

.kr-btn[aria-busy="true"]::before {
    content: "";
    flex: none;
    width: 1em;
    height: 1em;
    border: 2px solid currentColor;
    border-top-color: transparent;
    border-radius: var(--kr-radius-circle);
    animation: kr-spin 0.8s linear infinite;
}

/* Any other async control (a menu item, an icon button) opts in with
   .kr-busy-control. The spinner is absolutely positioned so switching it on
   cannot reflow the control it sits in. */
.kr-busy-control[aria-busy="true"] {
    position: relative;
    cursor: progress;
    pointer-events: none;
}

.kr-busy-control[aria-busy="true"]::after {
    content: "";
    position: absolute;
    top: 50%;
    inset-inline-end: var(--kr-space-2);
    width: 0.9em;
    height: 0.9em;
    margin-top: -0.45em;
    border: 2px solid currentColor;
    border-top-color: transparent;
    border-radius: var(--kr-radius-circle);
    animation: kr-spin 0.8s linear infinite;
}

/* Region busy — add .kr-busy in the markup, toggle aria-busy from JS. */
.kr-busy {
    position: relative;
}

.kr-busy[aria-busy="true"] {
    cursor: progress;
    pointer-events: none;
}

/* Dim the contents, not the box, so the spinner below stays at full strength. */
.kr-busy[aria-busy="true"] > * {
    opacity: 0.45;
    transition: opacity var(--kr-transition-fast);
}

.kr-busy[aria-busy="true"]::after {
    content: "";
    position: absolute;
    top: 50%;
    inset-inline-start: 50%;
    z-index: var(--kr-z-base);
    width: var(--kr-loader-size);
    height: var(--kr-loader-size);
    margin: calc(var(--kr-loader-size) / -2) 0 0 calc(var(--kr-loader-size) / -2);
    border: var(--kr-loader-ring) solid var(--kr-color-pink-light);
    border-top-color: var(--kr-primary);
    border-radius: var(--kr-radius-circle);
    animation: kr-spin 0.8s linear infinite;
}

@media (prefers-reduced-motion: reduce) {
    /* Keep the indicator, drop the spin: a steady ring still reads as "busy". */
    .kr-spinner,
    .kr-btn[aria-busy="true"]::before,
    .kr-busy-control[aria-busy="true"]::after,
    .kr-busy[aria-busy="true"]::after {
        animation: none;
    }
}

/* ========================================================================
 * Filter pills — white pill, navy border, pink when active
 * (mockup: "Favoriet / Grappig / Voor hem / Voor haar / Kids")
 * ======================================================================== */
.kr-pill {
    display: inline-flex;
    align-items: center;
    gap: var(--kr-space-2);
    font-family: var(--kr-font-button);
    font-size: var(--kr-text-sm);
    letter-spacing: var(--kr-tracking-button);
    text-transform: uppercase;
    color: var(--kr-primary);
    background: var(--kr-surface);
    border: 2px solid var(--kr-primary);
    border-radius: var(--kr-radius-pill);
    padding: 0.5em 1.2em;
    /* The pill is an ACTION as well as a filter. The address book's "Bewerken"
       / "Verwijderen" were bare ghost buttons that did not read as buttons at
       all, and the client's own reference for what they should look like is
       this row (KAARTEN / KADOOS / ALLES). So the pill grows the interactive
       manners a button needs — pointer cursor, no link underline, a visible
       focus ring, and a --kr-tap-target-high row on touch — rather than a
       near-copy component being invented for it. Lay several out side by side
       in a `.kr-btn-row`. */
    cursor: pointer;
    text-decoration: none;
    transition:
        color var(--kr-transition-fast),
        background var(--kr-transition-fast),
        border-color var(--kr-transition-fast);
}

.kr-pill:hover {
    color: var(--kr-accent);
    border-color: var(--kr-accent);
}

.kr-pill:focus-visible {
    outline: 2px solid var(--kr-focus-ring);
    outline-offset: 2px;
}

@media (pointer: coarse) {
    .kr-pill {
        min-block-size: var(--kr-tap-target);
    }
}

.kr-pill.is-active,
.kr-pill[aria-pressed="true"] {
    color: var(--kr-accent-contrast);
    background: var(--kr-accent);
    border-color: var(--kr-accent);
}

/* Tab variant — navy-filled at rest (used as a filter tablist, e.g. the order
 * wizard's kado filters). Light-pink text on navy (~10:1); pink-light on hover;
 * pink fill with navy text when active. */
.kr-pill--tab {
    color: var(--kr-btn-primary-text);
    background: var(--kr-primary);
    border-color: var(--kr-primary);
}

.kr-pill--tab:hover {
    color: var(--kr-accent-contrast);
    background: var(--kr-btn-soft-bg);
    border-color: var(--kr-btn-soft-bg);
}

.kr-pill--tab.is-active,
.kr-pill--tab[aria-pressed="true"] {
    color: var(--kr-accent-contrast);
    background: var(--kr-accent);
    border-color: var(--kr-accent);
}

/* ========================================================================
 * Cards
 * ======================================================================== */
.kr-card {
    display: flex;
    flex-direction: column;
    background: var(--kr-surface);
    border-radius: var(--kr-radius-lg);
    box-shadow: var(--kr-shadow-md);
    overflow: hidden;
    transition:
        transform var(--kr-transition),
        box-shadow var(--kr-transition);
}

.kr-card:hover {
    transform: translateY(-4px);
    box-shadow: var(--kr-shadow-lg);
}

.kr-card__media {
    aspect-ratio: 3 / 4;
    overflow: hidden;
    background: var(--kr-section-pink);
}

.kr-card__media img {
    width: 100%;
    height: 100%;
    object-fit: cover;
}

.kr-card__body {
    display: flex;
    flex-direction: column;
    gap: var(--kr-space-2);
    padding: var(--kr-space-4);
}

.kr-card__title {
    font-family: var(--kr-font-heading);
    font-size: var(--kr-text-lg);
    margin: 0;
}

.kr-card__price {
    font-weight: var(--kr-weight-bold);
    color: var(--kr-primary); /* pink on white fails contrast; navy is safe */
}

/* ========================================================================
 * Scalloped card (.kr-scallop-card)
 * ------------------------------------------------------------------------
 * A filled panel with a thin outline whose ENTIRE perimeter is a run of
 * semicircular bumps — top, bottom, left, right AND the four corners. The
 * postage-stamp / paper-doily edge from the account design. There is no
 * straight segment anywhere on the outline.
 *
 * HOW IT IS DRAWN. The silhouette is the designer's own SVG — one closed path,
 * dropped in verbatim — rendered as an inline <svg> behind the card's content:
 *
 *     <div class="kr-scallop-card">
 *         [ get_template_part( 'template-parts/components/scallop-bg' ) ]
 *         … content …
 *     </div>
 *
 * template-parts/components/scallop-bg.php holds the only copy of the artwork;
 * every consumer includes it. Nothing about the shape is computed here. The
 * corner bumps are drawn as real three-quarter circles in the path itself,
 * which is the entire point of moving to it: they are exactly as round as the
 * bumps along the edges, because that is how they were drawn.
 *
 * THE GEOMETRY, for anyone sizing a card. Bump radius r = 11.86 user units,
 * pitch 2r = 23.72. The bump centres sit on the body rectangle, 8 across × 13
 * down, and each corner centre is shared by the two runs meeting there — which
 * is what makes a corner one round bump rather than a seam. The path's real
 * bounds, and therefore the viewBox, are x 51.44 → 241.58 and y 39.45 → 347.86:
 * 190.14 × 308.41, a natural aspect ratio of ~0.617 (close to 5:8). So a bump
 * eats 11.86 / 190.14 = 6.24% of the card's width on the left and right, and
 * 11.86 / 308.41 = 3.85% of its height on the top and bottom — that is what the
 * content padding has to clear, and it is why the inline padding below is a
 * percentage rather than a fixed value.
 *
 * COLOURS STAY TOKENS. An <svg> ELEMENT in the document inherits `fill`,
 * `stroke` and `stroke-width` from CSS, so the whole palette is still custom
 * properties and the tint modifiers below keep working. That is exactly why the
 * shape lives in markup and not in `mask-image: url("data:image/svg+xml,…")` or
 * `border-image`: a data URI is an isolated document that cannot read
 * `var(--kr-*)`, so either of those routes would force hard-coded hex, which the
 * design system forbids. The price is one extra line of markup per card, which
 * the template part makes trivial.
 *
 * THE OUTLINE is a real SVG `stroke` with `vector-effect="non-scaling-stroke"`,
 * so it holds an even weight however the box stretches. It replaces the four
 * chained `drop-shadow()`s the old gradient build needed and is strictly better:
 * a stroke is a true offset curve, not four axis-aligned copies, so it no longer
 * thins out on the diagonals of a bump. It also sidesteps the filter-vs-mask
 * ordering trap that ruled `mask` out before — there is now neither a filter nor
 * a mask. The stroke is centred on the path, so its outer half falls outside the
 * viewBox; `overflow: visible` on the <svg> lets that half paint instead of
 * shaving the line to half weight.
 *
 * THE ONE TRADE-OFF: `preserveAspectRatio="none"`. The path has a fixed bump
 * count (8 × 13), so the only way to fill an arbitrary box is to stretch it,
 * and the bumps ovalise as the card's aspect ratio strays from the path's ~0.617.
 * Near it — the desktop account sidebar measures 288 × 453, i.e. 0.636 — it is
 * not perceptible. On a short, wide card it is: 13 shallow ripples down the
 * short sides and 8 fat bumps across the top, which is what the account nav
 * looks like below 900px where it becomes a horizontal bar (572 × 211 = 2.7).
 * Known and accepted. Keep scallop cards tallish. Two ways out, neither
 * shipped: `mask-border` / `-webkit-mask-box-image` with
 * `mask-border-repeat: round` would 9-slice the silhouette and keep every bump
 * circular at any size (alpha-only, so no hard-coded colours) — but Firefox
 * still does not implement it; or a PHP helper could emit a path with the right
 * bump count for a given box, at the cost of no longer being the designer's file.
 *
 * TUNE IT with the custom properties — that is the supported API:
 *   --kr-scallop-fill        panel colour     (default: the pink section tint)
 *   --kr-scallop-line        outline colour   (default: navy)
 *   --kr-scallop-line-width  outline weight
 *   --kr-scallop-rise        room reserved for the TOP and BOTTOM bumps. The
 *                            left/right ones need no token: their depth is
 *                            exactly 6.24% of the card's width, so the inline
 *                            padding is written as a percentage and is always
 *                            right. The block axis cannot be — CSS percentages
 *                            resolve against the containing block's *width* —
 *                            so this token stands in: 18px clears a card up to
 *                            ~470px tall (11.86 / 308.41 = 3.85% of the height).
 *                            Raise it on a taller card.
 *   --kr-scallop-padding     inner padding, on top of that room
 *
 * (`--kr-scallop-size` is gone — the bump diameter is no longer ours to set, it
 * falls out of the path and the box. Its only consumer was the styleguide's
 * peach demo, which now demonstrates --kr-scallop-line-width instead.)
 *
 * Contrast: navy on the pink tint is 12.4:1, so any normal body copy inside the
 * default card passes AAA. Pink TEXT on this tint is only 2.6:1 — it fails at
 * every size, which is why the account nav's active item is navy with a pink
 * rule rather than pink text.
 * ======================================================================== */
.kr-scallop-card {
    --kr-scallop-rise: 18px;
    --kr-scallop-fill: var(--kr-section-pink);
    --kr-scallop-line: var(--kr-primary);
    --kr-scallop-line-width: 1.5px;
    --kr-scallop-padding: var(--kr-space-5);

    position: relative;
    /* `position` is fair game for a consumer to override — the account sidebar
       goes sticky on desktop and static under 900px — and a static card would
       let the absolutely-positioned backdrop escape all the way to the viewport.
       Layout containment makes the card the containing block for it either way,
       without dictating a `position` value. */
    contain: layout;
    /* Own stacking context, so the z-index:-1 backdrop stays behind the card's
       content but never falls behind the page. */
    isolation: isolate;
    /* Room for the bumps, then the real padding inside them. The bumps scale
       with the box (6.24% of the width, 3.85% of the height), so the inline
       padding is a percentage — exact at any width, which matters on the mobile
       account nav where the card is 570px wide and its side bumps are 36px deep.
       CSS has no "percentage of my own height", so the block axis uses the
       --kr-scallop-rise token: 18px clears a card up to ~470px tall. */
    padding-block: calc(var(--kr-scallop-rise) + var(--kr-scallop-padding));
    padding-inline: calc(6.24% + var(--kr-scallop-padding));
    color: var(--kr-text);
}

/* The silhouette itself. Markup: template-parts/components/scallop-bg.php —
   include it as the first child of every .kr-scallop-card. */
.kr-scallop-card__bg {
    position: absolute;
    inset: 0;
    z-index: -1;
    display: block;
    width: 100%;
    height: 100%;
    /* The stroke straddles the path, so its outer half lies outside the
       viewBox. Show it rather than clipping the line to half its weight. */
    overflow: visible;
    fill: var(--kr-scallop-fill);
    stroke: var(--kr-scallop-line);
    stroke-width: var(--kr-scallop-line-width);
    pointer-events: none;
}

/* Safety net. The shape is markup now, so a consumer can forget it; degrade to
   a plain rounded panel rather than an invisible card. */
.kr-scallop-card:not(:has(> .kr-scallop-card__bg)) {
    background-color: var(--kr-scallop-fill);
    border: var(--kr-scallop-line-width) solid var(--kr-scallop-line);
    border-radius: var(--kr-radius-lg);
}

/* Tint variants — the fill is the only thing that changes; the outline stays
   navy, which clears 4.5:1 on every tint in the palette. */
.kr-scallop-card--cyan {
    --kr-scallop-fill: var(--kr-section-cyan);
}

.kr-scallop-card--peach {
    --kr-scallop-fill: var(--kr-section-peach);
}

/* ========================================================================
 * Badges & hearts
 * ======================================================================== */
.kr-badge {
    display: inline-flex;
    align-items: center;
    gap: var(--kr-space-1);
    font-family: var(--kr-font-body);
    font-weight: var(--kr-weight-semibold);
    font-size: var(--kr-text-xs);
    letter-spacing: var(--kr-tracking-wide);
    text-transform: uppercase;
    color: var(--kr-accent-contrast);
    background: var(--kr-accent);
    border-radius: var(--kr-radius-pill);
    padding: 0.3em 0.8em;
}

.kr-badge--navy {
    background: var(--kr-primary);
    color: var(--kr-primary-contrast);
}

/* Numeric count badge — the compact, circular form of .kr-badge for item
   counts (e.g. the header cart). Sizes to a single digit and grows for two;
   light-pink fill with navy text (very high contrast). */
.kr-badge--count {
    justify-content: center;
    min-width: 1.5em;
    height: 1.5em;
    padding-inline: 0.4em;
    font-size: var(--kr-text-xs);
    font-weight: var(--kr-weight-bold);
    line-height: 1;
    letter-spacing: 0;
    text-transform: none;
    background: var(--kr-color-pink-light);
}

/* Decorative heart bullet used across the mockup. */
.kr-heart::before {
    content: "♥";
    color: var(--kr-accent);
    margin-right: 0.35em;
}

/* ========================================================================
 * Toasts — non-blocking notices (the design-system replacement for alert()).
 * Driven by js/kr-toast.js → window.krToast(message, { type }).
 * Navy text on a brand tint per type; high contrast throughout.
 *
 * Reworked after the client's report on the "toegevoegd aan je winkelwagen"
 * notice: it was a cyan panel inside a heavy pink border with a
 * BEKIJK WINKELWAGEN button sitting in it. Now:
 *   - the fill is the soft pink (--kr-color-pink-light), not cyan;
 *   - the heavy border is gone — a hairline --kr-border is all that is left,
 *     the elevation does the separating;
 *   - there is no call-to-action in the body (see .kr-toast__action below);
 *   - a real close <button> sits top-right, on the shared 44px .kr-close
 *     target, with the accessible name "Melding sluiten".
 * Navy on #FFCAFD is 10.2:1.
 * ======================================================================== */
.kr-toasts {
    position: fixed;
    inset-block-end: var(--kr-space-5);
    inset-inline: 0;
    z-index: var(--kr-z-toast);
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: var(--kr-space-2);
    padding-inline: var(--kr-gutter);
    pointer-events: none; /* let clicks fall through the gaps… */
}

.kr-toast {
    pointer-events: auto; /* …but the toasts themselves are interactive */
    position: relative; /* the close button is parked in the top-right corner */
    display: flex;
    align-items: center;
    gap: var(--kr-space-3);
    width: max-content;
    max-width: min(30rem, 100%);
    /* Trailing room for the 44px close target so a long message never runs
       under it. Top/bottom stay generous enough that the target does not
       overhang the panel. */
    padding: var(--kr-space-4) var(--kr-space-3) var(--kr-space-4)
        var(--kr-space-5);
    padding-inline-end: calc(var(--kr-tap-target) + var(--kr-space-2));
    font-family: var(--kr-font-body);
    font-size: var(--kr-text-base);
    line-height: var(--kr-leading-snug);
    color: var(--kr-primary);
    background: var(--kr-color-pink-light);
    border: 1px solid var(--kr-border);
    border-radius: var(--kr-radius-md);
    box-shadow: var(--kr-shadow-lg);
    animation: kr-toast-in var(--kr-transition) both;
}

/* Success is the base look — the "toegevoegd aan je winkelwagen" notice. It
   used to override the fill to cyan; that override is what the client asked us
   to drop, so the class stays (JS emits it) with nothing left to say. */

/* Errors get the strongest treatment: deep pink with white text and a leading
   white warning glyph, so they read as a problem rather than just another
   notice. The same-colour border preserves the toast hairline without a navy
   edge that would compete with the dark fill. */
.kr-toast--error {
    background: var(--kr-color-pink-deep);
    color: var(--kr-color-white);
    border-color: var(--kr-color-pink-deep);
    box-shadow: var(--kr-shadow-pink);
    font-weight: var(--kr-weight-semibold);
}

.kr-toast--error::before {
    content: "\26A0\FE0E"; /* ⚠ forced to text (white), not colour-emoji */
    flex: none;
    font-size: 1.3em;
    line-height: 1;
    color: var(--kr-color-white);
}

.kr-toast--error .kr-close,
.kr-toast--error .kr-toast__close,
.kr-toast--error .kr-close:hover,
.kr-toast--error .kr-toast__close:hover,
.kr-toast--error .kr-close:focus-visible,
.kr-toast--error .kr-toast__close:focus-visible {
    color: var(--kr-color-white);
}

.kr-toast--info {
    background: var(--kr-section-peach);
    border-color: var(--kr-color-peach);
}

.kr-toast__msg {
    flex: 1 1 auto;
}

/* No call-to-action in a toast. The BEKIJK WINKELWAGEN button that used to sit
   in the cart notice is what the client asked to have removed: a toast says
   what happened, the header cart icon is how you go and look at it.
   `.kr-toast__action` is kept as a selector purely to hide the element for as
   long as callers still pass an `action` option to krToast() — the real fix is
   to stop passing it (js/quickview.js, js/kr-kalender-product.js), after which
   both this rule and the `viewCart` strings can go. */
.kr-toast__action {
    display: none;
}

/* The close button. Box, colour and 44px hit area come from the shared
   .kr-close rule at the top of this file; only the corner placement is here. */
.kr-toast__close {
    position: absolute;
    top: var(--kr-space-1);
    inset-inline-end: var(--kr-space-1);
}

.kr-toast.is-leaving {
    animation: kr-toast-out var(--kr-transition-fast) forwards;
}

/* Reduced motion zeroes --kr-transition* in tokens.css, so the animations
   above collapse to instant — no separate override needed here. */
@keyframes kr-toast-in {
    from {
        opacity: 0;
        transform: translateY(14px);
    }
    to {
        opacity: 1;
        transform: none;
    }
}

@keyframes kr-toast-out {
    from {
        opacity: 1;
        transform: none;
    }
    to {
        opacity: 0;
        transform: translateY(10px);
    }
}

/* ========================================================================
 * Notices — the inline, in-flow sibling of the toast.
 *
 * WooCommerce prints its own banners (cart item removed, coupon applied,
 * login failed, …) as `.woocommerce-message` / `.woocommerce-info` /
 * `.woocommerce-error`. This dresses them on brand wherever a wrapper carries
 * `.kr-notices` (cart) or `.kr-account-notices` (auth screens — the original
 * home of this treatment, generalised here so both surfaces share one
 * component instead of two near-copies).
 *
 * It also has to *undo* WooCommerce's default chrome, which is otherwise
 * visible straight through the brand fill:
 *   - a 3px #8fae1b (olive-green) `border-top`;
 *   - an absolutely-positioned `::before` glyph from the "WooCommerce" icon
 *     font, parked at `left: 1.5em` inside a `3.5em` left gutter. When the
 *     padding is overridden without also moving the glyph, it lands on top of
 *     the first characters of the message — the stray mark in the bug report.
 * Both are neutralised below and the glyph is replaced with a real text
 * character in the body font, laid out against a matching left gutter.
 *
 * Colour follows the toast vocabulary: navy on a brand tint, 4px leading
 * edge. Never white on pink — see tokens.css / CLAUDE.md.
 *
 * `.woocommerce-NoticeGroup` is the third host, and the only one this theme does
 * not write itself: WooCommerce's checkout.js injects
 * `<div class="woocommerce-NoticeGroup woocommerce-NoticeGroup-checkout">` into
 * the checkout form at runtime to show validation errors, and prepends another
 * one for update_order_review failures. Treating that div as a notice host means
 * the AJAX errors are dressed identically to the server-rendered ones without
 * touching WooCommerce's JS.
 *
 * `!important` is used on exactly the four properties that the legacy
 * css/kind-recart.css still claims with `!important` on a bare
 * `.woocommerce-message, .woocommerce-info` selector (background, color,
 * padding, line-height). That file is enqueued site-wide by the old
 * [kind_recart] shortcode class and is due to be sunsetted; when it goes,
 * these four `!important`s can go with it.
 * ======================================================================== */
.kr-notices:empty,
.kr-account-notices:empty {
    display: none;
}

/* The runtime-injected group needs air of its own — it has no wrapper to give
   it any, and on checkout it lands directly above the two-column grid. */
.woocommerce-NoticeGroup {
    margin-bottom: var(--kr-space-5);
}

/* WooCommerce prints `.woocommerce-error` as a <ul>. Strip the list chrome so
   the banner box below is the only visible container. */
:is(.kr-notices, .kr-account-notices, .woocommerce-NoticeGroup) ul,
:is(.kr-notices, .kr-account-notices, .woocommerce-NoticeGroup) ol {
    list-style: none;
    margin: 0;
    padding: 0;
}

:is(.kr-notices, .kr-account-notices, .woocommerce-NoticeGroup) .woocommerce-message,
:is(.kr-notices, .kr-account-notices, .woocommerce-NoticeGroup) .woocommerce-info,
:is(.kr-notices, .kr-account-notices, .woocommerce-NoticeGroup) .woocommerce-error,
:is(.kr-notices, .kr-account-notices, .woocommerce-NoticeGroup) .woocommerce-notice {
    position: relative;
    margin: 0 0 var(--kr-space-4);
    /* Left gutter = glyph offset + glyph column, so text never runs under it. */
    padding: var(--kr-space-4) var(--kr-space-5) var(--kr-space-4)
        calc(var(--kr-space-5) + 1.75rem) !important;
    border: 0;
    border-inline-start: 4px solid var(--kr-color-cyan);
    /* A one-line banner is only ~38px tall, where the card radius (16px+) curves
       the short edges into a stadium. Same reasoning as --kr-btn-radius-sm. */
    border-radius: var(--kr-radius-sm);
    background: var(--kr-section-cyan) !important;
    color: var(--kr-primary) !important;
    font-family: var(--kr-font-body);
    font-size: var(--kr-text-base);
    line-height: var(--kr-leading-snug) !important;
    list-style: none;
    box-shadow: var(--kr-shadow-sm);
}

:is(.kr-notices, .kr-account-notices, .woocommerce-NoticeGroup) :last-child.woocommerce-message,
:is(.kr-notices, .kr-account-notices, .woocommerce-NoticeGroup) :last-child.woocommerce-info,
:is(.kr-notices, .kr-account-notices, .woocommerce-NoticeGroup) :last-child.woocommerce-error,
:is(.kr-notices, .kr-account-notices, .woocommerce-NoticeGroup) :last-child.woocommerce-notice {
    margin-bottom: 0;
}

/* Replaces WooCommerce's icon-font ::before: a plain text glyph in the body
   font, aligned to the first line of the message inside the left gutter. */
:is(.kr-notices, .kr-account-notices, .woocommerce-NoticeGroup) .woocommerce-message::before,
:is(.kr-notices, .kr-account-notices, .woocommerce-NoticeGroup) .woocommerce-info::before,
:is(.kr-notices, .kr-account-notices, .woocommerce-NoticeGroup) .woocommerce-error::before,
:is(.kr-notices, .kr-account-notices, .woocommerce-NoticeGroup) .woocommerce-notice::before {
    content: "\2713"; /* ✓ */
    position: absolute;
    top: var(--kr-space-4);
    inset-inline-start: var(--kr-space-5);
    width: 1.25rem;
    height: auto;
    margin: 0;
    padding: 0;
    font-family: var(--kr-font-body);
    font-size: 1.05em;
    font-weight: var(--kr-weight-bold);
    line-height: var(--kr-leading-snug);
    text-align: start;
    color: inherit;
    background: none;
}

/* Informational — warm peach, matching .kr-toast--info. */
:is(.kr-notices, .kr-account-notices, .woocommerce-NoticeGroup) .woocommerce-info {
    border-inline-start-color: var(--kr-color-peach);
    background: var(--kr-section-peach) !important;
}

:is(.kr-notices, .kr-account-notices, .woocommerce-NoticeGroup) .woocommerce-info::before {
    content: "\2139\FE0E"; /* ℹ forced to text, not colour-emoji */
}

/* Errors — pink tint with a saturated pink edge, navy text (~4.8:1). */
:is(.kr-notices, .kr-account-notices, .woocommerce-NoticeGroup) .woocommerce-error {
    border-inline-start-color: var(--kr-accent);
    background: var(--kr-section-pink) !important;
}

:is(.kr-notices, .kr-account-notices, .woocommerce-NoticeGroup) .woocommerce-error::before {
    content: "\26A0\FE0E"; /* ⚠ forced to text, not colour-emoji */
}

:is(.kr-notices, .kr-account-notices, .woocommerce-NoticeGroup) li + li {
    margin-top: var(--kr-space-2);
}

/* Inline links — e.g. the "Ongedaan maken?" undo link WooCommerce appends to
   the item-removed message. Pink-on-tint would drop to ~2.6:1, so hover
   thickens the underline instead of recolouring the text. */
:is(.kr-notices, .kr-account-notices, .woocommerce-NoticeGroup) a:not(.button) {
    color: var(--kr-primary);
    font-weight: var(--kr-weight-semibold);
    text-decoration: underline;
    text-underline-offset: 2px;
}

:is(.kr-notices, .kr-account-notices, .woocommerce-NoticeGroup) a:not(.button):hover,
:is(.kr-notices, .kr-account-notices, .woocommerce-NoticeGroup) a:not(.button):focus-visible {
    text-decoration-thickness: 2px;
}

/* WooCommerce sometimes puts a CTA in the notice (`<a class="button">Bekijk
   winkelmand</a>`) and floats it. Un-float it and give it the compact brand
   button — same corner as .kr-btn--sm, not a pill. */
:is(.kr-notices, .kr-account-notices, .woocommerce-NoticeGroup) .button {
    float: none;
    display: inline-flex;
    align-items: center;
    margin-inline-start: var(--kr-space-3);
    padding: 0.4em 1em;
    font-family: var(--kr-font-button);
    font-size: var(--kr-text-sm);
    letter-spacing: var(--kr-tracking-button);
    text-transform: uppercase;
    text-decoration: none;
    white-space: nowrap;
    color: var(--kr-btn-primary-text);
    background: var(--kr-primary);
    border: 0;
    border-radius: var(--kr-btn-radius-sm);
    transition:
        color var(--kr-transition-fast),
        background var(--kr-transition-fast);
}

:is(.kr-notices, .kr-account-notices, .woocommerce-NoticeGroup) .button:hover {
    color: var(--kr-accent-contrast);
    background: var(--kr-accent);
}

/* ========================================================================
 * Forms
 * ======================================================================== */
.kr-input,
input[type="text"],
input[type="email"],
input[type="search"],
input[type="tel"],
input[type="password"],
input[type="number"],
input[type="url"],
input[type="date"],
textarea,
select {
    width: 100%;
    font-family: var(--kr-font-body);
    font-size: var(--kr-text-base);
    color: var(--kr-field-text);
    background: var(--kr-field-bg);
    border: 2px solid transparent;
    border-radius: var(--kr-field-radius);
    padding: 0.85em 1.2em;
    transition:
        border-color var(--kr-transition-fast),
        background var(--kr-transition-fast),
        box-shadow var(--kr-transition-fast);
}

textarea {
    border-radius: var(--kr-field-radius);
    min-height: 8rem;
    resize: vertical;
}

/* Cosmetic focus state. Uses background-COLOR (not the shorthand) so it never
   wipes background-image arrows on appearance:none selects. */
.kr-input:focus,
input:focus,
textarea:focus,
select:focus {
    background-color: var(--kr-field-bg-focus);
    border-color: var(--kr-accent);
}

/* Visible keyboard focus — must not be removed (WCAG 2.4.7). Navy outline
   clears 3:1 on any field/page background; pink alone does not. */
.kr-input:focus-visible,
input:focus-visible,
textarea:focus-visible,
select:focus-visible {
    outline: 3px solid var(--kr-primary);
    outline-offset: 2px;
    box-shadow: var(--kr-focus-shadow);
}

/* Shrink-to-fit field — for controls whose value has a fixed width (a date, a
   postcode) and which sit beside a label rather than in a stacked form column.
   Needs the element qualifier to outrank `input[type="date"]`'s width: 100%. */
input.kr-input--auto,
select.kr-input--auto,
.kr-input--auto {
    width: auto;
    max-width: 100%;
}

::placeholder {
    color: var(--kr-field-placeholder);
    opacity: 1;
}

label {
    display: inline-block;
    font-family: var(--kr-font-body);
    font-weight: var(--kr-weight-bold);
    color: var(--kr-heading);
    margin-bottom: var(--kr-space-2);
}

/* Field group: navy label · soft input · italic hint (account forms). */
.kr-field {
    display: flex;
    flex-direction: column;
    margin-bottom: var(--kr-space-4);
}

.kr-field__label {
    font-family: var(--kr-font-body);
    font-weight: var(--kr-weight-bold);
    color: var(--kr-heading);
    margin-bottom: var(--kr-space-2);
}

.kr-field__hint {
    font-size: var(--kr-text-sm);
    font-style: italic;
    color: var(--kr-text-muted);
    margin-top: var(--kr-space-1);
}

/* Two fields on one row (e.g. Voornaam / Achternaam). */
.kr-field-row {
    display: grid;
    gap: var(--kr-space-4);
    grid-template-columns: 1fr 1fr;
}

@media (max-width: 520px) {
    .kr-field-row {
        grid-template-columns: 1fr;
    }
}

/* ========================================================================
 * Checkboxes & radios — pink-light fill, navy tick (account forms)
 * ======================================================================== */
.kr-check {
    display: flex;
    align-items: flex-start;
    gap: var(--kr-space-2);
    font-size: var(--kr-text-sm);
    font-style: italic;
    color: var(--kr-text);
    cursor: pointer;
    margin-bottom: var(--kr-space-2);
}

.kr-check input[type="checkbox"],
.kr-check input[type="radio"] {
    appearance: none;
    -webkit-appearance: none;
    flex: none;
    width: 1.15em;
    height: 1.15em;
    margin: 0.1em 0 0;
    padding: 0;
    background: var(--kr-surface);
    border: 2px solid var(--kr-primary);
    border-radius: var(--kr-radius-xs);
    cursor: pointer;
    transition: background var(--kr-transition-fast);
}

.kr-check input[type="radio"] {
    border-radius: var(--kr-radius-circle);
}

.kr-check input[type="checkbox"]:checked {
    background: var(--kr-color-pink-light);
    /* navy check mark */
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath fill='none' stroke='%2300009c' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round' d='M3 8.5l3.2 3.2L13 4.5'/%3E%3C/svg%3E");
    background-size: 80% 80%;
    background-position: center;
    background-repeat: no-repeat;
}

/* Navy dot inside a white ring — the same navy-on-light logic as the checkbox's
   tick. The dot used to be --kr-color-pink-light, which on the white/cream
   surfaces this control sits on was almost indistinguishable from the unchecked
   state (WCAG 1.4.11 non-text contrast). */
.kr-check input[type="radio"]:checked {
    background: var(--kr-primary);
    box-shadow: inset 0 0 0 3px var(--kr-surface);
}

.kr-check input:focus-visible {
    outline: 3px solid var(--kr-focus-ring);
    outline-offset: 2px;
}

/* ========================================================================
 * Range slider (.kr-range) — the size / zoom control
 *
 * The client's redesign of the card-editor toolbar replaces the browser's grey
 * default with the brand: a NAVY bar with fully rounded ends, and a round thumb
 * that is soft pink inside a navy ring. Put `.kr-range` on any
 * `<input type="range">` and it looks like her toolbar; the editor is wired up
 * to it separately.
 *
 * WHY EVERY RULE IS WRITTEN TWICE. The two engines expose the parts under
 * different pseudo-elements (`::-webkit-slider-runnable-track` +
 * `::-webkit-slider-thumb`, `::-moz-range-track` + `::-moz-range-thumb`) and —
 * this is the part that bites — a selector list containing a pseudo-element one
 * engine does not know is dropped WHOLE by that engine. So they cannot be
 * comma-joined; each engine gets its own copy of the same declarations.
 *
 * WebKit does not centre the thumb on the track for you the way Firefox does,
 * hence the negative `margin-top` of half the overshoot.
 *
 * Sizes come from --kr-range-* in tokens.css. The thumb is 26px, which clears
 * the 24px WCAG 2.2 target minimum; the whole control is given a 44px row so a
 * finger has something to land on.
 * ======================================================================== */
.kr-range {
    -webkit-appearance: none;
    appearance: none;
    inline-size: 100%;
    min-block-size: var(--kr-tap-target);
    margin: 0;
    padding: 0;
    background: transparent; /* the track pseudo-element paints the bar */
    cursor: pointer;
    /* The native tint would otherwise repaint the track pink on some engines. */
    accent-color: auto;
}

.kr-range::-webkit-slider-runnable-track {
    height: var(--kr-range-track-height);
    background: var(--kr-primary);
    border: 0;
    border-radius: var(--kr-radius-pill);
}

.kr-range::-moz-range-track {
    height: var(--kr-range-track-height);
    background: var(--kr-primary);
    border: 0;
    border-radius: var(--kr-radius-pill);
}

.kr-range::-webkit-slider-thumb {
    -webkit-appearance: none;
    appearance: none;
    width: var(--kr-range-thumb-size);
    height: var(--kr-range-thumb-size);
    background: var(--kr-color-pink-light);
    border: var(--kr-range-thumb-border) solid var(--kr-primary);
    border-radius: var(--kr-radius-circle);
    box-sizing: border-box;
    cursor: grab;
    /* WebKit aligns the thumb's top edge with the track's; Firefox centres it.
       Lift it by half the difference so both engines agree. */
    margin-top: calc(
        (var(--kr-range-track-height) - var(--kr-range-thumb-size)) / 2
    );
    transition: transform var(--kr-transition-fast);
}

.kr-range::-moz-range-thumb {
    width: var(--kr-range-thumb-size);
    height: var(--kr-range-thumb-size);
    background: var(--kr-color-pink-light);
    border: var(--kr-range-thumb-border) solid var(--kr-primary);
    border-radius: var(--kr-radius-circle);
    box-sizing: border-box;
    cursor: grab;
    transition: transform var(--kr-transition-fast);
}

.kr-range:hover::-webkit-slider-thumb {
    transform: scale(1.08);
}

.kr-range:hover::-moz-range-thumb {
    transform: scale(1.08);
}

.kr-range:active::-webkit-slider-thumb {
    cursor: grabbing;
}

.kr-range:active::-moz-range-thumb {
    cursor: grabbing;
}

/* Keyboard focus is on the input itself, so one ring covers both engines.
   Firefox also draws its own dotted inner ring — turn that one off only. */
.kr-range:focus-visible {
    outline: 3px solid var(--kr-focus-ring);
    outline-offset: 4px;
    border-radius: var(--kr-radius-pill);
}

.kr-range::-moz-focus-outer {
    border: 0;
}

.kr-range:disabled {
    opacity: 0.5;
    cursor: not-allowed;
}

/* Vertical variant — the editor's font-size slider is rotated -90deg by its own
   (legacy) CSS. Nothing to do here but say it is expected: the pseudo-elements
   rotate with the input, so the component survives the transform intact. */

/* One engine per rule again — a list containing a pseudo-element the engine
   does not know is dropped whole, which would silently take the other with it. */
@media (prefers-reduced-motion: reduce) {
    .kr-range::-webkit-slider-thumb {
        transition: none;
    }

    .kr-range::-moz-range-thumb {
        transition: none;
    }
}

/* Search field with attached round button (header pattern). */
.kr-search {
    display: flex;
    align-items: center;
    gap: var(--kr-space-2);
    background: var(--kr-surface);
    border: 2px solid var(--kr-border);
    border-radius: var(--kr-radius-pill);
    padding-right: var(--kr-space-1);
}

.kr-search input {
    border: none;
    background: transparent;
    border-radius: 0;
    flex: 1;
}

.kr-search input:focus {
    background: transparent;
    box-shadow: none;
}

.kr-search button {
    flex: none;
    width: 2.4em;
    height: 2.4em;
    border-radius: var(--kr-radius-circle);
    background: var(--kr-primary);
    color: var(--kr-primary-contrast);
    display: inline-flex;
    align-items: center;
    justify-content: center;
}

/* Search suggestions (HP1) — the type-ahead panel under a search field. Markup: template-parts/header/search.php + searchform.php. Behaviour: js/product-search-suggest.js (ARIA combobox + listbox). */
.kr-search-suggest { position: relative; --kr-suggest-pull-start: 0px; --kr-suggest-pull-end: 0px; }
.kr-search-suggest__panel { position: absolute; top: calc(100% + var(--kr-space-4)); left: calc(var(--kr-suggest-pull-start) * -1); right: calc(var(--kr-suggest-pull-end) * -1); z-index: var(--kr-z-sticky); max-height: min(60vh, 26rem); overflow-y: auto; overscroll-behavior: contain; padding: var(--kr-space-2); background: var(--kr-bg); border: 1px solid var(--kr-primary); border-radius: var(--kr-radius-md); box-shadow: var(--kr-shadow-lg); }
.kr-search-suggest__panel[hidden], .kr-search-suggest__empty[hidden] { display: none; }
.kr-search-suggest__list { list-style: none; margin: 0; padding: 0; }
.kr-search-suggest__option { display: flex; align-items: center; gap: var(--kr-space-3); min-height: var(--kr-tap-target); padding: var(--kr-space-2); border-radius: var(--kr-radius-sm); color: var(--kr-text); cursor: pointer; }
.kr-search-suggest__option:hover, .kr-search-suggest__option.is-active { background: var(--kr-field-bg); }
.kr-search-suggest__thumb { flex: none; display: flex; align-items: center; justify-content: center; width: var(--kr-tap-target); height: var(--kr-tap-target); overflow: hidden; border-radius: var(--kr-radius-xs); background: var(--kr-surface); }
.kr-search-suggest__thumb img { width: 100%; height: 100%; object-fit: cover; }
.kr-search-suggest__text { display: flex; flex-direction: column; gap: var(--kr-space-1); min-width: 0; }
.kr-search-suggest__title { font-size: var(--kr-text-base); line-height: var(--kr-leading-snug); color: var(--kr-text); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.kr-search-suggest__cat { font-size: var(--kr-text-sm); line-height: var(--kr-leading-snug); color: var(--kr-field-placeholder); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.kr-search-suggest__empty { margin: 0; padding: var(--kr-space-3) var(--kr-space-2); font-size: var(--kr-text-sm); font-style: italic; color: var(--kr-field-placeholder); }
.search-form.kr-search-suggest { --kr-suggest-pull-end: var(--kr-space-1); }
@media (max-width: 760px) { .kr-search-suggest__panel { max-height: min(55vh, 22rem); } }


/* ========================================================================
 * Carousel controls (round nav arrows in the mockup)
 * ======================================================================== */
.kr-carousel-nav {
    width: 2.6rem;
    height: 2.6rem;
    border-radius: var(--kr-radius-circle);
    background: var(--kr-surface);
    color: var(--kr-primary);
    box-shadow: var(--kr-shadow-sm);
    display: inline-flex;
    align-items: center;
    justify-content: center;
    transition:
        background var(--kr-transition-fast),
        color var(--kr-transition-fast);
}

.kr-carousel-nav:hover {
    background: var(--kr-accent);
    color: var(--kr-accent-contrast);
}

/* ========================================================================
 * Doodle link — italic, navy, hand-drawn dashed underline
 * ("liever doorgaan zonder inloggen", "wachtwoord vergeten", ...)
 * ======================================================================== */
.kr-link-doodle {
    display: inline-block;
    font-family: var(--kr-font-body);
    font-style: italic;
    font-weight: var(--kr-weight-regular);
    color: var(--kr-primary);
    text-decoration: underline;
    text-decoration-style: dashed;
    text-decoration-thickness: 1px;
    text-underline-offset: 4px;
    transition: color var(--kr-transition-fast);
}

.kr-link-doodle:hover,
.kr-link-doodle:focus-visible {
    color: var(--kr-accent);
    text-decoration-color: var(--kr-accent);
}

.kr-link-doodle--center {
    display: block;
    text-align: center;
}

/* ========================================================================
 * Sort / select pill — pink-pale fill, navy border, chevron
 * ("Adressen sorteren op: [ Standaard v ]")
 * ======================================================================== */
.kr-select-pill {
    display: inline-flex;
    align-items: center;
    width: auto;
    font-family: var(--kr-font-button);
    font-size: var(--kr-text-base);
    letter-spacing: var(--kr-tracking-button);
    text-transform: uppercase;
    color: var(--kr-primary);
    background-color: var(--kr-color-pink-pale);
    border: 2px solid var(--kr-primary);
    border-radius: var(--kr-radius-pill);
    padding: 0.55em 2.8em 0.55em 1.4em;
    cursor: pointer;
    /* navy chevron */
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath fill='none' stroke='%2300009c' stroke-width='2' stroke-linecap='round' stroke-linejoin='round' d='M4 6l4 4 4-4'/%3E%3C/svg%3E");
    background-repeat: no-repeat;
    background-position: right 1.1em center;
    background-size: 0.9em;
    appearance: none;
    -webkit-appearance: none;
}

.kr-select-pill:focus {
    background-color: var(--kr-color-pink-pale);
    border-color: var(--kr-accent);
}

.kr-select-pill:focus-visible {
    outline: 3px solid var(--kr-primary);
    outline-offset: 2px;
    box-shadow: var(--kr-focus-shadow);
}

/* Text variant — body font, sentence case. For pills whose value is content
   ("Standaard", "A5 liggend") rather than a UI command; the uppercase Drawing
   Doodle treatment mangles product/variant names. */
.kr-select-pill--text {
    font-family: var(--kr-font-body);
    font-size: var(--kr-text-sm);
    text-transform: none;
    letter-spacing: var(--kr-tracking-normal);
}

/* Compact variant — for short values such as a quantity. */
.kr-select-pill--compact {
    padding: 0.55em 2.4em 0.55em 1em;
    background-position: right 0.8em center;
}

.kr-sort {
    display: flex;
    align-items: center;
    gap: var(--kr-space-3);
    flex-wrap: wrap;
}

.kr-sort__label {
    font-style: italic;
    color: var(--kr-text);
}

/* ========================================================================
 * Address card — bold navy name, italic address, kebab menu
 * ======================================================================== */
.kr-address-card {
    position: relative;
    display: flex;
    flex-direction: column;
    gap: var(--kr-space-2);
    background: var(--kr-surface);
    border: 2px solid var(--kr-card-border);
    border-radius: var(--kr-radius-lg);
    padding: var(--kr-space-5) var(--kr-space-5) var(--kr-space-5);
    transition:
        border-color var(--kr-transition),
        box-shadow var(--kr-transition);
}

.kr-address-card:hover {
    border-color: var(--kr-primary);
    box-shadow: var(--kr-shadow-sm);
}

.kr-address-card__name {
    font-family: var(--kr-font-body);
    font-weight: var(--kr-weight-bold);
    font-size: var(--kr-text-md);
    color: var(--kr-heading);
    margin: 0;
    padding-right: 2rem; /* room for the kebab */
}

.kr-address-card__lines {
    font-style: italic;
    line-height: var(--kr-leading-snug);
    color: var(--kr-text);
    margin: 0;
}

/* Vertical "kebab" actions menu (three dots). */
.kr-kebab {
    position: absolute;
    top: var(--kr-space-4);
    right: var(--kr-space-4);
    display: inline-flex;
    flex-direction: column;
    gap: 3px;
    padding: var(--kr-space-2);
    border-radius: var(--kr-radius-circle);
    line-height: 0;
    transition: background var(--kr-transition-fast);
}

.kr-kebab::before,
.kr-kebab::after,
.kr-kebab span {
    content: "";
    display: block;
    width: 5px;
    height: 5px;
    border-radius: var(--kr-radius-circle);
    background: var(--kr-primary);
}

.kr-kebab:hover {
    background: var(--kr-section-pink);
}

.kr-kebab:focus-visible {
    outline: 3px solid var(--kr-primary);
    outline-offset: 2px;
    background: var(--kr-section-pink);
}

/* 2-up responsive grid of address cards. */
.kr-address-grid {
    display: grid;
    gap: var(--kr-space-5);
    grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
}

/* ========================================================================
 * Hero banner — full-bleed background, centred image, CTA bottom-right
 * (home-page header; reusable via template-parts/blocks/hero-banner.php)
 * ======================================================================== */
.kr-hero-banner {
    position: relative;
    background-color: var(--kr-color-peach); /* fallback behind the image */
    background-position: center;
    background-size: cover;
    background-repeat: no-repeat;
    overflow: hidden;
}

.kr-hero-banner__inner {
    position: relative;
    display: flex;
    align-items: flex-end;
    justify-content: center;
    min-height: clamp(18rem, 30vw, 34rem);
}

.kr-hero-banner__media {
    display: flex;
    align-items: flex-end;
    justify-content: center;
}

.kr-hero-banner__media img {
    width: auto;
    max-height: clamp(14rem, 26vw, 32rem);
    object-fit: contain;
}

/* CTA floats over the background, lower-right, aligned to the container edge. */
.kr-hero-banner__actions {
    position: absolute;
    right: 0;
    bottom: clamp(1.5rem, 12%, 5rem);
    margin: 0;
}

@media (max-width: 768px) {
    .kr-hero-banner {
        padding-block: var(--kr-space-6);
    }
    .kr-hero-banner__inner {
        flex-direction: column;
        align-items: center;
        min-height: 0;
        gap: var(--kr-space-5);
    }
    .kr-hero-banner__media img {
        max-height: clamp(12rem, 60vw, 22rem);
    }
    .kr-hero-banner__actions {
        position: static;
        bottom: auto;
    }
}

/* ========================================================================
 * Product category slider (Swiper) — narrower than content, hover-card slides
 * (template-parts/blocks/category-slider.php; init js/category-slider.js)
 * ======================================================================== */
.kr-category-slider {
    position: relative;
    width: 80%; /* intentionally narrower than the 85% content width */
    max-width: 1400px;
    margin-inline: auto;
}

/* Section sits flush (no band padding) so slides span its full height. */
.kr-category-slider-section {
    padding-block: 0;
}

.kr-category-slider .swiper-slide {
    height: auto; /* equal-height slides regardless of label length */
}

.kr-category-slide {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: flex-end;
    gap: var(--kr-space-4);
    height: 100%;
    /* Slide (and hover card) runs the full height of the section, edge to edge,
       no rounded corners. A bit more padding at the bottom gives breathing room
       below the label — and the hover background fills it top to bottom. */
    padding-block: var(--kr-space-4) var(--kr-space-6);
    padding-inline: var(--kr-space-3);
    text-align: center;
    text-decoration: none;
    background: transparent;
    transition: background var(--kr-transition);
}

.kr-category-slide__media {
    display: flex;
    align-items: flex-end;
    justify-content: center;
    min-height: clamp(7rem, 12vw, 11rem);
}

.kr-category-slide__media img {
    flex: none;
    width: auto;
    /* SVGs exported with only a viewBox (no width/height attrs) have an aspect
       ratio but no intrinsic pixel size, so width:auto + max-height alone make
       them render at 0px. A definite height anchors them; the ratio sets width. */
    height: clamp(7rem, 12vw, 11rem);
    max-width: 100%;
    object-fit: contain;
}

.kr-category-slide__title {
    font-family: var(--kr-font-button);
    font-size: calc(var(--kr-text-base) + 2px);
    letter-spacing: var(--kr-tracking-button);
    text-transform: uppercase;
    line-height: 1;
    /* A normal navy button at rest — the whole slide stays the single link. */
    color: var(--kr-btn-primary-text);
    background: var(--kr-primary);
    border: 2px solid var(--kr-primary);
    border-radius: var(--kr-btn-radius);
    padding: 0.6em 1.4em;
    transition:
        background var(--kr-transition),
        color var(--kr-transition),
        border-color var(--kr-transition);
}

/* Hover / keyboard focus: pink-pale card + the title becomes a navy pill. */
.kr-category-slide:hover,
.kr-category-slide:focus-visible {
    background: var(--kr-color-pink-pale);
}

.kr-category-slide:hover .kr-category-slide__title,
.kr-category-slide:focus-visible .kr-category-slide__title {
    /* Standard button hover flip: navy → light-pink, navy text (WCAG-safe). */
    background: var(--kr-btn-soft-bg);
    border-color: var(--kr-btn-soft-bg);
    color: var(--kr-primary);
}

/* Bare navy chevrons sitting just outside the track. */
.kr-category-slider__nav {
    position: absolute;
    top: 42%;
    transform: translateY(-50%);
    z-index: 2;
    width: clamp(1.1rem, 1.6vw, 1.6rem);
    padding: 0;
    color: var(--kr-primary);
    background: transparent;
    border: 0;
    cursor: pointer;
    transition:
        color var(--kr-transition-fast),
        opacity var(--kr-transition-fast);
}

.kr-category-slider__nav svg {
    display: block;
    width: 100%;
    height: auto;
}

.kr-category-slider__nav:hover {
    color: var(--kr-accent);
}

.kr-category-slider__nav--prev {
    left: -2.5rem;
}
.kr-category-slider__nav--next {
    right: -2.5rem;
}

.kr-category-slider__nav.swiper-button-disabled {
    opacity: 0.3;
    cursor: default;
}

@media (max-width: 768px) {
    .kr-category-slider {
        width: 88%;
    }
    .kr-category-slider__nav--prev {
        left: -1.5rem;
    }
    .kr-category-slider__nav--next {
        right: -1.5rem;
    }
}

/* M1 + M2 — two category buttons with the third peeking (decided 8 Sept) */
@media (max-width: 639px) {
    .kr-category-slider { width: 94%; }
    .kr-category-slider__nav { display: none; }
}

/* ========================================================================
 * Kadoos product carousel — filter pills swap pre-rendered Swiper carousels
 * (template-parts/blocks/kadoos-carousel.php; init js/kadoos-carousel.js)
 * ======================================================================== */
.kr-kadoos {
    position: relative;
    /* Cyan band dialled back so it reads as a soft tint behind the cards
       (overrides the full-strength .kr-section--cyan fill on this block).
       HP3: 30%, not the 50% it was — that is the value in the client's own
       source file for this band. */
    background: color-mix(in srgb, var(--kr-section-cyan) 30%, transparent);
}

/* Decorative speech blob (SVG carries its own text). In normal flow so it
   reserves its own space, flush to the left edge of the screen (no gutter). */
.kr-kadoos__blob {
    width: clamp(15rem, 32vw, 34rem);
    margin: 0 0 var(--kr-space-4);
    pointer-events: none;
}
.kr-kadoos__blob img {
    width: 100%;
    height: auto;
}

/* Filter pills row. */
.kr-kadoos__filters {
    position: relative;
    z-index: 2;
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    gap: var(--kr-space-3);
    margin-bottom: var(--kr-space-3); /* sit closer to the slider */
}

/* Active filter = pink outline (per design), distinct from the global
   .kr-pill.is-active pink fill used elsewhere. */
.kr-kadoos .kr-kadoos__filter.is-active {
    color: var(--kr-accent);
    background: var(--kr-surface);
    border-color: var(--kr-accent);
}

/* Carousels — only the active one shows; the rest stay rendered but hidden. */
.kr-kadoos__carousel {
    position: relative;
    display: none;
}
.kr-kadoos__carousel.is-active {
    display: block;
}

.kr-kadoos__swiper {
    padding-top: var(--kr-space-3); /* room for the heart badge + its shadow */
}

/* Bare navy chevrons just outside the track. */
.kr-kadoos__nav {
    position: absolute;
    top: 45%;
    transform: translateY(-50%);
    z-index: 2;
    width: clamp(1.1rem, 1.6vw, 1.6rem);
    padding: 0;
    color: var(--kr-primary);
    background: transparent;
    border: 0;
    cursor: pointer;
    transition:
        color var(--kr-transition-fast),
        opacity var(--kr-transition-fast);
}
.kr-kadoos__nav svg {
    display: block;
    width: 100%;
    height: auto;
}
.kr-kadoos__nav:hover {
    color: var(--kr-accent);
}
.kr-kadoos__nav--prev {
    left: -2.5rem;
}
.kr-kadoos__nav--next {
    right: -2.5rem;
}
.kr-kadoos__nav.swiper-button-disabled {
    opacity: 0.3;
    cursor: default;
}

.kr-kadoos__action {
    margin-top: var(--kr-space-8);
}

/* ---- Product card -------------------------------------------------------- */
.kr-product-card {
    position: relative;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: var(--kr-space-4); /* space between the image and the cart link */
    height: 100%;
    padding-top: 1.4rem; /* room so the heart badge straddles the card top */
}

.kr-product-card__media {
    position: relative;
    width: 100%;
    aspect-ratio: 1 / 1;
    background: var(--kr-surface);
    border-radius: var(--kr-radius-lg);
    box-shadow: var(--kr-shadow-sm);
    overflow: hidden;
}
.kr-product-card__link {
    display: flex;
    width: 100%;
    height: 100%;
}
.kr-product-card__media img {
    width: 100%;
    height: 100%;
    object-fit: contain;
    padding: var(--kr-space-4);
}

.kr-product-card__cart {
    position: relative;
    display: inline-block;
    font-family: var(--kr-font-button);
    font-size: calc(var(--kr-text-sm) * 1.35);
    letter-spacing: var(--kr-tracking-button);
    text-transform: uppercase;
    color: var(--kr-primary);
    text-decoration: none;
    padding-top: var(--kr-space-3);
    padding-bottom: var(--kr-space-2);
    transition: color var(--kr-transition-fast);
}
/* Light-pink underline, wider than the text. */
.kr-product-card__cart::after {
    content: "";
    position: absolute;
    left: 50%;
    bottom: 0;
    transform: translateX(-50%);
    width: calc(100% + 2.2rem);
    height: 4px;
    border-radius: var(--kr-radius-pill);
    background: var(--kr-color-pink-light);
}
.kr-product-card__cart:hover {
    color: var(--kr-accent);
}

/* ---- Wishlist heart (native) -------------------------------------------- */
.kr-wishlist-heart {
    position: absolute;
    /* centred on the top-right corner: half the 2.6rem badge overhangs the top,
       half overhangs the right. The card's padding-top keeps the top overhang
       inside the slide so Swiper doesn't clip it. */
    top: 0.1rem;
    right: -1.3rem;
    z-index: 3;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 2.6rem;
    height: 2.6rem;
    padding: 0;
    background: var(--kr-surface);
    border-radius: var(--kr-radius-circle);
    box-shadow: var(--kr-shadow-sm);
    cursor: pointer;
}
.kr-wishlist-heart__icon {
    width: 1.45rem;
    height: 1.45rem;
    object-fit: contain;
    transition: transform var(--kr-transition-fast);
}
/* Swap empty/full heart by wishlist state. */
.kr-wishlist-heart__icon--full {
    display: none;
}
.kr-wishlist-heart.is-active .kr-wishlist-heart__icon--empty {
    display: none;
}
.kr-wishlist-heart.is-active .kr-wishlist-heart__icon--full {
    display: block;
}
.kr-wishlist-heart:hover .kr-wishlist-heart__icon {
    transform: scale(1.12);
}
.kr-wishlist-heart.is-loading {
    opacity: 0.6;
    pointer-events: none;
}

@media (max-width: 768px) {
    .kr-kadoos__blob {
        width: 11rem;
    }
    .kr-kadoos__nav--prev {
        left: -1.25rem;
    }
    .kr-kadoos__nav--next {
        right: -1.25rem;
    }
}

/* M3 — the speech cloud as large as the phone allows. Client asked for 200%; 30rem is 2x the 15rem it renders at, min() caps it at the screen. */
@media (max-width: 767px) { .kr-kadoos__blob { width: min(30rem, 100%); } }

/* ========================================================================
 * Text + image split — narrow text column (1/3) beside a wide image (2/3)
 * (template-parts/blocks/text-image-split.php)
 * ======================================================================== */
.kr-text-image {
    --kr-ti-pad-block: clamp(3rem, 5vw, 6rem); /* band padding; media-bg cancels it to span full height */
    background: var(--kr-color-pink-light);
    padding-block: var(--kr-ti-pad-block); /* coloured band — top/bottom breathing room */
}

.kr-text-image__grid {
    display: grid;
    grid-template-columns: 1.2fr 2fr; /* text a bit wider than 1/3 · image 2/3 */
    gap: var(--kr-space-6);
    align-items: center;
    /* Full-width: the left edge lines up with the site container, while the
       image runs all the way to the right edge of the page. */
    padding-left: max(
        calc((100% - var(--kr-container-width)) / 2),
        calc((100vw - var(--kr-container-max)) / 2)
    );
    padding-right: 0;
}

/* Text column: a little more breathing room top and bottom. */
.kr-text-image__text {
    padding-block: var(--kr-space-4);
}

/* Optional reversed layout: image on the left (bleeds to the left edge). */
.kr-text-image--image-left .kr-text-image__grid {
    grid-template-columns: 2fr 1.2fr;
    padding-left: 0;
    padding-right: max(
        calc((100% - var(--kr-container-width)) / 2),
        calc((100vw - var(--kr-container-max)) / 2)
    );
}
.kr-text-image--image-left .kr-text-image__media {
    order: -1;
}

/* Contained variant: both columns inside the container, rounded image, no bleed.
   (Placed after the image-left rules so it overrides their bleed padding/columns.) */
.kr-text-image--contained {
    /* Behang: more breathing room top/bottom than the default band. */
    --kr-ti-pad-block: clamp(4rem, 6vw, 7.5rem);
}
.kr-text-image--contained .kr-text-image__grid {
    grid-template-columns: 1fr 1fr;
    padding-inline: 0;
    gap: var(--kr-space-7); /* a bit more space between image and text (behang) */
    width: 85%; /* narrower than the 90% container → more space on the sides */
}
.kr-text-image--contained .kr-text-image__media img {
    border-radius: var(--kr-radius-lg);
    box-shadow: var(--kr-shadow-md);
}

.kr-text-image__btn {
    margin-top: var(--kr-space-6);
}

.kr-text-image__title {
    margin-top: 0;
    margin-bottom: var(--kr-space-4);
    font-size: calc(var(--kr-text-2xl) * 0.8); /* 0.8× the default h2 */
    color: var(--kr-heading);
}

.kr-text-image__body {
    color: var(--kr-text);
}
.kr-text-image__body p {
    font-style: italic; /* brand running copy */
    font-weight: var(--kr-weight-light);
    line-height: var(--kr-leading-normal);
    margin: 0 0 var(--kr-space-4);
}
.kr-text-image__body p:last-child {
    margin-bottom: 0;
}
/* Inline subheadings (e.g. "Van Tropisch behang …") stay upright + bold. */
.kr-text-image__body :is(h2, h3, h4, h5, strong, b) {
    font-style: normal;
    font-weight: var(--kr-weight-bold);
    color: var(--kr-heading);
}
/* HP4 — inline links inside the prose blocks: read as links without shouting.
   The client links the bold words herself in the editor (ACF WYSIWYG link button). */
.kr-text-image__body a,
.kr-text-aside .kr-body-text a {
    color: var(--kr-link);
    text-decoration: underline;
    text-decoration-color: var(--kr-accent);
    text-decoration-thickness: 2px;
    text-underline-offset: 0.15em;
    font-weight: inherit;
}
.kr-text-image__body a:hover,
.kr-text-aside .kr-body-text a:hover {
    text-decoration-color: currentColor;
}
.kr-text-image__body a:focus-visible,
.kr-text-aside .kr-body-text a:focus-visible {
    outline: 2px solid var(--kr-focus-ring, var(--kr-color-navy));
    outline-offset: 2px;
    border-radius: var(--kr-radius-xs);
}
/* Heading-level subheadings get top spacing to group with their paragraph. */
.kr-text-image__body :is(h2, h3, h4, h5):not(:first-child) {
    margin-top: var(--kr-space-5);
}
/* 'Tekst & beeld' split: bold inline text renders white (not the contained behang). */
.kr-text-image:not(.kr-text-image--contained) .kr-text-image__body :is(strong, b) {
    color: var(--kr-color-white);
}

.kr-text-image__media img {
    width: 100%;
    height: auto;
}

/* Optional decorative background behind the media half. The image (above) sits
   on top — use a transparent foreground (PNG/SVG) to let it show through. The
   column stretches to the grid row, then negative block margins (equal to the
   band padding) grow it past the padding so the backdrop spans the section
   top-to-bottom, edge to edge. */
.kr-text-image--media-bg .kr-text-image__media {
    align-self: stretch;
    margin-block: calc(-1 * var(--kr-ti-pad-block));
    display: flex;
    align-items: center;
    justify-content: center;
    background-image: var(--kr-ti-media-bg, none);
    background-position: center;
    background-size: cover;
    background-repeat: no-repeat;
}
/* Contained layout already rounds the foreground image — round the backdrop too. */
.kr-text-image--contained.kr-text-image--media-bg .kr-text-image__media {
    border-radius: var(--kr-radius-lg);
    overflow: hidden;
}

@media (max-width: 860px) {
    .kr-text-image__grid,
    .kr-text-image--image-left .kr-text-image__grid {
        grid-template-columns: 1fr;
        padding-inline: var(--kr-gutter); /* normal gutters when stacked */
    }
    /* Contained keeps its container gutters (no extra padding), just stacks. */
    .kr-text-image--contained .kr-text-image__grid {
        grid-template-columns: 1fr;
    }
    .kr-text-image__text {
        padding-block: var(--kr-space-2);
    }
    .kr-text-image--image-left .kr-text-image__media {
        order: 0;
    }
    /* Stacked: drop the full-height bleed so the backdrop stays within its row. */
    .kr-text-image--media-bg .kr-text-image__media {
        margin-block: 0;
    }
}

/* ========================================================================
 * Top products (best sellers) — heading + 5-column grid, cards rotate on hover
 * (template-parts/blocks/top-products.php)
 * ======================================================================== */
.kr-top-products {
    /* A bit less top spacing than the default section gap. */
    padding-top: calc(var(--kr-section-gap) * 0.65);
}
.kr-top-products__head {
    margin-bottom: var(--kr-space-8); /* more space between the title and the cards */
}
.kr-top-products__icon img {
    width: clamp(4rem, 8vw, 7rem);
    height: auto;
    margin-inline: auto;
}
/* Wrap shrink-wraps to the title text so the wave can be sized relative to it. */
.kr-top-products__title-wrap {
    display: inline-block;
}
.kr-top-products__title {
    margin: 0;
}
.kr-top-products__accent {
    color: var(--kr-accent); /* the "5!" in pink */
}
/* Wave = 170% of the title text width, centred under it. */
.kr-top-products__wave {
    display: block;
    width: 65%;
    margin-left:auto;
    margin-right:auto;
    margin-top: var(--kr-space-3);
}
.kr-top-products__wave img {
    display: block;
    width: 100%;
    height: auto;
}

/* Plain grid (no slider) — it's a fixed top 5, and a grid doesn't clip the
   cc-mockup card-back the way a Swiper's overflow does. */
.kr-top-products__grid {
    display: grid;
    grid-template-columns: repeat(var(--kr-top-cols, 5), minmax(0, 1fr));
    gap: var(--kr-space-6) var(--kr-space-7); /* row · wider column gap */
    align-items: stretch; /* HP6: artwork shapes differ; stretch + margin-top:auto on the button keeps buttons aligned */
}
@media (max-width: 1100px) {
    .kr-top-products__grid {
        grid-template-columns: repeat(3, minmax(0, 1fr));
    }
}
@media (max-width: 700px) {
    .kr-top-products__grid {
        grid-template-columns: repeat(2, minmax(0, 1fr));
    }
}

/* M4 — on phones the top-5 is a 3-up scrolling row with paging chevrons. Markup: template-parts/blocks/top-products.php; paging: js/category-slider.js. */
.kr-top-products__track { position: relative; }
.kr-top-products__nav { display: none; }
@media (max-width: 767px) {
    .kr-top-products__grid { display: flex; gap: var(--kr-space-3); overflow-x: auto; scroll-snap-type: x mandatory; scrollbar-width: none; padding-block: var(--kr-space-2); }
    .kr-top-products__grid::-webkit-scrollbar { display: none; }
    .kr-top-products__grid > .kr-top-card { flex: 0 0 calc((100% - 2 * var(--kr-space-3)) / 3); min-width: 0; scroll-snap-align: start; }
    .kr-top-products .kr-config-badge { font-size: var(--kr-text-xs); }
    .kr-top-products__track.is-scrollable .kr-top-products__nav { position: absolute; top: 50%; transform: translateY(-50%); z-index: 3; display: flex; align-items: center; justify-content: center; width: var(--kr-tap-target); height: var(--kr-tap-target); padding: 0; color: var(--kr-primary); background: var(--kr-surface); border: 0; border-radius: var(--kr-radius-circle); box-shadow: var(--kr-shadow-sm); cursor: pointer; }
    .kr-top-products__nav--prev { left: 0; }
    .kr-top-products__nav--next { right: 0; }
    .kr-top-products__nav svg { display: block; width: 1.25rem; height: auto; }
    .kr-top-products__nav[disabled] { opacity: 0.3; cursor: default; }
    .kr-top-products__nav:focus-visible { outline: 2px solid var(--kr-focus-ring, var(--kr-color-navy)); outline-offset: 2px; }
}

.kr-top-card {
    position: relative; /* anchors the .kr-config-badge to the card's top-centre */
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: var(--kr-space-5);
}

/* Card image reuses the cc-mockup component (3D card-back via ::before, and the
   hover translate/rotate). Override its shrink-wrap so the artwork fills the
   slide at its natural proportions, and point the back image at the local SVG. */
.kr-top-card__media.cc-mockup {
    display: block;
    width: 100%;
    /* --mock-back is set inline (absolute URL) in the block. */
}
.kr-top-card__media.cc-mockup:hover {
    z-index: 2;
}
.kr-top-card__media.cc-mockup > img {
    width: 100% !important;
    height: auto !important;
}

/* ========================================================================
 * Newsletter — full-bleed background, centred Forminator form, side blurbs
 * (template-parts/blocks/newsletter.php)
 * ======================================================================== */
.kr-newsletter {
    background-color: var(--kr-color-cream); /* #fffbf8 (≈ #FFFBF9), behind the SVG */
    /* The image (passed in via --kr-nl-bg from the block) sits under a flat 30%
       cream wash, so it renders at 70% opacity over the cream band (wash = 1 −
       image opacity). */
    background-image:
        linear-gradient(
            color-mix(in srgb, var(--kr-color-cream) 30%, transparent),
            color-mix(in srgb, var(--kr-color-cream) 30%, transparent)
        ),
        var(--kr-nl-bg, none);
    background-size: cover;
    background-position: center;
    background-repeat: no-repeat;
    padding-block: clamp(4rem, 6vw, 8rem); /* extra top/bottom breathing room */
}

.kr-newsletter__inner {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: clamp(2rem, 4vw, 4rem); /* more space between the blurbs and the form */
}

/* Side blurbs hug the centred form. */
.kr-newsletter__left,
.kr-newsletter__right {
    flex: 1 1 0;
    display: flex;
}
.kr-newsletter__left {
    justify-content: flex-end;
    transform: translate(0.5rem, -1rem); /* slight up nudge, more space kept */
}
.kr-newsletter__right {
    justify-content: flex-start;
    transform: translate(-0.5rem, 1rem); /* slight down nudge, more space kept */
}
.kr-newsletter__left img,
.kr-newsletter__right img {
    width: 100%;
    max-width: clamp(10rem, 20vw, 17rem); /* smaller decorative images */
    height: auto;
}

.kr-newsletter__form {
    flex: 0 0 auto;
    align-self: center; /* form stays centred; blurbs are nudged around it */
    width: clamp(15rem, 24vw, 20rem); /* slightly smaller form */
    text-align: center;
}

/* ---- Forminator form styling (scoped) ----------------------------------
 * Override the plugin's defaults: white pill input, navy "Aanmelden" button.
 * !important is used deliberately to win over Forminator's own stylesheet. */
.kr-newsletter__form .forminator-input,
.kr-newsletter__form input[type="email"],
.kr-newsletter__form input[type="text"] {
    width: 100% !important;
    background: var(--kr-surface) !important;
    border: 2px solid var(--kr-border) !important;
    border-radius: var(--kr-radius-pill) !important;
    color: var(--kr-text) !important;
    font-family: var(--kr-font-body) !important;
    font-style: normal !important;
    padding: 0.9em 1.4em !important;
}
.kr-newsletter__form ::placeholder {
    font-style: italic !important;
    color: var(--kr-field-placeholder) !important;
}

.kr-newsletter__form .forminator-button,
.kr-newsletter__form button[type="submit"] {
    display: flex !important; /* block-level so margin-left:auto pushes it right */
    width: fit-content;
    align-items: center;
    justify-content: center;
    margin-top: var(--kr-space-4);
    margin-left: auto !important; /* sit at the right side of the form */
    margin-right: 0 !important;
    padding: 0.6em 2.6em !important; /* less top/bottom → shorter button */
    background: var(--kr-primary) !important;
    color: var(--kr-btn-primary-text) !important; /* standard button text colour */
    border: 2px solid var(--kr-primary) !important;
    border-radius: var(--kr-btn-radius) !important;
    font-family: var(--kr-font-button) !important; /* standard button font (Drawing Doodle) */
    font-weight: var(--kr-weight-regular) !important;
    font-size: calc(var(--kr-text-base) + 2px) !important;
    letter-spacing: var(--kr-tracking-button) !important;
    text-transform: uppercase !important;
    cursor: pointer;
    transition:
        background var(--kr-transition),
        color var(--kr-transition);
}
.kr-newsletter__form .forminator-button:hover,
.kr-newsletter__form button[type="submit"]:hover {
    background: var(--kr-btn-soft-bg) !important;
    border-color: var(--kr-btn-soft-bg) !important;
    color: var(--kr-primary) !important;
}

@media (max-width: 900px) {
    .kr-newsletter__inner {
        flex-direction: column;
    }
    .kr-newsletter__left,
    .kr-newsletter__right {
        justify-content: center;
        transform: none; /* drop the desktop diagonal nudges when stacked */
    }
    .kr-newsletter__left img,
    .kr-newsletter__right img {
        max-width: 15rem;
    }
    .kr-newsletter__form {
        align-self: center; /* reset the desktop drop when stacked */
        width: min(100%, 22rem);
    }
}

/* ========================================================================
 * Text + aside image — two titles + rich text, small image bottom-centred right
 * (template-parts/blocks/text-image-aside.php)
 * ======================================================================== */
.kr-text-aside__grid {
    display: grid;
    grid-template-columns: 1.7fr 1fr; /* wide text · narrow image column */
    gap: var(--kr-space-6);
    align-items: stretch;
}

.kr-text-aside__title {
    margin: 0 0 var(--kr-space-2);
    font-size: var(--kr-text-3xl);
    color: var(--kr-heading);
}
.kr-text-aside__subtitle {
    margin: 0 0 var(--kr-space-6);
    font-family: var(--kr-font-heading);
    font-size: var(--kr-text-xl);
    line-height: var(--kr-leading-snug);
    color: var(--kr-heading);
}

/* Small image, centred at the bottom of its column. */
.kr-text-aside__media {
    display: flex;
    align-items: flex-end;
    justify-content: center;
}
.kr-text-aside__media img {
    width: clamp(9rem, 16vw, 15rem);
    max-width: 100%;
    height: auto;
}

@media (max-width: 860px) {
    .kr-text-aside__grid {
        grid-template-columns: 1fr;
    }
    .kr-text-aside__media {
        margin-top: var(--kr-space-5);
    }
}

/* ========================================================================
 * Integration guards
 * The base input/button rules are intentionally global (whole-site brand),
 * which means they also hit WordPress core + WooCommerce markup. These rules
 * keep those surfaces working. Keep them last so they win.
 * ======================================================================== */

/* ---- Default WP search form (searchform.php, widgets, 404, no-results) -
 * Without this the global input rule turns the search field into a solid
 * pink box and the icon-less submit button renders invisible. */
.search-form {
    display: flex;
    align-items: center;
    gap: var(--kr-space-2);
    max-width: 420px;
    background: var(--kr-surface);
    border: 2px solid var(--kr-border);
    border-radius: var(--kr-radius-pill);
    padding-right: var(--kr-space-1);
}

.search-form .search-field {
    flex: 1;
    background: transparent;
    border: none;
    border-radius: 0;
}

.search-form .search-field:focus {
    background: transparent;
}

.search-form .search-submit {
    flex: none;
    width: 2.6em;
    height: 2.6em;
    padding: 0;
    border-radius: var(--kr-radius-circle);
    background-color: var(--kr-primary);
    color: var(--kr-primary-contrast);
    /* magnifier glyph (cream on navy) */
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cg fill='none' stroke='%23fffbf8' stroke-width='2' stroke-linecap='round'%3E%3Ccircle cx='11' cy='11' r='7'/%3E%3Cpath d='M21 21l-4.3-4.3'/%3E%3C/g%3E%3C/svg%3E");
    background-repeat: no-repeat;
    background-position: center;
    background-size: 1.1em;
}

/* ---- WooCommerce buttons -----------------------------------------------
 * `.button` is styled brand-wide as the navy primary. Restore priority for
 * the real commerce CTAs and cover disabled/quantity states. */
.button.alt,
.single_add_to_cart_button,
.wc-block-components-button {
    background: var(--kr-accent);
    border-color: var(--kr-accent);
    color: var(--kr-accent-contrast);
}

.button.alt:hover,
.single_add_to_cart_button:hover,
.wc-block-components-button:hover {
    background: var(--kr-primary);
    border-color: var(--kr-primary);
    color: var(--kr-btn-primary-text);
}

.button[disabled],
.button:disabled,
.button.disabled {
    opacity: 0.5;
    cursor: not-allowed;
    transform: none;
    box-shadow: none;
}

/* Quantity field must stay compact, not the global width:100% pink box. */
.quantity .qty,
input.qty {
    width: auto;
    min-width: 3.5em;
    text-align: center;
}

/* ---- Same-tone backgrounds ---------------------------------------------
 * --kr-field-bg equals the pink-pale section tint, so borderless fields
 * become invisible inside a pink band. Give them a white fill there. */
.kr-section--pink :is(input, textarea, select),
.kr-bg-pink-pale :is(input, textarea, select),
.kr-bg-pink :is(input, textarea, select) {
    background-color: var(--kr-color-white);
}

/* ========================================================================
 * Shop categories grid — product category cards (first-product artwork in the
 * cc-mockup card-back + a navy pill label)
 * (template-parts/blocks/category-grid.php — the WooCommerce shop landing)
 * ======================================================================== */

/* Shop landing wants a tighter frame than the standard 90% container so the
   category cards sit in from the edges — drop this row to 80% (still capped at
   --kr-container-max). Scoped to the shop block; doesn't affect other reuses. */
.kr-shop-categories > .kr-container {
    width: 80%;
}

.kr-shop-categories__title {
    margin: 0 0 var(--kr-space-8);
    font-size: var(--kr-text-3xl);
}

/* Responsive grid; --kr-cat-cols (default 4) is set inline by the block.
   No overflow clipping, so the cc-mockup card-back can peek out behind cards. */
.kr-category-grid {
    display: grid;
    grid-template-columns: repeat(var(--kr-cat-cols, 4), minmax(0, 1fr));
    gap: var(--kr-space-8) var(--kr-space-6); /* row · column */
    align-items: stretch; /* DA10: category images differ in shape; keep the name pills aligned */
}
@media (max-width: 1100px) {
    .kr-category-grid {
        grid-template-columns: repeat(3, minmax(0, 1fr));
    }
}
@media (max-width: 760px) {
    .kr-category-grid {
        grid-template-columns: repeat(2, minmax(0, 1fr));
    }
}
@media (max-width: 420px) {
    .kr-category-grid {
        grid-template-columns: minmax(0, 1fr);
    }
}

.kr-category-card {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: var(--kr-space-4);
    text-decoration: none;
}

/* Card image reuses the cc-mockup component (3D card-back via ::before + the
   hover translate/rotate). Override its shrink-wrap so the artwork fills the
   column at its natural proportions; --mock-back is set inline in the block. */
.kr-category-card__media.cc-mockup {
    display: block;
    width: 100%;
}
.kr-category-card__media.cc-mockup:hover {
    z-index: 2;
}
.kr-category-card__media.cc-mockup > img {
    width: 100% !important;
    height: auto !important;
}

/* Navy button pill at rest (mirrors .kr-category-slide__title). */
.kr-category-card__title {
    font-family: var(--kr-font-button);
    font-size: calc(var(--kr-text-base) + 2px);
    letter-spacing: var(--kr-tracking-button);
    text-transform: uppercase;
    line-height: 1;
    text-align: center;
    color: var(--kr-btn-primary-text);
    background: var(--kr-primary);
    border: 2px solid var(--kr-primary);
    border-radius: var(--kr-btn-radius);
    padding: 0.6em 1.4em;
    transition:
        background var(--kr-transition),
        color var(--kr-transition),
        border-color var(--kr-transition);
}

/* Hover / keyboard focus: standard button flip (navy → light-pink, navy text). */
.kr-category-card:hover .kr-category-card__title,
.kr-category-card:focus-visible .kr-category-card__title {
    background: var(--kr-btn-soft-bg);
    border-color: var(--kr-btn-soft-bg);
    color: var(--kr-primary);
}

/* ========================================================================
 * Product category archive — filter sidebar + tiles + quick-view popup
 * (woocommerce/taxonomy-product_cat.php, template-parts/product/*,
 *  inc/product-archive.php, js/product-archive.js)
 * Replaces the legacy shortcodes/product-page design (now sunsetted).
 * ======================================================================== */

/* ---- Layout: filter sidebar + product main ------------------------------ */
.kr-product-archive {
    padding-block: var(--kr-section-gap);
}

.kr-product-archive__header {
    margin-bottom: var(--kr-space-8);
    text-align: left;
}

/* Intro band: title + description on the left, the count/sort toolbar pinned to
   the bottom-right and aligned with the last line of the description. */
.kr-product-archive__intro {
    display: flex;
    align-items: flex-end;
    justify-content: space-between;
    gap: var(--kr-space-6);
    margin-bottom: var(--kr-space-8);
}
.kr-product-archive__intro .kr-product-archive__header {
    flex: 1 1 auto;
    margin-bottom: 0;
}
.kr-product-archive__intro .kr-product-toolbar {
    flex: 0 0 auto;
}
@media (max-width: 768px) {
    .kr-product-archive__intro {
        flex-direction: column;
        align-items: flex-start;
        gap: var(--kr-space-4);
    }
}
@media (max-width: 768px) {
    .kr-product-archive__intro .kr-product-toolbar--archive {
        align-self: stretch;
        justify-content: flex-end;
    }
}

.kr-product-archive__title {
    margin: 0 0 var(--kr-space-3);
    font-size: var(--kr-text-3xl);
}
.kr-product-archive__description {
    max-width: var(--kr-container-narrow);
    color: var(--kr-text); /* brand navy (matches the homepage editorial copy), not the ink body colour */
    line-height: var(--kr-leading-normal);
}

.kr-product-archive__layout {
    display: grid;
    grid-template-columns: minmax(0, 18rem) minmax(0, 1fr);
    gap: var(--kr-space-7);
    align-items: start;
}
@media (max-width: 980px) {
    .kr-product-archive__layout {
        grid-template-columns: minmax(0, 1fr);
        gap: var(--kr-space-5);
    }
}

/* ---- Filter sidebar ----------------------------------------------------- */
.kr-product-filters {
    padding: var(--kr-space-7) var(--kr-space-6); /* generous top/bottom, a little more on the sides */
    background: var(--kr-color-pink-pale);
    border-radius: var(--kr-radius-xl);
}

.kr-product-filters__header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--kr-space-3);
}

.kr-product-filters__heading {
    margin: 0;
    font-size: var(--kr-text-xl);
    text-transform: uppercase;
}

/* Collapse toggle — only shown when the sidebar stacks (mobile). */
.kr-product-filters__toggle {
    display: none;
    padding: var(--kr-space-2);
    color: var(--kr-primary);
    background: transparent;
    border: 0;
    border-radius: var(--kr-radius-circle);
    cursor: pointer;
}
.kr-product-filters__toggle-icon {
    display: inline-block;
    font-size: var(--kr-text-sm);
    transition: transform var(--kr-transition);
}

.kr-product-filters__list {
    margin-top: var(--kr-space-4);
    display: flex;
    flex-direction: column;
    gap: var(--kr-space-1);
}

.kr-product-filters__option {
    display: flex;
    align-items: center;
    gap: var(--kr-space-2);
    margin: 0; /* cancel the global form-label margin so the list gap controls spacing */
    color: var(--kr-text);
    font-weight: var(--kr-weight-semibold);
    cursor: pointer;
    transition: color var(--kr-transition);
}
.kr-product-filters__option:hover {
    color: var(--kr-accent);
}

/* Hide the native control; the box below is the visible checkbox. */
.kr-product-filters__checkbox {
    position: absolute;
    width: 1px;
    height: 1px;
    margin: -1px;
    padding: 0;
    border: 0;
    overflow: hidden;
    clip: rect(0 0 0 0);
    white-space: nowrap;
}
.kr-product-filters__box {
    flex: none;
    width: 18px;
    height: 18px;
    background: var(--kr-color-white);
    border: 1px solid var(--kr-primary);
    border-radius: var(--kr-radius-xs);
    transition:
        background var(--kr-transition),
        border-color var(--kr-transition);
}
.kr-product-filters__option:hover .kr-product-filters__box {
    border-color: var(--kr-accent);
}
/* Checked = a solid light-pink fill (no checkmark); navy border keeps it defined. */
.kr-product-filters__checkbox:checked + .kr-product-filters__box {
    background: var(--kr-color-pink-light);
}
.kr-product-filters__checkbox:focus-visible + .kr-product-filters__box {
    box-shadow: var(--kr-focus-shadow);
}
.kr-product-filters__count {
    color: var(--kr-text-muted);
    font-size: var(--kr-text-sm);
    font-weight: var(--kr-weight-regular);
}

/* Disabled (zero results in the current selection). */
.kr-product-filters__option.is-empty {
    opacity: 0.5;
}
.kr-product-filters__option.is-empty .kr-product-filters__checkbox {
    pointer-events: none;
}

/* Mobile: collapsible list behind the toggle.
 *
 * Collapsed, this is a BAR, not a panel: the desktop sidebar's 48px/32px
 * padding and 24-32px heading made it "enorm" on a phone — it filled a third of
 * the screen before a single product showed. It keeps the full width (that part
 * was fine) and loses the height: normal control padding, a heading at reading
 * size, and a tighter corner because a ~48px bar with a 32px radius closes into
 * a stadium. The toggle keeps a full 44px target. */
@media (max-width: 980px) {
    .kr-product-filters {
        padding: var(--kr-space-2) var(--kr-space-3);
        border-radius: var(--kr-radius-lg);
    }
    .kr-product-filters__heading {
        font-size: var(--kr-text-md);
    }
    .kr-product-filters__toggle {
        display: inline-flex;
        align-items: center;
        justify-content: center;
        inline-size: var(--kr-tap-target);
        block-size: var(--kr-tap-target);
        padding: 0;
        /* Undo the bar's own left padding on the trailing edge so the 44px
           target reaches the corner instead of floating away from it. */
        margin-inline-end: calc(var(--kr-space-3) * -1);
    }
    .kr-product-filters__list {
        max-height: 0;
        margin-top: 0;
        opacity: 0;
        overflow: hidden;
        transition:
            max-height var(--kr-transition),
            opacity var(--kr-transition),
            margin-top var(--kr-transition);
    }
    .kr-product-filters.is-open {
        padding-bottom: var(--kr-space-4);
    }
    .kr-product-filters.is-open .kr-product-filters__list {
        /* Rows are 44px tap targets now, so the open height has to allow for
           ~25 categories rather than the ~26 short rows 40rem used to hold. */
        max-height: 70rem;
        margin-top: var(--kr-space-3);
        opacity: 1;
    }
    .kr-product-filters.is-open .kr-product-filters__toggle-icon {
        transform: rotate(180deg);
    }
    /* Each row is a tap target of its own once the list is open. */
    .kr-product-filters__option {
        min-block-size: var(--kr-tap-target);
    }
}

/* ---- Toolbar: result count + sort --------------------------------------- */
.kr-product-toolbar {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--kr-space-3);
}

.kr-product-toolbar__count {
    margin: 0;
    font-family: var(--kr-font-heading);
    font-size: var(--kr-text-md);
    text-transform: uppercase;
    color: var(--kr-text);
}
.kr-product-toolbar__total {
    font-weight: var(--kr-weight-bold);
}

.kr-product-toolbar__sep {
    font-family: var(--kr-font-heading);
    font-size: var(--kr-text-md);
    color: var(--kr-color-pink-light);
}

.kr-product-toolbar__sort {
    display: flex;
    align-items: center;
    gap: var(--kr-space-2);
}
.kr-product-toolbar__sort label {
    margin: 0; /* cancel the global form-label margin-bottom so it centres in the row */
    font-family: var(--kr-font-heading);
    font-size: var(--kr-text-md);
    text-transform: uppercase;
    color: var(--kr-text);
    line-height: 1;
    white-space: nowrap;
}
.kr-product-toolbar__select {
    appearance: none;
    -webkit-appearance: none;
    /* DA4: longer sort labels must never widen the toolbar on phones. */
    max-width: 100%;
    min-width: 0;
    padding: 0.5em 2.4em 0.5em 1em; /* room on the right for the custom arrow */
    background-color: var(--kr-color-pink-light);
    /* Custom navy chevron so the arrow stays dark even though the value text is
       white (the native arrow follows `color` in some browsers). A token can't be
       used inside a data-URI, so the navy hex is inlined like the other SVG icons. */
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%2300009c' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M6 9l6 6 6-6'/%3E%3C/svg%3E");
    background-repeat: no-repeat;
    background-position: right 0.9em center;
    background-size: 0.7em;
    color: var(--kr-text);
    border: 1px solid var(--kr-color-pink-light);
    border-radius: var(--kr-radius-sm);
    font-family: var(--kr-font-heading);
    font-size: var(--kr-text-base);
    text-transform: uppercase;
    cursor: pointer;
    transition: box-shadow var(--kr-transition), border-color var(--kr-transition);
}
/* Keep the dropdown list readable (navy on the OS-default light menu). */
.kr-product-toolbar__select option {
    color: var(--kr-text);
}
.kr-product-toolbar__select:focus-visible {
    outline: none;
    border-color: var(--kr-accent);
    box-shadow: var(--kr-focus-shadow);
}

/* ---- Product grid + tiles -----------------------------------------------
 *
 * COLUMN COUNT IS A FLOOR, NOT JUST A CEILING. `auto-fill` with a 13rem (208px)
 * minimum needs a ~448px content box for two columns; a 390px phone gives the
 * container about 351px, so the grid quietly collapsed to ONE enormous card per
 * row on the card archives and on Favorieten. Below 600px the track count is
 * therefore stated outright: exactly two, each free to be as narrow as it needs
 * (`minmax(0, 1fr)` — `0`, not `13rem`, or the tracks overflow the row).
 *
 * `min(13rem, 100%)` in the auto-fill case is the same guard for a container
 * that is narrower than one track, e.g. this grid inside the account column.
 * ------------------------------------------------------------------------ */
.kr-product-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(min(13rem, 100%), 1fr));
    gap: var(--kr-space-8) var(--kr-space-6); /* row · column (row gap clears the heart) */
    align-items: start;
}

@media (max-width: 600px) {
    .kr-product-grid {
        grid-template-columns: repeat(2, minmax(0, 1fr));
        /* Row gap has to clear the badge overhanging the top of a tile (-0.7rem,
           and it may now be two lines) plus the heart overhanging the bottom
           (-0.9rem) of the tile above it. */
        gap: var(--kr-space-7) var(--kr-space-4);
    }
}
.kr-product-grid__empty {
    grid-column: 1 / -1;
    text-align: center;
    color: var(--kr-text-muted);
    font-size: var(--kr-text-md);
}

.kr-product-tile {
    position: relative;
}

.kr-product-tile__link {
    display: block;
    width: 100%;
    padding: 0;
    background: none;
    border: 0;
    cursor: pointer;
    text-decoration: none;
}

/* Configurable tiles reuse the cc-mockup 3D card-back; override its shrink-wrap
   so the artwork fills the column at its natural proportions. */
.kr-product-tile__media.cc-mockup {
    display: block;
    width: 100%;
}
.kr-product-tile__media.cc-mockup:hover {
    z-index: 2;
}
.kr-product-tile__media.cc-mockup > img {
    width: 100% !important;
    height: auto !important;
}

/* Plain media (non-configurable, or any hidden-category product): white rounded
   card — applies whether the wrapper is a link or a quick-view trigger. */
.kr-product-tile__media:not(.cc-mockup) {
    display: block;
    background: var(--kr-surface);
    border-radius: var(--kr-radius-md);
    box-shadow: var(--kr-shadow-sm);
    overflow: hidden;
    transition: transform var(--kr-transition), box-shadow var(--kr-transition);
}
.kr-product-tile__link:hover .kr-product-tile__media:not(.cc-mockup) {
    transform: translateY(-3px);
    box-shadow: var(--kr-shadow-md);
}
.kr-product-tile__media:not(.cc-mockup) img {
    display: block;
    width: 100%;
    height: auto;
}

.kr-product-tile__link:focus-visible {
    outline: 2px solid var(--kr-focus-ring);
    outline-offset: 4px;
    border-radius: var(--kr-radius-sm);
}

/* "Aanpasbare voorkant" ribbon — shared badge marking a personalisable product.
   Reused by the product-archive tile (template-parts/product/tile.php) and the
   top-products card (template-parts/blocks/top-products.php). It anchors to the
   top-centre of the artwork, so its host card must be position:relative and the
   badge must sit OUTSIDE the .cc-mockup element (which tilts on hover). */
.kr-config-badge {
    position: absolute;
    top: -0.7rem;
    left: 50%;
    transform: translateX(-50%);
    z-index: 4;
    padding: 0.4em 1.2em;
    background: var(--kr-primary);
    color: var(--kr-btn-primary-text);
    font-family: var(--kr-font-heading);
    font-size: var(--kr-text-xs);
    text-transform: uppercase;
    white-space: nowrap;
    text-align: center;
    line-height: var(--kr-leading-snug);
    border-radius: var(--kr-radius-pill);
}

/* Two columns on a phone make each tile ~165px wide, and "Aanpasbare voorkant"
   on one line is wider than that. The client's explicit instruction is that
   this badge must NOT get smaller — it becomes unreadable. So the TYPE SIZE IS
   UNCHANGED and the ribbon is allowed to run to two lines instead, which keeps
   it inside its tile without touching legibility. */
@media (max-width: 600px) {
    .kr-config-badge {
        white-space: normal;
        max-inline-size: calc(100% - var(--kr-space-2));
        padding-inline: var(--kr-space-3);
    }
}

/* Native wishlist heart — straddles the tile's bottom-right corner, overhanging
   outside the card like the carousel cards do (default heart look: white circle
   + soft shadow, no border). */
.kr-product-tile .kr-wishlist-heart {
    top: auto;
    right: -0.9rem;
    bottom: -0.9rem;
}

/* ---- Pagination --------------------------------------------------------- */
.kr-product-pagination {
    margin-top: var(--kr-space-7);
    text-align: center;
}
.kr-product-pagination__list {
    display: inline-flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: center;
    gap: var(--kr-space-2);
}
.kr-product-pagination__btn {
    min-width: 2.75rem;
    padding: 0.5em 1em;
    background: var(--kr-color-white);
    color: var(--kr-primary);
    border: 2px solid var(--kr-primary);
    border-radius: var(--kr-radius-pill);
    font-family: var(--kr-font-button);
    font-size: var(--kr-text-base);
    letter-spacing: var(--kr-tracking-button);
    cursor: pointer;
    transition: background var(--kr-transition), color var(--kr-transition), transform var(--kr-transition-fast);
}
.kr-product-pagination__btn:hover {
    background: var(--kr-color-pink-light);
    transform: translateY(-2px);
}
.kr-product-pagination__btn.is-active {
    background: var(--kr-primary);
    color: var(--kr-btn-primary-text);
}
.kr-product-pagination__dots {
    padding-inline: var(--kr-space-1);
    color: var(--kr-primary);
    font-family: var(--kr-font-button);
}

/* ---- Loading state (AJAX swap) ------------------------------------------ */
.kr-product-grid--loading {
    position: relative;
    min-height: 12rem;
    opacity: 0.6;
}
.kr-product-loading {
    grid-column: 1 / -1;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: var(--kr-space-4);
    padding: var(--kr-space-8) var(--kr-space-4);
    font-family: var(--kr-font-heading);
    font-size: var(--kr-text-lg);
    color: var(--kr-primary);
    text-transform: uppercase;
}
.kr-product-loading::after {
    content: "";
    width: var(--kr-loader-size-lg);
    height: var(--kr-loader-size-lg);
    border: var(--kr-loader-ring) solid var(--kr-color-pink-light);
    border-top-color: var(--kr-primary);
    border-radius: var(--kr-radius-circle);
    animation: kr-spin 1s linear infinite;
}
@keyframes kr-spin {
    to {
        transform: rotate(360deg);
    }
}

/* ========================================================================
 * Quick-view popup (configurable products) — template-parts/product/quickview
 * ======================================================================== */
.kr-quickview {
    position: fixed;
    inset: 0;
    z-index: var(--kr-z-modal);
    display: none;
    align-items: center;
    justify-content: center;
    padding: var(--kr-space-4);
    background: rgba(0, 0, 0, 0.6);
}
.kr-quickview.is-open {
    display: flex;
}

.kr-quickview__dialog {
    position: relative;
    width: 100%;
    max-width: 1100px;
    max-height: 90vh;
    overflow-y: auto;
    padding: var(--kr-space-7);
    background: var(--kr-color-cream);
    border-radius: var(--kr-radius-lg);
    box-shadow: var(--kr-shadow-lg);
}

/* Box, glyph size and the 44px hit area come from the shared .kr-close rule at
   the top of this file. The offsets shrink to compensate: the target grew from
   ~26px to 44px, so pulling it 8px/12px in keeps the × where it always sat. */
.kr-quickview__close {
    position: absolute;
    top: var(--kr-space-2);
    right: var(--kr-space-3);
    z-index: 2;
}

/* Two columns: card image on the left, everything else on the right. */
.kr-quickview__grid {
    display: grid;
    grid-template-columns: minmax(0, 0.85fr) minmax(0, 1fr);
    gap: var(--kr-space-7);
    align-items: stretch;
}
@media (max-width: 800px) {
    .kr-quickview__grid {
        grid-template-columns: 1fr;
        gap: var(--kr-space-5);
    }
}

/* ---- Left: card image -------------------------------------------------- */
.kr-quickview__gallery {
    display: flex;
    align-items: center;
    justify-content: center;
    padding-block: var(--kr-space-8); /* extra breathing room above/below the image */
}
.kr-quickview__main-img {
    display: flex;
    align-items: flex-start;
    justify-content: center;
    width: 65%; /* smaller card in the column */
}
.kr-quickview__main-img img {
    width: 100%;
    height: auto;
    max-height: 70vh;
    object-fit: contain;
}
/* Greeting-card products reuse the cc-mockup 3D card-back (like the tile/slider);
   --mock-back is set inline by the JS. Fill the column and drop the in-modal tilt. */
.kr-quickview__main-img.cc-mockup {
    display: block;
    width: 65%; /* smaller card in the column */
}
.kr-quickview__main-img.cc-mockup > img {
    width: 100% !important;
    height: auto !important;
    max-height: none;
}
.kr-quickview__main-img.cc-mockup:hover {
    transform: none;
}

/* ---- Right: info ------------------------------------------------------- */
.kr-quickview__info {
    display: flex;
    flex-direction: column;
    min-width: 0;
}

.kr-quickview__title {
    margin: 0 0 var(--kr-space-4);
    font-size: var(--kr-text-xl);
}

/* Plain price — shown only for simple products (.kr-quickview--simple); configurable
   cards show price per size / in the stacking-discount panel instead. */
.kr-quickview__price {
    display: none;
    margin: 0 0 var(--kr-space-5);
    /* Body font for legible numerals — matches .kr-quickview__bulk-total / .kr-card__price. */
    font-size: var(--kr-text-xl);
    font-weight: var(--kr-weight-bold);
    color: var(--kr-text);
}
.kr-quickview--simple .kr-quickview__price {
    display: block;
}
/* Simple products have no size picker or stacking-discount tabs. */
.kr-quickview--simple .kr-quickview__tabs,
.kr-quickview--simple .kr-quickview__panels {
    display: none;
}

/* Tab switcher — two rounded-rect buttons (shown on both tabs): white with a
   navy outline, the active one filled light-pink (keeping the navy outline). */
.kr-quickview__tabs {
    display: flex;
    gap: var(--kr-space-3);
    margin-bottom: var(--kr-space-5);
}
.kr-quickview__tab {
    padding: 0.45em 1.5em;
    background: var(--kr-color-white);
    color: var(--kr-primary);
    border: 2px solid var(--kr-primary);
    border-radius: var(--kr-radius-md);
    font-family: var(--kr-font-button);
    font-size: var(--kr-text-base);
    letter-spacing: var(--kr-tracking-button);
    cursor: pointer;
    transition: background var(--kr-transition), color var(--kr-transition), border-color var(--kr-transition);
}
.kr-quickview__tab.is-active {
    background: var(--kr-color-pink-pale);
    border-color: var(--kr-primary);
    color: var(--kr-primary);
}

/* Panels */
.kr-quickview__panels {
    flex: 1;
}
.kr-quickview__panel {
    display: none;
}
.kr-quickview__panel.is-active {
    display: block;
}
.kr-quickview__panel-title {
    margin: 0 0 var(--kr-space-3);
    font-size: var(--kr-text-2xl);
}

/* Size picker (1 kaart) */
.kr-quickview__sizes {
    display: flex;
    flex-direction: column;
    gap: var(--kr-space-3);
}
.kr-quickview__size {
    display: flex;
    align-items: center;
    gap: var(--kr-space-3);
    margin: 0;
    color: var(--kr-text);
    font-weight: var(--kr-weight-regular);
    cursor: pointer;
}
.kr-quickview__size input {
    flex: none;
    width: 18px;
    height: 18px;
    appearance: none;
    -webkit-appearance: none;
    background: var(--kr-color-white);
    /* Navy boundary so an empty radio is clearly visible (pink-light fails 1.4.11). */
    border: 2px solid var(--kr-primary);
    border-radius: var(--kr-radius-circle);
    cursor: pointer;
    transition: border-color var(--kr-transition), background var(--kr-transition);
}
.kr-quickview__size input:checked {
    background: var(--kr-color-pink-light);
    border-color: var(--kr-primary);
}
.kr-quickview__size input:focus-visible {
    box-shadow: var(--kr-focus-shadow);
}
.kr-quickview__size-name {
    font-family: var(--kr-font-body);
    font-style: italic;
}
.kr-quickview__size-price {
    font-weight: var(--kr-weight-bold);
}

/* CK4: a size row whose variation could not be resolved is disabled, never guessed. */
.kr-quickview__size.is-disabled {
    cursor: not-allowed;
    color: var(--kr-text-muted);
}
.kr-quickview__size.is-disabled input {
    cursor: not-allowed;
    opacity: .5;
}

/* Bulk / stapelkorting */
.kr-quickview__bulk-field {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--kr-space-4);
    margin-bottom: var(--kr-space-5);
}
.kr-quickview__bulk-field label {
    margin: 0;
    font-family: var(--kr-font-body);
    font-size: var(--kr-text-base);
    color: var(--kr-text);
}
.kr-quickview__select {
    appearance: none;
    -webkit-appearance: none;
    min-width: 5rem;
    padding: 0.4em 2.2em 0.4em 1em;
    background-color: var(--kr-field-bg); /* pink-pale field fill */
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%2300009c' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M6 9l6 6 6-6'/%3E%3C/svg%3E");
    background-repeat: no-repeat;
    background-position: right 0.7em center;
    background-size: 0.7em;
    color: var(--kr-primary);
    border: 2px solid transparent; /* borderless light-pink fill; the focus ring uses border-color */
    border-radius: var(--kr-radius-md);
    font-family: var(--kr-font-body);
    font-size: var(--kr-text-base);
    cursor: pointer;
}
.kr-quickview__select:focus-visible {
    outline: none;
    border-color: var(--kr-accent);
    box-shadow: var(--kr-focus-shadow);
}

.kr-quickview__bulk-price {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: var(--kr-space-4);
    margin-bottom: var(--kr-space-6);
}
.kr-quickview__bulk-price-label {
    font-family: var(--kr-font-body);
    font-size: var(--kr-text-base);
    color: var(--kr-text);
}
.kr-quickview__bulk-price-amounts {
    display: inline-flex;
    align-items: baseline;
    gap: var(--kr-space-3);
}
.kr-quickview__bulk-original {
    color: var(--kr-text-muted);
    text-decoration: line-through;
}
.kr-quickview__bulk-original:empty {
    display: none;
}
.kr-quickview__bulk-total {
    font-weight: var(--kr-weight-bold);
    color: var(--kr-text);
}

/* Discount tiers (no header row). */
.kr-quickview__rates {
    display: flex;
    flex-direction: column;
    gap: var(--kr-space-2);
}
.kr-quickview__rate-row {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--kr-space-4);
    color: var(--kr-text);
}
.kr-quickview__rate-range {
    font-weight: var(--kr-weight-bold);
}
.kr-quickview__rate-row.is-active {
    color: var(--kr-accent);
}

/* ---- Thumbnail strip (drives the left image) -------------------------- */
.kr-quickview__strip {
    display: flex;
    align-items: center;
    gap: var(--kr-space-3);
    margin-top: var(--kr-space-6);
}
.kr-quickview__strip.is-single {
    display: none;
}
.kr-quickview__thumbs {
    display: flex;
    flex: 1;
    gap: var(--kr-space-3);
    overflow: hidden;
}
.kr-quickview__thumbs img {
    width: 5.5rem;
    height: 5.5rem;
    object-fit: cover;
    background: var(--kr-color-white);
    border: 2px solid transparent;
    border-radius: var(--kr-radius-sm);
    cursor: pointer;
    transition: border-color var(--kr-transition);
}
.kr-quickview__thumbs img.is-active,
.kr-quickview__thumbs img:hover {
    border-color: var(--kr-primary);
}
.kr-quickview__nav {
    flex: none;
    display: flex;
    align-items: center;
    justify-content: center;
    width: 1.6rem;
    padding: 0;
    color: var(--kr-primary);
    background: none;
    border: 0;
    cursor: pointer;
    transition: color var(--kr-transition-fast);
}
.kr-quickview__nav svg {
    width: 100%;
    height: auto;
    pointer-events: none;
}
.kr-quickview__nav:hover {
    color: var(--kr-accent);
}

/* ---- Actions ---------------------------------------------------------- */
.kr-quickview__actions {
    display: flex;
    gap: var(--kr-space-4);
    margin-top: var(--kr-space-6);
}
/* Equal-width buttons: 50/50 with two, full-width when Personaliseren is hidden. */
.kr-quickview__actions .kr-btn {
    flex: 1;
}
/* Buttons are plain design-system components: Personaliseren = .kr-btn--soft
   (light-pink fill, navy label), Winkelmand = .kr-btn (standard). No bespoke
   button styling — the only rule here is the JS hide toggle (base .kr-btn sets
   display:inline-flex, which would otherwise defeat the plain [hidden]). */
.kr-quickview__personalize[hidden] {
    display: none;
}

@media (max-width: 800px) {
    .kr-quickview__dialog {
        padding: var(--kr-space-5);
        max-height: 92vh;
    }
}
@media (max-width: 480px) {
    .kr-quickview__tabs {
        flex-wrap: wrap;
    }
    .kr-quickview__actions {
        flex-direction: column;
    }
}

/* ========================================================================
 * Dimension fields — custom-size products priced per m² (maatwerk behang)
 *
 * A Breedte / Hoogte pair plus a live price indication. Built entirely from
 * existing form primitives (.kr-field-row, .kr-field, .kr-field__label,
 * .kr-input, .kr-field__hint); the only new pieces are the heading and the
 * summary line. Used inside the quick-view popup and on the single-product
 * add-to-cart form (app/wallpaper/includes/modal.php).
 * ======================================================================== */
.kr-dimensions {
    margin-bottom: var(--kr-space-5);
}

.kr-dimensions__title {
    margin: 0 0 var(--kr-space-3);
    font-size: var(--kr-text-2xl);
}

/* The two fields sit tighter than in a stacked account form. */
.kr-dimensions .kr-field {
    margin-bottom: var(--kr-space-3);
}

/* "7,50 m² × € 12,50 per m²" — amount right-aligned, like the bulk-price row. */
.kr-dimensions__summary {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: var(--kr-space-3);
    margin: 0;
    min-height: 1.5em;
}
.kr-dimensions__summary:empty {
    display: none;
}

.kr-dimensions__calc {
    color: var(--kr-text-muted);
    font-size: var(--kr-text-sm);
}

.kr-dimensions__total {
    /* Body font for legible numerals — matches .kr-quickview__bulk-total. */
    font-size: var(--kr-text-xl);
    font-weight: var(--kr-weight-bold);
    color: var(--kr-text);
}

.kr-dimensions__note {
    margin: var(--kr-space-1) 0 0;
    font-size: var(--kr-text-sm);
    font-style: italic;
    color: var(--kr-text-muted);
}

/* "per m²" appended to a price wherever it renders (tiles, product page). */
.kr-price-unit {
    font-size: var(--kr-text-sm);
    font-weight: var(--kr-weight-regular);
    color: var(--kr-text-muted);
}

@media (max-width: 480px) {
    .kr-dimensions__summary {
        flex-direction: column;
        align-items: flex-start;
        gap: var(--kr-space-1);
    }
}

/* ========================================================================
 * Step indicator — the 4-step order funnel
 * ("1. Bewerken  2. Winkelmand & adressen  3. Verzenden  4. Afrekenen")
 *
 * Replaces the Divi-era `.cart-steps` markup from the old [cart_step] shortcode
 * (styles were parked in sunsetted/css/style.css): same cyan band + navy text,
 * rebuilt on tokens.
 * ======================================================================== */
.kr-steps {
    background: var(--kr-section-cyan);
    border-radius: var(--kr-radius-md);
    padding: var(--kr-space-3) var(--kr-space-5);
}

.kr-steps__list {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: center;
    gap: var(--kr-space-2) var(--kr-space-5);
    margin: 0;
    padding: 0;
    list-style: none;
}

.kr-steps__item {
    margin: 0;
}

.kr-steps__link {
    display: inline-flex;
    align-items: baseline;
    gap: 0.3em;
    font-family: var(--kr-font-body);
    font-size: var(--kr-text-sm);
    color: var(--kr-primary);
    text-decoration: none;
    transition: color var(--kr-transition-fast);
}

a.kr-steps__link:hover,
a.kr-steps__link:focus-visible {
    color: var(--kr-link-hover);
}

/* Current step: bold, not a link. */
.kr-steps__item.is-current .kr-steps__link {
    font-weight: var(--kr-weight-bold);
    cursor: default;
}

@media (max-width: 640px) {
    .kr-steps__list {
        flex-direction: column;
        align-items: flex-start;
    }
}

/* ========================================================================
 * Cart page — "Winkelmandje"
 * (woocommerce/cart.php + template-parts/cart/*)
 *
 * The page shell and the two-column split below are shared with checkout
 * (step 4, woocommerce/checkout-page.php): steps 2, 3 and 4 are one design
 * family, so `.kr-checkout-page` / `.kr-checkout-layout` are aliases here rather
 * than a second near-identical copy further down the file. Only the pieces that
 * are genuinely checkout-only live in the "Checkout page" section at the end.
 * ======================================================================== */
.kr-cart-page,
.kr-checkout-page {
    padding-block: var(--kr-space-7) var(--kr-space-9);
}

/* Title left, step indicator pinned right — collapses to stacked on tablet. */
.kr-cart-page__head,
.kr-checkout-page__head {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: var(--kr-space-5);
    margin-bottom: var(--kr-space-6);
}

.kr-cart-page__title,
.kr-checkout-page__title {
    margin: 0;
    font-size: var(--kr-text-2xl);
}

/* Spacing only — the banners themselves are the shared .kr-notices component
   (see the "Notices" block above), which also handles the empty case. */
.kr-cart-page__notices,
.kr-checkout__notices {
    margin-bottom: var(--kr-space-6);
}

/* 60/35 split from the design; single column under 1000px. */
.kr-cart-layout,
.kr-checkout-layout {
    display: grid;
    grid-template-columns: minmax(0, 3fr) minmax(0, 1.75fr);
    gap: var(--kr-space-6);
    align-items: start;
}

@media (max-width: 1000px) {
    .kr-cart-layout,
    .kr-checkout-layout {
        grid-template-columns: 1fr;
    }
}

.kr-cart-items {
    display: flex;
    flex-direction: column;
    gap: var(--kr-space-5);
}

/* The native "update cart" submit is a no-JS fallback: js/kr-cart.js submits the
   form itself when a quantity changes, and hides this. The explicit [hidden] rule
   is required — base .kr-btn sets display:inline-flex, which beats the UA's
   [hidden] { display: none } on specificity. */
.kr-cart-items__update {
    align-self: flex-start;
}

.kr-cart-items__update[hidden] {
    display: none;
}

/* ---- Border-only card shell (.kr-panel) ---------------------------------
 * Outline only: no fill and no shadow, so the surface sits directly on the cream
 * page background (per the cart design). Everything inside it is navy/ink on
 * cream, which is the same pairing the rest of the page already uses.
 *
 * This is the cart design's base surface. `.kr-cart-item` is the line-item
 * composition of it (artwork column + details column); `.kr-panel` is the bare
 * shell, for any block that must read as a sibling of those cards — e.g. the
 * delivery-mode chooser on step 3. */
.kr-panel,
.kr-cart-item {
    background: transparent;
    border: 1px solid var(--kr-card-border);
    border-radius: var(--kr-radius-xl);
    padding: var(--kr-space-6);
}

/* ---- Line item card ----------------------------------------------------- */
.kr-cart-item {
    position: relative;
    display: grid;
    grid-template-columns: minmax(140px, 200px) minmax(0, 1fr);
    gap: var(--kr-space-5) var(--kr-space-6);
}

@media (max-width: 620px) {
    .kr-panel,
    .kr-cart-item {
        padding: var(--kr-space-5);
    }

    .kr-cart-item {
        grid-template-columns: 1fr;
    }
}

/* Shared .kr-close metrics (44px target, bigger glyph); offsets pulled in so
   the × stays in the same optical corner as before it grew. */
.kr-cart-item__remove {
    position: absolute;
    top: var(--kr-space-2);
    right: var(--kr-space-3);
    z-index: var(--kr-z-base);
}

.kr-cart-item__media {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: var(--kr-space-3);
    text-align: center;
}

.kr-cart-item__preview {
    display: block;
    width: 100%;
    border-radius: var(--kr-radius-sm);
    overflow: hidden;
}

.kr-cart-item__preview img {
    width: 100%;
    height: auto;
}

/* Non-personalised greeting cards show the product thumb dressed in the shared
   cc-mockup 3D card-back (same as tiles/quick-view) — undo the plain preview's
   clipping so the card-back can peek out, and its shrink-wrap so the art fills
   the media column. */
.kr-cart-item__preview.cc-mockup {
    display: block;
    width: 100%;
    border-radius: 0;
    overflow: visible;
}

.kr-cart-item__preview.cc-mockup > img {
    width: 100% !important;
    height: auto !important;
}

.kr-cart-item__edit {
    font-size: var(--kr-text-sm);
}

/* ---- Details column ----------------------------------------------------- */
.kr-cart-item__details {
    display: flex;
    flex-direction: column;
    gap: var(--kr-space-4);
    padding-right: var(--kr-space-5); /* clear of the remove X */
}

/* ---- Labelled row (.kr-labelled-row) ------------------------------------
 * Bold navy label in a fixed column, control in the rest. The rhythm the cart
 * design uses for Maat / Aantal / Prijs / Bezorgadres — shared so any screen in
 * the flow (e.g. step 3's Bezorgdatum rows) lines up identically.
 * `.kr-cart-item__row` is the original name and stays as its alias. */
.kr-labelled-row,
.kr-cart-item__row {
    display: grid;
    grid-template-columns: 7.5rem minmax(0, 1fr);
    align-items: center;
    gap: var(--kr-space-4);
}

/* Wider label column, for rows that stand alone in a panel rather than in the
   line-item card's narrower details column. */
.kr-labelled-row--wide {
    grid-template-columns: 11rem minmax(0, 1fr);
}

@media (max-width: 480px) {
    .kr-labelled-row,
    .kr-cart-item__row {
        grid-template-columns: 1fr;
        gap: var(--kr-space-2);
    }
}

.kr-labelled-row__label,
.kr-cart-item__label {
    margin: 0;
    font-family: var(--kr-font-body);
    font-weight: var(--kr-weight-bold);
    font-size: var(--kr-text-base);
    color: var(--kr-heading);
}

.kr-labelled-row__control,
.kr-cart-item__control {
    display: flex;
    align-items: center;
    min-width: 0;
}

.kr-cart-item__product {
    /* MR10b: a single unbroken title must wrap inside the minmax(0,1fr) cell. */
    overflow-wrap: anywhere;
}

.kr-cart-item__price {
    font-family: var(--kr-font-body);
    color: var(--kr-text);
}

.kr-cart-item__price .amount {
    font-weight: var(--kr-weight-regular);
}

/* ---- Bezorgadres block -------------------------------------------------- */
.kr-cart-item__address {
    display: flex;
    flex-direction: column;
    gap: var(--kr-space-3);
}

.kr-cart-item__address-summary {
    margin: 0;
    font-style: italic;
    line-height: var(--kr-leading-snug);
    color: var(--kr-text);
}

.kr-cart-item__address-empty {
    color: var(--kr-text-muted);
}

.kr-cart-item__actions {
    display: flex;
    flex-wrap: wrap;
    gap: var(--kr-space-3);
}

/* Both address buttons share one width so they stack as a tidy pair. */
.kr-cart-item__actions .kr-btn {
    min-width: 11rem;
}

.kr-cart-item__book[hidden],
.kr-cart-item__form[hidden] {
    display: none;
}

.kr-cart-item__form {
    padding: var(--kr-space-4);
    background: var(--kr-section-pink);
    border-radius: var(--kr-radius-md);
}

.kr-cart-item__form .kr-field:last-of-type {
    margin-bottom: 0;
}

.kr-cart-item__form-actions {
    display: flex;
    flex-wrap: wrap;
    gap: var(--kr-space-3);
    margin-top: var(--kr-space-4);
}

.kr-cart-item__split {
    align-self: flex-start;
    font-size: var(--kr-text-sm);
    padding: 0;
}

.kr-cart-item__feedback {
    margin: 0;
    font-size: var(--kr-text-sm);
    font-style: italic;
    color: var(--kr-text-muted);
}

.kr-cart-item__feedback:empty {
    display: none;
}

.kr-cart-item__feedback.is-error {
    color: var(--kr-accent);
    font-style: normal;
}

/* Invalid address (blocked at "Naar verzenden"). */
.kr-cart-item__address.is-invalid {
    outline: 2px solid var(--kr-accent);
    outline-offset: var(--kr-space-2);
    border-radius: var(--kr-radius-sm);
}

/* The line's own busy state is the shared .kr-busy region component (see
   "Busy / loading states" above) — the card carries .kr-busy and js/kr-cart.js
   toggles aria-busy on it. */

/* ---- Empty cart --------------------------------------------------------- */
.kr-cart-empty {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: var(--kr-space-5);
    background: var(--kr-surface);
    border: 1px solid var(--kr-card-border);
    border-radius: var(--kr-radius-xl);
    padding: var(--kr-space-7);
}

.kr-cart-empty__text {
    margin: 0;
    font-size: var(--kr-text-md);
    color: var(--kr-text);
}

/* ========================================================================
 * Order summary card — pink header band, hairline rows, bold total
 * (cart + verzenden steps; reusable for any "wat kost het" panel)
 * ======================================================================== */
.kr-summary {
    background: var(--kr-surface);
    border: 1px solid var(--kr-primary);
    border-radius: var(--kr-radius-xl);
    overflow: hidden; /* clips the header band into the rounded corners */
}

.kr-summary__header {
    background: var(--kr-section-pink);
    padding: var(--kr-space-5) var(--kr-space-6);
}

.kr-summary__title {
    margin: 0;
    font-size: var(--kr-text-xl);
    color: var(--kr-heading);
}

.kr-summary__body {
    padding: var(--kr-space-5) var(--kr-space-6) var(--kr-space-6);
}

.kr-summary__rows {
    margin: 0;
}

.kr-summary__row {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: var(--kr-space-4);
    padding-block: var(--kr-space-3);
    border-bottom: 1px solid var(--kr-border);
    font-family: var(--kr-font-body);
    color: var(--kr-text);
}

.kr-summary__row dt,
.kr-summary__row dd {
    margin: 0;
}

.kr-summary__row dt {
    font-weight: var(--kr-weight-bold);
}

/* Secondary rows (verzendkosten, kortingen) read lighter than subtotaal/totaal. */
.kr-summary__row:not(.kr-summary__row--total) dd {
    font-style: italic;
}

.kr-summary__row--coupon dt {
    font-weight: var(--kr-weight-regular);
    font-style: italic;
}

.kr-summary__row--total {
    border-bottom: 0;
    font-weight: var(--kr-weight-bold);
}

.kr-summary__row--total dd {
    font-weight: var(--kr-weight-bold);
}

.kr-summary__pending {
    font-style: italic;
    color: var(--kr-text-muted);
}

.kr-summary__action {
    margin-top: var(--kr-space-5);
}

/* ========================================================================
 * Coupon field — pill input with an inline submit chevron
 * ======================================================================== */
.kr-coupon {
    position: relative;
    display: flex;
    align-items: center;
    margin-top: var(--kr-space-4);
}

/* Deliberately NOT the standard pink field fill: on the summary card this reads
   as a quiet, outlined pill (per the design), so it overrides the base input. */
.kr-coupon__input {
    width: 100%;
    background: var(--kr-surface);
    border: 1px solid var(--kr-border);
    border-radius: var(--kr-radius-pill);
    padding: 0.7em 3em 0.7em 1.4em;
    font-style: italic;
    color: var(--kr-field-text);
}

.kr-coupon__input:focus {
    background-color: var(--kr-surface);
    border-color: var(--kr-accent);
}

.kr-coupon__submit {
    position: absolute;
    right: 0.5em;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 2em;
    height: 2em;
    padding: 0;
    color: var(--kr-primary);
    background: none;
    border: 0;
    border-radius: var(--kr-radius-circle);
    cursor: pointer;
    transition:
        color var(--kr-transition-fast),
        background var(--kr-transition-fast);
}

.kr-coupon__submit svg {
    width: 1em;
    height: 1em;
}

.kr-coupon__submit:hover {
    color: var(--kr-accent-contrast);
    background: var(--kr-accent);
}

/* ========================================================================
 * Segmented toggle (.kr-segmented) — a small set of mutually exclusive modes
 * shown as a row of button-shaped chips ("Bestelling verzenden: per kaart /
 * per bestelling").
 *
 * Real radios, visually hidden inside their <label>: the group keeps native
 * radio semantics (arrow-key roving focus, single selection, and a value that
 * still posts when JS is off) while wearing the brand's button skin. The
 * inactive chip is the soft button (light-pink fill, navy text — 10.2:1) and
 * the checked one flips to the primary button (navy fill, light-pink text —
 * 10.2:1). White-on-pink is never used; see the a11y note in CLAUDE.md.
 * ======================================================================== */
.kr-segmented {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--kr-space-2) var(--kr-space-4);
}

.kr-segmented__legend {
    margin: 0;
    font-family: var(--kr-font-body);
    font-weight: var(--kr-weight-bold);
    font-size: var(--kr-text-base);
    color: var(--kr-heading);
}

.kr-segmented__options {
    display: flex;
    flex-wrap: wrap;
    gap: var(--kr-space-2);
}

.kr-segmented__option {
    position: relative;
    display: inline-flex;
    margin: 0;
}

/* Hidden, but still focusable AND still the hit area: it covers the whole chip,
   so the pointer never lands on a dead label. (Not `display: none` — that would
   drop the control out of the tab order.) */
.kr-segmented__input {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    margin: 0;
    opacity: 0;
    cursor: pointer;
}

.kr-segmented__chip {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    font-family: var(--kr-font-button);
    font-size: var(--kr-text-base);
    letter-spacing: var(--kr-tracking-button);
    line-height: 1;
    padding: 0.7em 1.6em;
    color: var(--kr-primary);
    background: var(--kr-btn-soft-bg);
    border: 2px solid var(--kr-btn-soft-bg);
    border-radius: var(--kr-btn-radius);
    transition:
        background var(--kr-transition),
        color var(--kr-transition),
        border-color var(--kr-transition),
        transform var(--kr-transition-fast);
}

.kr-segmented__input:checked ~ .kr-segmented__chip {
    background: var(--kr-primary);
    border-color: var(--kr-primary);
    color: var(--kr-btn-primary-text);
}

/* Hover only outlines the inactive chip — filling it would make hover
   indistinguishable from the checked state. */
.kr-segmented__input:not(:checked):hover ~ .kr-segmented__chip {
    border-color: var(--kr-primary);
    transform: translateY(-1px);
}

.kr-segmented__input:focus-visible ~ .kr-segmented__chip {
    outline: 3px solid var(--kr-primary);
    outline-offset: 2px;
    box-shadow: var(--kr-focus-shadow);
}

.kr-segmented__input:disabled ~ .kr-segmented__chip {
    opacity: 0.5;
    cursor: not-allowed;
}

@media (max-width: 420px) {
    .kr-segmented__options {
        width: 100%;
    }

    .kr-segmented__option {
        flex: 1 1 0;
    }

    .kr-segmented__chip {
        width: 100%;
        padding-inline: var(--kr-space-3);
    }
}

/* ========================================================================
 * Date chooser (.kr-datechooser / .kr-datepick / .kr-date-tile)
 *
 * A normal <input type="date"> PLUS a radio group of tear-off calendar sheets
 * for the next few valid days, kept in sync in both directions. The field stays
 * the canonical control — it is the one that posts, the one PHP validates, and
 * the only one that exists without JS. js/kr-cart.js reveals the tile row and
 * builds it from the field's own `min` attribute, which is the same minimum
 * KindRecartShortcode::validate_delivery_date() enforces, so a tile can never
 * offer a date the back end would reject.
 *
 * Selection cue: dashed pink border + pink-pale fill, with the text staying
 * NAVY and going bold. Brand pink on white is only 2.9:1 and would fail WCAG
 * at this size, so pink carries the border, never the letters. Navy on the
 * pink-pale sheet is 12.4:1; navy on the plain white sheet is 14.2:1.
 * ======================================================================== */
.kr-datechooser {
    display: flex;
    flex-direction: column;
    gap: var(--kr-space-3);
}

.kr-datechooser__more {
    align-self: flex-start;
    font-size: var(--kr-text-sm);
    padding: 0;
    background: none;
    border: 0;
    cursor: pointer;
}

.kr-datepick {
    display: flex;
    align-items: stretch;
    gap: var(--kr-space-2);
}

.kr-datepick[hidden] {
    display: none;
}

/* Bare navy chevrons just outside the track — same treatment as the carousels. */
.kr-datepick__nav {
    flex: none;
    display: flex;
    align-items: center;
    justify-content: center;
    width: 1.5rem;
    padding: 0;
    color: var(--kr-primary);
    background: none;
    border: 0;
    cursor: pointer;
    transition: color var(--kr-transition-fast);
}

.kr-datepick__nav svg {
    width: 100%;
    height: auto;
    pointer-events: none;
}

.kr-datepick__nav:hover {
    color: var(--kr-accent);
}

.kr-datepick__nav:disabled {
    opacity: 0.3;
    cursor: default;
}

.kr-datepick__tiles {
    display: flex;
    flex: 1 1 auto;
    min-width: 0;
    gap: var(--kr-space-2);
}

/* One tear-off sheet: a weekday header strip over the date, split by a dashed
   "perforation". The <label> is the sheet, so the whole tile is the hit area. */
.kr-date-tile {
    position: relative;
    flex: 1 1 0;
    min-width: 3.75rem;
    max-width: 7rem;
    display: flex;
    flex-direction: column;
    margin: 0;
    overflow: hidden;
    text-align: center;
    background: var(--kr-surface);
    border: 2px solid var(--kr-card-border);
    border-radius: var(--kr-btn-radius-sm);
    cursor: pointer;
    transition:
        background var(--kr-transition-fast),
        border-color var(--kr-transition-fast);
}

.kr-date-tile__input {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    margin: 0;
    opacity: 0;
    cursor: pointer;
}

.kr-date-tile__day {
    display: block;
    padding: var(--kr-space-1);
    font-family: var(--kr-font-body);
    font-size: var(--kr-text-xs);
    font-weight: var(--kr-weight-bold);
    line-height: 1.4;
    color: var(--kr-heading);
    background: var(--kr-color-pink-pale);
    border-bottom: 1px dashed var(--kr-card-border);
}

.kr-date-tile__date {
    display: block;
    padding: var(--kr-space-2) var(--kr-space-1);
    font-family: var(--kr-font-body);
    font-size: var(--kr-text-sm);
    line-height: 1.2;
    color: var(--kr-text);
    white-space: nowrap;
}

.kr-date-tile:hover {
    border-color: var(--kr-primary);
}

.kr-date-tile:has(.kr-date-tile__input:checked) {
    background: var(--kr-color-pink-pale);
    border-style: dashed;
    border-color: var(--kr-accent);
}

.kr-date-tile:has(.kr-date-tile__input:checked) .kr-date-tile__date {
    font-weight: var(--kr-weight-bold);
}

.kr-date-tile:has(.kr-date-tile__input:focus-visible) {
    outline: 3px solid var(--kr-primary);
    outline-offset: 2px;
}

.kr-date-tile:has(.kr-date-tile__input:disabled) {
    opacity: 0.45;
    cursor: not-allowed;
    border-style: solid;
}

.kr-date-tile:has(.kr-date-tile__input:disabled):hover {
    border-color: var(--kr-card-border);
}

/* ========================================================================
 * Verzenden step (cart step 3) — bezorgdatum per kaart / hele bestelling
 *
 * There is no separate mockup for this step: the CART design (step 2) is the
 * spec. So the step reuses step 2's components wholesale rather than restating
 * them — `.kr-cart-item` for the line-item cards (artwork column included),
 * `.kr-labelled-row` for the label/value rhythm, `.kr-panel` for the chooser and
 * the whole-order field, `.kr-input` / `.kr-check` for the controls, and the very
 * same order-summary card template-part on the right. What remains below is only
 * what is genuinely specific to this step.
 * ======================================================================== */
.kr-verzending__head {
    margin-bottom: var(--kr-space-5);
}

.kr-verzending__title {
    margin: 0 0 var(--kr-space-2);
    font-size: var(--kr-text-xl);
}

.kr-verzending__intro {
    margin: 0;
    font-style: italic;
    color: var(--kr-text-muted);
}

/* Mode chooser — the shared `.kr-segmented` toggle. It sits bare above the
   cards it controls (no panel shell): the two chips already read as a control,
   and boxing them would compete with the line-item cards below. */
.kr-verzending__modes {
    margin: 0 0 var(--kr-space-5);
}

.kr-verzending__section[hidden] {
    display: none;
}

/* Same stack rhythm as `.kr-cart-items` on step 2, so both steps' card stacks
   sit on an identical grid. */
.kr-verzending__items {
    display: flex;
    flex-direction: column;
    gap: var(--kr-space-5);
}

/* The date chooser wants the card's full width for its tile row, so the details
   column only clears the remove X on the row that actually sits under it. */
.kr-cart-item--verzending .kr-cart-item__details {
    padding-right: 0;
}

.kr-cart-item--verzending .kr-cart-item__details > .kr-labelled-row:first-child {
    padding-right: var(--kr-space-5);
}

.kr-verzending__value {
    font-family: var(--kr-font-body);
    color: var(--kr-text);
}

.kr-verzending__address {
    font-style: italic;
    line-height: var(--kr-leading-snug);
    color: var(--kr-text);
}

.kr-verzending__note {
    margin: var(--kr-space-4) 0 0;
    font-size: var(--kr-text-sm);
    font-style: italic;
    color: var(--kr-text-muted);
}

.kr-verzending__actions {
    margin-top: var(--kr-space-5);
}

/* ---- Live shipping feedback ---------------------------------------------
 * The wrapper carries `.kr-panel` (shell) and `.kr-busy` (the shared loading
 * region — see "Busy / loading states"); its INNER markup is the back end's own
 * fragment, KindRecartShortcode::get_verzending_summary(), which is also what the
 * AJAX refresh returns. That PHP is not ours to change, so its legacy
 * `.kind-verzending__*` class names are styled here rather than renamed. */
.kr-verzending__summary {
    margin-top: var(--kr-space-5);
}

.kr-verzending__summary:empty {
    display: none;
}

.kr-verzending__summary .kind-verzending__summary-header {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    justify-content: space-between;
    gap: var(--kr-space-3);
    margin-bottom: var(--kr-space-4);
}

/* The fragment uses an <h3>; strip the display-heading treatment so it reads as
   a card label like Maat / Aantal / Bezorgdatum rather than a section title. */
.kr-verzending__summary .kind-verzending__summary-title {
    margin: 0;
    font-family: var(--kr-font-body);
    font-weight: var(--kr-weight-bold);
    font-size: var(--kr-text-base);
    letter-spacing: var(--kr-tracking-normal);
    text-transform: none;
    color: var(--kr-heading);
}

.kr-verzending__summary .kind-verzending__summary-count {
    font-size: var(--kr-text-sm);
    font-style: italic;
    color: var(--kr-text-muted);
}

.kr-verzending__summary .kind-verzending__summary-list {
    display: flex;
    flex-direction: column;
    gap: var(--kr-space-3);
    margin: 0;
}

.kr-verzending__summary .kind-verzending__summary-row {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: var(--kr-space-4);
}

.kr-verzending__summary .kind-verzending__summary-row dt {
    font-family: var(--kr-font-body);
    font-weight: var(--kr-weight-bold);
    color: var(--kr-heading);
}

.kr-verzending__summary .kind-verzending__summary-row dd {
    margin: 0;
    color: var(--kr-text);
}

/* The order-summary card is this design's single totals surface — exactly as on
   step 2 — and js/kr-cart.js already keeps its shipping + total in sync on every
   refresh. So the fragment's duplicate grand total is not shown a second time. */
.kr-verzending__summary .kind-verzending__summary-row--total {
    display: none;
}

.kr-verzending__summary .kind-verzending__summary-empty {
    font-style: italic;
    color: var(--kr-text-muted);
}

/* One chip per shipping package — the reason a split order costs more. */
.kr-verzending__summary .kind-verzending__summary-packages {
    display: flex;
    flex-wrap: wrap;
    gap: var(--kr-space-2);
    margin: var(--kr-space-4) 0 0;
    padding: 0;
    list-style: none;
}

.kr-verzending__summary .kind-verzending__summary-packages li {
    font-size: var(--kr-text-sm);
    color: var(--kr-accent-contrast);
    background: var(--kr-section-pink);
    border-radius: var(--kr-radius-pill);
    padding: var(--kr-space-1) var(--kr-space-3);
}

.kr-input.is-invalid {
    border-color: var(--kr-accent);
}

/* ========================================================================
 * Modal — generic centred dialog on a dimmed scrim
 *
 * The quick-view popup (.kr-quickview) predates this and keeps its own
 * feature-scoped styling; this is the reusable version for everything since.
 * Conventions are shared with it deliberately: `.is-open` toggles display,
 * z-index is --kr-z-modal, and the JS owns Esc / overlay-click / focus trap /
 * focus restore.
 * ======================================================================== */
.kr-modal {
    position: fixed;
    inset: 0;
    z-index: var(--kr-z-modal);
    display: none;
    align-items: center;
    justify-content: center;
    padding: var(--kr-space-4);
    /* Navy scrim rather than black: keeps the brand warmth of the page behind. */
    background: rgba(0, 0, 156, 0.28);
}

.kr-modal.is-open {
    display: flex;
}

.kr-modal__dialog {
    position: relative;
    width: 100%;
    max-width: 30rem;
    max-height: 90vh;
    overflow-y: auto;
    background: var(--kr-bg);
    border-radius: var(--kr-radius-lg);
    box-shadow: var(--kr-shadow-lg);
    padding: var(--kr-space-6);
}

/* A modal that has something to SHOW as well as something to say (a preview, a
   product) needs two columns to say it in. Only the width changes; everything
   else is the same dialog. */
.kr-modal--wide .kr-modal__dialog {
    max-width: 52rem;
}

/* Shared .kr-close metrics (44px target, bigger glyph); offsets pulled in so
   the × stays in the same optical corner as before it grew. */
.kr-modal__close {
    position: absolute;
    top: var(--kr-space-2);
    right: var(--kr-space-3);
}

.kr-modal__title {
    margin: 0 0 var(--kr-space-4);
    text-align: center;
    font-size: var(--kr-text-xl);
}

.kr-modal__intro {
    margin: 0 0 var(--kr-space-5);
    font-size: var(--kr-text-sm);
    font-style: italic;
    color: var(--kr-text);
}

.kr-modal__intro strong {
    font-weight: var(--kr-weight-bold);
    font-style: normal;
}

.kr-modal__body {
    display: flex;
    flex-direction: column;
    gap: var(--kr-space-4);
}

.kr-modal__actions {
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    gap: var(--kr-space-4);
    margin-top: var(--kr-space-6);
}

.kr-modal__feedback {
    margin: var(--kr-space-3) 0 0;
    font-size: var(--kr-text-sm);
    font-style: italic;
    text-align: center;
    color: var(--kr-text-muted);
}

.kr-modal__feedback:empty {
    display: none;
}

.kr-modal__feedback.is-error {
    color: var(--kr-accent);
    font-style: normal;
}

/* Prevent the page scrolling behind an open modal. */
body.kr-modal-open {
    overflow: hidden;
}

/* ========================================================================
 * Selectable address option — the address-book modal's list row
 *
 * White + navy border at rest, pink-pale + pink border when chosen. The
 * optional leading control (radio or checkbox) sits outside the card so the
 * card itself stays a clean, tappable block.
 * ======================================================================== */
.kr-address-option {
    /* Positioned: the kebab and its menu anchor to the row, not the dialog. */
    position: relative;
    display: flex;
    align-items: center;
    gap: var(--kr-space-3);
}

/* Single-pick variant (a line of 1 card): the whole card IS the control, so the
   radio is visually hidden but stays focusable and announced. The multi variant
   (.is-multi — one line going to several addresses) shows the circles. */
.kr-address-list:not(.is-multi) .kr-address-option__control {
    position: absolute;
    width: 1px;
    height: 1px;
    opacity: 0;
    pointer-events: none;
}

.kr-address-option:focus-within .kr-address-option__card {
    outline: 3px solid var(--kr-primary);
    outline-offset: 2px;
}

.kr-address-option__control {
    flex: none;
    appearance: none;
    -webkit-appearance: none;
    width: 1.15rem;
    height: 1.15rem;
    margin: 0;
    padding: 0;
    background: var(--kr-surface);
    border: 2px solid var(--kr-primary);
    border-radius: var(--kr-radius-circle);
    cursor: pointer;
    transition: background var(--kr-transition-fast);
}

.kr-address-option__control:checked {
    background: var(--kr-accent);
    box-shadow: inset 0 0 0 3px var(--kr-surface);
    border-color: var(--kr-accent);
}

.kr-address-option__control:focus-visible {
    outline: 3px solid var(--kr-primary);
    outline-offset: 2px;
}

/* The card is a <label>, so clicking anywhere on it toggles the control. */
.kr-address-option__card {
    position: relative;
    flex: 1;
    min-width: 0;
    display: block;
    margin: 0;
    background: var(--kr-surface);
    border: 1px solid var(--kr-primary);
    border-radius: var(--kr-radius-lg);
    padding: var(--kr-space-4) var(--kr-space-6) var(--kr-space-4) var(--kr-space-5);
    cursor: pointer;
    transition:
        background var(--kr-transition-fast),
        border-color var(--kr-transition-fast);
}

.kr-address-option.is-selected .kr-address-option__card {
    background: var(--kr-section-pink);
    border-color: var(--kr-accent);
}

.kr-address-option__name {
    display: block;
    margin: 0 0 var(--kr-space-2);
    font-family: var(--kr-font-body);
    font-weight: var(--kr-weight-bold);
    font-size: var(--kr-text-base);
    color: var(--kr-heading);
    padding-right: var(--kr-space-4); /* clear of the kebab */
}

.kr-address-option__lines {
    display: block;
    margin: 0;
    font-style: italic;
    font-size: var(--kr-text-sm);
    line-height: var(--kr-leading-snug);
    color: var(--kr-text);
}

/* Kebab reuses .kr-kebab but centres vertically inside this card. */
.kr-address-option .kr-kebab {
    top: 50%;
    right: var(--kr-space-3);
    transform: translateY(-50%);
}

.kr-address-option__menu {
    position: absolute;
    top: 50%;
    right: var(--kr-space-7);
    z-index: var(--kr-z-dropdown);
    display: flex;
    flex-direction: column;
    min-width: 9rem;
    padding: var(--kr-space-2);
    background: var(--kr-surface);
    border: 1px solid var(--kr-card-border);
    border-radius: var(--kr-radius-md);
    box-shadow: var(--kr-shadow-md);
}

.kr-address-option__menu[hidden] {
    display: none;
}

.kr-address-option__menu button {
    font-family: var(--kr-font-body);
    font-size: var(--kr-text-sm);
    text-align: left;
    color: var(--kr-primary);
    padding: var(--kr-space-2) var(--kr-space-3);
    border-radius: var(--kr-radius-sm);
    cursor: pointer;
}

.kr-address-option__menu button:hover {
    background: var(--kr-section-pink);
}

.kr-address-option__empty {
    margin: 0;
    font-style: italic;
    text-align: center;
    color: var(--kr-text-muted);
}

/* The list itself. Promoted to a real component when the address book moved out
   of the modal: inside `.kr-modal__body` these are the same values that wrapper
   already sets, so the dialog is unchanged, but the account page can now use
   `.kr-address-list` on a bare <ul> and get the same rhythm. */
.kr-address-list {
    display: flex;
    flex-direction: column;
    gap: var(--kr-space-4);
    margin: 0;
    padding: 0;
    list-style: none;
}

/* ---- Static variant: a row with nothing to select ----------------------
 *
 * The account's "Adressen" page shows the same rows, but there is no choice to
 * make there — the card is a <div>, not a <label> around a control, and its two
 * actions are shown outright instead of behind the kebab. So: no pointer cursor,
 * and room for an actions column that wraps under the card on narrow screens. */
.kr-address-option--static .kr-address-option__card {
    flex: 1 1 16rem;
    cursor: default;
}

.kr-address-option--static {
    flex-wrap: wrap;
    row-gap: var(--kr-space-3);
}

/* The selectable variant outlines the card when anything inside the row takes
   focus, because there the card IS the control. Here it is not: focus lands on
   Bewerken / Verwijderen / the confirm, which draw their own ring. */
.kr-address-option--static:focus-within .kr-address-option__card {
    outline: none;
}

.kr-address-option__actions {
    flex: none;
    display: flex;
    flex-wrap: wrap;
    gap: var(--kr-space-2);
}

.kr-address-option__actions[hidden] {
    display: none;
}

/* ========================================================================
 * Inline confirm — "Zeker weten?" without a browser dialog
 *
 * `window.confirm()` cannot be styled, cannot be branded and freezes the page,
 * so destructive actions in this theme flip their control row to this instead:
 * the question plus the two answers, in place. The JS moves focus to the
 * confirming button and back to the trigger on cancel.
 *
 * NOT to be confused with `.kr-confirm` further down — that is the thank-you
 * page's confirmation BANNER. This one is the are-you-sure prompt, hence the
 * longer name.
 *
 * First consumer: deleting an address on /mijn-account/edit-address/.
 * ======================================================================== */
.kr-inline-confirm {
    flex: none;
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--kr-space-3);
}

.kr-inline-confirm[hidden] {
    display: none;
}

/* Navy on cream / on white = 13.8:1. */
.kr-inline-confirm__question {
    margin: 0;
    font-size: var(--kr-text-sm);
    font-style: italic;
    line-height: var(--kr-leading-snug);
    color: var(--kr-text);
}

/* ========================================================================
 * Selectable choice — radio/checkbox + label card + optional detail panel
 *
 * The generic form of the payment-method row: a bordered card that fills pink
 * when its control is checked, with a panel that expands underneath for the
 * option's own fields. Same visual language as `.kr-address-option` (white +
 * navy at rest, pink-pale + pink when chosen), but built for markup where the
 * control, the label and the panel are SIBLINGS inside one element — which is
 * exactly the shape WooCommerce's `checkout/payment-method.php` produces and
 * which gateways' JS depends on, so the component adapts to the markup rather
 * than the other way round.
 *
 *   <li class="kr-choice">
 *     <input class="kr-choice__control" type="radio">
 *     <label class="kr-choice__label">…</label>
 *     <div class="kr-choice__panel">…</div>   (optional)
 *
 * The checked state uses `:has()` because nothing adds a class to the row.
 * Where `:has()` is unsupported the control still shows its own checked state —
 * the card just doesn't tint, which is a fallback, not a failure.
 * ======================================================================== */
.kr-choice-list {
    display: flex;
    flex-direction: column;
    gap: var(--kr-space-3);
    margin: 0;
    padding: 0;
    list-style: none;
}

.kr-choice {
    display: grid;
    grid-template-columns: auto minmax(0, 1fr);
    align-items: center;
    column-gap: var(--kr-space-3);
    margin: 0;
    padding: var(--kr-space-4) var(--kr-space-5);
    background: var(--kr-surface);
    border: 1px solid var(--kr-primary);
    border-radius: var(--kr-radius-lg);
    transition:
        background var(--kr-transition-fast),
        border-color var(--kr-transition-fast);
}

.kr-choice:has(.kr-choice__control:checked) {
    background: var(--kr-section-pink);
    border-color: var(--kr-accent);
}

.kr-choice__control {
    flex: none;
    appearance: none;
    -webkit-appearance: none;
    width: 1.15rem;
    height: 1.15rem;
    margin: 0;
    padding: 0;
    background: var(--kr-surface);
    border: 2px solid var(--kr-primary);
    border-radius: var(--kr-radius-circle);
    cursor: pointer;
    transition: background var(--kr-transition-fast);
}

.kr-choice__control:checked {
    background: var(--kr-accent);
    border-color: var(--kr-accent);
    box-shadow: inset 0 0 0 3px var(--kr-surface);
}

.kr-choice__control:focus-visible {
    outline: 3px solid var(--kr-primary);
    outline-offset: 2px;
}

.kr-choice__label {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--kr-space-3);
    margin: 0;
    font-family: var(--kr-font-body);
    font-weight: var(--kr-weight-bold);
    font-size: var(--kr-text-base);
    color: var(--kr-heading);
    cursor: pointer;
}

.kr-choice__icon {
    display: inline-flex;
    align-items: center;
    gap: var(--kr-space-2);
}

.kr-choice__icon img {
    max-height: 1.6rem;
    width: auto;
}

/* Spans both columns so it sits under the control, not beside it. The gateway
   scripts slide this open/closed with inline display, which a grid item honours. */
.kr-choice__panel {
    grid-column: 1 / -1;
    margin-top: var(--kr-space-3);
    padding-top: var(--kr-space-3);
    border-top: 1px solid var(--kr-border);
    font-size: var(--kr-text-sm);
    line-height: var(--kr-leading-snug);
    color: var(--kr-text);
}

.kr-choice__panel > p {
    margin: 0 0 var(--kr-space-2);
    font-style: italic;
}

.kr-choice__panel > p:last-child {
    margin-bottom: 0;
}

/* ========================================================================
 * Checkout page — "Afrekenen" (funnel step 4)
 * (woocommerce/checkout-page.php + woocommerce/checkout/* + template-parts/checkout/*)
 *
 * The page shell (.kr-checkout-page) and the two-column grid (.kr-checkout-layout)
 * are the cart's, aliased in the "Cart page" section above. What lives here is
 * the work of dressing WooCommerce's OWN checkout markup — which this theme
 * restyles rather than rewrites, so that gateways, checkout.js and the
 * update_order_review AJAX keep working. Everything is scoped under `.kr-checkout`
 * (the wrapper in checkout-page.php) so it can outrank woocommerce.css without
 * `!important` and never leaks onto another page.
 * ======================================================================== */
.kr-checkout-layout__main {
    display: flex;
    flex-direction: column;
    gap: var(--kr-space-5);
}

/* WooCommerce's two customer columns are stacked, not side by side: on this shop
   the second one only ever holds the order-notes block (the shipping address is
   per line item and was chosen in the cart). */
.kr-checkout .col2-set {
    display: flex;
    flex-direction: column;
    gap: var(--kr-space-5);
}

.kr-checkout .col2-set .col-1,
.kr-checkout .col2-set .col-2 {
    width: auto;
    float: none;
}

/* Empty when order notes are switched off — don't leave a gap for it. */
.kr-checkout .woocommerce-additional-fields:empty,
.kr-checkout .col-2:empty {
    display: none;
}

/* ---- Panels (the border-only .kr-panel shell, per the cart design) ------- */
.kr-checkout__panel {
    display: flex;
    flex-direction: column;
}

.kr-checkout__panel-title {
    margin: 0 0 var(--kr-space-4);
    font-size: var(--kr-text-lg);
    color: var(--kr-heading);
}

.kr-checkout__panel-note {
    margin: 0 0 var(--kr-space-5);
    font-size: var(--kr-text-sm);
    font-style: italic;
    line-height: var(--kr-leading-snug);
    color: var(--kr-text-muted);
}

.kr-checkout__errors {
    align-items: flex-start;
    gap: var(--kr-space-5);
}

.kr-checkout__errors .kr-checkout__panel-note,
.kr-checkout__errors .kr-notices {
    margin: 0;
    align-self: stretch;
}

/* ---- Billing fields ------------------------------------------------------
 * `woocommerce_form_field()` emits `<p class="form-row …"><label>…<span
 * class="woocommerce-input-wrapper"><input class="input-text">`. That markup is
 * left exactly as WooCommerce writes it — checkout.js adds and removes
 * `.woocommerce-invalid` / `.woocommerce-validated` on those `.form-row`s, and
 * plugins add fields to the same loop — so the `.kr-field` look is applied to it
 * from here instead of being baked into a rewritten template. */
.kr-checkout .woocommerce-billing-fields__field-wrapper,
.kr-checkout .woocommerce-additional-fields__field-wrapper {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    column-gap: var(--kr-space-4);
}

.kr-checkout .form-row {
    display: flex;
    flex-direction: column;
    grid-column: 1 / -1;
    margin: 0 0 var(--kr-space-4);
    padding: 0;
}

/* The name pair — WooCommerce's own first/last row classes, mapped onto the
   design system's .kr-field-row rhythm. */
.kr-checkout .form-row-first {
    grid-column: 1 / 2;
}

.kr-checkout .form-row-last {
    grid-column: 2 / -1;
}

@media (max-width: 620px) {
    .kr-checkout .form-row-first,
    .kr-checkout .form-row-last {
        grid-column: 1 / -1;
    }
}

.kr-checkout .form-row > label {
    /* = .kr-field__label */
    font-family: var(--kr-font-body);
    font-weight: var(--kr-weight-bold);
    color: var(--kr-heading);
    margin-bottom: var(--kr-space-2);
}

.kr-checkout .required {
    color: var(--kr-accent-contrast);
    text-decoration: none;
    border: 0;
}

.kr-checkout .woocommerce-input-wrapper {
    display: block;
    width: 100%;
}

.kr-checkout .form-row .input-text,
.kr-checkout .form-row select,
.kr-checkout .form-row textarea {
    width: 100%;
}

/* Checkboxes inside a form-row (create account, terms) are the .kr-check
   component, so the row must not force them into a column. */
.kr-checkout .form-row > .kr-check,
.kr-checkout .form-row > label.checkbox {
    flex-direction: row;
}

.kr-checkout .form-row .kr-check input,
.kr-checkout label.checkbox input[type="checkbox"] {
    width: auto;
}

/* ---- Validation ----------------------------------------------------------
 * checkout.js flags the ROW (`.woocommerce-invalid`), then appends a
 * `<p class="checkout-inline-error-message">` under the field. WooCommerce
 * paints all of that in its own `--wc-red`, which is not in this palette; the
 * cart already has a vocabulary for "this line is wrong" (a pink edge — see
 * `.kr-cart-item__address.is-invalid`), so checkout reuses it: pink border,
 * pink-pale fill, navy text. Colour is never the only cue — the fill changes
 * too and the message spells the problem out.
 *
 * The selectors deliberately mirror WooCommerce's own shape
 * (`.woocommerce form .form-row.woocommerce-invalid label`) so they match its
 * specificity exactly and win on cascade order — components.css is enqueued
 * after woocommerce-general. No `!important` needed. */
.kr-checkout form .form-row.woocommerce-invalid input.input-text,
.kr-checkout form .form-row.woocommerce-invalid select,
.kr-checkout form .form-row.woocommerce-invalid textarea {
    border-color: var(--kr-accent);
    background-color: var(--kr-section-pink);
}

.kr-checkout form .form-row.woocommerce-invalid label {
    color: var(--kr-heading);
}

.kr-checkout form .form-row.woocommerce-validated input.input-text,
.kr-checkout form .form-row.woocommerce-validated select {
    border-color: var(--kr-border);
}

/* Navy on the pink-pale field fill (~10:1) — a red this small would be the
   least readable text on the page. */
.kr-checkout .checkout-inline-error-message {
    margin: var(--kr-space-1) 0 0;
    font-size: var(--kr-text-sm);
    font-style: italic;
    line-height: var(--kr-leading-snug);
    color: var(--kr-heading);
}

.kr-checkout .checkout-inline-error-message::before {
    content: "\26A0\FE0E"; /* ⚠ forced to text, not colour-emoji */
    margin-inline-end: 0.4em;
    font-style: normal;
}

/* Country / state select2 — give the enhanced control the plain field's skin so
   it doesn't sit in the form as a stray grey box. */
.kr-checkout .select2-container .select2-selection--single {
    height: auto;
    background: var(--kr-field-bg);
    border: 2px solid transparent;
    border-radius: var(--kr-field-radius);
    padding: 0.6em 0.6em 0.6em 0;
}

.kr-checkout .select2-container .select2-selection--single .select2-selection__rendered {
    color: var(--kr-field-text);
    line-height: var(--kr-leading-normal);
    padding-left: 1.2em;
}

/* ---- Notices, login and coupon toggles -----------------------------------
 * `woocommerce_before_checkout_form` prints all three inside .kr-notices (see
 * woocommerce/checkout/form-checkout.php); the banners themselves are the shared
 * notices component. Only the two collapsible forms need anything extra. */
.kr-checkout .woocommerce-form-login,
.kr-checkout .checkout_coupon {
    margin: var(--kr-space-4) 0 0;
    padding: var(--kr-space-5);
    background: var(--kr-surface);
    border: 1px solid var(--kr-card-border);
    border-radius: var(--kr-radius-lg);
}

.kr-checkout .woocommerce-form-login .form-row,
.kr-checkout .checkout_coupon .form-row {
    display: flex;
    flex-direction: column;
    margin-bottom: var(--kr-space-4);
}

/* ---- Order review card ---------------------------------------------------
 * `#order_review` is the cart's .kr-summary card. The table inside it is still a
 * real <table> with WooCommerce's original root classes, because
 * WC_AJAX::update_order_review() replaces that exact element on every refresh —
 * so the brand look is done to the rows rather than to the markup. */
.kr-checkout .kr-order-review {
    width: 100%;
    margin: 0;
    border-collapse: collapse;
    border: 0;
    font-family: var(--kr-font-body);
    font-size: var(--kr-text-base);
    color: var(--kr-text);
}

/* Visually hidden, not removed: the design has no header row, but the column
   names are still the table's only structural labels for a screen reader. */
.kr-checkout .kr-order-review thead {
    position: absolute;
    width: 1px;
    height: 1px;
    overflow: hidden;
    clip: rect(0 0 0 0);
    clip-path: inset(50%);
    white-space: nowrap;
}

.kr-checkout .kr-order-review th,
.kr-checkout .kr-order-review td {
    padding: var(--kr-space-3) 0;
    border: 0;
    border-bottom: 1px solid var(--kr-border);
    text-align: left;
    vertical-align: top;
    line-height: var(--kr-leading-snug);
}

.kr-checkout .kr-order-review td {
    text-align: right;
    white-space: nowrap;
    padding-left: var(--kr-space-4);
}

.kr-checkout .kr-order-review tbody .product-name {
    font-weight: var(--kr-weight-bold);
    color: var(--kr-heading);
    white-space: normal;
}

.kr-checkout .kr-order-review .product-quantity {
    font-weight: var(--kr-weight-regular);
    color: var(--kr-text-muted);
}

/* Per-card bezorgadres / bezorgdatum — the cart already chose these; here they
   are read-only confirmation, so they read as quiet meta under the card name. */
.kr-order-review__delivery {
    margin: var(--kr-space-2) 0 0;
    font-size: var(--kr-text-sm);
    font-weight: var(--kr-weight-regular);
    color: var(--kr-text-muted);
}

.kr-order-review__delivery dt {
    margin: var(--kr-space-2) 0 0;
    font-weight: var(--kr-weight-bold);
    color: var(--kr-text);
}

.kr-order-review__delivery dt:first-child {
    margin-top: 0;
}

.kr-order-review__delivery dd {
    margin: 0;
    font-style: italic;
    line-height: var(--kr-leading-snug);
}

.kr-checkout .kr-order-review tfoot th {
    font-weight: var(--kr-weight-bold);
    color: var(--kr-heading);
}

.kr-checkout .kr-order-review tfoot td {
    font-style: italic;
}

.kr-checkout .kr-order-review .order-total th,
.kr-checkout .kr-order-review .order-total td {
    border-bottom: 0;
    padding-bottom: 0;
    font-weight: var(--kr-weight-bold);
    font-style: normal;
    font-size: var(--kr-text-md);
}

/* Shipping rates — one block per bezorgadres, because the back end builds one
   shipping package per address/date pair. */
.kr-checkout .woocommerce-shipping-methods {
    display: flex;
    flex-direction: column;
    gap: var(--kr-space-2);
    margin: 0;
    padding: 0;
    list-style: none;
    text-align: left;
    white-space: normal;
}

.kr-checkout .woocommerce-shipping-methods label {
    display: inline;
    margin: 0 0 0 var(--kr-space-2);
    font-weight: var(--kr-weight-regular);
    font-style: normal;
    color: var(--kr-text);
}

.kr-checkout .shipping__inner_list {
    margin: 0;
    padding: 0;
    list-style: none;
}

.kr-checkout .woocommerce-shipping-destination {
    margin: var(--kr-space-2) 0 0;
    font-size: var(--kr-text-sm);
    font-style: italic;
    color: var(--kr-text-muted);
}

/* ---- Payment ------------------------------------------------------------- */
.kr-payment {
    margin-top: var(--kr-space-5);
}

.kr-payment__title {
    margin: 0 0 var(--kr-space-3);
    font-family: var(--kr-font-body);
    font-weight: var(--kr-weight-bold);
    font-size: var(--kr-text-base);
    color: var(--kr-heading);
}

.kr-payment__place-order {
    display: flex;
    flex-direction: column;
    gap: var(--kr-space-4);
    margin: var(--kr-space-5) 0 0;
    padding: 0;
}

.kr-checkout .woocommerce-terms-and-conditions-wrapper {
    font-size: var(--kr-text-sm);
    color: var(--kr-text-muted);
}

.kr-checkout .woocommerce-privacy-policy-text p:last-child {
    margin-bottom: 0;
}

/* ---- Busy states ---------------------------------------------------------
 * WooCommerce blocks `.woocommerce-checkout-payment` / the review table while
 * update_order_review runs, and the whole form while the order is placed. Its
 * blockUI overlay is kept (it is what swallows clicks, and removing it would
 * change behaviour, not just looks) but made invisible, and js/kr-checkout.js
 * puts `aria-busy` on the same regions so the design system's own dim + spinner
 * takes over. `!important` is unavoidable: blockUI writes its opacity inline. */
.kr-checkout .blockUI.blockOverlay {
    opacity: 0 !important;
}

/* ---- WooCommerce stylesheet guards --------------------------------------
 * woocommerce.css is still enqueued site-wide, and a handful of its checkout
 * rules are written at a specificity the design system cannot reach from a
 * single class — `.woocommerce-checkout #payment ul.payment_methods li` carries
 * an id, and `.woocommerce table.shop_table` outranks a two-class selector. The
 * house convention for that is this "integration guard" shape (see the section
 * of the same name earlier in this file): match WooCommerce's own selector and
 * add one class, so the component wins on specificity rather than on
 * `!important`. Nothing here is new design — it is the same component values,
 * re-asserted.
 *
 * Dequeuing woocommerce.css instead was rejected: it also dresses the cart,
 * account and shop surfaces this theme has not rebuilt yet. */

/* The order-review table. WooCommerce gives .shop_table a 1px box, a 5px
   radius, separate borders and 9px/12px cells; the summary card wants hairline
   rows and no box of its own. */
.kr-checkout .kr-summary table.kr-order-review {
    border: 0;
    border-radius: 0;
    border-collapse: collapse;
    border-spacing: 0;
    margin: 0;
}

.kr-checkout table.kr-order-review th,
.kr-checkout table.kr-order-review td {
    padding: var(--kr-space-3) 0;
    border-top: 0;
    border-bottom: 1px solid var(--kr-border);
    vertical-align: top;
    line-height: var(--kr-leading-snug);
}

.kr-checkout table.kr-order-review td {
    padding-left: var(--kr-space-4);
}

/* The product cell is a <td>, so the right-aligned money rule above catches it
   unless it is put back. */
.kr-checkout table.kr-order-review tbody td.product-name {
    text-align: left;
    white-space: normal;
}

.kr-checkout table.kr-order-review .order-total th,
.kr-checkout table.kr-order-review .order-total td {
    border-bottom: 0;
    padding-bottom: 0;
}

/* Payment method rows. Two things to undo: the id-scoped `line-height: 2` /
   margins, and the clearfix `::before` / `::after` WooCommerce puts on every
   <li> — in a grid container those become two stray grid items and push the
   radio out of place. */
.kr-checkout #payment ul.payment_methods li.kr-choice {
    line-height: var(--kr-leading-normal);
    margin: 0;
    padding: var(--kr-space-4) var(--kr-space-5);
}

.kr-checkout #payment ul.payment_methods li.kr-choice:not(.woocommerce-notice)::before,
.kr-checkout #payment ul.payment_methods li.kr-choice:not(.woocommerce-notice)::after {
    content: none;
    display: none;
}

.kr-checkout #payment ul.payment_methods li input.kr-choice__control {
    margin: 0;
}

.kr-checkout #payment ul.payment_methods li.kr-choice img {
    margin: 0;
    float: none;
    vertical-align: middle;
}

.kr-checkout #payment ul.payment_methods.kr-choice-list {
    margin: 0;
    padding: 0;
    border-radius: 0;
    background: none;
}

/* The place-order button. `.button alt` is kept on it for gateway CSS, and
   WooCommerce paints that WooCommerce-purple; the id wins the colour back. */
.kr-checkout #place_order {
    color: var(--kr-btn-primary-text);
    background-color: var(--kr-primary);
    border: 2px solid var(--kr-primary);
    border-radius: var(--kr-btn-radius);
}

.kr-checkout #place_order:hover,
.kr-checkout #place_order:focus-visible {
    color: var(--kr-primary);
    background-color: var(--kr-btn-soft-bg);
    border-color: var(--kr-btn-soft-bg);
}

/* The payment block's own chrome: woocommerce.css paints `#payment` grey, gives
   the method list a bottom rule, and draws each `.payment_box` as a grey
   speech-bubble with a CSS triangle. Inside the summary card all of that is
   noise — the .kr-choice card already carries the state. */
.kr-checkout #payment.kr-payment {
    background: none;
    border-radius: 0;
    padding: 0;
}

.kr-checkout #payment ul.payment_methods.kr-choice-list {
    border-bottom: 0;
}

.kr-checkout #payment div.payment_box.kr-choice__panel {
    width: auto;
    margin: var(--kr-space-3) 0 0;
    padding: var(--kr-space-3) 0 0;
    font-size: var(--kr-text-sm);
    color: var(--kr-text);
    background: none;
    border-radius: 0;
}

.kr-checkout #payment div.payment_box.kr-choice__panel::before {
    content: none;
    display: none;
}

.kr-checkout #payment div.form-row.kr-payment__place-order {
    padding: 0;
}

/* The fields themselves. `.woocommerce form .form-row .input-text` outranks the
   global input rule in the Forms section, so without this the checkout is the
   one screen in the theme with white, thin-bordered inputs instead of the
   pink-pale `.kr-field` fill the cart and the auth screens use. Same selector
   shape as WooCommerce's, so it wins on cascade order — the values are lifted
   verbatim from the Forms section, not invented here. */
.kr-checkout form .form-row .input-text,
.kr-checkout form .form-row textarea,
.kr-checkout form .form-row select {
    font-family: var(--kr-font-body);
    font-size: var(--kr-text-base);
    color: var(--kr-field-text);
    background-color: var(--kr-field-bg);
    border: 2px solid transparent;
    border-radius: var(--kr-field-radius);
    padding: 0.85em 1.2em;
}

.kr-checkout form .form-row .input-text:focus,
.kr-checkout form .form-row textarea:focus,
.kr-checkout form .form-row select:focus {
    background-color: var(--kr-field-bg-focus);
    border-color: var(--kr-accent);
}

/* WCAG 2.4.7 — the navy outline must survive the guard above. */
.kr-checkout form .form-row .input-text:focus-visible,
.kr-checkout form .form-row textarea:focus-visible,
.kr-checkout form .form-row select:focus-visible {
    outline: 3px solid var(--kr-primary);
    outline-offset: 2px;
    box-shadow: var(--kr-focus-shadow);
}

/* ========================================================================
 * Order confirmation — the order-received ("bedankt") state
 * (woocommerce/checkout/thankyou.php + woocommerce/order/order-details*.php)
 *
 * This block supersedes the earlier "Order received (thank you)" section, which
 * left WooCommerce's stock thankyou.php in place and only dressed it. The
 * confirmation is the emotional peak of the funnel, so it is now a themed
 * template — and what lives here is a real set of components rather than
 * selectors aimed at core markup.
 *
 * Everything below is deliberately UNSCOPED (no `.kr-checkout` ancestor): the
 * same order-details templates also render on My Account → bestelling bekijken,
 * where that wrapper does not exist. Where woocommerce.css outranks a plain
 * class, the "integration guard" block at the end re-asserts the same values —
 * same house convention as the checkout guards above.
 * ======================================================================== */

/* ---- General primitives that surfaced here ------------------------------
 * Two small, screen-agnostic pieces. They are written here because this screen
 * is where they first appeared, but nothing about them is confirmation-specific
 * — reach for them anywhere. */

/* A row of buttons that wraps instead of overflowing. */
.kr-btn-row {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--kr-space-4);
    margin: 0;
}

.kr-btn-row--end {
    justify-content: flex-end;
}

.kr-btn-row--center {
    justify-content: center;
}

/* Numbered explanation list — pink disc, navy numeral (navy-on-pink ≈4.8:1;
   white would fail). An <ol>, so the numbers survive CSS being unavailable. */
.kr-steplist {
    counter-reset: kr-steplist;
    display: flex;
    flex-direction: column;
    gap: var(--kr-space-4);
    margin: 0;
    padding: 0;
    list-style: none;
}

.kr-steplist__item {
    display: grid;
    grid-template-columns: 2rem minmax(0, 1fr);
    align-items: start;
    gap: var(--kr-space-4);
    margin: 0;
    font-family: var(--kr-font-body);
    line-height: var(--kr-leading-snug);
    color: var(--kr-text);
}

.kr-steplist__item::before {
    counter-increment: kr-steplist;
    content: counter(kr-steplist);
    display: flex;
    align-items: center;
    justify-content: center;
    width: 2rem;
    height: 2rem;
    font-family: var(--kr-font-body);
    font-weight: var(--kr-weight-bold);
    font-size: var(--kr-text-sm);
    color: var(--kr-accent-contrast);
    background: var(--kr-accent);
    border-radius: var(--kr-radius-circle);
}

/* ---- Page stack ---------------------------------------------------------
 * The thank-you body is a single column of blocks. The gap does the spacing so
 * the blocks themselves stay margin-free — which also absorbs whatever gateways
 * and tracking plugins print from `woocommerce_thankyou` between them. */
.kr-thankyou {
    display: flex;
    flex-direction: column;
    gap: var(--kr-space-6);
}

.kr-thankyou__next-title {
    margin: 0 0 var(--kr-space-5);
    font-size: var(--kr-text-lg);
    color: var(--kr-heading);
}

.kr-thankyou__actions {
    margin: 0;
}

/* ---- Confirmation banner (.kr-confirm) ----------------------------------
 * The "het is gelukt" moment: badge + message + one reassuring line. Peach band
 * for success, pink band for the failed-payment branch — the same two tints the
 * notices component uses, so a confirmation and a notice never disagree about
 * what "good" and "mis" look like. Generic on purpose: any terminal state
 * (bestelling geplaatst, wachtwoord gewijzigd) can use it. */
.kr-confirm {
    display: grid;
    grid-template-columns: auto minmax(0, 1fr);
    align-items: start;
    gap: var(--kr-space-4) var(--kr-space-5);
    margin: 0;
    padding: var(--kr-space-6);
    background: var(--kr-section-peach);
    border: 1px solid var(--kr-card-border);
    border-radius: var(--kr-radius-xl);
}

@media (max-width: 620px) {
    .kr-confirm {
        grid-template-columns: 1fr;
        padding: var(--kr-space-5);
    }
}

.kr-confirm__badge {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 3.25rem;
    height: 3.25rem;
    /* Navy on pink (~4.8:1). Never white on pink. */
    color: var(--kr-accent-contrast);
    background: var(--kr-accent);
    border-radius: var(--kr-radius-circle);
}

.kr-confirm__badge svg {
    width: 1.75rem;
    height: 1.75rem;
}

.kr-confirm__body {
    display: flex;
    flex-direction: column;
    gap: var(--kr-space-3);
    min-width: 0;
}

/* `__message` is either the element itself (failed branch) or a wrapper around
   WooCommerce's own `checkout/order-received.php` paragraph — hence both. */
.kr-confirm__message,
.kr-confirm__message > p {
    margin: 0;
    padding: 0;
    font-family: var(--kr-font-heading);
    font-size: var(--kr-text-xl);
    line-height: var(--kr-leading-snug);
    color: var(--kr-heading);
    background: none;
    border: 0;
}

.kr-confirm__lede {
    margin: 0;
    font-size: var(--kr-text-md);
    line-height: var(--kr-leading-normal);
    color: var(--kr-text);
}

.kr-confirm__lede strong {
    font-weight: var(--kr-weight-semibold);
}

.kr-confirm--error {
    background: var(--kr-section-pink);
    border-color: var(--kr-accent);
}

/* ---- Order facts (.kr-order-facts) --------------------------------------
 * Ordernummer · besteldatum · e-mail · totaal · betaalmethode. A label/value
 * grid rather than WooCommerce's uppercase, dashed-divider strip — uppercase
 * mini-labels above a value are exactly the look the house rules ban. */
.kr-order-facts {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(11rem, 1fr));
    gap: var(--kr-space-5);
    margin: 0;
    padding: var(--kr-space-5) var(--kr-space-6);
    list-style: none;
    border: 1px solid var(--kr-card-border);
    border-radius: var(--kr-radius-xl);
}

.kr-order-facts__item {
    display: flex;
    flex-direction: column;
    gap: var(--kr-space-1);
    margin: 0;
    min-width: 0;
}

.kr-order-facts__label {
    font-family: var(--kr-font-body);
    font-weight: var(--kr-weight-bold);
    font-size: var(--kr-text-sm);
    color: var(--kr-text);
}

.kr-order-facts__value {
    font-family: var(--kr-font-body);
    font-weight: var(--kr-weight-regular);
    font-size: var(--kr-text-md);
    line-height: var(--kr-leading-snug);
    color: var(--kr-heading);
    overflow-wrap: anywhere;
}

/* ---- Order table (.kr-order-table) --------------------------------------
 * The line items, inside the shared `.kr-summary` card. Still a real <table>
 * (see the note at the top of woocommerce/order/order-details.php), styled into
 * the same hairline label/value rhythm as `.kr-order-review` on the checkout —
 * which stays scoped under `.kr-checkout` because it must also outrank
 * woocommerce.css there, so the two cannot share one selector list. */
.kr-order-table {
    width: 100%;
    margin: 0;
    border: 0;
    border-collapse: collapse;
    font-family: var(--kr-font-body);
    font-size: var(--kr-text-base);
    color: var(--kr-text);
}

/* Visually hidden, not removed: the design has no header row, but the column
   names are still the table's only structural labels for a screen reader. */
.kr-order-table thead {
    position: absolute;
    width: 1px;
    height: 1px;
    overflow: hidden;
    clip: rect(0 0 0 0);
    clip-path: inset(50%);
    white-space: nowrap;
}

.kr-order-table th,
.kr-order-table td {
    padding: var(--kr-space-4) 0;
    border: 0;
    border-bottom: 1px solid var(--kr-border);
    text-align: left;
    vertical-align: top;
    line-height: var(--kr-leading-snug);
}

.kr-order-table td {
    padding-left: var(--kr-space-4);
    text-align: right;
    white-space: nowrap;
}

.kr-order-table tbody td.product-name {
    text-align: left;
    white-space: normal;
}

.kr-order-table tfoot th {
    font-weight: var(--kr-weight-bold);
    color: var(--kr-heading);
}

.kr-order-table tfoot td {
    font-style: italic;
}

/* The order total is the row that matters — and it is always the last of
   WooCommerce's `get_order_item_totals()` keys. */
.kr-order-table .kr-order-table__total--order_total th,
.kr-order-table .kr-order-table__total--order_total td {
    font-weight: var(--kr-weight-bold);
    font-style: normal;
    font-size: var(--kr-text-md);
}

.kr-order-table__note td,
.kr-order-table__actions td {
    text-align: left;
    white-space: normal;
    font-style: normal;
}

/* Nothing under the last row: the card's own padding closes it off. */
.kr-order-table tfoot tr:last-child th,
.kr-order-table tfoot tr:last-child td {
    border-bottom: 0;
    padding-bottom: 0;
}

/* ---- One order line (.kr-order-line) ------------------------------------ */
.kr-order-line {
    display: grid;
    grid-template-columns: 3.5rem minmax(0, 1fr);
    align-items: start;
    gap: var(--kr-space-4);
}

.kr-order-line__media {
    display: block;
}

.kr-order-line__media img {
    display: block;
    width: 100%;
    height: auto;
    border-radius: var(--kr-radius-xs);
}

.kr-order-line__body {
    min-width: 0;
}

.kr-order-line__name {
    display: block;
    font-weight: var(--kr-weight-bold);
    color: var(--kr-heading);
}

.kr-order-line__name a {
    color: inherit;
}

.kr-order-line__qty {
    font-weight: var(--kr-weight-regular);
    color: var(--kr-text-muted);
}

/* ---- Item meta (.kr-item-meta) ------------------------------------------
 * `wc_display_item_meta()`'s output. On this shop that is the per-card
 * BEZORGADRES and BEZORGDATUM — the cart writes them onto the order item as
 * visible meta — so it reads as quiet delivery info under the card name, the
 * same rhythm `.kr-order-review__delivery` gives it on the checkout. */
.kr-item-meta {
    margin: var(--kr-space-2) 0 0;
    padding: 0;
    list-style: none;
    font-size: var(--kr-text-sm);
    line-height: var(--kr-leading-snug);
    color: var(--kr-text-muted);
}

.kr-item-meta li {
    margin: 0 0 var(--kr-space-1);
    list-style: none;
}

.kr-item-meta li:last-child {
    margin-bottom: 0;
}

.kr-item-meta .wc-item-meta-label {
    font-weight: var(--kr-weight-bold);
    color: var(--kr-text);
}

.kr-item-meta p {
    display: inline;
    margin: 0;
    font-style: italic;
}

/* ---- Customer details (.kr-order-customer) ------------------------------ */
.kr-order-customer {
    margin: 0;
}

.kr-order-customer__title {
    margin: 0 0 var(--kr-space-4);
    font-size: var(--kr-text-lg);
    color: var(--kr-heading);
}

.kr-order-customer__columns {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(16rem, 1fr));
    gap: var(--kr-space-6);
}

.kr-order-customer__address {
    display: block;
    margin: 0;
    font-family: var(--kr-font-body);
    font-style: normal;
    line-height: var(--kr-leading-normal);
    color: var(--kr-text);
}

.kr-order-customer__line {
    display: block;
    color: var(--kr-text-muted);
    overflow-wrap: anywhere;
}

/* ---- WooCommerce stylesheet guards --------------------------------------
 * Same convention as the checkout guards above: match woocommerce.css's own
 * selector shape and add one class, so the component wins on specificity rather
 * than on `!important`. No new design here — the values are the ones already
 * declared above, re-asserted. */

/* `.woocommerce ul.order_details li` floats each fact, uppercases it, shrinks it
   to .715em and hangs a dashed divider off it — the very "kicker label" look the
   house rules ban. */
.woocommerce ul.order_details.kr-order-facts {
    margin: 0;
}

.woocommerce ul.order_details.kr-order-facts li {
    float: none;
    margin: 0;
    padding: 0;
    border-right: 0;
    font-size: inherit;
    line-height: inherit;
    text-transform: none;
}

.woocommerce ul.order_details.kr-order-facts li strong {
    display: block;
    font-size: var(--kr-text-md);
    line-height: var(--kr-leading-snug);
    text-transform: none;
}

/* `.woocommerce table.shop_table` draws a 1px box with a 5px radius, separate
   borders and 9px/12px cells; inside the summary card the table wants hairline
   rows and no box of its own. */
.woocommerce table.shop_table.kr-order-table {
    margin: 0;
    border: 0;
    border-radius: 0;
    border-collapse: collapse;
    border-spacing: 0;
}

.woocommerce table.kr-order-table th,
.woocommerce table.kr-order-table td {
    padding: var(--kr-space-4) 0;
    border-top: 0;
    border-bottom: 1px solid var(--kr-border);
    vertical-align: top;
    line-height: var(--kr-leading-snug);
}

.woocommerce table.kr-order-table td {
    padding-left: var(--kr-space-4);
}

.woocommerce table.kr-order-table tfoot tr:last-child th,
.woocommerce table.kr-order-table tfoot tr:last-child td {
    border-bottom: 0;
    padding-bottom: 0;
}

/* WooCommerce floats the meta label and clears it, which stacks the label and
   its value into a ragged two-column drift inside a narrow cell. */
.woocommerce td.product-name .kr-item-meta .wc-item-meta-label {
    display: inline;
    float: none;
    clear: none;
    margin-right: var(--kr-space-1);
}

/* Both sections get a 2em bottom margin from woocommerce.css; the `.kr-thankyou`
   stack owns the spacing here (and the account page has its own rhythm). */
.woocommerce .woocommerce-order-details.kr-order-details,
.woocommerce .woocommerce-customer-details.kr-order-customer {
    margin-bottom: 0;
}

/* The grey rounded `<address>` box, replaced by the `.kr-panel` shell around it. */
.woocommerce .woocommerce-customer-details address.kr-order-customer__address {
    width: auto;
    padding: 0;
    border: 0;
    border-radius: 0;
}

/* ========================================================================
 * "Gratis downloads" category — mint band, single-choice pill row and an
 * alternating media/text list of free printables.
 *
 * Composition lives in woocommerce/taxonomy-product_cat-gratis_downloads.php +
 * template-parts/product/download-{filters,item}.php. The list is written as a
 * reusable block (.kr-download-list / .kr-download-item) rather than page CSS:
 * an alternating preview-beside-copy list with one call to action per row is a
 * pattern the shop will want again. Demo in template-styleguide.php.
 * ======================================================================== */

/* ---- Header: the category name centred over the pill row ---------------- */
.kr-downloads__header {
    text-align: center;
}
.kr-downloads__header .kr-product-archive__description {
    margin-inline: auto;
}

/* ---- Filter pills — single-choice, one centred row ---------------------- */
.kr-downloads__filters {
    margin-top: var(--kr-space-5);
}
.kr-downloads__filter-list {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: center;
    gap: var(--kr-space-3);
    margin: 0;
    padding: 0;
    list-style: none;
}

/* ---- The list ----------------------------------------------------------- */
.kr-download-list {
    /* A deliberately narrow editorial measure inside the wide page container —
       the design sets these rows well inside the frame, and it keeps each text
       column at a readable ~45 characters. */
    max-width: var(--kr-container-narrow);
    margin-inline: auto;
    margin-block-start: var(--kr-space-8);
    display: grid;
    gap: var(--kr-space-8);
}

.kr-download-list__empty {
    margin: 0;
    text-align: center;
    color: var(--kr-text);
}

/* ---- One row: preview beside copy, mirrored on every other row ---------- */
.kr-download-item {
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    gap: var(--kr-space-6);
    /* The copy sits on the baseline of the preview, not centred against it. */
    align-items: end;
}

.kr-download-item__media {
    position: relative; /* anchors the shared .kr-wishlist-heart */
    margin: 0;
}

.kr-download-item__image {
    display: block;
    width: 100%;
    height: auto;
    /* Printables are A4 portrait; hold that shape so a row of mixed uploads
       still lines up, and contain rather than crop the artwork. */
    aspect-ratio: 1 / 1.414;
    object-fit: contain;
    object-position: center;
}

.kr-download-item__body {
    padding-bottom: var(--kr-space-2);
}

.kr-download-item__title {
    /* Not a display heading: the design sets the download name in bold body
       type, so the row reads as a caption to the preview. */
    margin: 0 0 var(--kr-space-2);
    font-family: var(--kr-font-body);
    font-weight: var(--kr-weight-bold);
    font-size: var(--kr-text-md);
    line-height: var(--kr-leading-snug);
    color: var(--kr-heading);
}

.kr-download-item__text {
    color: var(--kr-text); /* brand navy, like the archive intro copy */
    font-size: var(--kr-text-sm);
    line-height: var(--kr-leading-normal);
}
.kr-download-item__text > p {
    margin: 0 0 var(--kr-space-2);
}
.kr-download-item__text > p:last-child {
    margin-bottom: 0;
}

.kr-download-item__btn {
    margin-top: var(--kr-space-5);
}

/* Mirrored row: preview on the right, copy set flush to it on the left. */
.kr-download-item--mirrored .kr-download-item__media {
    order: 2;
}
.kr-download-item--mirrored .kr-download-item__body {
    order: 1;
    text-align: right;
}

/* ---- Load more ---------------------------------------------------------- */
.kr-downloads__more {
    margin-top: var(--kr-space-8);
    text-align: center;
}

/* ---- Stacked: one column, preview first, copy always left-aligned -------- */
@media (max-width: 700px) {
    .kr-download-item {
        grid-template-columns: minmax(0, 1fr);
        gap: var(--kr-space-4);
        align-items: start;
    }
    .kr-download-item__media {
        max-width: 20rem;
    }
    .kr-download-item--mirrored .kr-download-item__media {
        order: 0;
    }
    .kr-download-item--mirrored .kr-download-item__body {
        order: 0;
        text-align: left;
    }
    .kr-download-list {
        gap: var(--kr-space-7);
    }
}

/* HP6 / DA10 — buttons and name pills sit at the bottom of their card so a
   squarer image never pulls them up (grids above use align-items: stretch). */
.kr-top-card__btn { margin-top: auto; }
.kr-category-card__title { margin-top: auto; }
