/* Holo Frontier — Cart Quantity Picker
 *
 * Shared styling for the two-state add-to-cart flow (Picking is the
 * baseline view shown immediately on load, Added takes over once
 * something's actually in the cart, and stays there — there's no "Add
 * more" escape hatch back to Picking, the Added-state stepper edits the
 * cart line directly) on both the single product page (.ct-cart-actions,
 * reusing WooCommerce's native quantity stepper) and archive/category
 * cards (.ct-woo-card-actions, custom-built stepper — the loop template
 * has no quantity input by default).
 *
 * Colors are pulled from the surrounding page's own CSS custom properties
 * (--hf-navy/--hf-orange/etc, defined per-context by holo-frontier-
 * product-page.css on the single product page and holo-frontier-shop-
 * listing.css on archive pages) with hardcoded fallbacks so this still
 * looks right even if one of those stylesheets isn't loaded.
 */

.hf-cqp-enhanced {
    --hf-cqp-navy: var(--hf-navy, #1B2545);
    --hf-cqp-orange: var(--hf-orange, #E8622B);
    --hf-cqp-accent: var(--hf-text-accent, #185FA5);
    --hf-cqp-text-secondary: var(--hf-text-secondary, #6b6a63);
    --hf-cqp-text-muted: var(--hf-text-muted, #9a988f);
    --hf-cqp-border: var(--hf-border-strong, #d3d1c7);
    /* Same red already used site-wide for warning-toned UI — the "Live
       Break" corner badge (holo-frontier-shop-listing.css) and the
       pre-order "ended" state (holo-frontier-preorder-comingsoon.css use
       a near-identical #a3392e) — reused here for the error message. */
    --hf-cqp-danger: #c0392b;
    /* Added-to-cart confirmation only — distinct from the orange CTA/navy
       text used everywhere else, so the "it worked" moment reads clearly
       at a glance. Not used elsewhere in this stylesheet. */
    --hf-cqp-success: #1e8e3e;
    --hf-cqp-success-bg: rgba(30, 142, 62, 0.08);
    --hf-cqp-success-border: rgba(30, 142, 62, 0.3);
    font-family: inherit;
}

/* Data blobs are never meant to render. */
.hf-cqp-data {
    display: none !important;
}

/* WooCommerce core's own add-to-cart.js inserts a plain "View cart" link
   right after whichever button it saw the click/submit on (our hidden
   native button in both contexts) every time `added_to_cart` fires — see
   AddToCartHandler.prototype.updateButton in
   assets/js/frontend/add-to-cart.js. Our own .hf-cqp-added row already
   covers that, so the native duplicate is hidden here rather than left
   to show up as a second, redundant "View cart" box. */
.hf-cqp-enhanced .added_to_cart.wc-forward {
    display: none !important;
}

/* holo-frontier-shop-listing.js keeps its own "X in cart · view cart"
   paragraph live via the *same* cart-change events this plugin listens
   to (added_to_cart/wc_fragments_refreshed/etc) and re-inserts it on
   every one of them — removing the PHP render action alone
   (holo-frontier-cart-quantity-picker.php) only stops the very first,
   page-load copy; this catches every JS-re-inserted one afterwards, on
   any card this plugin has taken over. */
ul.products li.product .ct-woo-card-actions.hf-cqp-enhanced ~ .hf-listing-in-cart,
ul.products li.product:has(.ct-woo-card-actions.hf-cqp-enhanced) .hf-listing-in-cart {
    display: none !important;
}

@keyframes hf-cqp-spin {
    to { transform: rotate(360deg); }
}

/* display:block removes the SVG from inline text flow — as an inline
   replaced element it otherwise sits on its parent's text baseline, which
   leaves a few pixels of "descender" gap below it inside whatever wraps
   it. That's invisible where the SVG is itself a direct flex child (flex
   blockifies it anyway), but .hf-cqp-added-remove wraps its trash icon in
   an extra <span> first (so it and the visually-hidden text label can be
   flex siblings) — there, the SVG stayed in a normal inline context
   *inside that span* and rendered visibly off-center/skewed within the
   button despite the button's own flex centering. */
.hf-cqp-icon {
    display: block;
    flex: none;
}

.hf-cqp-spin {
    animation: hf-cqp-spin 0.7s linear infinite;
}

@media (prefers-reduced-motion: reduce) {
    .hf-cqp-spin {
        animation-duration: 1.6s;
    }
}

/* ------------------------------------------------------------------
 * Single product page (.ct-cart-actions)
 *
 * Keeps the existing element order (native .quantity, native button)
 * in the DOM untouched and only relies on flex `order` + show/hide per
 * state, so nothing needs to be relocated across Blocksy's own markup
 * boundaries — important for variable products, where Blocksy/WooCommerce
 * regenerate the whole .woocommerce-variation-add-to-cart subtree on
 * every variation change.
 * ------------------------------------------------------------------ */

.single-product .ct-cart-actions.hf-cqp-enhanced,
.single-product .woocommerce-variation-add-to-cart.hf-cqp-enhanced {
    display: flex;
    flex-direction: column;
    align-items: stretch;
    gap: 8px;
}

.single-product .hf-cqp-enhanced .quantity { order: 2; }
.single-product .hf-cqp-enhanced .hf-cqp-already { order: 1; }
.single-product .hf-cqp-enhanced .hf-cqp-preview { order: 3; }
.single-product .hf-cqp-enhanced .hf-cqp-stock-warning { order: 4; }
.single-product .hf-cqp-enhanced .hf-cqp-actions { order: 5; }
.single-product .hf-cqp-enhanced .single_add_to_cart_button { order: 6; }
.single-product .hf-cqp-enhanced .hf-cqp-added { order: 7; }

/* The native button is only ever triggered programmatically now (see
   confirm() in the JS, which briefly flips it to type="submit" to fire a
   real add-to-cart) — there's no state where the user sees it directly,
   since Picking (stepper + Confirm) is the baseline view shown on load. */
.single-product .hf-cqp-enhanced .single_add_to_cart_button {
    display: none !important;
}

/* Picking (stepper + preview + Confirm) is the default view on load —
   hidden only once actually Added, when the Added-state block takes over. */
.single-product .hf-cqp-enhanced[data-hf-cqp-state="added"] .quantity,
.single-product .hf-cqp-enhanced[data-hf-cqp-state="added"] .hf-cqp-already,
.single-product .hf-cqp-enhanced[data-hf-cqp-state="added"] .hf-cqp-preview,
.single-product .hf-cqp-enhanced[data-hf-cqp-state="added"] .hf-cqp-stock-warning,
.single-product .hf-cqp-enhanced[data-hf-cqp-state="added"] .hf-cqp-actions,
.single-product .hf-cqp-enhanced[data-hf-cqp-state="picking"] .hf-cqp-added {
    display: none !important;
}

/* ------------------------------------------------------------------
 * Shared inner pieces (both contexts) — Picking state
 * ------------------------------------------------------------------ */

.hf-cqp-preview {
    font-size: 12px;
    color: var(--hf-cqp-text-secondary);
    margin: 0;
}

/* Fixed one-line height, always reserved regardless of whether the text
   is actually populated (see render() in the JS, which clears the text
   rather than hiding the element — same treatment as .hf-cqp-stock-warning
   below) — on archive grids, letting this line's presence/absence change
   a card's height throws the "Confirm add to cart" buttons out of
   alignment with the neighbouring cards in the same row, since each
   card's height is otherwise driven purely by its own content. */
.hf-cqp-already {
    font-size: 12px;
    line-height: 15px;
    height: 15px;
    color: var(--hf-cqp-text-secondary);
    margin: 0;
    overflow: hidden;
}

/* Fixed one-line height, always reserved regardless of whether the text
   is actually populated (see updateStockWarning() in the JS, which clears
   the text rather than hiding the element) — on archive grids, letting
   this line's presence/absence change a card's height throws the
   "Confirm add to cart" buttons out of alignment with the neighbouring
   cards in the same row, since each card's height is otherwise driven
   purely by its own content. */
.hf-cqp-stock-warning {
    font-size: 12px;
    font-weight: 600;
    line-height: 15px;
    height: 15px;
    color: var(--hf-cqp-orange);
    margin: 0;
    overflow: hidden;
}

.hf-cqp-already .hf-cqp-qty,
.hf-cqp-preview .hf-cqp-total {
    font-weight: 600;
    color: var(--hf-cqp-navy);
}

.hf-cqp-actions {
    display: flex;
    align-items: center;
    gap: 12px;
}

.hf-cqp-confirm {
    flex: 1;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 6px;
    background: var(--hf-cqp-orange);
    color: #fff !important;
    border: none;
    /* Matches the native "Add to cart" button's own radius (see
       .single_add_to_cart_button in holo-frontier-product-page and
       .ct-woo-card-actions .button in holo-frontier-shop-listing) — both
       use 8px, not a full pill, despite "pill-shaped" being the general
       shorthand used for these buttons elsewhere. */
    border-radius: 8px;
    font-size: 13px;
    font-weight: 600;
    padding: 10px 16px;
    min-height: 40px;
    cursor: pointer;
    text-decoration: none;
    transition: filter 0.15s ease;
}

.hf-cqp-confirm:hover {
    filter: brightness(1.05);
}

.hf-cqp-confirm:disabled {
    opacity: 0.6;
    cursor: not-allowed;
}

.hf-cqp-confirm:focus-visible,
.hf-cqp-added-viewcart:focus-visible,
.hf-cqp-added-remove:focus-visible,
.hf-cqp-added-dec:focus-visible,
.hf-cqp-added-inc:focus-visible,
.hf-cqp-added-qty:focus-visible {
    outline: 2px solid var(--hf-cqp-accent);
    outline-offset: 2px;
}

/* Custom stepper (Picking state, archive cards only — single product
   reuses the native Blocksy stepper, styled separately by
   holo-frontier-product-page). */
.hf-cqp-stepper {
    display: flex;
    align-items: stretch;
    justify-content: center;
    border: 1px solid var(--hf-cqp-border);
    border-radius: 8px;
    overflow: hidden;
    height: 36px;
}

.hf-cqp-stepper button {
    flex: none;
    width: 34px;
    background: #fff;
    border: none;
    color: var(--hf-cqp-navy);
    font-size: 16px;
    line-height: 1;
    cursor: pointer;
}

.hf-cqp-stepper button:hover:not(:disabled) {
    background: var(--hf-cqp-navy);
    color: #fff;
}

.hf-cqp-stepper button:disabled {
    color: var(--hf-cqp-text-muted);
    cursor: not-allowed;
}

.hf-cqp-stepper input {
    flex: 1;
    min-width: 0;
    border: none;
    border-left: 1px solid var(--hf-cqp-border);
    border-right: 1px solid var(--hf-cqp-border);
    text-align: center;
    font-size: 13px;
    font-weight: 600;
    color: var(--hf-cqp-navy);
    -moz-appearance: textfield;
}

.hf-cqp-stepper input::-webkit-outer-spin-button,
.hf-cqp-stepper input::-webkit-inner-spin-button {
    -webkit-appearance: none;
    margin: 0;
}

/* ------------------------------------------------------------------
 * Added state (both contexts) — success notice, quantity/View Cart/
 * Remove action row, and "N item(s) in cart" summary line.
 * ------------------------------------------------------------------ */

.hf-cqp-added {
    display: flex;
    flex-direction: column;
    align-items: stretch;
    width: 100%;
    gap: 8px;
}

.hf-cqp-added-notice {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 6px;
    width: 100%;
    margin: 0;
    min-height: 36px;
    padding: 8px 12px;
    background: var(--hf-cqp-success-bg);
    border: 1px solid var(--hf-cqp-success-border);
    border-radius: 8px;
    color: var(--hf-cqp-success);
    font-size: 13px;
    font-weight: 600;
    box-sizing: border-box;
}

/* Row has exactly two top-level flex children: .hf-cqp-added-primary
   (stepper + View Cart, grouped) and .hf-cqp-added-remove. Only Remove
   ever drops to its own line when space runs out — stepper and View
   Cart wrap as a single unit, never split from each other. Splitting
   them into three independent siblings (the original approach) let the
   browser wrap in a way that isolated the stepper alone on one line
   with View Cart and Remove paired below it, which read as broken. */
.hf-cqp-added-row {
    display: flex;
    flex-wrap: wrap;
    align-items: stretch;
    gap: 8px;
    width: 100%;
}

.hf-cqp-added-row--busy {
    cursor: progress;
}

/* No flex-wrap here deliberately — stepper and View Cart stay on one
   line together at every width down to the forced mobile stack (see the
   media queries below, which switch this to flex-direction:column
   instead). View Cart alone absorbs any squeeze via its own
   flex-shrink/min-width:0. Wrapping internally here (tried, reverted)
   let this group get sized down by the outer row's line-fitting pass
   before its children's own wrap was evaluated, splitting stepper from
   View Cart well before Remove actually needed to give way — the
   opposite of the intended "Remove moves below first" order. Basis is
   sized to the group's real minimum comfortable content width (stepper
   ~114px + gap + View Cart's own ~106px minimum) so the *outer* row
   reserves the right amount of space for the pair as a whole. */
.hf-cqp-added-primary {
    flex: 1 1 228px;
    min-width: 0;
    display: flex;
    align-items: stretch;
    gap: 8px;
}

/* Quantity stepper — same visual language as the Picking-state stepper
   (.hf-cqp-stepper) but a separate class since it's a distinct element
   editing the live cart line rather than a pre-add pick. */
.hf-cqp-added-stepper {
    flex: 0 0 auto;
    display: flex;
    align-items: stretch;
    border: 1px solid var(--hf-cqp-border);
    border-radius: 8px;
    overflow: hidden;
    height: 40px;
}

.hf-cqp-added-dec,
.hf-cqp-added-inc {
    flex: none;
    width: 36px;
    min-width: 36px;
    background: #fff;
    border: none;
    color: var(--hf-cqp-navy);
    font-size: 16px;
    line-height: 1;
    cursor: pointer;
}

.hf-cqp-added-dec:hover:not(:disabled),
.hf-cqp-added-inc:hover:not(:disabled) {
    background: var(--hf-cqp-navy);
    color: #fff;
}

/* A muted text color alone read as too subtle at this icon size (still
   white background, same as enabled) — a light grey fill makes "can't go
   further" (e.g. + once the cart already holds all available stock)
   unmistakable at a glance, matching the same treatment the qty input
   itself already gets when disabled (.hf-cqp-added-qty:disabled below). */
.hf-cqp-added-dec:disabled,
.hf-cqp-added-inc:disabled {
    background: var(--hf-surface-1, #f5f5f2);
    color: var(--hf-cqp-text-muted);
    cursor: not-allowed;
}

/* Extra ancestor-scoped specificity (.hf-cqp-added-stepper .hf-cqp-added-qty,
   not just .hf-cqp-added-qty alone) is deliberate, not decorative — the
   theme's own generic `input[type="number"]` rule carries a type+attribute
   selector, which otherwise outranks a lone class selector regardless of
   stylesheet load order and was overriding width/padding here (a real bug
   caught in testing: the qty input was rendering ~86px wide with 15px
   inherited side padding instead of the 40px/no-padding declared below,
   bloating the whole stepper and starving View Cart of room next to it). */
.hf-cqp-added-stepper .hf-cqp-added-qty {
    width: 40px;
    min-width: 0;
    padding: 0;
    border: none;
    border-left: 1px solid var(--hf-cqp-border);
    border-right: 1px solid var(--hf-cqp-border);
    text-align: center;
    font-size: 13px;
    font-weight: 600;
    color: var(--hf-cqp-navy);
    -moz-appearance: textfield;
}

.hf-cqp-added-qty:disabled {
    color: var(--hf-cqp-text-muted);
    background: var(--hf-surface-1, #f5f5f2);
}

.hf-cqp-added-qty::-webkit-outer-spin-button,
.hf-cqp-added-qty::-webkit-inner-spin-button {
    -webkit-appearance: none;
    margin: 0;
}

/* Primary CTA — grows to fill any extra space .hf-cqp-added-primary is
   given beyond the stepper's width, shrinks (min-width:0) if that group
   gets squeezed instead of wrapping. Basis matches its own real minimum
   comfortable content width (icon + "View Cart" + padding) — see the
   comment on .hf-cqp-added-primary for why that matters to the wrap
   calculation one level up. */
.hf-cqp-added-viewcart {
    flex: 1 1 106px;
    min-width: 0;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 6px;
    min-height: 40px;
    background: var(--hf-cqp-orange);
    color: #fff !important;
    border: none;
    border-radius: 8px;
    font-size: 13px;
    font-weight: 600;
    padding: 0 14px;
    text-decoration: none;
    box-sizing: border-box;
    transition: filter 0.15s ease;
}

.hf-cqp-added-viewcart:hover {
    filter: brightness(1.05);
}

/* Secondary action — icon-only by default (both contexts): a bordered
   square button rather than solid, so it doesn't compete with the
   primary orange CTA, and compact so .hf-cqp-added-primary + Remove fit
   on one line at typical card/summary widths, matching the reference
   design. The accessible name still carries "Remove" via aria-label on
   the button; the text label itself only becomes visible in the
   fully-stacked mobile layout (see the media queries below), where it's
   the row's own text-style secondary action instead of a boxed icon. */
.hf-cqp-added-remove {
    flex: 0 0 auto;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 6px;
    width: 40px;
    min-height: 40px;
    padding: 0;
    background: #fff;
    border: 1px solid var(--hf-cqp-border);
    border-radius: 8px;
    color: var(--hf-cqp-text-secondary);
    font-size: 13px;
    font-weight: 600;
    cursor: pointer;
    white-space: nowrap;
    transition: background 0.15s ease, color 0.15s ease, border-color 0.15s ease;
}

.hf-cqp-added-remove-label {
    position: absolute;
    width: 1px;
    height: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    white-space: nowrap;
    border: 0;
}

.hf-cqp-added-remove:hover:not(:disabled) {
    background: var(--hf-cqp-danger);
    border-color: var(--hf-cqp-danger);
    color: #fff;
}

.hf-cqp-added-remove:disabled {
    opacity: 0.6;
    cursor: not-allowed;
}

.hf-cqp-added-error {
    margin: 0;
    font-size: 12px;
    font-weight: 600;
    color: var(--hf-cqp-danger);
    text-align: center;
}

.hf-cqp-added-error[hidden] {
    display: none !important;
}

/* ------------------------------------------------------------------
 * Archive / category card (.ct-woo-card-actions)
 *
 * Already display:flex; flex-direction:column (see holo-frontier-shop-
 * listing.css) — this plugin's injected pieces just join that flow as
 * additional flex children, order-controlled the same way as the single
 * product page above. Stepper and "Add to cart" each get their own
 * full-width row, stacked — not side by side (tried, reverted: too tight
 * next to a compact stepper on any but the widest cards).
 * ------------------------------------------------------------------ */

ul.products li.product .ct-woo-card-actions.hf-cqp-enhanced .hf-cqp-already { order: 1; width: 100%; text-align: center; }
ul.products li.product .ct-woo-card-actions.hf-cqp-enhanced .hf-cqp-stepper { order: 2; width: 100%; }
ul.products li.product .ct-woo-card-actions.hf-cqp-enhanced .hf-cqp-preview { order: 3; width: 100%; text-align: center; }
ul.products li.product .ct-woo-card-actions.hf-cqp-enhanced .hf-cqp-stock-warning { order: 4; width: 100%; text-align: center; }
ul.products li.product .ct-woo-card-actions.hf-cqp-enhanced .hf-cqp-actions { order: 5; width: 100%; }
ul.products li.product .ct-woo-card-actions.hf-cqp-enhanced .add_to_cart_button { order: 6; }
ul.products li.product .ct-woo-card-actions.hf-cqp-enhanced .hf-cqp-added { order: 7; }

/* The native ajax_add_to_cart link is only ever triggered programmatically
   now (see confirm() in the JS) — there's no state where the user sees it
   directly, since Picking (stepper + Confirm) is the baseline view shown
   on load. */
ul.products li.product .ct-woo-card-actions.hf-cqp-enhanced .add_to_cart_button {
    display: none !important;
}

ul.products li.product .ct-woo-card-actions.hf-cqp-enhanced[data-hf-cqp-state="added"] .hf-cqp-already,
ul.products li.product .ct-woo-card-actions.hf-cqp-enhanced[data-hf-cqp-state="added"] .hf-cqp-stepper,
ul.products li.product .ct-woo-card-actions.hf-cqp-enhanced[data-hf-cqp-state="added"] .hf-cqp-preview,
ul.products li.product .ct-woo-card-actions.hf-cqp-enhanced[data-hf-cqp-state="added"] .hf-cqp-stock-warning,
ul.products li.product .ct-woo-card-actions.hf-cqp-enhanced[data-hf-cqp-state="added"] .hf-cqp-actions,
ul.products li.product .ct-woo-card-actions.hf-cqp-enhanced[data-hf-cqp-state="picking"] .hf-cqp-added {
    display: none !important;
}

ul.products li.product .ct-woo-card-actions.hf-cqp-enhanced .hf-cqp-confirm {
    width: 100%;
}

/* ------------------------------------------------------------------
 * Responsive behaviour for the Added-state action row.
 *
 * .hf-cqp-added-primary (stepper + View Cart) and Remove already wrap
 * as a unit at any width via flex-wrap (see .hf-cqp-added-row/-primary
 * above) — Remove drops to its own line first, then, if the card is
 * narrower still, the stepper and View Cart wrap against each other
 * inside .hf-cqp-added-primary too. These breakpoints (matching the
 * grid's own column breakpoint in holo-frontier-shop-listing.css:
 * 600px -> 2 columns) additionally force a full stack with a
 * comfortable ~44px touch target and un-hide Remove's text label once
 * cards get narrow enough that even the auto-wrap would look cramped,
 * rather than relying on wrapping alone to decide when that happens.
 * ------------------------------------------------------------------ */
@media (max-width: 600px) {
    ul.products.columns-4 li.product .hf-cqp-added-row,
    ul.products.columns-4 li.product .hf-cqp-added-primary {
        flex-direction: column;
        align-items: stretch;
    }
    /* Same flex-grow:0 fix as .hf-cqp-added-viewcart below, one level up:
       .hf-cqp-added-primary's base rule is flex:1 1 228px, meant to grow
       *horizontally* to fill .hf-cqp-added-row when they're laid out side
       by side. Once the row above flips to a column, that flex-grow
       instead pulled from leftover *vertical* space in the row (e.g. next
       to a taller "Remove" sibling), inflating .hf-cqp-added-primary well
       past what its own children (stepper + View Cart) needed and leaving
       a visible empty gap below them, above Remove — the actual gap
       reported after the first flex-grow fix, which only caught
       .hf-cqp-added-viewcart's own grow and missed this one, its parent,
       having the identical problem. */
    ul.products.columns-4 li.product .hf-cqp-added-primary {
        flex: 0 0 auto;
    }
    ul.products.columns-4 li.product .hf-cqp-added-stepper {
        width: 100%;
        height: 44px;
    }
    ul.products.columns-4 li.product .hf-cqp-added-dec,
    ul.products.columns-4 li.product .hf-cqp-added-inc {
        width: 44px;
        min-width: 44px;
    }
    /* The qty input's base rule is a fixed width:40px (right for the
       compact, auto-width desktop stepper) — once the stepper above is
       stretched to width:100% here, that fixed width left dec/input/inc
       clustered on the left with the rest of the full-width stepper empty
       on the right. flex:1 grows it to fill exactly the leftover space
       between the two 44px end buttons, matching how the original
       Picking-state stepper's own input (.hf-cqp-stepper input) already
       does this. */
    ul.products.columns-4 li.product .hf-cqp-added-stepper .hf-cqp-added-qty {
        flex: 1;
        width: auto;
    }
    ul.products.columns-4 li.product .hf-cqp-added-viewcart {
        /* flex-grow:0 override — the base rule's flex:1 1 106px is
           meant to grow *horizontally* to fill leftover width next to
           the stepper. Once .hf-cqp-added-primary flips to a column
           (above), that same flex-grow instead pulls from any leftover
           *vertical* space in the column — and since li.product's own
           column-flex chain can hand down a lot of that when a card
           sits in a grid row next to a taller neighbour, this button
           was ballooning to fill it rather than sitting at its own
           44px height. width:100% here already gets it full-width;
           flex-basis:auto+grow:0 is what keeps its height intentional. */
        flex: 0 0 auto;
        width: 100%;
        min-height: 44px;
    }
    /* Secondary, text-style action rather than a boxed button once
       stacked full-width — matches the mobile-specific treatment
       requested for Remove. */
    ul.products.columns-4 li.product .hf-cqp-added-remove {
        width: 100%;
        min-height: 44px;
        background: none;
        border: none;
        color: var(--hf-cqp-danger);
        text-decoration: underline;
    }
    ul.products.columns-4 li.product .hf-cqp-added-remove:hover:not(:disabled) {
        background: none;
        color: var(--hf-cqp-danger);
        filter: brightness(1.15);
    }
    ul.products.columns-4 li.product .hf-cqp-added-remove-label {
        /* Un-hide at this breakpoint — full-width text link needs a
           visible label, not just an icon. */
        position: static;
        width: auto;
        height: auto;
        margin: 0;
        overflow: visible;
        clip: auto;
    }
}

/* ------------------------------------------------------------------
 * Cart-count badge on the product image (archive cards only).
 *
 * `figure` (holo-frontier-shop-listing.css) is the loop template's own
 * image wrapper — position:relative, overflow:hidden, aspect-ratio 1/1 —
 * and is already the positioning context WooCommerce/Blocksy's native
 * "Sale" badge uses (top:15px/left:15px — see blocksy/.../badges.scss).
 * Anchored bottom-right here so it never collides with that badge or
 * with the tag corner badge ("Live Break"/"Sealed"/etc, top-right of the
 * *card*, above the image entirely — see .hf-listing-card-badge in
 * holo-frontier-shop-listing.css).
 *
 * Uses the site-wide --hf-orange variable directly (matching
 * .hf-cqp-frontier-points below) rather than the --hf-cqp-orange alias
 * used everywhere else in this file — this badge lives inside `figure`,
 * a *sibling* of .ct-woo-card-actions.hf-cqp-enhanced (which is what
 * actually defines that alias), not a descendant of it, so the alias
 * never resolves here. Left as var(--hf-cqp-orange) originally, which
 * silently fell back to a fully transparent background (an unresolved
 * custom property makes the whole declaration invalid, not "use the
 * fallback further up the chain") — rendering as a blank white circle
 * with just its box-shadow visible, no visible count, once a card
 * actually had something in the cart to badge.
 * ------------------------------------------------------------------ */
.hf-cqp-cart-badge {
    position: absolute;
    bottom: 8px;
    right: 8px;
    z-index: 2;
    display: flex;
    align-items: center;
    justify-content: center;
    min-width: 20px;
    height: 20px;
    padding: 0 5px;
    border-radius: 999px;
    background: var(--hf-orange, #E8622B);
    color: #fff;
    font-family: inherit;
    font-size: 11px;
    font-weight: 700;
    line-height: 1;
    box-shadow: 0 2px 4px rgba(0, 0, 0, 0.25);
}

.hf-cqp-cart-badge[hidden] {
    display: none;
}

/* ------------------------------------------------------------------
 * "Earn N Frontier Points" line (both contexts) — rendered by PHP as a
 * sibling of the price, *outside* .ct-cart-actions/.ct-woo-card-actions
 * (see hf_cqp_render_frontier_points in the PHP), so it uses the site's
 * own --hf-* variables directly with the same fallbacks as
 * .hf-cqp-enhanced's own --hf-cqp-* aliases, rather than those aliases
 * themselves — being a sibling, not a descendant, of .hf-cqp-enhanced,
 * it wouldn't inherit them.
 * ------------------------------------------------------------------ */
.hf-cqp-frontier-points {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 4px;
    font-family: inherit;
    font-size: 12px;
    color: var(--hf-text-secondary, #6b6a63);
    margin: 4px 0 0;
}

.hf-cqp-frontier-points strong {
    color: var(--hf-navy, #1B2545);
    font-weight: 600;
}

.hf-cqp-frontier-points-icon {
    flex: none;
    font-size: 12px;
    line-height: 1;
}

/* Sits between the price (order:4) and .ct-woo-card-actions (order:5) in
   shop-listing.css's flex-column card — sharing order:5 with the latter
   and relying on source order to land first within that shared bucket
   (rendered via an earlier hook, woocommerce_after_shop_loop_item_title,
   vs. the add-to-cart area's woocommerce_after_shop_loop_item) avoids
   needing a fractional order value between two whole-number ones. */
ul.products li.product .hf-cqp-frontier-points {
    order: 5;
    width: 100%;
}

.single-product .hf-cqp-frontier-points {
    justify-content: flex-start;
}

/* ------------------------------------------------------------------
 * Single product page — stock-limit visual for Blocksy's native
 * .ct-increase stepper control (a <span>, not a real <button>, so it has
 * no native :disabled state of its own — see holo-frontier-product-page
 * for its normal styling). The functional cap itself comes from keeping
 * the native input's own `max` attribute in sync (syncNativeStepper() in
 * the JS); this class is the matching visual/interaction cue.
 * ------------------------------------------------------------------ */
.single-product .ct-increase.hf-cqp-native-limit {
    opacity: 0.4;
    pointer-events: none;
    cursor: not-allowed;
}

/* ------------------------------------------------------------------
 * Single product page — the summary column is much wider than an
 * archive card at most sizes (full viewport width once it stacks below
 * the gallery, not a narrow grid column), so .hf-cqp-added-primary +
 * Remove's own auto-wrap (see above) comfortably keeps everything on
 * one line through tablet widths without any help here. This only
 * forces the full mobile stack — and un-hides Remove's text label, per
 * "secondary text-style action" on mobile — once it's genuinely a phone
 * width, narrower than product-page.css needs to even consider.
 * ------------------------------------------------------------------ */
@media (max-width: 600px) {
    .single-product .hf-cqp-enhanced .hf-cqp-added-row,
    .single-product .hf-cqp-enhanced .hf-cqp-added-primary {
        flex-direction: column;
        align-items: stretch;
    }
    /* Same flex-grow:0 fix as .hf-cqp-added-viewcart below, one level up
       — see the matching comment on the archive breakpoint above for why
       .hf-cqp-added-primary itself needs this too. */
    .single-product .hf-cqp-enhanced .hf-cqp-added-primary {
        flex: 0 0 auto;
    }
    .single-product .hf-cqp-enhanced .hf-cqp-added-stepper {
        width: 100%;
        height: 44px;
    }
    .single-product .hf-cqp-enhanced .hf-cqp-added-dec,
    .single-product .hf-cqp-enhanced .hf-cqp-added-inc {
        width: 44px;
        min-width: 44px;
    }
    /* Same fix as the archive breakpoint above — the qty input's fixed
       width:40px base rule left it clustered with dec/inc on the left
       once the stepper stretched to width:100%, with empty space on the
       right; flex:1 fills that space. */
    .single-product .hf-cqp-enhanced .hf-cqp-added-stepper .hf-cqp-added-qty {
        flex: 1;
        width: auto;
    }
    .single-product .hf-cqp-enhanced .hf-cqp-added-viewcart {
        /* Same flex-grow:0 fix as the archive breakpoint above — see its
           comment. */
        flex: 0 0 auto;
        width: 100%;
        min-height: 44px;
    }
    .single-product .hf-cqp-enhanced .hf-cqp-added-remove {
        width: 100%;
        min-height: 44px;
        background: none;
        border: none;
        color: var(--hf-cqp-danger);
        text-decoration: underline;
    }
    .single-product .hf-cqp-enhanced .hf-cqp-added-remove:hover:not(:disabled) {
        background: none;
        color: var(--hf-cqp-danger);
        filter: brightness(1.15);
    }
    .single-product .hf-cqp-enhanced .hf-cqp-added-remove-label {
        position: static;
        width: auto;
        height: auto;
        margin: 0;
        overflow: visible;
        clip: auto;
    }
}
