/* ══════════════════════════════════════════════════════════════════════
   Customer reviews.

   No design system of its own: every colour, radius, space and font here
   resolves to an --codleade-* token from assets/css/base.css, and the two
   buttons (.write-review-toggle, .submit-review-btn) are already part of
   base.css's shared button contract, so this file gives them no styling.

   Star colour is its own role: Site Identity → Appearance → Rating Stars
   (--codleade-c-stars, default gold), falling back to the brand when
   emptied. It is set on the star tokens in single-product.css.
   ══════════════════════════════════════════════════════════════════════ */

/*
 * The star tokens, the read-only star glyphs and the rating line under the
 * product title live in template-parts/product/single-product.css: that line
 * is above the fold, and this stylesheet is loaded non-blocking (it styles the
 * section below the product). See defer_style() in inc/performance/assets.php.
 */

.codleade-reviews {
    width: 100%;
    padding: var(--codleade-space-xl) 0;
    /* The anchor target. Without it, jumping from the rating link under the
       product title parks the section heading underneath the sticky header. */
    scroll-margin-top: calc(100px + var(--codleade-admin-bar, 0px));
}

.codleade-reviews-inner {
    width: 100%;
    max-width: var(--codleade-container);
    margin: 0 auto;
    padding: 0 16px;
    /* Belt and braces against a long unbreakable review word widening the
       page — the same min-width:0 rule the product columns carry. */
    min-width: 0;
}

.codleade-reviews-title {
    margin: 0 0 28px;
    font-size: 1.125rem;
    font-weight: 700;
    line-height: 1.3;
    text-transform: uppercase;
    text-align: center;
    color: var(--codleade-text-primary);
}


/* ── Summary ───────────────────────────────────────────────────────────
   Three columns on desktop, stacked on mobile. Single-column is the
   BASE and the grid is opt-in at 768px up, so the narrow layout can
   never depend on a rule being unset later.                            */

.codleade-reviews-summary {
    display: grid;
    grid-template-columns: minmax(0, 1fr);
    gap: 28px;
    align-items: center;
    padding: 0 0 28px;
    border-bottom: 1px solid var(--codleade-border, #e5e7eb);
}

.codleade-reviews-average {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 8px;
    min-width: 0;
}

.codleade-reviews-average-row {
    display: flex;
    align-items: center;
    column-gap: 10px;
    row-gap: 4px;
    flex-wrap: wrap;
    justify-content: center;
    min-width: 0;
}

.codleade-reviews-average-value {
    font-size: 0.875rem;
    font-weight: 700;
    line-height: 1.4;
    color: var(--codleade-text-primary);
    white-space: nowrap;
}

.codleade-reviews-average-count {
    margin: 0;
    font-size: 0.8125rem;
    color: var(--codleade-text-secondary);
}

/* ── Rating distribution ─────────────────────────────────────────────── */

.codleade-reviews-distribution {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: 6px;
    min-width: 0;
}

.codleade-reviews-distribution-row {
    display: grid;
    /* The count column is fixed so every bar starts and ends on the same
       two vertical lines regardless of whether a row reads 0 or 1 204. */
    grid-template-columns: auto minmax(0, 1fr) 2.5ch;
    align-items: center;
    gap: 10px;
}

.codleade-reviews-distribution-stars {
    display: inline-flex;
    line-height: 0;
}

.codleade-reviews-distribution-track {
    display: block;
    height: 8px;
    min-width: 0;
    background: var(--codleade-bg-secondary, #f3f4f6);
    border-radius: var(--codleade-radius);
    overflow: hidden;
}

.codleade-reviews-distribution-fill {
    display: block;
    height: 100%;
    background: var(--codleade-star-color);
    border-radius: inherit;
}

.codleade-reviews-distribution-count {
    font-size: 0.75rem;
    font-variant-numeric: tabular-nums;
    color: var(--codleade-text-secondary);
    text-align: end;
}

/* ── Call to action ───────────────────────────────────────────────────── */

.codleade-reviews-cta {
    display: flex;
    justify-content: center;
    min-width: 0;
}

.codleade-reviews-cta .write-review-toggle {
    width: 100%;
    max-width: 260px;
}

.codleade-reviews-closed,
.codleade-reviews-empty {
    margin: 0;
    font-size: 0.8125rem;
    color: var(--codleade-text-secondary);
    text-align: center;
}

.codleade-reviews-empty {
    padding: 28px 0 0;
}

/* ── Review list ──────────────────────────────────────────────────────── */

.codleade-reviews-list {
    list-style: none;
    margin: 0;
    padding: 0;
}

.codleade-review {
    padding: 22px 0;
    border-bottom: 1px solid var(--codleade-border, #e5e7eb);
    min-width: 0;
}

.codleade-review-head {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    /* Column and row gaps differ on purpose: 12px reads well between the
       name block and the date side by side, but is too airy once the date
       wraps underneath. */
    column-gap: 12px;
    row-gap: 4px;
    flex-wrap: wrap;
    margin-bottom: 8px;
}

.codleade-review-head-main {
    display: flex;
    align-items: baseline;
    column-gap: 10px;
    row-gap: 2px;
    flex-wrap: wrap;
    /* Takes the room the date does not. min-width: 0 is kept deliberately:
       this block is still a flex child that must be allowed to shrink below
       its content rather than push the date out of the row — it applies to
       whatever it holds, now and later. */
    flex: 1 1 auto;
    min-width: 0;
}

/*
 * Deliberately NOT a filled chip.
 *
 * This was `background: var(--codleade-brand)` with white text. On a store whose
 * brand colour is pure black — which this one is — that rendered as a hard
 * black badge, which fought the star rating beside it for the eye at every
 * viewport width. The information is unchanged; only its weight is.
 *
 * It carried a leading middot to hold it off the author name. The name is no
 * longer displayed, so the separator has gone with it — the row's 10px
 * column-gap is now the only thing between it and the stars, which is enough.
 */
.codleade-review-verified {
    display: inline-flex;
    align-items: center;
    font-size: 0.6875rem;
    font-weight: 600;
    line-height: 1.4;
    color: var(--codleade-text-secondary);
    background: none;
    border: 0;
    padding: 0;
    text-transform: none;
    letter-spacing: normal;
    white-space: nowrap;
}

.codleade-review-date {
    font-size: 0.75rem;
    line-height: 1.4;
    color: var(--codleade-text-secondary);
    white-space: nowrap;
    /* Pinned to the far end while it shares the row, and never compressed —
       a date that wraps or ellipsises is worse than one that drops to its
       own line, which is what the narrow breakpoint below does. */
    flex: none;
    margin-inline-start: auto;
}

.codleade-review-title {
    margin: 0 0 6px;
    font-size: 0.875rem;
    font-weight: 700;
    line-height: 1.35;
    color: var(--codleade-text-primary);
    overflow-wrap: anywhere;
}

.codleade-review-body {
    font-size: 0.875rem;
    line-height: 1.6;
    color: var(--codleade-text-secondary);
    min-width: 0;
    overflow-wrap: anywhere;
}

.codleade-review-body p {
    margin: 0 0 8px;
}

.codleade-review-body p:last-child {
    margin-bottom: 0;
}

/* A review the visitor can see only because it is their own, still held. */
.codleade-review.is-pending {
    opacity: 0.75;
}

.codleade-review-pending {
    margin: 8px 0 0;
    font-size: 0.75rem;
    font-style: italic;
    color: var(--codleade-text-secondary);
}

/* ── Write-review form ────────────────────────────────────────────────── */

.codleade-review-form-panel {
    /* The panel is a <dialog>. Its UA chrome (absolute position, border,
       padding, background, width) must not show on the inline panel that the
       no-JavaScript fallback displays. */
    position: static;
    inset: auto;
    width: auto;
    height: auto;
    max-width: none;
    max-height: none;
    margin: 0;
    padding: 24px 0 4px;
    color: inherit;
    background: none;
    border: 0;
    border-bottom: 1px solid var(--codleade-border, #e5e7eb);
}

.codleade-review-form-title {
    margin: 0 0 16px;
    font-size: 0.9375rem;
    font-weight: 700;
    text-align: center;
    color: var(--codleade-text-primary);
}

.codleade-review-form-notice {
    margin: 0;
    font-size: 0.8125rem;
    text-align: center;
    color: var(--codleade-text-secondary);
}

.codleade-review-form {
    display: flex;
    flex-direction: column;
    gap: 14px;
    max-width: 640px;
    margin: 0 auto;
}

.codleade-review-form[hidden] {
    display: none;
}

/* ── Form fields ──────────────────────────────────────────────────────
   Every selector in this block is scoped to .codleade-reviews on purpose.
   `.codleade-field-label` is ALSO the admin panel's class
   (inc/admin/support/admin-support.css), and `.codleade-field-error-message` is the
   COD form's. Neither stylesheet meets this one today — one is admin-only,
   and the cod-form.css overlap is only a shared prefix — but an unscoped
   `.codleade-field` here would be one rename away from restyling the checkout
   form sitting on this very page. The scope costs a selector and removes
   the whole class of problem.                                            */

.codleade-reviews .codleade-field {
    display: flex;
    flex-direction: column;
    gap: 6px;
    margin: 0;
    min-width: 0;
}

.codleade-rating-field {
    border: 0;
    padding: 0;
    align-items: center;
}

/* "Votre note" sits centred above the row of stars. */
.codleade-reviews .codleade-rating-field > .codleade-field-label {
    display: block;
    width: 100%;
    text-align: center;
}

.codleade-reviews .codleade-field-label {
    font-size: 0.75rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.02em;
    color: var(--codleade-text-primary);
    padding: 0;
}

.codleade-reviews .codleade-field .required {
    color: var(--codleade-brand);
}

.codleade-reviews .codleade-field-input {
    width: 100%;
    font: inherit;
    font-size: 0.875rem;
    padding: 10px 12px;
    color: var(--codleade-text-primary);
    background: var(--codleade-bg-primary, #fff);
    border: 1px solid #dedede;
    border-radius: var(--codleade-radius);
    outline: none;
}

/* The privacy opt-in checkbox: a control beside its label, not a stacked
   label-over-input like the text fields. */
.codleade-reviews .codleade-field-inline {
    flex-direction: row;
    align-items: center;
    gap: 8px;
}

.codleade-reviews .codleade-field-inline label {
    font-size: 0.75rem;
    line-height: 1.4;
    color: var(--codleade-text-secondary);
}

.codleade-reviews .codleade-field-inline input[type="checkbox"] {
    flex: none;
    width: 16px;
    height: 16px;
    margin: 0;
    accent-color: var(--codleade-brand);
}

.codleade-reviews textarea.codleade-field-input {
    min-height: 120px;
    resize: vertical;
}

.codleade-reviews .codleade-field-input:focus {
    border-color: var(--codleade-brand);
}

/* ── Interactive star rating ──────────────────────────────────────────
   Native radio inputs, no JavaScript.

   The radios are printed 1 → 5 and this row is not reversed: DOM order is
   visual order, so the arrow keys move the same way the stars do. The fill
   cannot use a sibling combinator in that order (`~` only reaches later
   siblings), so it is written against the row with `:has()`: the row that
   contains the checked radio N fills its first N stars. One rule per N,
   because the selector has to name the number.

   The input is not display:none — a hidden form control is unreachable by
   keyboard and invisible to assistive tech. It is clipped instead, so the
   radio group keeps native arrow-key navigation and its focus ring is
   drawn on the label via :focus-visible.                                */

.codleade-rating-input {
    /* Containing block for the clipped radios below, so they resolve against
       this row rather than the initial containing block. */
    position: relative;
    display: flex;
    justify-content: center;
    /* No gap: each star's 40px box is its whole touch target, so the boxes
       touch and there is no dead space between two stars. */
    gap: 0;
}

.codleade-rating-radio {
    position: absolute;
    width: 1px;
    height: 1px;
    margin: -1px;
    padding: 0;
    overflow: hidden;
    clip: rect(0 0 0 0);
    clip-path: inset(50%);
    border: 0;
    white-space: nowrap;
}

.codleade-rating-star {
    --codleade-star-size: var(--codleade-icon-size-5xl);
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 40px;
    height: 40px;
    padding: 0;
    cursor: pointer;
    color: var(--codleade-star-empty);
    border-radius: var(--codleade-radius);
}

/* Chosen rating: the row holding checked radio N fills stars 1…N. The rule is
   switched off while the pointer is over the row, so the hover preview below
   is the only fill on screen during a hover; leaving the row brings the chosen
   rating back, since its radio is still checked. A colour swap only. */
.codleade-reviews .codleade-rating-input:has(> .codleade-rating-radio[value="1"]:checked):not(:has(> .codleade-rating-star:hover)) > .codleade-rating-star:nth-of-type(-n+1),
.codleade-reviews .codleade-rating-input:has(> .codleade-rating-radio[value="2"]:checked):not(:has(> .codleade-rating-star:hover)) > .codleade-rating-star:nth-of-type(-n+2),
.codleade-reviews .codleade-rating-input:has(> .codleade-rating-radio[value="3"]:checked):not(:has(> .codleade-rating-star:hover)) > .codleade-rating-star:nth-of-type(-n+3),
.codleade-reviews .codleade-rating-input:has(> .codleade-rating-radio[value="4"]:checked):not(:has(> .codleade-rating-star:hover)) > .codleade-rating-star:nth-of-type(-n+4),
.codleade-reviews .codleade-rating-input:has(> .codleade-rating-radio[value="5"]:checked):not(:has(> .codleade-rating-star:hover)) > .codleade-rating-star:nth-of-type(-n+5) {
    color: var(--codleade-star-color);
}

/* Hover preview: hovering star N fills stars 1…N, the rating a click would
   give. The pointer is over exactly one star, so exactly one of these matches. */
.codleade-reviews .codleade-rating-input:has(> .codleade-rating-star:nth-of-type(1):hover) > .codleade-rating-star:nth-of-type(-n+1),
.codleade-reviews .codleade-rating-input:has(> .codleade-rating-star:nth-of-type(2):hover) > .codleade-rating-star:nth-of-type(-n+2),
.codleade-reviews .codleade-rating-input:has(> .codleade-rating-star:nth-of-type(3):hover) > .codleade-rating-star:nth-of-type(-n+3),
.codleade-reviews .codleade-rating-input:has(> .codleade-rating-star:nth-of-type(4):hover) > .codleade-rating-star:nth-of-type(-n+4),
.codleade-reviews .codleade-rating-input:has(> .codleade-rating-star:nth-of-type(5):hover) > .codleade-rating-star:nth-of-type(-n+5) {
    color: var(--codleade-star-color);
}

.codleade-rating-radio:focus-visible + .codleade-rating-star {
    outline: 2px solid var(--codleade-brand);
    outline-offset: 2px;
}

/* ── Optional photo / video ───────────────────────────────────────────
   A visually-hidden file input with the drop area as its <label>. The
   input is clipped rather than display:none so it keeps native keyboard
   focus and native screen-reader semantics — the label is only the
   appearance. Clicking the label activates the input for free; no
   JavaScript is involved in making the control work.                    */

.codleade-reviews .codleade-media-field {
    align-items: center;
}

.codleade-reviews .codleade-media-input {
    position: absolute;
    width: 1px;
    height: 1px;
    margin: -1px;
    padding: 0;
    overflow: hidden;
    clip: rect(0 0 0 0);
    clip-path: inset(50%);
    border: 0;
    white-space: nowrap;
}

.codleade-reviews .codleade-media-drop {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 8px;
    /* Square-ish and capped, so the zone never becomes a full-width band on
       desktop; `width: 100%` up to the cap keeps it comfortable on a phone. */
    width: 100%;
    max-width: 260px;
    min-height: 150px;
    padding: 18px 16px;
    text-align: center;
    cursor: pointer;
    color: var(--codleade-text-secondary);
    background: var(--codleade-bg-primary, #fff);
    border: 1px solid var(--codleade-border, #e5e7eb);
    border-radius: var(--codleade-radius);
}

/* Focus lands on the clipped input, so the ring has to be drawn on the
   label the customer can actually see. */
.codleade-reviews .codleade-media-input:focus-visible + .codleade-media-drop {
    outline: 2px solid var(--codleade-brand);
    outline-offset: 2px;
}

.codleade-reviews .codleade-upload-icon {
    width: var(--codleade-icon-size-9xl);
    height: var(--codleade-icon-size-9xl);
    display: block;
}

.codleade-reviews .codleade-media-hint {
    font-size: 0.75rem;
    font-weight: 600;
    line-height: 1.4;
}

.codleade-reviews .codleade-media-filename[data-state="error"] {
    color: var(--codleade-brand);
    font-weight: 700;
}

.codleade-reviews .codleade-media-filename {
    font-size: 0.6875rem;
    line-height: 1.4;
    color: var(--codleade-text-secondary);
    /* A chosen filename can be long and unbreakable; it wraps inside the
       zone rather than widening it. */
    overflow-wrap: anywhere;
    max-width: 100%;
}

/* ── Media attached to a published review ─────────────────────────────
   A grid of fixed-ratio cells, not a block image.

   The point is that ONE photo is one compact thumbnail. Rendered as a
   plain block, a single upload filled the review column and roughly
   doubled the height of every review carrying one, which pushed the
   next review off the screen.

   `auto-fill` + minmax means the same two declarations cover every
   width: cells stay at least their minimum, share the leftover space,
   and the grid wraps to as many columns as fit. The max-width is what
   keeps a lone thumbnail small — without it a single cell would stretch
   to the full column and the whole problem comes back.                 */

.codleade-reviews .codleade-review-media {
    list-style: none;
    margin: 10px 0 0;
    padding: 0;
    display: grid;
    /* Mobile baseline: two columns, so thumbnails stay finger-sized
       rather than shrinking to three or four across a narrow screen. */
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 8px;
    /* The cap that stops one image stretching the review. */
    max-width: 260px;
    min-width: 0;
}

.codleade-reviews .codleade-review-media-item {
    /* Square cells, so a portrait and a landscape upload sit in the same
       grid without one of them setting the row height. */
    aspect-ratio: 1;
    min-width: 0;
    overflow: hidden;
    border: 1px solid var(--codleade-border, #e5e7eb);
    border-radius: var(--codleade-radius);
    background: var(--codleade-bg-secondary, #f3f4f6);
}

/*
 * Scoped under .codleade-reviews, and that is not cosmetic.
 *
 * woocommerce-layout.css ships `.woocommerce img, .woocommerce-page img
 * { height: auto; max-width: 100% }`, and <body> carries both of those
 * classes on every product page. That selector is (0,1,1); a bare
 * `.codleade-review-media-image` is (0,1,0), so WooCommerce won — its
 * `height: auto` in particular defeats the `height: 100%` below and the
 * image stops filling its cell. The extra class makes this (0,2,0).
 */
.codleade-reviews .codleade-review-media-image,
.codleade-reviews .codleade-review-media-video {
    display: block;
    width: 100%;
    height: 100%;
    /* The cell is square and the upload is not; cover crops it centrally
       rather than letterboxing or distorting it. */
    object-fit: cover;
}

.codleade-reviews .codleade-review-media-video {
    background: #000;
}

/*
 * Video gets two cells and a 16/9 box.
 *
 * A <video controls> in a ~120px square is unusable — the native control
 * bar alone is wider than the cell. Spanning two columns is the smallest
 * change that makes it playable while keeping it inside the same grid,
 * and 16/9 matches what phones actually record.
 */
.codleade-reviews .codleade-review-media-item.is-video {
    grid-column: span 2;
    aspect-ratio: 16 / 9;
}

/* comment_form() wraps its output in #respond; it must not add a second
   box around the panel that already frames the form. */
.codleade-review-form-panel .comment-respond {
    margin: 0;
    padding: 0;
    border: 0;
}

.codleade-review-form .form-submit {
    margin: 4px 0 0;
    text-align: center;
}

/* ── Write-review dialog ──────────────────────────────────────────────
   The panel is a native <dialog>, and it is a modal only while it is open:
   showModal() puts it in the top layer and makes the page behind it inert, so
   nothing between it and <body> can re-anchor it and no z-index is needed.
   Closed, and without JavaScript, it is the inline panel above.

   The dialog itself is the overlay. Its own background is the dim, and the
   ::backdrop is cleared: the browser's default backdrop would dim the whole
   viewport, the admin bar included.

   Centred from 768px, a bottom sheet below. The box scrolls on its own, so a
   long form on a short screen never pushes the close button off the top.      */

/* Starts below the WordPress admin bar, so a logged-in reader still sees the
   top of the dialog. The box is centred in what is left, never pushed up. */
.codleade-review-form-panel:modal {
    position: fixed;
    top: var(--codleade-admin-bar, 0px);
    inset-inline: 0;
    bottom: 0;
    width: 100%;
    height: auto;
    max-width: none;
    max-height: none;
    display: flex;
    align-items: center;
    justify-content: center;
    margin: 0;
    padding: 16px;
    border: 0;
    color: inherit;
    background: rgba(0, 0, 0, 0.5);
    overflow-y: auto;
    overscroll-behavior: contain;
}

.codleade-review-form-panel::backdrop {
    background: transparent;
}

.codleade-review-form-panel:modal .codleade-review-dialog-box {
    position: relative;
    /* margin: auto centres the box inside the overlay and, unlike
       align-items: center, cannot push its top edge out of reach. */
    margin: auto;
    width: 100%;
    max-width: 480px;
    max-height: 90vh;
    max-height: 90dvh;
    overflow-y: auto;
    overscroll-behavior: contain;
    /* The box is laid out, painted and styled on its own: the dialog's
       content cannot force a relayout of the product page behind it. */
    contain: layout style paint;
    padding: 24px;
    background: var(--codleade-bg-primary, #fff);
    border: 1px solid var(--codleade-border, #e5e7eb);
    border-radius: var(--codleade-radius);
}

.codleade-review-dialog-box .codleade-review-form-title {
    /* Keeps the title clear of the close button in the top corner. */
    padding: 0 32px;
}

.codleade-review-dialog-close {
    position: absolute;
    top: 10px;
    inset-inline-end: 10px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 36px;
    height: 36px;
    margin: 0;
    padding: 0;
    color: var(--codleade-text-primary);
    background: none;
    border: 0;
    border-radius: var(--codleade-radius);
    cursor: pointer;
}

.codleade-review-dialog-close svg {
    width: 18px;
    height: 18px;
}

.codleade-review-dialog-close:hover {
    background: var(--codleade-bg-secondary, #f3f4f6);
}

.codleade-review-dialog-close:focus-visible {
    outline: 2px solid var(--codleade-text-primary, #111827);
    outline-offset: 2px;
}

/* Outcome of a submission from the dialog (reviews.js). */
.codleade-review-dialog-status {
    margin: 0 0 16px;
    padding: 12px 14px;
    font-size: 0.875rem;
    line-height: 1.4;
    color: var(--codleade-text-primary);
    border: 1px solid var(--codleade-border, #e5e7eb);
    border-radius: var(--codleade-radius);
}

.codleade-review-dialog-status[data-tone="error"] {
    color: var(--codleade-c-discount, #b42318);
    border-color: currentColor;
}

@media (prefers-reduced-motion: no-preference) {
    .codleade-review-form-panel:modal {
        animation: codleade-review-fade 0.18s ease-out;
    }

    .codleade-review-form-panel:modal .codleade-review-dialog-box {
        animation: codleade-review-rise 0.18s ease-out;
    }
}

@keyframes codleade-review-fade {
    from { opacity: 0; }
}

@keyframes codleade-review-rise {
    from { opacity: 0; transform: translateY(12px); }
}

@media (max-width: 767px) {
    .codleade-review-form-panel:modal {
        align-items: flex-end;
        padding: 0;
    }

    .codleade-review-form-panel:modal .codleade-review-dialog-box {
        max-width: none;
        max-height: 90vh;
        max-height: 90dvh;
        padding: 24px 24px calc(24px + env(safe-area-inset-bottom, 0px));
        border-bottom: 0;
        border-radius: var(--codleade-radius) var(--codleade-radius) 0 0;
    }

    .codleade-review-dialog-box .codleade-review-form-title {
        padding: 0 28px;
    }

    @media (prefers-reduced-motion: no-preference) {
        .codleade-review-form-panel:modal .codleade-review-dialog-box {
            animation: codleade-review-sheet 0.18s ease-out;
        }
    }
}

@keyframes codleade-review-sheet {
    from { transform: translateY(100%); }
}

/* Compact dialog: tighter spacing, a shorter text area, a one-line photo zone
   and a full-width 48px submit. Scoped to the dialog so the inline panel
   (no-script fallback) keeps the full-size form. */
.codleade-reviews .codleade-review-dialog-box .codleade-review-form {
    gap: 14px;
}

.codleade-reviews .codleade-review-dialog-box .codleade-field-label {
    font-size: 12px;
}

.codleade-reviews .codleade-review-dialog-box .codleade-rating-star {
    --codleade-star-size: 26px;
}

.codleade-reviews .codleade-review-dialog-box textarea.codleade-field-input {
    min-height: 110px;
}

.codleade-reviews .codleade-review-dialog-box .codleade-media-field {
    /* The field's label stretches to the input's width, like every other label. */
    align-items: stretch;
}

.codleade-reviews .codleade-review-dialog-box .codleade-media-drop {
    flex-direction: row;
    align-items: center;
    justify-content: flex-start;
    gap: 10px;
    width: 100%;
    max-width: none;
    height: 56px;
    min-height: 0;
    padding: 0 14px;
    text-align: start;
    border: 1px dashed #dedede;
    border-radius: 13px;
}

.codleade-reviews .codleade-review-dialog-box .codleade-upload-icon {
    flex: none;
    width: 18px;
    height: 18px;
}

.codleade-reviews .codleade-review-dialog-box .codleade-media-hint {
    flex: none;
    font-size: 13px;
    font-weight: 500;
    color: var(--codleade-text-primary);
}

.codleade-reviews .codleade-review-dialog-box .codleade-media-filename {
    flex: 1 1 auto;
    min-width: 0;
    overflow: hidden;
    white-space: nowrap;
    text-overflow: ellipsis;
    overflow-wrap: normal;
    text-align: end;
    font-size: 12px;
}

.codleade-reviews .codleade-review-dialog-box .submit-review-btn {
    display: block;
    width: 100%;
    height: 48px;
}

.codleade-reviews .codleade-review-dialog-box .form-submit {
    margin: 0;
}

/* Phones: the dialog is a bottom sheet that always fits the screen. Its top
   stops 24px below the top of the viewport (or below the admin bar, when one
   is shown); anything taller scrolls inside the sheet. The bottom padding
   clears the home indicator. */
@media (max-width: 767px) {
    /* margin-top: auto pins the sheet to the bottom edge; the centring
       margin from the desktop box would otherwise float it mid-screen. */
    .codleade-reviews .codleade-review-form-panel:modal .codleade-review-dialog-box {
        margin: auto 0 0;
        max-height: calc(100vh - var(--codleade-admin-bar, 0px) - 24px);
        max-height: calc(100dvh - var(--codleade-admin-bar, 0px) - 24px);
        padding: 20px 16px calc(12px + env(safe-area-inset-bottom, 0px));
    }

    .codleade-reviews .codleade-review-dialog-box .codleade-review-form-title {
        font-size: 16px;
        padding: 0 28px;
        margin-bottom: 12px;
    }

    .codleade-reviews .codleade-review-dialog-box .codleade-review-form {
        gap: 12px;
    }

    .codleade-reviews .codleade-review-dialog-box .codleade-field-label {
        font-size: 11px;
    }

    .codleade-reviews .codleade-review-dialog-box .codleade-field-input:not(textarea) {
        height: 44px;
    }

    .codleade-reviews .codleade-review-dialog-box textarea.codleade-field-input {
        height: 84px;
        min-height: 0;
    }

    .codleade-reviews .codleade-review-dialog-box .codleade-rating-star {
        --codleade-star-size: 24px;
    }

    .codleade-reviews .codleade-review-dialog-box .codleade-media-drop,
    .codleade-reviews .codleade-review-dialog-box .codleade-review-turnstile,
    .codleade-reviews .codleade-review-dialog-box .codleade-review-turnstile-widget {
        width: 100%;
    }

    .codleade-reviews .codleade-review-dialog-box .submit-review-btn {
        height: 46px;
    }
}

/* ── Turnstile (only printed when enabled in Codleade → Integrations) ─ */

/* Reserves the widget's height (65px flexible, 140px compact) so it does not
   shift the submit button when Cloudflare's iframe arrives. */
/* Nothing sizes Cloudflare's box or its iframe: the widget picks its own
   width (flexible fills the field) and height, and this only reserves the
   65px so the submit button does not move when the iframe arrives. */
.codleade-reviews .codleade-review-turnstile {
    min-width: 0;
}

.codleade-reviews .codleade-review-turnstile-widget {
    min-height: 65px;
}

.codleade-reviews .codleade-review-turnstile-error {
    margin: 0;
    font-size: 13px;
    line-height: 1.4;
    text-align: center;
    color: var(--codleade-brand);
    font-weight: 700;
}

/* ── "Voir tout" ──────────────────────────────────────────────────────── */

/* The button's visual treatment is .fpc3-view-all in base.css; only its
   placement lives here. */
.codleade-reviews-more {
    display: flex;
    justify-content: center;
    padding: 22px 0 0;
}

/* display:flex above would otherwise out-rank the UA's [hidden]. */
.codleade-reviews-more[hidden] {
    display: none;
}

/* ── Pagination ───────────────────────────────────────────────────────── */

.codleade-reviews-pagination {
    padding: 22px 0 0;
}

.codleade-reviews-pagination .page-numbers {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    gap: 6px;
}

.codleade-reviews-pagination a.page-numbers,
.codleade-reviews-pagination span.page-numbers {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 34px;
    height: 34px;
    padding: 0 10px;
    font-size: 0.8125rem;
    text-decoration: none;
    color: var(--codleade-text-primary);
    border: 1px solid var(--codleade-border, #e5e7eb);
    border-radius: var(--codleade-radius);
}

.codleade-reviews-pagination span.page-numbers.current {
    color: var(--codleade-bg-primary, #fff);
    background: var(--codleade-brand);
    border-color: var(--codleade-brand);
}

/* ── Breakpoints ──────────────────────────────────────────────────────── */

/*
 * From a comfortable phone width upward the grid stops being a fixed pair of
 * columns and becomes "as many ~104px cells as fit, up to four". One rule
 * covers large phones, tablets and desktop — there is no separate tablet
 * layout to keep in sync, because auto-fill already is the tablet layout.
 *
 * 4 x 104 + 3 x 8 = 440, so the max-width admits exactly four columns and no
 * fifth. A single photo still occupies one 104px cell.
 */
@media (min-width: 480px) {
    .codleade-reviews .codleade-review-media {
        grid-template-columns: repeat(auto-fill, minmax(104px, 1fr));
        max-width: 440px;
    }
}

@media (min-width: 768px) {
    .codleade-reviews-summary {
        /* Distribution gets the extra width: it is the only column whose
           content is a measurement rather than a line of text. */
        grid-template-columns: minmax(0, 1fr) minmax(0, 1.3fr) minmax(0, 1fr);
        gap: 32px;
    }

    /* Dividers between the three columns, drawn on the columns themselves so
       they disappear with the grid on narrow viewports. */
    .codleade-reviews-distribution,
    .codleade-reviews-cta {
        padding-inline-start: 32px;
        border-inline-start: 1px solid var(--codleade-border, #e5e7eb);
    }
}

@media (min-width: 992px) {
    .codleade-reviews {
        padding: var(--codleade-space-xl) 0;
    }

    .codleade-reviews-inner {
        max-width: 1300px;
        padding: 0 40px;
    }

    .codleade-reviews-title {
        margin-bottom: 32px;
    }
}

@media (max-width: 767px) {
    /* iOS Safari zooms the page into any focused field under 16px, and the
       14px desktop size triggered it on every tap into the review form.
       16px on phones only — no maximum-scale in the viewport, which would
       also take pinch-zoom away from people who need it. */
    .codleade-reviews .codleade-field-input {
        font-size: 16px;
    }

    .codleade-review-head {
        /* The date stops being a right-hand column and joins the flow, so a
           long author name never squeezes it to an ellipsis. */
        flex-direction: column;
        align-items: flex-start;
        row-gap: 6px;
        column-gap: 0;
    }

    .codleade-review-head-main {
        /* The row's main axis is now vertical, where `flex: 1 1 auto` would
           let this block stretch. It should size to its content and let the
           date sit directly under it. */
        flex: none;
        width: 100%;
    }

    .codleade-review-date {
        /* margin-inline-start: auto pushes to the END of the main axis, which is now
           the BOTTOM — it would drop the date to the foot of the block. */
        margin-inline-start: 0;
    }

    .codleade-reviews-cta .write-review-toggle {
        max-width: none;
    }
}

/* ── Submit in flight ──────────────────────────────────────────────────────
 *
 * The one visual for the submission lock in reviews.js. The button keeps every
 * bit of its styling from base.css's button contract; this only dims it and
 * stops a second pointer press landing on it while the first submission is on
 * its way.
 *
 * It is NOT the guard. The guard is the flag in reviews.js, which holds even
 * with CSS or pointer events unavailable — and the button deliberately never
 * gets `disabled`, because a disabled submit control is dropped from the
 * payload and some browsers cancel the navigation already under way.
 */
.codleade-reviews form[aria-busy="true"] .submit-review-btn {
    opacity: 0.65;
    cursor: progress;
    pointer-events: none;
}

.codleade-reviews .codleade-review-dialog-box .submit-review-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 8px;
}

.codleade-review-spinner {
    display: none;
    flex: none;
    width: 16px;
    height: 16px;
    border: 2px solid currentColor;
    border-inline-end-color: transparent;
    border-radius: 50%;
}

form[aria-busy="true"] .codleade-review-spinner {
    display: inline-block;
}

@media (prefers-reduced-motion: no-preference) {
    form[aria-busy="true"] .codleade-review-spinner {
        animation: codleade-review-spin 0.7s linear infinite;
    }
}

@keyframes codleade-review-spin {
    to { transform: rotate(360deg); }
}

/* ── Thank-you panel (replaces the form after a successful submission) ── */

.codleade-reviews .codleade-review-dialog-box .codleade-review-thanks {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 12px;
    padding: 16px 0 4px;
    text-align: center;
}

.codleade-reviews .codleade-review-dialog-box .codleade-review-thanks[hidden] {
    display: none;
}

.codleade-review-thanks-icon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 56px;
    height: 56px;
    border-radius: 50%;
    color: var(--codleade-bg-primary, #fff);
    background: var(--codleade-brand);
}

.codleade-review-thanks-icon svg {
    width: 28px;
    height: 28px;
}

.codleade-reviews .codleade-review-thanks-title {
    margin: 0;
    font-size: 16px;
    font-weight: 700;
    color: var(--codleade-text-primary);
}

.codleade-reviews .codleade-review-thanks-pending {
    margin: 0;
    font-size: 13px;
    line-height: 1.4;
    color: var(--codleade-text-secondary);
}

.codleade-reviews .codleade-review-thanks-pending[hidden] {
    display: none;
}

.codleade-reviews .codleade-review-thanks-close {
    width: 100%;
    margin-top: 8px;
}
