/**
 * Composite BOM Manager — Frontend (kit page redesign)
 *
 * Slims kit-product pages so they read as one product, not three product cards
 * stacked. Targets `body.cbm-composite-page` (added via PHP body_class filter
 * for any composite product with a CBM quantity map).
 *
 * Spec: claude/KIT_PAGE_DESIGN.md
 */

/* =========================================================================
   1. Layout — hide the right sidebar so the info col grows wider
   ========================================================================= */

body.cbm-composite-page #product-sidebar,
body.cbm-composite-page .col.large-3.product-sidebar {
    display: none !important;
}

/* On kit pages the info col fills the remaining 6/12 columns. Flatsome's
   `.product-info.col-fit.col-divided` is `flex: 1` so it auto-grows when
   the sidebar is removed; no explicit width needed. */

/* =========================================================================
   2. Slim component rows
   Hide the underlying-product cruft inside each component:
   - "Hot Socks Pearl" h3 (composited_product_title)
   - The underlying product image (composited_product_image / images)
   - "Available options:" label (component_section_title)
   - The auto-selected single product dropdown (component_options)
   - Per-component variation price ("56,00 kr each")
   - Per-component variation availability ("Lagerstatus: På lager")
   - Per-component qty controls + ATC button (kit has its own)
   - The auto-injected "Antal tilpasses..." hint (CBM v3.x adds this; redundant
     once the qty is hidden entirely)
   ========================================================================= */

body.cbm-composite-page .composite_component .composited_product_title_wrapper,
body.cbm-composite-page .composite_component .composited_product_images,
body.cbm-composite-page .composite_component .composited_product_image,
body.cbm-composite-page .composite_component .composited_product_details_wrapper > .composited_product_images,
/* Hide the underlying product's description (CP renders the assigned
   product's short_description here). The kit doesn't want each component
   echoing "Pelini consists of 50% pima cotton..." three times — the yarn's
   own description belongs on its own product page, not in the kit
   configurator. */
body.cbm-composite-page .composite_component .component_description_wrapper,
body.cbm-composite-page .composite_component .composited_product_short_description,
body.cbm-composite-page .composite_component .component_section_title,
body.cbm-composite-page .composite_component .component_options_select_wrapper,
body.cbm-composite-page .composite_component .component_options_thumbnails,
/* Hide the entire variation summary wrap inside each component — kit total
   handles price, sticky ATC handles stock, and the kit-level qty stepper
   replaces per-component quantity. The .single_variation_wrap stays in the
   DOM for CP machinery (events fire on hidden elements). */
body.cbm-composite-page .composite_component .component_summary .single_variation_wrap,
body.cbm-composite-page .composite_component .cbm-qty-info,
body.cbm-composite-page .composite_component .reset_variations {
    display: none !important;
}

/* Also reset the .component_inner padding so the variations table sits
   flush against the previous element with no trailing whitespace. */
body.cbm-composite-page .composite_component .component_inner {
    padding-bottom: 0 !important;
}

/* Composited details: the inner layout is `images + details` flex by default.
   With images hidden, drop the flex gutter so the variations table sits
   flush left. */
body.cbm-composite-page .composite_component .composited_product_details_wrapper {
    display: block;
}

body.cbm-composite-page .composite_component .details.component_data {
    width: 100%;
    padding: 0;
    margin: 0;
}

/* Component title — the role label (e.g. "Hovedfarve"). Calmer than the
   default h2 size; we'll append the BOM qty inline via JS. */
body.cbm-composite-page .composite_component .component_title {
    font-size: 1.05em;
    font-weight: 600;
    margin: 0 0 8px;
    text-transform: none;
    letter-spacing: 0;
}
body.cbm-composite-page .composite_component .component_title_text {
    font-size: 1em;
}
body.cbm-composite-page .composite_component .component_title .cbm-bom-qty {
    color: #666;
    font-weight: 400;
    margin-left: 6px;
}

/* Tighten vertical spacing between components — they're now slim rows,
   not cards, so they should sit closer. */
body.cbm-composite-page .composite_component {
    margin-bottom: 18px;
    padding-bottom: 0;
    border-bottom: none;
}
body.cbm-composite-page .composite_component.last {
    margin-bottom: 24px;
}

/* The variations <table> contains the swatches. Strip the table frame so
   the swatch grid sits naturally under the role label. */
body.cbm-composite-page .composite_component table.variations,
body.cbm-composite-page .composite_component table.variations tbody,
body.cbm-composite-page .composite_component table.variations tr,
body.cbm-composite-page .composite_component table.variations td {
    display: block;
    width: 100%;
    border: none;
    padding: 0;
    margin: 0;
    background: transparent;
}
/* Hide the "Farve" label cell — the role label above already establishes
   what's being chosen. The "Farve: <name>" line below the swatches is
   added by the swatch plugin (vis-selected-label) and is the one we keep. */
body.cbm-composite-page .composite_component table.variations .label {
    display: none !important;
}
body.cbm-composite-page .composite_component table.variations .value {
    display: block;
    padding: 0;
}

/* Yarn product name now lives in .cbm-bom-qty (part of the component
   title row), not on the dynamic "Farve: <color>" line. Static info
   belongs with static info. See updateComponentBomQty() in frontend.js
   and the v3.6.2 reasoning in claude/KIT_PAGE_DESIGN.md. */

/* =========================================================================
   3. Section dividers — visual separation between the Specifikationer block,
   the size step, and the colors step. Mirrors the visual rhythm of the
   simple-PDP info col.
   ========================================================================= */

body.cbm-composite-page .cbm-step-heading {
    font-size: 0.85em;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: #999;
    margin: 18px 0 8px;
    padding-top: 12px;
    border-top: 1px solid #e8e8e8;
}

/* =========================================================================
   4. Size chip row
   Replaces the size component's `<select>` dropdown with a chip row.
   ========================================================================= */

/* Size component: the chip row + driver hint sit between .component_title_wrapper
   and .component_inner. We collapse .component_inner entirely — the underlying
   <select> stays in the DOM (chips dispatch change events to it) but doesn't
   take any layout space. jQuery .val()/.trigger() and CP's own listeners work
   on display:none elements. */
body.cbm-composite-page .composite_component.cbm-size-component .component_inner {
    display: none !important;
}

.cbm-size-chips {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
    margin: 0 0 8px;
}
.cbm-size-chip {
    appearance: none;
    display: inline-flex;        /* center the label vertically + horizontally */
    align-items: center;
    justify-content: center;
    border: 1.5px solid #ddd;
    background: #fff;
    color: #333;
    padding: 5px 13px;           /* slimmer block (text size unchanged) */
    min-width: 44px;
    min-height: 34px;
    font-size: 0.95em;
    font-weight: 500;
    line-height: 1.2;
    border-radius: 4px;
    cursor: pointer;
    transition: border-color 0.12s ease, background-color 0.12s ease;
    text-align: center;
}
.cbm-size-chip:hover {
    border-color: #888;
}
.cbm-size-chip.cbm-size-chip--selected {
    border-color: #222;
    background: #222;
    color: #fff;
}
.cbm-size-chip[disabled],
.cbm-size-chip.cbm-size-chip--disabled {
    opacity: 0.4;
    cursor: not-allowed;
    text-decoration: line-through;
}

/* BOM driver hint under the chip row (sizeful) or above the first color
   component (sizeless). Identical styling in both modes. */
.cbm-bom-driver-hint {
    font-size: 0.9em;
    color: #666;
    margin: 0 0 4px;
    min-height: 1.3em; /* reserve a line so layout doesn't jump on selection */
}

/* Sizeless kits: hint stands alone above the first composite_component,
   so give it a little more breathing room. */
.composite_form > .cbm-bom-driver-hint {
    margin: 0 0 12px;
}

/* Simple-product components (printed pattern, hardware, fixed includes)
   contribute to BOM pricing but aren't a customer choice — hide their
   configurator row. They're surfaced by name in the BOM driver hint
   via PHP's componentSimpleIncludes config. See KIT_SIZELESS_AND_WEIGHT_SPEC.md. */
.cbm-composite-page .composite_component.cbm-simple-include {
    display: none;
}

/* Fixed-colour components: the designer has chosen the colour, the customer
   cannot pick. Render the component as a compact static row (32 px thumb +
   colour name) instead of the swatch grid. The underlying <select> stays in
   the DOM (hidden alongside other CP plumbing) so form serialisation works.
   The variations form / swatch grid that CP renders inside .component_summary
   is hidden in full — the static row is the only colour info shown.
   See claude/KIT_FIXED_COLOR_SPEC.md. */
.cbm-composite-page .composite_component.cbm-fixed-color .component_summary {
    display: none !important;
}
.cbm-fixed-color-row {
    display: flex;
    align-items: center;
    gap: 8px;
    margin: 4px 0 0;
}
.cbm-fixed-color-row__thumb {
    width: 32px;
    height: 32px;
    flex: 0 0 32px;
    object-fit: cover;
    border-radius: 2px;
    /* No border, no shadow, no hover state — must not read as a control. */
    background: #f5f5f5;
}
.cbm-fixed-color-row__thumb:empty {
    /* Variation has no image — keep the placeholder square so the row
       still aligns with sibling fixed components. */
    background: #eee;
}
.cbm-fixed-color-row__name {
    font-size: 0.95rem;
    line-height: 1.3;
    color: #333;
}

/* ---- Manifest mode (prototype v3.8) ----
   When every yarn component is fixed (allColorsFixed), the per-component
   fixed rows are consolidated into one "Farver i sættet" grid. Hide the
   individual composite_components (their <select>/qty inputs stay in the
   DOM for CP serialization) and show the manifest grid instead. */
.cbm-composite-page.cbm-manifest-mode .composite_component.cbm-fixed-color {
    display: none !important;
}
.cbm-color-manifest {
    margin: 6px 0 18px;
}
.cbm-color-manifest__heading {
    font-size: 0.95rem;
    font-weight: 600;
    color: #333;
    margin: 0 0 12px;
}
.cbm-color-manifest__grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(130px, 1fr));
    gap: 14px 16px;
}
.cbm-manifest-chip {
    display: flex;
    align-items: center;
    gap: 9px;
    /* Read-only — no hover, no cursor, no border. Information, not a control. */
}
.cbm-manifest-chip__thumb {
    width: 44px;
    height: 44px;
    flex: 0 0 44px;
    border-radius: 4px;
    background-color: #f0f0f0;
    background-size: cover;
    background-position: center;
}
.cbm-manifest-chip__body {
    line-height: 1.3;
    min-width: 0;
}
.cbm-manifest-chip__name {
    font-size: 0.85rem;
    color: #333;
}
.cbm-manifest-chip__qty {
    /* Inline with the name (e.g. "Pistacie (190) ×4"), not on its own line. */
    font-size: 0.8rem;
    font-weight: 600;
    color: #666;
    margin-left: 5px;
    white-space: nowrap;
}

/* Sizeless kits: a single "Onesize" chip in the size slot, matching the size
   chip styling so the layout reads consistently across kits. Non-interactive
   (nothing to select) — rendered in the selected state with no hover/pointer. */
.cbm-size-chip--onesize {
    cursor: default;
}
.cbm-size-chip--onesize:hover {
    border-color: #222; /* override the interactive hover — there's nothing to pick */
}
/* Heading above the Onesize chip — mirrors the size-component title on
   multi-size kits so the size slot reads identically across kit types. */
.cbm-onesize-row {
    margin: 0 0 14px;
}
.cbm-onesize-heading {
    font-size: 1.05em;
    font-weight: 600;
    margin: 0 0 8px;
}
.cbm-manifest-chip.is-oos {
    opacity: 0.5;
}
.cbm-manifest-chip.is-oos .cbm-manifest-chip__name::after {
    content: " — udsolgt";
    color: #b00020;
    font-weight: 600;
}
@media (max-width: 549px) {
    .cbm-color-manifest__grid {
        grid-template-columns: repeat(2, 1fr);
    }
}

/* Row-layout variant ("one line per component", Rauma-style) — kept for
   comparing against the grid. Activated by adding .cbm-color-manifest--rows. */
.cbm-color-manifest--rows .cbm-color-manifest__grid {
    display: block;
}
.cbm-color-manifest--rows .cbm-manifest-chip {
    gap: 12px;
    padding: 9px 2px;
    border-bottom: 1px solid #eee;
}
.cbm-color-manifest--rows .cbm-manifest-chip__thumb {
    width: 48px;
    height: 48px;
    flex-basis: 48px;
}
.cbm-color-manifest--rows .cbm-manifest-chip__name {
    font-size: 0.95rem;
}

/* =========================================================================
   Choosable colour components (v3.9) — compact row + popup swatch picker
   Kits where the customer picks colours (allowed variations > 1) no longer
   render the full swatch wall inline. Each component collapses to one
   compact row (thumb + selected colour + "Skift farve"); clicking it opens
   the component's existing swatch grid as a modal overlay. The grid, its
   hidden <select> and the vis-selected-label never move in the DOM — the
   modal is pure CSS on .component_summary — so the swatches plugin, BOM
   filtering and CP form serialisation are untouched.
   See claude/KIT_COLORWAY_SPEC.md.
   ========================================================================= */

.cbm-composite-page .composite_component.cbm-choosable-color .component_summary {
    display: none !important;
}

/* Open state: the summary becomes the modal panel. All the underlying-product
   cruft inside it (title, images, price, qty) is already hidden by the slim-row
   rules in section 2, leaving exactly the swatch grid + "Farve:" label.
   Layout (Rauma-style): header spans the top; hero pane (large colour image)
   left; the scrollable details wrapper (with the swatch grid) right. The hero
   and the details wrapper are both direct children of .component_summary, so
   a grid on the panel places them without moving any WC/CP DOM. */
.cbm-composite-page .composite_component.cbm-choosable-color.cbm-modal-open .component_summary {
    display: grid !important;
    /* Hero column ~42% of the panel (Rauma proportions) — the colour
       preview is the point of the modal, give it real estate. Rows:
       header / hero+swatches / confirm footer. */
    grid-template-columns: minmax(300px, 42%) minmax(0, 1fr);
    grid-template-rows: auto minmax(0, 1fr) auto;
    column-gap: 26px;
    position: fixed;
    z-index: 1001;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    width: min(96vw, 1100px);
    /* DEFINITE height, not max-height: the minmax(0,1fr) grid row only
       shrinks (and thus lets the swatch column scroll) against a definite
       container height. With max-height the column lays out at full content
       height and the panel clips the bottom rows without any scrollbar. */
    height: min(84vh, 720px);
    overflow: hidden;
    background: #fff;
    border-radius: 8px;
    box-shadow: 0 12px 40px rgba(0, 0, 0, 0.22);
    padding: 0 18px 18px;
}
.cbm-modal-open .cbm-color-modal-hero {
    grid-column: 1;
    grid-row: 2;
    min-height: 0;
    /* Flex column so the IMAGE shrinks (cover-crops) when img + thumb strip
       + name exceed the row track — otherwise the hero overflows its grid
       row and the confirm footer overlaps the thumbs. */
    display: flex;
    flex-direction: column;
}
/* The scroll container is TAGGED BY JS (ensureModalChrome): the direct child
   of .component_summary that holds the swatch grid. CP nests the grid at
   varying depths, so no structural selector is reliable here. */
.cbm-modal-open .component_summary > .cbm-color-modal-scroll {
    grid-column: 2;
    grid-row: 2;
    min-height: 0;
    overflow-y: auto;
    -webkit-overflow-scrolling: touch;
}

/* Hero pane — ONLY the selected colour's own images (never the kit gallery).
   Revealed as a flex COLUMN — the image must be able to flex-shrink when
   img + thumb strip + name exceed the grid row, or the hero overflows onto
   the confirm footer (this rule is later in the cascade than the layout
   rules above, so the display value must be set HERE). */
.cbm-color-modal-hero {
    display: none; /* only in the open modal */
}
.cbm-modal-open .cbm-color-modal-hero {
    display: flex;
    flex-direction: column;
}
.cbm-color-modal-hero__img {
    position: relative; /* hosts the prev/next arrows */
    width: 100%;
    aspect-ratio: 1 / 1;
    flex: 0 1 auto;
    min-height: 120px; /* never shrink into a sliver */
    border-radius: 6px;
    background-color: #f5f5f5;
    /* contain, not cover: show the FULL photo (non-square images were
       cropped top/bottom — owner-reported). Same convention as the PDP
       gallery and the swatch grid. */
    background-size: contain;
    background-repeat: no-repeat;
    background-position: center;
}

/* Prev/next navigation — replicates the PDP gallery's Flickity chevrons
   (recorded on Karlas: 36×102px transparent button, thin dark chevron SVG,
   no circle/background/shadow). On the image on BOTH devices:
   - Desktop: hidden until hero hover, then opacity .7 (1 on button hover).
   - Phone: always visible at .7 (no hover exists).
   Only rendered when the colour has multiple photos (--multi). */
.cbm-color-modal-hero__nav {
    display: none;
    position: absolute;
    top: 50%;
    transform: translateY(-50%);
    width: 36px;
    height: 102px;
    max-height: 70%;
    padding: 0;
    border: none;
    background: transparent;
    color: #111;
    cursor: pointer;
    box-shadow: none;
}
/* PDP parity: hovering the arrow itself tints it the THEME PRIMARY (the
   golden orange, #dd9933 — recorded from the PDP gallery arrow hover, NOT
   the terracotta ATC red); back to dark on un-hover. */
.cbm-color-modal-hero__nav:hover {
    background: transparent;
    color: var(--fs-color-primary, #dd9933);
}
.cbm-color-modal-hero__nav--prev {
    left: 2px;
}
.cbm-color-modal-hero__nav--next {
    right: 2px;
}
.cbm-hero-chevron {
    display: block;
    width: 60%;
    height: 100%;
    margin: 0 auto;
    fill: currentColor;
}
.cbm-color-modal-hero--multi .cbm-color-modal-hero__nav {
    display: block;
    opacity: 0.7;
    transition: opacity 0.15s ease;
}
@media (hover: hover) and (pointer: fine) {
    /* Desktop: revealed on hero hover, full strength on button hover. */
    .cbm-color-modal-hero--multi .cbm-color-modal-hero__nav {
        opacity: 0;
        pointer-events: none;
    }
    .cbm-color-modal-hero--multi:hover .cbm-color-modal-hero__nav {
        opacity: 0.7;
        pointer-events: auto;
    }
    .cbm-color-modal-hero--multi .cbm-color-modal-hero__nav:hover {
        opacity: 1;
        color: var(--fs-color-primary, #dd9933);
    }
}
.cbm-color-modal-hero__thumbs,
.cbm-color-modal-hero__name {
    flex: 0 0 auto;
}
.cbm-color-modal-hero__img--empty {
    background-image: none;
}
.cbm-color-modal-hero__name {
    margin-top: 10px;
    font-size: 1.05em;
    font-weight: 600;
    color: #333;
    min-height: 1.3em;
}

/* Search box under the title row. */
.cbm-color-modal-header__row {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
}
.cbm-color-modal-search-wrap {
    position: relative; /* anchors the clear (×) button */
    margin: 10px 0 0;
}
.cbm-color-modal-search {
    display: block;
    width: 100%;
    margin: 0;
    padding: 8px 36px 8px 12px; /* right space for the × */
    font-size: 0.95em;
    border: 1.5px solid #ddd;
    border-radius: 4px;
    box-shadow: none;
}
.cbm-color-modal-search:focus {
    border-color: #888;
    outline: none;
    box-shadow: none;
}
/* Hide the browser's own type=search cancel × — we render our own
   (consistent across browsers, big enough for touch). */
.cbm-color-modal-search::-webkit-search-cancel-button {
    -webkit-appearance: none;
    appearance: none;
}
/* Clear (×): only visible while the field has text (:placeholder-shown —
   no JS state). Mirrors the PDP colour search's .vis-swatch-search__clear. */
.cbm-color-modal-search-clear {
    display: none;
    position: absolute;
    top: 50%;
    right: 4px;
    transform: translateY(-50%);
    width: 32px;
    height: 32px;
    padding: 0;
    margin: 0;
    border: none;
    background: transparent;
    color: #888;
    font-size: 22px;
    line-height: 1;
    cursor: pointer;
    text-transform: none;
    font-weight: normal;
}
.cbm-color-modal-search:not(:placeholder-shown) + .cbm-color-modal-search-clear {
    display: block;
}
.cbm-color-modal-search-clear:hover,
.cbm-color-modal-search-clear:focus {
    color: #333;
    background: transparent;
    outline: none;
}
/* Swatches filtered out by the search box. */
.vis-swatch.cbm-search-miss {
    display: none !important;
}

/* Mobile: bottom sheet, hero as a compact strip above the grid. */
@media (max-width: 549px) {
    .cbm-composite-page .composite_component.cbm-choosable-color.cbm-modal-open .component_summary {
        grid-template-columns: minmax(0, 1fr);
        /* header, scroll area (hero lives INSIDE it and scrolls away with
           the swatches — Rauma behaviour), confirm footer */
        grid-template-rows: auto minmax(0, 1fr) auto;
        column-gap: 0;
        top: auto;
        bottom: 0;
        left: 0;
        transform: none;
        width: 100vw;
        height: 85vh; /* definite for the same grid-scroll reason as desktop */
        border-radius: 12px 12px 0 0;
    }
    /* Hero is prepended into the scroll host by JS on coarse pointers. */
    .cbm-modal-open .cbm-color-modal-scroll .cbm-color-modal-hero {
        display: flex;
        flex-direction: column;
        align-items: center;
        gap: 6px;
        margin: 0 0 12px;
    }
    /* Rauma-proportioned preview: dominant, centered above the grid. */
    .cbm-color-modal-hero__img {
        width: min(64vw, 280px);
        aspect-ratio: 1 / 1;
        flex: 0 0 auto;
    }
    .cbm-color-modal-hero__name {
        margin-top: 0;
        font-size: 1.05em;
        text-align: center;
    }
    .cbm-modal-open .component_summary > .cbm-color-modal-scroll {
        grid-column: 1;
        grid-row: 2;
    }
    .cbm-modal-open .cbm-color-modal-footer {
        grid-row: 3;
    }
}

/* Header injected by JS at the top of the summary. Spans both modal columns;
   the panel itself doesn't scroll (only the swatch column does), so no sticky
   positioning is needed. */
.cbm-color-modal-header {
    display: none; /* only visible in the open modal */
    grid-column: 1 / -1;
    grid-row: 1;
    background: #fff;
    padding: 14px 0 10px;
    margin: 0 0 10px;
    border-bottom: 1px solid #eee;
}
.cbm-modal-open .cbm-color-modal-header {
    display: block;
}
.cbm-color-modal-title {
    font-weight: 600;
    font-size: 1.05em;
    color: #222;
}
.cbm-color-modal-close {
    flex: 0 0 auto;
    appearance: none;
    border: none;
    background: transparent;
    font-size: 24px;
    line-height: 1;
    padding: 4px 8px;
    margin: 0;
    color: #555;
    cursor: pointer;
}
.cbm-color-modal-close:hover {
    color: #000;
    background: transparent;
}

/* Confirm footer ("Vælg denne farve") — all devices. Picking a colour keeps
   the modal open (the hero + image set is the point); this button is the
   explicit confirm/dismiss. Selection is already live when it's pressed. */
.cbm-color-modal-footer {
    display: none;
}
.cbm-modal-open .cbm-color-modal-footer {
    display: block;
    grid-column: 1 / -1;
    grid-row: 3;
    padding: 10px 0 2px;
    border-top: 1px solid #eee;
    background: #fff;
}
/* Confirm button carries the theme's "button alt" classes so it looks like
   every other primary shop button (Læg i kurv etc.) — only layout here. */
.cbm-color-modal-done.button {
    display: block;
    width: 100%;
    margin: 0;
}

/* Pick line — unit price + item number for the selected colour. Mobile puts it
   directly ABOVE the confirm button; desktop moves it to the button's left
   (see the min-width rule below). Styling mirrors the buy box: the price in
   body colour, the unit and item number small and muted like .gc-sku-inline,
   so the two readouts read as the same thing in two places. */
.cbm-color-modal-pick {
    min-height: 1.2em; /* reserve the line so the button never jumps */
    margin-bottom: 8px;
    line-height: 1.35;
}
/* Colour name — the buy box's own treatment for the chosen variation
   (.gc-atc-color: regular weight, muted), so the modal's readout and the
   sticky bar's read as one voice. */
.cbm-color-modal-pick__name {
    display: block;
    font-size: 0.9em;
    font-weight: 400;
    color: #666;
}
.cbm-color-modal-pick__price {
    display: block;
    font-size: 0.95em;
    color: #333;
}
.cbm-color-modal-pick__price del {
    opacity: 0.6;
    margin-right: 3px;
}
.cbm-color-modal-pick__price ins {
    text-decoration: none;
    font-weight: 600;
}
.cbm-color-modal-pick__unit,
.cbm-color-modal-pick__sku {
    font-size: 0.75em;
    color: #999;
}
/* The unit qualifies the amount rather than continuing it — a single word
   space read as one run of text. */
.cbm-color-modal-pick__unit {
    margin-left: 6px;
}
.cbm-color-modal-pick__sku {
    display: block;
}
/* Desktop: the footer sits under the SWATCH column only (owner request —
   a full-modal-width button read as oversized) and the button shrinks to
   its natural width, right-aligned like a dialog confirm. Mobile keeps the
   full-width bottom-sheet confirm above. */
@media (min-width: 550px) {
    .cbm-modal-open .cbm-color-modal-footer {
        grid-column: 2;
        /* Pick line left, confirm right — one row, baseline-aligned. */
        display: flex;
        align-items: center;
        justify-content: space-between;
        gap: 16px;
        text-align: right;
    }
    .cbm-color-modal-done.button {
        display: inline-block;
        width: auto;
        flex: none;
    }
    .cbm-color-modal-pick {
        margin-bottom: 0;
        text-align: left;
    }
}

/* Hero thumb strip — the selected colour's own photos (variation image +
   token-matched gallery siblings). Click swaps the big image. */
.cbm-color-modal-hero__thumbs {
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    gap: 6px;
    min-width: 0;
    margin-top: 8px;
}
.cbm-color-modal-hero__thumbs:empty {
    display: none;
}
.cbm-color-modal-hero__thumb {
    width: 56px;
    height: 56px;
    border-radius: 4px;
    background-color: #f0f0f0;
    background-size: contain; /* consistent with the hero + row thumbs */
    background-repeat: no-repeat;
    background-position: center;
    border: 2px solid transparent;
    cursor: pointer;
}
.cbm-color-modal-hero__thumb--active {
    border-color: #222;
}

/* Backdrop — one shared element on <body>, toggled with the lock class. */
.cbm-color-modal-backdrop {
    display: none;
    position: fixed;
    inset: 0;
    z-index: 1000;
    background: rgba(0, 0, 0, 0.45);
}
body.cbm-color-modal-lock {
    overflow: hidden;
}
body.cbm-color-modal-lock .cbm-color-modal-backdrop {
    display: block;
}

/* Compact picker row — interactive sibling of .cbm-fixed-color-row. Framed
   (unlike the fixed row) because it IS a control. */
.cbm-color-picker-row {
    display: flex;
    align-items: center;
    gap: 10px;
    margin: 4px 0 0;
    padding: 8px 10px;
    border: 1.5px solid #ddd;
    border-radius: 6px;
    background: #fff;
    cursor: pointer;
    transition: border-color 0.12s ease;
}
.cbm-color-picker-row:hover {
    border-color: #888;
}
.cbm-color-picker-row__thumb {
    width: 44px;
    height: 44px;
    flex: 0 0 44px;
    border-radius: 4px;
    background-color: #f0f0f0;
    /* contain, not cover: non-square yarn photos must not be cropped
       top/bottom (owner-reported on Test - Composite Kit). Matches the
       swatch grid's object-fit: contain. */
    background-size: contain;
    background-repeat: no-repeat;
    background-position: center;
}
.cbm-color-picker-row__name {
    flex: 1 1 auto;
    min-width: 0;
    font-size: 0.95rem;
    line-height: 1.3;
    color: #333;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
/* Stock warning on the row itself ("Udsolgt" / "Kun N på lager") — same
   orange as .cbm-stock-warning so the two signals read as one system. */
.cbm-color-picker-row__flag {
    flex: 0 0 auto;
    font-size: 0.85em;
    font-weight: 600;
    color: #b15a15;
    white-space: nowrap;
}
.cbm-color-picker-row__flag:empty {
    display: none;
}
.cbm-color-picker-row--warning {
    border-color: #b15a15;
}
.cbm-color-picker-row--warning:hover {
    border-color: #8f4408;
}
/* Match the swatch-grid OOS design on the row's colour thumb: dimmed +
   diagonal strikethrough (same gradient technique as .vis-out-of-stock). */
.cbm-color-picker-row--warning .cbm-color-picker-row__thumb {
    opacity: 0.45;
    position: relative;
}
.cbm-color-picker-row--warning .cbm-color-picker-row__thumb::after {
    content: '';
    position: absolute;
    inset: 0;
    border-radius: 4px;
    background: linear-gradient(
        to top right,
        transparent calc(50% - 0.75px),
        #999 calc(50% - 0.75px),
        #999 calc(50% + 0.75px),
        transparent calc(50% + 0.75px)
    );
    pointer-events: none;
}

.cbm-color-picker-row__btn {
    flex: 0 0 auto;
    font-size: 0.85em;
    font-weight: 600;
    color: #333;
    border: 1.5px solid #ddd;
    border-radius: 4px;
    padding: 6px 12px;
    background: #fff;
    white-space: nowrap;
}
.cbm-color-picker-row:hover .cbm-color-picker-row__btn {
    border-color: #888;
}

/* Preset-only kits (_cbm_colorways_lock): rows are information, not controls
   — style them EXACTLY like fixed-colour rows (borderless, 32px thumb) so
   mixed kits (locked choosable + fixed components, e.g. Frugtfest) read as
   one uniform list. The border is a control affordance; locked rows aren't
   controls (owner-reported inconsistency 2026-07-05). */
.cbm-color-picker-row--locked,
.cbm-color-picker-row--locked:hover {
    cursor: default;
    border: none;
    padding: 8px 0 0;
    background: transparent;
}
.cbm-color-picker-row--locked .cbm-color-picker-row__thumb {
    width: 32px;
    height: 32px;
    flex: 0 0 32px;
    border-radius: 2px;
}

/* =========================================================================
   Colorway presets (v3.9) — "Som på billedet" / curated chips + "Vælg selv"
   Rendered above the first choosable colour component from config.colorways.
   ========================================================================= */

.cbm-colorway-row {
    margin: 0 0 16px;
}
.cbm-colorway-heading {
    font-size: 1.05em;
    font-weight: 600;
    margin: 0 0 8px;
}
.cbm-colorway-chips {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
}
.cbm-colorway-chip {
    appearance: none;
    display: inline-flex;
    align-items: center;
    gap: 8px;
    border: 1.5px solid #ddd;
    background: #fff;
    color: #333;
    padding: 6px 12px;
    min-height: 40px;
    font-size: 0.95em;
    font-weight: 500;
    line-height: 1.2;
    border-radius: 4px;
    cursor: pointer;
    transition: border-color 0.12s ease;
    text-transform: none;
}
.cbm-colorway-chip:hover {
    border-color: #888;
    background: #fff;
    color: #333;
}
.cbm-colorway-chip.cbm-colorway-chip--selected {
    border-color: #222;
    box-shadow: 0 0 0 1px #222;
}
/* Mini colour previews inside a preset chip (up to 3). */
.cbm-colorway-chip__thumbs {
    display: inline-flex;
    gap: 2px;
}
.cbm-colorway-chip__thumb {
    width: 18px;
    height: 18px;
    border-radius: 3px;
    background-color: #f0f0f0;
    background-size: cover;
    background-position: center;
}
/* Curated colorway image (finished garment in those colours) — replaces the
   mini-dot mosaic when the colorway has an image. cover is deliberate here:
   it's a preview chip, not an inspectable photo. */
.cbm-colorway-chip__img {
    width: 32px;
    height: 32px;
    border-radius: 4px;
    background-color: #f0f0f0;
    background-size: cover;
    background-position: center;
}

/* ============================================================ */
/* Kit-only product page callout
   Rendered by render_kit_only_callout() on simple products flagged
   _cbm_kit_only=yes. Replaces the ATC area with a "buy as part of
   [Kit Name]" message. */
.cbm-kit-only-callout {
    border: 1px solid #d8d8d8;
    background: #fafafa;
    padding: 18px 20px;
    margin: 20px 0 24px;
    border-radius: 4px;
}
.cbm-kit-only-headline {
    margin: 0 0 8px;
    font-weight: 600;
    color: #333;
}
.cbm-kit-only-body {
    margin: 0 0 12px;
    color: #555;
}
.cbm-kit-only-link {
    color: inherit;
}
.cbm-kit-only-link:hover {
    text-decoration: underline;
}
.cbm-kit-only-button {
    display: inline-block;
}
.cbm-kit-only-list {
    margin: 8px 0 12px 20px;
    padding: 0;
}
.cbm-kit-only-list li {
    margin-bottom: 4px;
}

/* =========================================================================
   5. Sticky ATC bar (composite version)
   The bar pins to viewport bottom while scrolling within the composite form,
   releasing when the form scrolls past into Beskrivelse / Related products.

   IMPORTANT: position:sticky is on `.composite_data` (the parent of
   `.composite_wrap`), NOT on `.composite_wrap` itself. CP renders
   `.composite_data` as a thin element that ONLY contains the wrap — its
   height equals the wrap's height. A sticky element can only "stick" within
   the bounds of its containing block, so sticky on the wrap (parent height
   = wrap height) has zero room and the bar scrolls away with content.

   Promoting sticky one level up makes the containing block `form.composite_form`
   (which holds all the components above + the data div), giving the bar
   ~660px of stick room — enough to stay pinned while the user scrolls
   through the entire configurator. Mirrors how simple PDPs' sticky works
   (sticky on `.single_variation_wrap` within `form.variations_form.cart`,
   where the form is taller than the wrap).
   ========================================================================= */

body.cbm-composite-page .composite_data {
    position: -webkit-sticky;
    position: sticky;
    bottom: 0;
    z-index: 50;
    background: #fff;
    border-top: 1px solid #e8e8e8;
    padding-top: 10px;
    padding-bottom: 4px;
}

/* The wrap establishes the containing block for the absolute-positioned
   hero thumb (88×88) and other absolute children. Position: relative is
   required for that. CP's default stylesheet adds `padding-top: 2rem` via
   `.composite_form:not(.paged) .composite_wrap` which leaves a tall gap
   above the product line — kill it so the kit ATC top-aligns with the
   simple PDP ATC. */
body.cbm-composite-page .composite_wrap {
    position: relative;
    padding-top: 0 !important;
}

/* Dock the kit ATC with the gallery column's bottom — same horizontal
   alignment as the simple PDP. Mirrors `gc-has-sticky-atc` rules from the
   theme: zero out the col's bottom padding and the form's bottom margin
   so the form ends at the col bottom (= gallery col bottom via Flatsome's
   row equal-heights). Keeps `.composite_data` sticky-pinning aligned with
   the gallery thumbnails — both release together when the row scrolls past. */
body.cbm-composite-page .product-info.col {
    padding-bottom: 0 !important;
}
body.cbm-composite-page form.composite_form {
    margin-bottom: 0 !important;
}
/* Small gap between product section and description tabs (mirrors
   simple PDP's `.product-main { margin-bottom: 8px }`). */
body.cbm-composite-page .product-main {
    margin-bottom: 8px;
}

/* Mobile: heavier visual treatment (floating bar). */
@media (max-width: 849px) {
    body.cbm-composite-page .composite_data {
        margin: 0 -15px;
        padding: 10px 15px;
        border-top: none;
        box-shadow: 0 -4px 10px rgba(0,0,0,0.06);
    }
}

/* Composite price — make it the big dashed-top-bordered price line,
   matching the Price Line on simple PDPs. */
body.cbm-composite-page .composite_wrap .composite_price {
    margin: 0;
    padding: 4px 0;
    border-top: 1px dashed #ccc;
}
body.cbm-composite-page .composite_wrap .composite_price .price {
    /* CP's own `.composite_form .composite_price p.price` rule sets
       margin: 0 0 30px with the same specificity as ours; since CP loads
       after our CSS, !important is needed to win. Without this, a 30px
       phantom gap appears between the price text and Lagerstatus. */
    margin: 0 !important;
    font-weight: 600;
    font-size: 1.15em;
    color: #222;
}

/* Incomplete configuration: swap CP's running partial total for the kit's
   minimum ("Fra 118,00 kr."). See updateIncompleteConfigPrice() in
   frontend.js for why this is a visibility swap and not a text rewrite.
   .cbm-from-price mirrors .composite_price so the typography is identical. */
body.cbm-composite-page .composite_wrap .cbm-from-price {
    display: none;
    margin: 0;
    padding: 4px 0;
    border-top: 1px dashed #ccc;
}
body.cbm-composite-page .composite_wrap .cbm-from-price .price {
    margin: 0 !important;
    font-weight: 600;
    font-size: 1.15em;
    color: #222;
}
/* !important is required: CP shows the price element with jQuery .show(),
   which writes an inline `display: block` that beats any stylesheet rule.
   (Same class of conflict as the margin rule above.) It varies per kit
   whether CP has done so at the moment we toggle — Krokus never hit it,
   Frugthals always does — so the rule must win unconditionally. */
body.cbm-composite-page .composite_wrap.cbm-config-incomplete .composite_price {
    display: none !important;
}
body.cbm-composite-page .composite_wrap.cbm-config-incomplete .cbm-from-price {
    display: block;
}

/* Hide CP's default validation message + availability block — we render
   our own clean status line below in .cbm-atc-stock-status. CP's elements:
     .composite_message: "Please choose product options." (generic, English)
     .composite_availability: "Insufficient stock → Mønsterfarve" (untranslated,
       and creates an extra block between price and our Lagerstatus). */
body.cbm-composite-page .composite_wrap .composite_message,
body.cbm-composite-page .composite_wrap .composite_availability {
    display: none !important;
}

/* Action row: qty + button. Match the simple-PDP rhythm. */
body.cbm-composite-page .composite_wrap .composite_button {
    display: flex !important;
    align-items: flex-end;
    gap: 8px;
    flex-wrap: nowrap;
    margin-top: 8px;
    padding: 0;
    /* Reserve right column for the hero thumb */
    padding-right: 96px;
    position: relative;
}
/* Flatsome's default clearfix `::before` / `::after` (display: table) become
   flex items when the parent is flex, and the column-gap then adds 8px
   before the qty stepper and 8px after the ATC button. Drop them so qty
   sits flush at composite_button left (aligned with the SKU/Lagerstatus
   text above) and the ATC button extends fully to the thumb's 8px gap. */
body.cbm-composite-page .composite_wrap .composite_button::before,
body.cbm-composite-page .composite_wrap .composite_button::after {
    display: none !important;
    content: none !important;
}
body.cbm-composite-page .composite_wrap .composite_button .quantity {
    flex-shrink: 0;
    margin: 0;
}
body.cbm-composite-page .composite_wrap .composite_add_to_cart_button {
    flex: 1 1 auto;
    min-width: 0;
    white-space: nowrap;
    margin: 0;
}
/* Disabled state — subtle, not aggressive. */
body.cbm-composite-page .composite_wrap .composite_add_to_cart_button:disabled,
body.cbm-composite-page .composite_wrap .composite_add_to_cart_button.cbm-disabled {
    opacity: 0.5;
    cursor: not-allowed;
    pointer-events: none;
}

/* Product Line — two rows:
     Row 1: "{title} · str. {size}"
     Row 2: "{bomQty} × {color} + {bomQty} × {color}"
   Predictable two-row layout instead of relying on line-clamp wrap. */
.cbm-atc-product-line {
    font-size: 0.9em;
    font-weight: 600;
    color: #333;
    line-height: 1.3;
    margin: 0 0 4px;
    overflow-wrap: anywhere;
    /* Reserve right column for the hero thumb */
    padding-right: 96px;
}
.cbm-atc-product-line .cbm-atc-size {
    font-weight: 400;
    color: #666;
}
.cbm-atc-product-line .cbm-atc-components {
    /* Force a new visual row even if a parent rule sets `span { display: inline }`.
       Without this, on mobile the size span ("· str. XS") and components span
       ("1 × Okker + ...") render as one inline run, producing "XS1 × Okker". */
    display: block !important;
    font-weight: 400;
    color: #666;
}
.cbm-atc-product-line .cbm-atc-components:empty {
    display: none !important;
}

/* Stock status — sits directly below .composite_price, matching the
   simple PDP .woocommerce-variation-availability spacing exactly:
     price.bottom → stockP.top = 0px
     stockP.bottom → sku.top  = 0px
     sku.bottom    → qty.top  = 8px
   Persistent element with stable position; value updates per validation state. */
body.cbm-composite-page .cbm-atc-stock-status {
    margin: 0;
    padding-right: 96px; /* reserve thumb column */
}
body.cbm-composite-page .cbm-atc-stock-status .stock {
    margin: 0;
    font-size: 12.8px;
    font-weight: 700;
    color: inherit;
}
/* Default/incomplete prompts: muted, matching simple PDP defaults. */
body.cbm-composite-page .cbm-atc-stock-status .stock.gc-stock-default-text {
    font-weight: 400;
    color: #999;
}
/* Ready / at-cap (positive state): Flatsome leaf-green, matching the
   simple PDP `.stock.in-stock` colour so the kit ATC reads consistently. */
body.cbm-composite-page .cbm-atc-stock-status .stock.cbm-stock-ready {
    color: rgb(98, 125, 71);
}
/* Warning state (OOS / insufficient): orange. */
body.cbm-composite-page .cbm-atc-stock-status .stock.cbm-stock-warning {
    color: #b15a15;
}

/* SKU line — mirrors the simple PDP `.gc-sku-inline` exactly. Butts up
   against the Lagerstatus row above (0 gap), 8px space below to qty/button. */
body.cbm-composite-page .cbm-atc-sku {
    font-size: 0.75em;
    color: #999;
    margin: 0 0 8px;
    min-height: 1.2em;
    padding-right: 96px; /* reserve thumb column */
}

/* Disabled "+" button — Flatsome's stepper doesn't visually distinguish
   the disabled state, so we add a faded look. */
body.cbm-composite-page .composite_button .ux-quantity__button--plus:disabled,
body.cbm-composite-page .composite_button .ux-quantity__button--plus.disabled,
body.cbm-composite-page .composite_button .plus:disabled,
body.cbm-composite-page .composite_button .plus.disabled {
    opacity: 0.4;
    cursor: not-allowed;
    pointer-events: none;
}

/* Hero thumb — anchored to bottom-right of .composite_wrap. Sized to the
   price→button "buy block" (~84px) rather than the simple-PDP 88px, so its top
   sits at/below the dashed price line instead of poking ~4px above it. */
.cbm-atc-hero-thumb {
    position: absolute;
    right: 0;
    bottom: 0;
    width: 80px;
    height: 80px;
    background: #f5f5f5;
    border: 1px solid #e0e0e0;
    box-sizing: border-box;
    overflow: hidden;
    display: flex;
    align-items: center;
    justify-content: center;
}
.cbm-atc-hero-thumb:empty {
    display: none;
}
.cbm-atc-hero-thumb img {
    max-width: 100%;
    max-height: 100%;
    width: auto;
    height: auto;
    object-fit: contain;
    display: block;
}

@media (max-width: 849px) {
    /* Pull the thumb 15px in from the wrap's right edge for visual breathing
       room (the wrap stretches to the viewport edge inside the full-bleed
       sticky bar). Bottom stays at 0 so the thumb's bottom edge aligns with
       the qty/ATC button row's bottom — the floating-above-the-line bug
       from a previous iteration. */
    .cbm-atc-hero-thumb {
        right: 15px;
        bottom: 0;
    }
    /* Match the increased thumb right-offset: button padding-right reserves
       88 (thumb) + 15 (mobile right-offset) + 8 (visual gap) = 111px so the
       ATC button doesn't run flush against the thumb. */
    body.cbm-composite-page .composite_wrap .composite_button {
        padding-right: 111px;
    }
}

/* Quick View: never sticky inside the modal (fall back to static). */
.product-lightbox body.cbm-composite-page .composite_data,
.product-lightbox body.cbm-composite-page .composite_wrap,
.product-lightbox .composite_data,
.product-lightbox .composite_wrap {
    position: static !important;
    box-shadow: none !important;
    margin: 0 !important;
    padding: 0 !important;
    background: transparent !important;
}

/* =========================================================================
   6. Tighten the info col on kit pages — once the sidebar is gone there's
   ~540px to play with on desktop. The component blocks should fill that
   width but not stretch awkwardly wide on a 1440px viewport.
   ========================================================================= */

@media (min-width: 850px) {
    body.cbm-composite-page .product-info.col {
        max-width: 600px;
    }
}
