/**
 * AIEO Star Ratings — interactive widget + read-only aggregate.
 *
 * Colors + size come from CSS variables injected inline by AIEO_Ratings::enqueue_assets()
 * (mirrors the wishlist-heart pattern). The aggregate uses a two-layer technique:
 * a full empty-color background (5 stars) overlaid by a percentage-width clip
 * of filled-color stars — gives free half-star fidelity without storing
 * fractional ratings.
 */
:root {
    --aieo-rating-empty:     #d4d4d8;
    --aieo-rating-filled:    #F46767;   /* post-vote color (the viewer's own rating) */
    --aieo-rating-hover:     #F46767;
    --aieo-rating-pre-rated: #000000;   /* placeholder 5-stars before viewer has rated */
    --aieo-rating-size:      20px;
}

/* ------------------------------------------------------------------------
 * Interactive widget
 * --------------------------------------------------------------------- */

.aieo-rating-stars {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    margin: 4px 0;
    line-height: 1;
    /* On archive cards we don't want the wrapper stretching with the card —
       it'd inflate the row's gap budget. inline-flex on the wrapper +
       max-content on the row below pin it to its intrinsic width. */
    max-width: 100%;
}

.aieo-rating-stars__row {
    display: inline-flex;
    align-items: center;
    /* Operator-configurable spacing — `--aieo-rating-gap` is injected by
       AIEO_Ratings::enqueue_assets() from the Appearance panel ("Star gap
       — desktop / mobile" fields). 2px default matches the reference
       roosterx-theme rendering. */
    gap: var(--aieo-rating-gap, 2px);
    /* Pin to intrinsic width so even when a parent flex/grid stretches us,
       the buttons don't redistribute the slack into massive gaps. */
    width: max-content;
    max-width: 100%;
}

.aieo-rating-star {
    /* Defensive button reset — themes ship `.woocommerce .button { width:
       100% }`, `.product li button { min-width: 200px }`, etc. that win
       the specificity battle against our plain `.aieo-rating-star`. The
       60-px-wide / 14-px-tall buttons reported by DevTools on the test
       site are proof. We use `!important` on the dimensional properties
       to defeat those theme overrides — `!important` is justified here
       because these are corrective overrides against theme bugs, not
       cosmetic preferences, and there is no legitimate downstream
       caller that should win.
       min-width: 0 stops the implicit `min-width: auto` on flex items
       from inheriting the theme's `min-width: 200px`. */
    box-sizing: border-box !important;
    width: var(--aieo-rating-size) !important;
    min-width: 0 !important;
    max-width: var(--aieo-rating-size) !important;
    height: var(--aieo-rating-size) !important;
    min-height: 0 !important;
    max-height: var(--aieo-rating-size) !important;
    flex: 0 0 var(--aieo-rating-size) !important;
    padding: 0 !important;
    margin: 0 !important;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    border: none;
    background: transparent;
    color: var(--aieo-rating-empty);
    cursor: pointer;
    transition: color 120ms ease, transform 100ms ease;
    line-height: 1;
}
.aieo-rating-star:focus-visible { outline: 2px solid var(--aieo-rating-hover); outline-offset: 2px; border-radius: 2px; }
.aieo-rating-star:active { transform: scale(0.92); }
.aieo-rating-star.is-filled { color: var(--aieo-rating-filled); }

/* Pre-rated state: viewer hasn't voted yet AND `display_full_until_rated`
 * is on. PHP paints all 5 with `is-filled` so this rule wins via specificity. */
.aieo-rating-stars.is-unrated-full .aieo-rating-star.is-filled { color: var(--aieo-rating-pre-rated); }
.aieo-rating-aggregate.is-unrated-full .aieo-rating-aggregate__fg { color: var(--aieo-rating-pre-rated); }

/* Hover/focus paints stars 1..N filled. We paint the hovered star + every
 * preceding sibling on the same row. */
.aieo-rating-stars__row:hover .aieo-rating-star {
    color: var(--aieo-rating-empty);
}
.aieo-rating-stars__row .aieo-rating-star:hover,
.aieo-rating-stars__row .aieo-rating-star:hover ~ .aieo-rating-star {
    /* sibling combinator: hovered + all later — but stars are LTR so we want
     * hovered + all earlier. CSS has no "previous sibling", so we flip the
     * approach: paint everything by default on hover, then un-paint after. */
}
/* Trick for "hover paints up to and including N":
 * - on hover anywhere in the row, paint everything filled
 * - then for each star hovered, un-paint everything that comes after it
 */
.aieo-rating-stars__row:hover .aieo-rating-star {
    color: var(--aieo-rating-hover);
}
.aieo-rating-stars__row .aieo-rating-star:hover ~ .aieo-rating-star {
    color: var(--aieo-rating-empty);
}

.aieo-rating-stars.is-loading {
    opacity: 0.6;
    pointer-events: none;
}

.aieo-rating-stars.is-readonly .aieo-rating-star {
    cursor: default;
    pointer-events: none;
}

/* ───────────────────────────────────────────────────────────────────────
 * High-specificity override against theme button rules in mobile media
 * queries. The femme-fatale theme (and many WC themes) ship something like:
 *
 *   @media (max-width: 1025px) {
 *       button:not(.components-button):not(.pswp__button):not(.has-background) {
 *           height: 60px;
 *           min-width: 60px;
 *       }
 *   }
 *
 * That selector is specificity (0,3,1). The base `.aieo-rating-star` rule
 * above is (0,1,0) — we already have `!important` to beat it, but layered
 * defence: a higher-specificity selector here makes the cascade win obvious
 * even with `!important` stripped. Specificity calc:
 *   `.aieo-rating-stars .aieo-rating-stars__row button.aieo-rating-star`
 *   = 3 classes + 1 element = (0,3,2) → beats (0,3,1). Doubled into a media
 * query that explicitly matches the theme's breakpoint range so the cascade
 * shootout is unambiguous.
 * ─────────────────────────────────────────────────────────────────────── */
@media (max-width: 1025px) {
    .aieo-rating-stars .aieo-rating-stars__row button.aieo-rating-star,
    .aieo-rating-stars .aieo-rating-stars__row button.aieo-rating-star.is-filled {
        box-sizing: border-box !important;
        width: var(--aieo-rating-size) !important;
        min-width: 0 !important;
        max-width: var(--aieo-rating-size) !important;
        height: var(--aieo-rating-size) !important;
        min-height: 0 !important;
        max-height: var(--aieo-rating-size) !important;
        flex: 0 0 var(--aieo-rating-size) !important;
        padding: 0 !important;
        margin: 0 !important;
    }
    .aieo-rating-stars .aieo-rating-stars__row button.aieo-rating-star .aieo-rating-star-icon {
        width: var(--aieo-rating-size) !important;
        max-width: var(--aieo-rating-size) !important;
        min-width: 0 !important;
        height: var(--aieo-rating-size) !important;
        max-height: var(--aieo-rating-size) !important;
        min-height: 0 !important;
    }
}

/* Star-icon SVG inherits color via fill="currentColor".
 * Same defensive sizing as the button — `!important` to defeat theme
 * rules like `.product img, .product svg { width: 100% }` which would
 * otherwise stretch the icon inside an already-correct button box. */
.aieo-rating-star-icon {
    width: var(--aieo-rating-size) !important;
    max-width: var(--aieo-rating-size) !important;
    min-width: 0 !important;
    height: var(--aieo-rating-size) !important;
    max-height: var(--aieo-rating-size) !important;
    min-height: 0 !important;
    flex: 0 0 var(--aieo-rating-size) !important;
    display: block;
}

/* Caption — numeric "4.6 (128)" style label next to the row. */
.aieo-rating-caption {
    font-size: 13px;
    color: #4b5563;
    line-height: 1;
    white-space: nowrap;
}

/* Variant: archive card — lands directly under the buy button as the last
 * element of the tile. Stars on top, caption stacked below them, both
 * horizontally centered with the rest of the card content. */
.aieo-rating-stars--archive {
    --aieo-rating-size: 16px;
    flex-direction: column;
    align-items: center;
    gap: 4px;
    margin: 10px 0 4px;
}
.aieo-rating-stars--archive .aieo-rating-stars__row {
    /* Tighter gap on archive cards — they're narrow (often 50% of an
       already narrow mobile viewport), so even 2px between 5 stars
       feels overhung. 1px reads as nearly touching, which matches the
       roosterx theme reference styling. */
    gap: 1px;
}
.aieo-rating-stars--archive .aieo-rating-caption {
    font-size: 12px;
    text-align: center;
}

/* Mobile — shrink everything further on narrow viewports so the rating
 * widget fits inside a 50%-width archive card on a 360-380px phone with
 * room to spare for the caption underneath. */
@media (max-width: 768px) {
    .aieo-rating-stars--archive {
        --aieo-rating-size: 14px;
        gap: 3px;
        margin: 8px 0 4px;
    }
    .aieo-rating-stars--archive .aieo-rating-stars__row {
        gap: 1px;
    }
    .aieo-rating-stars--archive .aieo-rating-caption {
        font-size: 11px;
        line-height: 1.2;
        white-space: normal;
    }
}

/* Variant: single product page — sits between title and price.
 * Generous vertical space so the row breathes under the product title. */
.aieo-rating-stars--single {
    margin: 18px 0 22px;
}

/* Mobile single-product page — caption stacks UNDER the stars instead of
 * floating to the right of them. On narrow viewports the inline-row layout
 * with `flex-direction: row` would push the caption past the product
 * image's column edge. Column stacking keeps the row + caption inside the
 * container; the caption stays `white-space: nowrap` (NOT wrapped — wrapping
 * is what was causing the overflow in the first place because it forced the
 * caption to expand into the next line while still beside the stars).
 * Both children are horizontally centered to match the visual rhythm of
 * the rest of the mobile PDP (centred price, centred add-to-cart, etc.). */
@media (max-width: 768px) {
    .aieo-rating-stars--single {
        flex-direction: column;
        align-items: center;
        gap: 6px;
        margin: 14px 0 16px;
        min-width: 0;
        /* The wrapper itself spans the available width so its centred
           children land in the middle of the product summary column.
           Otherwise the inline-flex container is only as wide as its
           content and `align-items: center` is a no-op for sub-content
           that's narrower than its parent column. */
        display: flex;
        width: 100%;
    }
    .aieo-rating-stars--single .aieo-rating-caption {
        text-align: center;
    }
}

/* ------------------------------------------------------------------------
 * Read-only aggregate (half-star fidelity via percentage fill)
 * --------------------------------------------------------------------- */

.aieo-rating-aggregate {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    margin: 4px 0;
    line-height: 1;
}

.aieo-rating-aggregate__stars {
    position: relative;
    display: inline-block;
    line-height: 0;
}

.aieo-rating-aggregate__bg,
.aieo-rating-aggregate__fg {
    display: inline-flex;
    gap: 2px;
}

.aieo-rating-aggregate__bg {
    color: var(--aieo-rating-empty);
}

.aieo-rating-aggregate__fg {
    position: absolute;
    inset: 0;
    overflow: hidden;
    color: var(--aieo-rating-filled);
    /* width is set inline (e.g. style="width:92%") */
}

.aieo-rating-aggregate__bg-star,
.aieo-rating-aggregate__fg-star {
    width: var(--aieo-rating-size);
    height: var(--aieo-rating-size);
    display: block;
    flex-shrink: 0;
}

/* WC compat: ensure archive cards have a positioned containing block so
 * absolutely-positioned siblings (e.g. wishlist heart) keep their layout
 * even when the rating widget is added. We don't use absolute positioning
 * ourselves but keep this as a safety net. */
ul.products li.product,
.products .product,
.wc-block-product,
.wp-block-woocommerce-product,
.wc-block-product-template > li,
.wp-block-woocommerce-product-template > li,
.wc-block-grid__product,
:where(li, div).type-product {
    position: relative;
}
