/*
 * ShopOS Theme — shared chrome + primitive component classes.
 *
 * Scoped under .shopos-theme so nothing leaks if this file is accidentally
 * loaded elsewhere. Business components (cards, swatches, restock forms) live
 * in ShopOS Core modules. This file provides the primitives that those
 * modules (and Elementor widgets) can compose.
 */

/* -------------------------------------------------------------------------
 * 0. Defensive horizontal-overflow guard
 *
 * Any single rogue child wider than 100vw (a flex/grid container with
 * `min-width: auto`, an unbroken long word, an absolutely-positioned
 * element with negative inset, an Elementor section with `width: 100vw`
 * inside a padded parent) makes the entire page horizontally scrollable.
 * The QA reported the My Account mobile nav doing exactly that: the
 * pill row's flex-nowrap min-content was wider than the phone, the grid
 * track grew to fit, and the whole page started scrolling sideways.
 *
 * `overflow-x: clip` blocks page-level horizontal scroll without creating
 * a scroll container — so `position: sticky` on descendants still works
 * (which `overflow-x: hidden` would silently break). Legitimately-
 * scrollable rails (product slider, My Account mobile nav, etc.) own
 * their own inner scroll, which is unaffected. This is a safety net,
 * not a substitute for fixing the underlying cause — but without it,
 * one subtle sizing bug rotates straight into a visible page glitch.
 * ------------------------------------------------------------------------- */
html,
body {
    overflow-x: clip;
}

/* -------------------------------------------------------------------------
 * 1. Base typography + body chrome
 * ------------------------------------------------------------------------- */

.shopos-theme {
    font-family: var(--shopos-ui-font-body);
    font-size: var(--shopos-ui-text-md);
    line-height: var(--shopos-ui-leading-base);
    color: var(--shopos-ui-color-ink);
    background-color: var(--shopos-ui-color-page);
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
    text-rendering: optimizeLegibility;
}

.shopos-theme h1,
.shopos-theme h2,
.shopos-theme h3,
.shopos-theme h4,
.shopos-theme h5,
.shopos-theme h6 {
    font-family: var(--shopos-ui-font-display);
    line-height: var(--shopos-ui-leading-tight);
    font-weight: var(--shopos-ui-weight-semi);
    margin: 0 0 var(--shopos-ui-space-md);
    color: var(--shopos-ui-color-ink);
}

/* Lighter-As-Larger (§3): weights run against size. h6 is the eyebrow — label
   voice, sentence case, both scripts (No-Uppercase). */
.shopos-theme h1 { font-size: var(--shopos-ui-text-hero); font-weight: var(--shopos-ui-weight-regular); letter-spacing: var(--shopos-ui-tracking-tight); }
.shopos-theme h2 { font-size: var(--shopos-ui-text-xxl); font-weight: var(--shopos-ui-weight-medium); }
.shopos-theme h3 { font-size: var(--shopos-ui-text-xl); }
.shopos-theme h4 { font-size: var(--shopos-ui-text-lg); font-weight: var(--shopos-ui-weight-medium); line-height: var(--shopos-ui-leading-snug); }
.shopos-theme h5 { font-size: var(--shopos-ui-text-md); font-weight: var(--shopos-ui-weight-bold); }
.shopos-theme h6 { font-size: var(--shopos-ui-text-xs); font-weight: var(--shopos-ui-weight-semi); }

.shopos-theme p {
    margin: 0 0 var(--shopos-ui-space-md);
}

.shopos-theme small,
.shopos-theme .shopos-ui-text-sm { font-size: var(--shopos-ui-text-sm); }
.shopos-theme .shopos-ui-text-xs { font-size: var(--shopos-ui-text-xs); }
.shopos-theme .shopos-ui-text-muted { color: var(--shopos-ui-color-ink-muted); }

/* Prices, counts, quantities align on tabular figures (§6.4). WooCommerce
   wraps amounts in .woocommerce-Price-amount.amount; .price covers the wrapper. */
.shopos-theme .price,
.shopos-theme .amount,
.shopos-theme .woocommerce-Price-amount {
    font-variant-numeric: tabular-nums;
}

/* §6.4 price colors on every product loop. WooCommerce's loop palette
   (`.woocommerce ul.products li.product .price`, green #77a464, (0,4,2)) must
   lose on every archive — PLP flag on or off, Elementor grid or classic.
   `body.shopos-theme` mirrors the generic's ancestry one element deeper and
   the doubled `.price` lifts it clear: (0,7,3) with the :not() guards
   (repeated and negated classes all count), comfortably past (0,4,2), no
   !important. shopos-plp.css states the same values, so flag-on is a tie in
   agreement, not a fight.

   The :not(.cs-track):not(.cs-grid) guards are the same exclusion
   inc/woocommerce.php's mobile-columns rule carries: ProductSlider/
   CategorySlider tracks are ALSO `ul.products`, but their prices are skinned
   by the widget's own --cs-ink/--cs-accent variables, which the owner can
   retune per instance — a blanket theme rule here would out-gun that control
   and turn it dead. */
body.shopos-theme ul.products:not(.cs-track):not(.cs-grid) li.product .price.price {
    color: var(--shopos-ui-color-ink);
}

body.shopos-theme ul.products:not(.cs-track):not(.cs-grid) li.product .price.price del {
    color: var(--shopos-ui-color-ink-muted);
    opacity: 1;
}

body.shopos-theme ul.products:not(.cs-track):not(.cs-grid) li.product .price.price ins {
    color: var(--shopos-ui-color-accent);
    background: none;
    text-decoration: none;
}

.shopos-theme code,
.shopos-theme pre,
.shopos-theme kbd {
    font-family: var(--shopos-ui-font-mono);
    font-size: 0.95em;
}

/* -------------------------------------------------------------------------
 * 2. Links + focus
 * ------------------------------------------------------------------------- */

.shopos-theme a {
    color: inherit;
    text-decoration-thickness: 1px;
    text-underline-offset: 3px;
    transition: color var(--shopos-ui-motion-fast) var(--shopos-ui-ease);
}

/* No global hover-opacity. The previous `a:hover { opacity: 0.75 }`
   rule (and even a `:has()`-based override that exempted image
   anchors) read as a grey wash over product cards / category cards
   / gallery thumbs / slider cards. Components that genuinely want a
   text-link hover effect now opt in via `.shopos-ui-link--dim` or their own
   class — keeps the default crisp for image content. */
.shopos-theme a.shopos-ui-link--dim {
    transition: opacity var(--shopos-ui-motion-fast) var(--shopos-ui-ease),
                color var(--shopos-ui-motion-fast) var(--shopos-ui-ease);
}
.shopos-theme a.shopos-ui-link--dim:hover {
    opacity: 0.75;
}

.shopos-theme :where(a, button, summary, input, select, textarea, [tabindex]):focus-visible {
    outline: var(--shopos-ui-focus-outline);
    outline-offset: 2px;
}

/* -------------------------------------------------------------------------
 * 3. Layout helpers
 * ------------------------------------------------------------------------- */

.shopos-theme .shopos-ui-container,
.shopos-theme .shopos-ui-container--wide {
    margin-inline: auto;
    padding-inline: var(--shopos-ui-container-pad);
}
.shopos-theme .shopos-ui-container { max-width: var(--shopos-ui-container-max); }
.shopos-theme .shopos-ui-container--wide { max-width: var(--shopos-ui-container-wide); }  /* hero, PLP grid, editorial bands */

/* --- Composition patterns (§12) ------------------------------------------
 * The statement display (≤1 per page), hero, and section header. Latin
 * tracking on the display is zeroed under :lang(he) / .shopos-rtl. */

.shopos-theme .shopos-ui-display,
.shopos-theme h1.is-display {
    font-size: var(--shopos-ui-text-display);
    font-weight: var(--shopos-ui-weight-light);
    line-height: var(--shopos-ui-leading-flat);
    letter-spacing: var(--shopos-ui-tracking-tight);
    margin: 0 0 var(--shopos-ui-space-md);
}

/* Split hero (default): text column + full-height image on the wide grid. */
.shopos-theme .shopos-ui-hero {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: var(--shopos-ui-space-xl);
    align-items: center;
    padding-block: var(--shopos-ui-section-gap);
}
@media (max-width: 640px) {
    .shopos-theme .shopos-ui-hero { grid-template-columns: 1fr; }
}
.shopos-theme .shopos-ui-hero__copy {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: var(--shopos-ui-space-md);
}
.shopos-theme .shopos-ui-hero__lead {
    margin: 0;
    font-size: var(--shopos-ui-text-lg);
    font-weight: var(--shopos-ui-weight-light);
    line-height: var(--shopos-ui-leading-snug);
    color: var(--shopos-ui-color-ink-soft);
    max-inline-size: var(--shopos-ui-measure);
}
.shopos-theme .shopos-ui-hero__media {
    margin: 0;
}
.shopos-theme .shopos-ui-hero__media img {
    display: block;
    inline-size: 100%;
    block-size: 100%;
    object-fit: cover;
    aspect-ratio: 4 / 5;
    background: var(--shopos-ui-color-paper-dim);
}

/* Full-bleed hero: 16:9 image, ink scrim, Display in paper, one CTA. */
.shopos-theme .shopos-ui-hero--full {
    position: relative;
    display: block;
    padding: 0;
    aspect-ratio: 16 / 9;
    overflow: hidden;
}
.shopos-theme .shopos-ui-hero--full .shopos-ui-hero__media,
.shopos-theme .shopos-ui-hero--full .shopos-ui-hero__media img {
    position: absolute;
    inset: 0;
    inline-size: 100%;
    block-size: 100%;
    aspect-ratio: auto;
}
.shopos-theme .shopos-ui-hero--full .shopos-ui-hero__media::after {
    content: "";
    position: absolute;
    inset: 0;
    background: linear-gradient(transparent, var(--shopos-ui-overlay-scrim));
}
.shopos-theme .shopos-ui-hero--full .shopos-ui-hero__copy {
    position: absolute;
    z-index: 1;
    inset-block-end: var(--shopos-ui-section-gap);
    inset-inline-start: var(--shopos-ui-container-pad);
    inset-inline-end: var(--shopos-ui-container-pad);
    color: var(--shopos-ui-color-paper);
}
.shopos-theme .shopos-ui-hero--full .shopos-ui-display {
    color: var(--shopos-ui-color-paper);
}

/* Section header: Headline + optional "View all" link on the same baseline. */
.shopos-theme .shopos-ui-section-head {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: var(--shopos-ui-space-md);
    margin-block-end: var(--shopos-ui-space-lg);
}
.shopos-theme .shopos-ui-section-head > * {
    margin: 0;
}

/* An .is-inverted section paints ink and re-references the remapped ink ramp
   as its own colour/background (§7.3). The token remap alone isn't enough:
   inheritance carries the *computed* colour from <body>, so the scope must
   read the tokens here for components inside it to flip for free. */
.shopos-theme .is-inverted {
    background-color: var(--shopos-ui-color-paper);
    color: var(--shopos-ui-color-ink);
}

/* Editorial band (§12.5): full-width breath between product sections — the
   accent-soft tint OR .is-inverted slate (One-Ink-Moment). A Display /
   text-xxl statement + ≤1 CTA. */
.shopos-theme .shopos-ui-editorial-band {
    padding-block: var(--shopos-ui-section-gap);
    padding-inline: var(--shopos-ui-container-pad);
    background: var(--shopos-ui-color-accent-soft);
    color: var(--shopos-ui-color-ink);
}
.shopos-theme .shopos-ui-editorial-band.is-inverted {
    background: var(--shopos-ui-color-paper);   /* → ink via the remap */
}
.shopos-theme .shopos-ui-editorial-band__inner {
    max-width: var(--shopos-ui-container-max);
    margin-inline: auto;
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: var(--shopos-ui-space-lg);
}

.shopos-theme .shopos-ui-stack > * + * {
    margin-top: var(--shopos-ui-space-md);
}
.shopos-theme .shopos-ui-stack-lg > * + * {
    margin-top: var(--shopos-ui-space-lg);
}
.shopos-theme .shopos-ui-stack-xl > * + * {
    margin-top: var(--shopos-ui-space-xl);
}

.shopos-theme .shopos-ui-cluster {
    display: flex;
    flex-wrap: wrap;
    gap: var(--shopos-ui-space-sm);
    align-items: center;
}

/* WooCommerce / Elementor grid gutters share the card gap token. The bare
   `.shopos-theme ul.products` form is required: on classic (non-Elementor)
   archives `woocommerce` is a BODY class — the same element as
   `.shopos-theme` — so the descendant form on the last line never matches
   there and the grid rendered gapless ("products not spaced at all").
   Inert on WC's float fallback (gap needs grid/flex), so it is a pure
   safety net. The :not(.cs-*) guards keep it off the slider/grid widget
   tracks, whose gap is the widget's own owner-settable --cs-gap. */
.shopos-theme ul.products:not(.cs-track):not(.cs-grid),
.shopos-theme .elementor-products,
.shopos-theme .woocommerce ul.products {
    gap: var(--shopos-ui-card-gap);
}

/* Elementor's `.elementor-grid` archive grid declares
   `grid-template-columns: repeat(N, 1fr)`, and `1fr` is `minmax(auto, 1fr)`
   — the `auto` floor is each track's min-content. So one grid item whose
   min-content is wide (e.g. an un-shrinkable product image left behind by a
   third-party plugin that re-renders the loop) inflates its track and
   squeezes the rest of the row, blowing cards out past the page edge.
   Pinning the floor to 0 keeps the columns even regardless of item content.
   Column count still comes from Elementor's `--e-grid-columns` (which
   Elementor itself overrides per breakpoint), so responsiveness is intact;
   the `3` is only a fallback if the variable is somehow absent. */
.shopos-theme .woocommerce ul.products.elementor-grid {
    grid-template-columns: repeat(var(--e-grid-columns, 3), minmax(0, 1fr));
}

/* Hide the "View cart" link WooCommerce auto-injects next to the add-to-cart
   button after a successful AJAX add. The cart is reachable from the header
   utilities — the inline link clutters the loop card and confuses the eye. */
.shopos-theme .woocommerce a.added_to_cart,
.shopos-theme a.added_to_cart.wc-forward {
    display: none !important;
}

/* -------------------------------------------------------------------------
 * 4. Button primitive (.shopos-ui-btn)
 * ------------------------------------------------------------------------- */

.shopos-theme .shopos-ui-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: var(--shopos-ui-space-sm);
    min-height: var(--shopos-ui-button-height);
    padding: 0 var(--shopos-ui-button-padding-x);
    border-radius: var(--shopos-ui-button-radius);
    background: var(--shopos-ui-color-accent);
    color: var(--shopos-ui-color-accent-text);
    border: 1px solid var(--shopos-ui-color-accent);
    font-family: inherit;
    font-size: var(--shopos-ui-text-sm);
    font-weight: var(--shopos-ui-button-font-weight);
    letter-spacing: var(--shopos-ui-button-tracking);
    text-decoration: none;
    cursor: pointer;
    transition:
        background var(--shopos-ui-motion-fast) var(--shopos-ui-ease),
        color var(--shopos-ui-motion-fast) var(--shopos-ui-ease),
        transform var(--shopos-ui-motion-fast) var(--shopos-ui-ease);
}

/* DEEPEN (§8.2): darker fill on hover, press scale on :active. Buttons never
   lift — translateY on a button is a review-blocking defect in v3.
 *
 * :focus is grouped with :hover and the ink is declared with the fill (§7.4).
 * The lockstep twin of shopos-core/assets/css/shopos-ui.css — see the long note
 * there (BUGS.md row 6, instance 14). On a THEMED store these rules were never
 * the ones losing: `.shopos-theme .shopos-ui-btn` is [0,2,0] and prints after
 * hello, so the rest head won the tie by print order alone. They exist here to
 * keep the two copies value-identical (BloomStaticGuardsTest) and to make the
 * focus ring a decision rather than a leftover. */
.shopos-theme .shopos-ui-btn:hover,
.shopos-theme .shopos-ui-btn:focus {
    background: var(--shopos-ui-color-accent-hover);
    color: var(--shopos-ui-color-accent-text);
    /* The radius is restated at the state layer: Elementor kits emit
       `.elementor-kit-N button:focus` at [0,2,1], which beats the [0,2,0]
       rest head — a clicked button kept :focus and turned square. */
    border-radius: var(--shopos-ui-button-radius);
    outline: none;
}

.shopos-theme .shopos-ui-btn:focus-visible {
    outline: var(--shopos-ui-focus-outline);
    outline-offset: 2px;
}

.shopos-theme .shopos-ui-btn:active {
    transform: scale(0.985);
    background: var(--shopos-ui-color-accent-active);
}

.shopos-theme .shopos-ui-btn:disabled,
.shopos-theme .shopos-ui-btn[aria-disabled="true"] {
    opacity: 0.4;
    cursor: not-allowed;
    transform: none;
}

.shopos-theme .shopos-ui-btn--ghost {
    background: transparent;
    color: var(--shopos-ui-color-ink);
    border-color: color-mix(in srgb, var(--shopos-ui-color-ink) 22%, transparent);
}

.shopos-theme .shopos-ui-btn--ghost:hover,
.shopos-theme .shopos-ui-btn--ghost:focus {
    background: color-mix(in srgb, var(--shopos-ui-color-ink) 5%, transparent);
    color: var(--shopos-ui-color-ink);
    /* Restated for the same reason as the solid group above: the kit's square
       button:hover/:focus at [0,2,1] must never win the shape. */
    border-radius: var(--shopos-ui-button-radius);
}

/* The quiet voice: accent text, no chrome; hover deepens and underlines. */
.shopos-theme .shopos-ui-btn--link {
    background: transparent;
    border: none;
    color: var(--shopos-ui-color-accent);
    min-height: 0;
    padding: 0;
    letter-spacing: var(--shopos-ui-tracking-normal);
    text-decoration: none;
}

.shopos-theme .shopos-ui-btn--link:hover,
.shopos-theme .shopos-ui-btn--link:focus {
    background: transparent;
    color: var(--shopos-ui-color-accent-hover);
    text-decoration: underline;
    text-underline-offset: 3px;
    text-decoration-thickness: 1px;
    /* Inert on a chrome-less button, restated so the state layer stays whole. */
    border-radius: var(--shopos-ui-button-radius);
}

.shopos-theme .shopos-ui-btn--sm {
    min-height: var(--shopos-ui-button-height-sm);
    padding: 0 var(--shopos-ui-space-md);
    font-size: var(--shopos-ui-text-xs);
}

.shopos-theme .shopos-ui-btn--block {
    display: flex;
    width: 100%;
}

/* -------------------------------------------------------------------------
 * 5b. Icon button (.shopos-ui-iconbtn) — §9.2. The ONE icon-trigger
 *     primitive: a circle at every state, transparent at rest, tonal-fill
 *     hover (recipe 1), filled-glyph toggled state, background+color only.
 * ------------------------------------------------------------------------- */

.shopos-theme .shopos-ui-iconbtn {
    position: relative;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    inline-size: 40px;
    block-size: 40px;
    padding: 0;
    border: 1px solid var(--shopos-ui-color-hairline);
    border-radius: var(--shopos-ui-radius-round);
    background: var(--shopos-ui-color-paper);
    color: var(--shopos-ui-color-ink);
    cursor: pointer;
    transition:
        background-color var(--shopos-ui-motion-fast) var(--shopos-ui-ease),
        color var(--shopos-ui-motion-fast) var(--shopos-ui-ease);
}
/* §13's touch floor is the HIT AREA, not the painted box (owner ruling
   2026-08-06, BUGS.md row 34). The circle stays 40 — the board's density, and
   every icon trigger in the suite inherits it — while a transparent pseudo
   extends the tappable region to 44. Of the three shapes on offer this is the
   only one that changes nothing visible on any store and still serves a thumb;
   raising the paint to 44 would have moved every icon button and every sweep
   baseline with it.

   -2px on each side: 40 + (2 x 2) = 44. Base rung only — `--sm` (32) keeps
   §13's sanctioned desktop-density exception and `--lg` (48) is already past
   the floor. It paints nothing, so it cannot be seen; it is inside the button,
   so a press on it still activates the button. */
.shopos-theme .shopos-ui-iconbtn::after {
    content: "";
    position: absolute;
    inset: -2px;
}
.shopos-theme .shopos-ui-iconbtn .shopos-ui-icon,
.shopos-theme .shopos-ui-iconbtn svg {
    inline-size: 20px;
    block-size: 20px;
    stroke-width: 1.5;
}
/* The fill and its ink, together, on both states — see the §7.4 note above the
   .shopos-ui-btn hover rule. This is the trigger the owner met as a magenta box. */
.shopos-theme .shopos-ui-iconbtn:hover,
.shopos-theme .shopos-ui-iconbtn:focus {
    background-color: var(--shopos-ui-color-paper-dim);
    color: var(--shopos-ui-color-ink);
    /* Restated for the same kit-button:focus [0,2,1] collision as .shopos-ui-btn:
       without it the circle squares off after the first press. */
    border-radius: var(--shopos-ui-radius-round);
    outline: none;
}
.shopos-theme .shopos-ui-iconbtn:focus-visible {
    outline: var(--shopos-ui-focus-outline);
    outline-offset: 2px;
}
.shopos-theme .shopos-ui-iconbtn:active { background-color: color-mix(in srgb, var(--shopos-ui-color-ink) 10%, transparent); }
/* Toggled (e.g. wishlisted): the filled glyph carries the state; fill returns to paper. */
.shopos-theme .shopos-ui-iconbtn[aria-pressed="true"],
.shopos-theme .shopos-ui-iconbtn.is-selected { background-color: var(--shopos-ui-color-paper); }
.shopos-theme .shopos-ui-iconbtn:disabled,
.shopos-theme .shopos-ui-iconbtn[aria-disabled="true"] { opacity: 0.4; cursor: not-allowed; }

.shopos-theme .shopos-ui-iconbtn--sm { inline-size: 32px; block-size: 32px; }
.shopos-theme .shopos-ui-iconbtn--sm .shopos-ui-icon,
.shopos-theme .shopos-ui-iconbtn--sm svg { inline-size: 18px; block-size: 18px; }
.shopos-theme .shopos-ui-iconbtn--lg { inline-size: 48px; block-size: 48px; }

.shopos-theme .shopos-ui-iconbtn__count {
    position: absolute;
    inset-block-start: 0;
    inset-inline-end: 0;
    min-inline-size: 16px;
    block-size: 16px;
    padding-inline: 4px;
    border-radius: var(--shopos-ui-radius-round);
    background: var(--shopos-ui-color-accent);
    color: var(--shopos-ui-color-accent-text);
    font-size: var(--shopos-ui-text-xs);
    line-height: 16px;
    text-align: center;
}

/* -------------------------------------------------------------------------
 * 5. Input primitive (.shopos-ui-input, .shopos-ui-select, .shopos-ui-textarea)
 * ------------------------------------------------------------------------- */

.shopos-theme .shopos-ui-input,
.shopos-theme .shopos-ui-select,
.shopos-theme .shopos-ui-textarea {
    display: block;
    width: 100%;
    min-height: var(--shopos-ui-input-height);
    padding: 0 var(--shopos-ui-input-padding-x);
    border: var(--shopos-ui-input-border);
    border-radius: var(--shopos-ui-input-radius);
    background: var(--shopos-ui-input-bg);
    color: var(--shopos-ui-color-ink);
    font: inherit;
    transition:
        border-color var(--shopos-ui-motion-fast) var(--shopos-ui-ease),
        box-shadow var(--shopos-ui-motion-fast) var(--shopos-ui-ease);
}

.shopos-theme .shopos-ui-textarea {
    min-height: calc(var(--shopos-ui-input-height) * 2.5);
    padding: var(--shopos-ui-space-sm) var(--shopos-ui-input-padding-x);
    resize: vertical;
}

.shopos-theme .shopos-ui-input:hover,
.shopos-theme .shopos-ui-select:hover,
.shopos-theme .shopos-ui-textarea:hover {
    border: var(--shopos-ui-input-border-hover);
}

/* The §8.4 exception: text controls focus with an accent border + accent-soft
   halo instead of the global ink outline — the one warm focus in the system. */
.shopos-theme .shopos-ui-input:focus-visible,
.shopos-theme .shopos-ui-select:focus-visible,
.shopos-theme .shopos-ui-textarea:focus-visible {
    outline: none;
    border-color: var(--shopos-ui-color-accent);
    box-shadow: 0 0 0 3px var(--shopos-ui-color-accent-soft);
}

.shopos-theme .shopos-ui-input[aria-invalid="true"],
.shopos-theme .shopos-ui-input.is-error {
    border-color: var(--shopos-ui-color-danger);
}

.shopos-theme .shopos-ui-label {
    display: inline-block;
    font-size: var(--shopos-ui-text-xs);
    font-weight: var(--shopos-ui-weight-semi);
    color: var(--shopos-ui-color-ink);
    margin-bottom: var(--shopos-ui-space-xs);
}

/* Helper + error lines below the field (§9.3). */
.shopos-theme .shopos-ui-help {
    display: block;
    font-size: var(--shopos-ui-text-sm);
    color: var(--shopos-ui-color-ink-soft);
    margin-top: var(--shopos-ui-space-xs);
}

.shopos-theme .shopos-ui-err {
    display: block;
    font-size: var(--shopos-ui-text-sm);
    color: var(--shopos-ui-color-danger-text);
    margin-top: var(--shopos-ui-space-xs);
}

/* -------------------------------------------------------------------------
 * 6. Badge primitive (.shopos-ui-badge)
 * ------------------------------------------------------------------------- */

.shopos-theme .shopos-ui-badge {
    display: inline-flex;
    align-items: center;
    height: var(--shopos-ui-badge-height);
    padding: var(--shopos-ui-badge-padding);
    border-radius: var(--shopos-ui-badge-radius);
    background: color-mix(in srgb, var(--shopos-ui-color-ink) 7%, transparent);
    color: var(--shopos-ui-color-ink);
    font-size: var(--shopos-ui-badge-font);
    font-weight: var(--shopos-ui-weight-semi);
    white-space: nowrap;
}

.shopos-theme .shopos-ui-badge--success { background: var(--shopos-ui-color-success-soft); color: var(--shopos-ui-color-success-text); }
.shopos-theme .shopos-ui-badge--danger  { background: var(--shopos-ui-color-danger-soft);  color: var(--shopos-ui-color-danger-text); }
.shopos-theme .shopos-ui-badge--warning { background: var(--shopos-ui-color-warning-soft); color: var(--shopos-ui-color-warning-text); }
.shopos-theme .shopos-ui-badge--info    { background: var(--shopos-ui-color-info-soft);    color: var(--shopos-ui-color-info-text); }
/* Sale-Is-Accent (§3): the sale badge IS the accent badge. */
.shopos-theme .shopos-ui-badge--accent,
.shopos-theme .shopos-ui-badge--sale    { background: var(--shopos-ui-color-accent);       color: var(--shopos-ui-color-accent-text); }

/* -------------------------------------------------------------------------
 * 6b. Filter chip (.shopos-ui-chip) — §9.5. Hover recipe 2 (border→ink);
 *     selection inverts locally so a selected filter reads at a glance.
 * ------------------------------------------------------------------------- */

.shopos-theme .shopos-ui-chip {
    display: inline-flex;
    align-items: center;
    gap: var(--shopos-ui-space-xs);
    min-height: 32px;
    padding: 0 15px;
    border-radius: var(--shopos-ui-radius-pill);
    background: var(--shopos-ui-color-paper);
    color: var(--shopos-ui-color-ink);
    border: 1px solid var(--shopos-ui-color-hairline);
    font-size: var(--shopos-ui-text-xs);
    font-weight: var(--shopos-ui-weight-medium);
    white-space: nowrap;
    cursor: pointer;
    transition:
        background var(--shopos-ui-motion-fast) var(--shopos-ui-ease),
        color var(--shopos-ui-motion-fast) var(--shopos-ui-ease),
        border-color var(--shopos-ui-motion-fast) var(--shopos-ui-ease);
}

.shopos-theme .shopos-ui-chip:hover {
    border-color: color-mix(in srgb, var(--shopos-ui-color-ink) 25%, transparent);
}

/* Selection is the accent's voice. Text is accent-hover, not accent — the
   bare accent misses 4.5:1 on the tint at label size (§7.4). */
.shopos-theme .shopos-ui-chip[aria-pressed="true"],
.shopos-theme .shopos-ui-chip.is-selected {
    background: var(--shopos-ui-color-accent-soft);
    color: var(--shopos-ui-color-accent-hover);
    border-color: var(--shopos-ui-color-accent);
    font-weight: var(--shopos-ui-weight-semi);
}

.shopos-theme .shopos-ui-chip:disabled,
.shopos-theme .shopos-ui-chip[aria-disabled="true"] {
    opacity: 0.4;
    cursor: not-allowed;
}

/* -------------------------------------------------------------------------
 * 6c. Inline note (.shopos-ui-note) — §9.8. Full -soft fill + matching -text
 *     color; never a colored side-stripe.
 * ------------------------------------------------------------------------- */

.shopos-theme .shopos-ui-note {
    display: block;
    padding: var(--shopos-ui-space-sm) var(--shopos-ui-space-md);
    border-radius: var(--shopos-ui-radius-xs);
    background: var(--shopos-ui-color-paper-dim);
    color: var(--shopos-ui-color-ink-soft);
    font-size: var(--shopos-ui-text-sm);
    line-height: var(--shopos-ui-leading-base);
}

.shopos-theme .shopos-ui-note__lead {
    font-weight: var(--shopos-ui-weight-semi);
    margin-inline-end: var(--shopos-ui-space-xs);
}

.shopos-theme .shopos-ui-note--success { background: var(--shopos-ui-color-success-soft); color: var(--shopos-ui-color-success-text); }
.shopos-theme .shopos-ui-note--danger  { background: var(--shopos-ui-color-danger-soft);  color: var(--shopos-ui-color-danger-text); }
.shopos-theme .shopos-ui-note--warning { background: var(--shopos-ui-color-warning-soft); color: var(--shopos-ui-color-warning-text); }
.shopos-theme .shopos-ui-note--info    { background: var(--shopos-ui-color-info-soft);    color: var(--shopos-ui-color-info-text); }

/* -------------------------------------------------------------------------
 * 6d. Toast (.shopos-ui-toast) — §9.8. Bottom inline-center, slide-up entrance
 *     (instant under reduced motion via the motion token); one at a time.
 * ------------------------------------------------------------------------- */

.shopos-theme .shopos-ui-toast {
    position: fixed;
    inset-block-end: var(--shopos-ui-space-lg);
    inset-inline: 0;
    margin-inline: auto;
    width: max-content;
    max-width: min(92vw, 420px);
    z-index: var(--shopos-ui-z-toast);
    padding: var(--shopos-ui-space-sm) var(--shopos-ui-space-md);
    background: var(--shopos-ui-color-paper);
    color: var(--shopos-ui-color-ink);
    border: 1px solid var(--shopos-ui-color-hairline);
    border-radius: var(--shopos-ui-radius-md);
    box-shadow: var(--shopos-ui-shadow-lg);
    font-size: var(--shopos-ui-text-sm);
    animation: shopos-ui-toast-in var(--shopos-ui-motion-base) var(--shopos-ui-ease-spring);
}

@keyframes shopos-ui-toast-in {
    from { opacity: 0; transform: translateY(8px); }
    to   { opacity: 1; transform: translateY(0); }
}

/* -------------------------------------------------------------------------
 * 7. Card primitive (.shopos-ui-card)
 * ------------------------------------------------------------------------- */

.shopos-theme .shopos-ui-card {
    position: relative;
    display: flex;
    flex-direction: column;
    background: var(--shopos-ui-card-bg);
    border: var(--shopos-ui-card-border);
    border-radius: var(--shopos-ui-card-radius);
    box-shadow: var(--shopos-ui-card-shadow);
    overflow: hidden;
    /* motion-fast, not base (§8.3 as amended 2026-08-04): the card LIFT is a
       hover, and every hover in the system now settles at 160ms. The board has
       always drawn it that way — `.shopos-ui-card.is-lift` and the loop cards
       all carry `--motion-standard` — and 260ms is reserved for entrances. */
    transition:
        transform var(--shopos-ui-motion-fast) var(--shopos-ui-ease),
        box-shadow var(--shopos-ui-motion-fast) var(--shopos-ui-ease),
        border-color var(--shopos-ui-motion-fast) var(--shopos-ui-ease);
}

/* LIFT is opt-in (§9.6): a bare card is a static panel, `.is-lift` is the
   interactive one. Elementor HTML that hand-writes `shopos-ui-card` on a
   clickable card must add `is-lift` to keep the hover. */
.shopos-theme .shopos-ui-card.is-lift:hover {
    transform: translateY(var(--shopos-ui-card-hover-shift));
    border: var(--shopos-ui-card-border-hover);
    box-shadow: var(--shopos-ui-card-shadow-hover);
}

.shopos-theme .shopos-ui-card__media {
    aspect-ratio: var(--shopos-ui-card-aspect);
    block-size: var(--shopos-ui-card-h);
    background: var(--shopos-ui-card-plate);
    overflow: hidden;
}

.shopos-theme .shopos-ui-card__media img {
    width: 100%;
    height: 100%;
    object-fit: var(--shopos-ui-card-fit);
    display: block;
    transition: transform var(--shopos-ui-motion-slow) var(--shopos-ui-ease);
}

.shopos-theme .shopos-ui-card.is-lift:hover .shopos-ui-card__media img {
    transform: scale(1.03);
}

.shopos-theme .shopos-ui-card__body {
    padding: var(--shopos-ui-space-md);
    display: flex;
    flex-direction: column;
    gap: var(--shopos-ui-space-xs);
}

.shopos-theme .shopos-ui-card__title {
    font-size: var(--shopos-ui-text-md);
    font-weight: var(--shopos-ui-weight-medium);
    line-height: var(--shopos-ui-leading-snug);
    margin: 0;
}

.shopos-theme .shopos-ui-card__meta {
    color: var(--shopos-ui-color-ink-muted);
    font-size: var(--shopos-ui-text-sm);
}

/* -------------------------------------------------------------------------
 * 8. Motion utilities
 * ------------------------------------------------------------------------- */

.shopos-theme .shopos-ui-fade-in {
    animation: shopos-ui-fade-in var(--shopos-ui-motion-base) var(--shopos-ui-ease) both;
}
/* The One Gentle Spring (§8.6): entrances only. The overshoot lives in the
   ease — nothing bounces twice. */
.shopos-theme .shopos-ui-slide-up {
    animation: shopos-ui-slide-up var(--shopos-ui-motion-base) var(--shopos-ui-ease-spring) both;
}

@keyframes shopos-ui-fade-in {
    from { opacity: 0; }
    to   { opacity: 1; }
}

@keyframes shopos-ui-slide-up {
    from { opacity: 0; transform: translateY(8px); }
    to   { opacity: 1; transform: translateY(0); }
}

/* -------------------------------------------------------------------------
 * 9. Loading state helpers
 * ------------------------------------------------------------------------- */

.shopos-theme.is-loading {
    cursor: progress;
}

.shopos-theme .shopos-ui-skeleton {
    background: linear-gradient(
        90deg,
        var(--shopos-ui-color-paper-dim) 25%,
        #e7e7ea 37%,
        var(--shopos-ui-color-paper-dim) 63%
    );
    background-size: 400% 100%;
    animation: shopos-ui-shimmer 1.4s ease infinite;
    border-radius: var(--shopos-ui-radius-xs);
}

/* §13: the shimmer is a loop, not a spinner — it stops under reduced motion
   (the module skeletons already do this; the primitive did not). */
@media (prefers-reduced-motion: reduce) {
    .shopos-theme .shopos-ui-skeleton {
        animation: none;
    }
}

@keyframes shopos-ui-shimmer {
    from { background-position: 200% 0; }
    to   { background-position: -200% 0; }
}

/* -------------------------------------------------------------------------
 * 10. Hebrew + Latin letter-form tuning
 * ------------------------------------------------------------------------- */

:root:lang(he) .shopos-theme,
.shopos-theme:lang(he) {
    --shopos-ui-tracking-tight:  0;
    --shopos-ui-tracking-normal: 0;
    --shopos-ui-tracking-wide:   0;
}

.shopos-theme:lang(he) h1,
.shopos-theme:lang(he) h2,
.shopos-theme:lang(he) h3,
.shopos-theme:lang(he) h4 {
    line-height: var(--shopos-ui-leading-snug);
}
