/* ==========================================================================
   #DIGX-REVIEWS
   Task 13, FIZI Reviews Espana -- SSR reviews widget styles.

   REDESIGN PASS 2 (2026-08-27): Nikita rejected pass 1 twice for being
   "styled from judgment" while a measured control sat one measurement away.
   This pass replaces every value below with a number read straight off the
   live Judge.me control (docs/CONTROL-SPEC-REVIEWS.md, measured via
   getComputedStyle at 1440px on the live theme 203203412293). Nothing here
   is eyeballed.

   Structural fixes this pass makes:
     1. Every font-size below is now a LITERAL px value, never `em`/`rem`.
        Pass 1 computed sizes from `calc()` chains against the theme's own
        --font--size-h2/h4 tokens relative to a shifted root, which is what
        produced the off-scale 15.2px/17.1px/12.35px/21.375px numbers Nikita
        flagged. The control uses fixed px throughout; so do we now.
     2. The summary row's three-baseline defect (avg/stars/count sitting on
        different lines in the rejected screenshot) is fixed with exactly
        ONE rule on .digx-reviews__summary-headline: align-items: center.
        No other layout trick is needed once that is set correctly.
        (PASS 3 CORRECTION: that was wrong, and the measurement in the pass-3
        note below says why. `align-items: center` centres BOXES, and the
        boxes were 24px and 45px, so it left an 11px offset. The element was
        renamed .digx-reviews__rating in pass 3 and every child now shares
        one box height, which is what actually equalises the edges.)
     3. The summary's star indicator is a SINGLE star icon next to the
        average number, not a 5-star row -- confirmed by opening the
        control's own screenshot (control-summary.png), not assumed: one
        purple star, "5.0", "7 reseñas", a mint "Verificado" pill, all on
        one baseline. The per-review row keeps its 5-star rating (that one
        genuinely is 5 stars, 136x24, confirmed in control-review-row.png).
     4. The "useful?" vote row and the funnel-icon filter square are KEPT
        (an earlier draft of this brief mistakenly said to delete them --
        corrected against control-review-row.png / control-filters.png,
        which show both are real parts of the control). Both are restyled
        onto the control's own measurements below, not removed.

   REDESIGN PASS 3 (2026-08-28) -- HEADER REBUILD + LEDGER PROMOTION.
   Two changes, both from Nikita's own words on the pass-2 render:
   "top part has to be completely redesigned, wrong font application, and
   redesign layout and alignment of this", plus his pick of the Ledger body
   layout out of the round-1 variant picker.

     A. LEDGER IS NOW THE DEFAULT BODY LAYOUT. The two-column review row
        (reviewer identity in a fixed 128px left rail, stars/title/body/
        photos/useful in the wide right column) moved out of
        the round-1 picker stylesheet and into the "review row: LEDGER"
        block near the bottom of this file. It needs NO data attribute now.
        The Replica and Gallery body layouts are deleted, not commented out.

     B. THE HEADER IS REBUILT AROUND THREE MEASURED DEFECTS, each fixed at
        its root rather than nudged:

        (a) THE STAR SAT 11px HIGHER THAN THE NUMBERS. Measured bottom
            edges at 1440px: star -975, average -986, count -986. The row
            was `align-items: center`, which centres a 24px-tall star BOX
            against a 45px-tall average BOX -- that is box centring, not
            text alignment, and it leaves exactly (45 - 24) / 2 = 10.5px
            of offset, which is the 11px in the measurement.
            THE FIX, and the rule to re-measure against: every child of
            .digx-reviews__rating is forced to the SAME box height,
            var(--digx-rating-line). When every flex item on a line has an
            identical cross size, `align-items: center` becomes a no-op and
            every child's bottom edge equals the row's own bottom edge. The
            expected delta is 0px, not "smaller".

        (b) `em` TYPE SURVIVED ON THE CONTAINERS. Leaf elements were pinned
            to px in pass 2, their WRAPPERS were not, so
            .digx-reviews-root / .digx-reviews__summary /
            .digx-reviews__controls all still computed the theme's inherited
            `font-size: 15.2px; line-height: 27.36px` (0.8em of a 19px root,
            1.8 line-height). Anything added to those wrappers later
            inherited the junk. Fixed at the source: .digx-reviews-root
            and .digx-reviews both declare a literal `font-size: 16px;
            line-height: 24px`, so every descendant inherits a sane value
            instead of a computed one.
            AND THE THEME TRAP (docs/CONTROL-SPEC-REVIEWS.md, "The theme
            trap that caused the type complaints"): the theme ships an
            INLINE `body p { line-height: 1.5 !important; margin-bottom:
            1.375em !important }`. No plain class selector can beat it. The
            summary average and the summary count were <p> elements whose
            line-height AND bottom margin both matter, so the average was
            carrying a phantom 41.25px bottom margin nothing could reset.
            Both are <span> now (snippets/digx-reviews-widget.liquid), as
            are the empty state and the load-more status. ONE <p> is left in
            the component -- .digx-review__body, frozen by the byte-parity
            contract with lib/reviews/fragments.ts -- and it is pinned with
            `!important` class declarations that DO outrank `body p`
            (specificity 0,2,0 against 0,0,2). See its own rule below.

        (c) A 952px DEAD GAP. Summary content measured 158px wide while the
            controls cluster started at x1110. That void is what reads as
            unfinished. Round 2 offered three answers behind a ?variants=1
            picker; see PASS 4 below for which one shipped.

        Also in scope, because he asked for the top to be redesigned: the
        heading was 20px/400, which matched Judge.me but reads as body copy
        rather than a section title. Pass 3 made it 24px/700/lh32.
        SUPERSEDED BY PASS 5 -- 24px/700 was still a style of our own
        invention, and that is the thing Nikita rejected next. The heading
        now carries the theme's own `section__title-text` class and this
        file declares no type on it at all. See the .digx-reviews__heading
        rule below.

   PASS 4 (2026-08-28) -- BREAKDOWN PROMOTED, FILTERS ON THE BOTTOM RAIL,
   EVERY STATE GIVEN A LOOK.

     A. BREAKDOWN IS THE HEADER. Nikita picked it out of the round-2
        picker, so every Breakdown rule folded into the summary block below
        as the plain default, and the picker's own stylesheet and script are
        DELETED, not commented out. Compact and Banner no longer exist, no
        attribute switches the header any more, and the whole harness is
        gone from the theme -- grep it and nothing comes back.

     B. THE FILTER + SORT CLUSTER SITS ON THE BOTTOM RAIL. Nikita: "align
        the filters to the bottom please". The header row was
        `align-items: center`, which floated a 48px cluster in the middle
        of a 136px distribution block. It is `align-items: end` now, with
        `align-self: end` restated on the cluster itself so the contract
        cannot be broken from the container. Test in the summary block.

     C. EVERY SETTING THAT CAN REMOVE A HEADER CHILD HAS A GRID ANSWER.
        grid-template-areas reserves a track whether or not the area has an
        occupant, so switching the distribution or the whole controls
        cluster off would have re-opened defect (c) as a "setting". The two
        --no-dist / --no-controls modifiers below redeclare the template.

     D. STATE SWEEP. Every interactive element in this component now has a
        rest / hover / focus-visible look, and the two that carry a
        persistent state (the filter button once a rating is applied, the
        vote button once pressed) look different from merely being hovered.
        Two real defects came out of it, both marked at their rule:
        the sort chevron had ZERO clearance from its own label, and the
        vote button's text was rgb(123,123,123) where the measured control
        is rgb(0,0,0) -- 4.23:1, under the AA body floor, from a value the
        control never had.

   PASS 5 (2026-08-29) -- THE SITE'S H2, THE HEADER'S DEAD SPACE, AND THE
   STAR'S OPTICAL CENTRE. Nikita on the pass-4 render: "You are not using
   the h2 from the rest of the website, also still feels badly aligned the
   first session an badly designed still."

     A. THE HEADING IS THE SITE'S OWN H2. Every type declaration is deleted
        from .digx-reviews__heading and the markup carries the theme's own
        `section__title-text` class instead. Full reasoning at that rule.
        This retires pass 3's 24px/700 heading AND pass 2's replication of
        Judge.me's 20px/400 one: where the site and the control disagree
        about a section heading, the site wins from here on.

     B. THE 128px VOID IN THE HEADER IS GONE, and it was a grid template,
        not a spacing value. The heading owned a full-width row above a
        136px row, so the 32px rating fell to the bottom of that row and
        left 24 + (136 - 32) = 128px under the title. The distribution now
        spans both rows and the heading and rating share the left column as
        a 12px-apart stack. Full derivation, and the row maths to
        re-measure, at "THE HEADER FROM 768px UP" below.

     C. THE SUMMARY STAR IS ALIGNED TO THE DIGITS' OPTICAL CENTRE, not to
        the middle of its own box. Pass 3 equalised the boxes and proved a
        0.00px edge delta; the star still read low because ink is not box.
        The correction is computed from the font's own capHeight and the
        SVG path's own bounds, and it moves the ink inside a box whose
        edges do not move. See .digx-reviews__summary-stars svg.

   PASS 6 (2026-08-29) -- COMPACT PROMOTED, PHOTOS AT 2x, THE SUMMARY IS A
   STICKY LEFT COLUMN, AND THE PRODUCT PAGE'S STARS JUMP HERE.
   Nikita on the round-3 picker: "I like compact, but I would increase the
   size of images like 2x. And make it so this part was fixed on the top and
   be in one column (left) while reviews are on the right", plus "Also this
   part has to be clickable with anchor link to this block as well".

     A. COMPACT IS THE BODY LAYOUT. Every rule that carried the round-3
        harness attribute in the picker's own stylesheet is folded in below
        with no attribute in front of it. Ledger, the round-1 pick, is
        DELETED -- its 128px identity rail is gone, not overridden. The
        picker's stylesheet, its script and the two asset tags that loaded
        them are deleted too: grep this theme for the harness attribute or
        either asset name and nothing comes back, exactly as round 2's
        harness left. The attribute name is deliberately not repeated
        anywhere in this theme, so that grep stays the honest check.

     B. REVIEW PHOTOS ARE 128px, twice the 64px they shipped at. The size has
        to come from CSS because the <img> carries width="64" height="64" in
        markup frozen by the byte-parity contract with lib/reviews/
        fragments.ts, and BOTH dimensions are set on both the anchor and the
        image so that 1:1 attribute ratio cannot leak back in. See the
        .digx-review__photo rule for the source-pixel arithmetic.

     C. THE SUMMARY IS A STICKY LEFT COLUMN FROM 1024px UP. The widget root
        stops being a block and becomes a two-track grid. Full derivation,
        the column arithmetic and the tall-summary guard are in "THE WIDGET
        IS TWO COLUMNS FROM 1024px UP" below.

     D. THE PRODUCT PAGE'S OWN STAR CLUSTER IS A LINK to this block.
        snippets/pdp-block-rating.liquid does the wrapping; the last section
        of this file styles it, and .digx-reviews carries the
        scroll-margin-top that keeps the heading out from under the page's
        own sticky header on arrival.

   Design tokens reused from snippets/css-variables.liquid so this component
   still inherits the storefront's brand type scale where the control does
   not dictate an exact literal value (font-family, the load-more CTA):
     --font--body (PF Agora Sans Pro stack) -- interactive labels, filter/
                          sort chrome, and the load-more CTA.
     --color--headings   #755BA6 brand purple -- kept ONLY where the control
                          itself is purple: the star glyph color (confirmed
                          by control-review-row.png; the control's product
                          widget runs purple stars, its homepage carousel
                          runs amber -- two different controls, two
                          different colors, both already correct pre-pass-2
                          and untouched here) and the load-more CTA (no
                          control equivalent to match).
     --color--text-light  #212121 @ 70% alpha -- filter/sort chrome chevron
                          well and non-control-specified meta text only.

   Every OTHER color below is now a literal value read off the control,
   because the control specifies it exactly and reusing a theme token would
   silently drift from the measurement the moment that token changes:
     rgb(0, 0, 0)          body/heading/avg/count/name/date-adjacent text
                            the control actually renders in pure black, per
                            CONTROL-SPEC-REVIEWS.md's "Body colour rgb(0,0,0)
                            in the product widget" (the carousel is
                            rgb(33,33,33) instead -- a different control,
                            untouched by this file).
     --digx-muted          the review date and the overlay's photo counter.
                            CONTROL-SPEC-REVIEWS.md documents the control's
                            muted colour as rgb(123,123,123); ours is
                            rgb(117,117,117), the only value in this file
                            that departs from a measurement for an
                            accessibility reason rather than a design one --
                            4.23:1 against 4.54:1, with the 4.5:1 AA body
                            floor in between. The arithmetic is on the token
                            itself. It is deliberately NOT the theme's own
                            --color--text-light (an alpha blend, not a flat
                            gray): swapping to that var would drift this off
                            the measured value in a different direction.
     rgba(126, 113, 204, .1)  avatar fill -- control's own
                            color(srgb .494 .443 .8 / .1), NOT the same
                            purple as --color--headings (#755BA6 = rgb(117,
                            91,166)) -- close but genuinely a different
                            color in the control, kept literal on purpose.
     rgb(156, 242, 231)    the summary "Verificado" pill background (mint) --
                            not a brand-family color, but this is exactly
                            what the control renders; inventing a purple/
                            off-palette substitute would be styling from
                            judgment again.

   Spacing is restricted to the 4/8/12/16/24/32/48/64/96/128px scale
   EXCEPT where the control measured something else and this file says so
   inline with a comment -- the in-scope instance is the review name row's
   6px gap (CONTROL-SPEC-REVIEWS.md line 65). The homepage carousel card
   also carries a documented 22px margin, but that element lives in
   assets/digx-reviews-carousel.css, owned by a different pass right now --
   not applied here.

   Mobile-first; no fixed widths below 768px that could overflow a 375px
   viewport (the control was measured at 1440px only, so below 768px this
   file falls back to flexible widths rather than guessing a mobile control
   that was never measured).
   ========================================================================== */

/* THE BLOCK ROOT -- renamed from .section-digx-reviews when the widget became a
   theme app extension (2026-09-07). The theme section used to wrap the widget in
   `class="section section--{id} section-digx-reviews"`; an app block owns no
   theme classes at all, so the same three layout values live on the block's own
   root element, and the colour tokens the block's settings write live here too.
   Each token's DEFAULT is the value this widget renders on the Spain store
   today, so the stylesheet alone reproduces Spain; the block's inline style
   overrides whichever ones the merchant set (an inline declaration outranks this
   rule), which is how Poland gets its own palette without a second stylesheet. */
.digx-reviews-root {
  /* --digx-brand    the widget's own accent: the star glyphs and the merchant
                     reply's rail. Was the hardcoded --digx-star below.
     --digx-heading  every place the theme's own headings colour token used to
                     resolve: the <h2>, focus rings, the sort control.
     --digx-muted    the muted grey, moved up here from .digx-reviews so the
                     block's setting can reach it (a declaration on .digx-reviews
                     would win against an inline style on this element, since
                     .digx-reviews is the closer ancestor of every consumer).
                     rgb(117,117,117) is 4.54:1 on white; the long note further
                     down says why it is not the control's rgb(123,123,123).
     --digx-text     the subtree's base text colour. */
  --digx-brand: #755BA6;
  --digx-heading: #755BA6;
  --digx-muted: rgb(117, 117, 117);
  --digx-text: rgb(0, 0, 0);

  max-width: 1200px;
  margin-inline: auto;
  padding: 48px 16px;
  /* DEFECT (b), fixed at the source. Without these two literals this
     element computes the theme's inherited 15.2px / 27.36px (0.8em of a
     19px root x 1.8), and so does every wrapper under it that does not
     declare its own size -- which is exactly how .digx-reviews__summary and
     .digx-reviews__controls ended up carrying `em`-derived type after
     pass 2 pinned only the leaves. Declared here and on .digx-reviews so
     the whole subtree inherits 16/24 instead of a computed fraction. */
  font-size: 16px;
  line-height: 24px;
}

@media screen and (min-width: 768px) {
  .digx-reviews-root {
    padding-inline: 32px;
  }
}

/* THE HEADING IS THE SITE'S OWN H2 NOW -- PASS 5, 2026-08-29.

   Nikita: "You are not using the h2 from the rest of the website." He is
   right, and this rule is why. It used to declare font-family, font-size,
   font-weight, line-height, text-transform, colour and letter-spacing, two
   of them with `!important` specifically to beat the theme -- so this
   heading could never be the site's heading, only a third style competing
   with it.

   ALL SEVEN DECLARATIONS ARE DELETED. The markup carries the theme's own
   `section__title-text` class instead (snippets/digx-reviews-widget.liquid),
   which is the class every real section title on this storefront uses:
   "BESTSELLERS", "FAQ", "MEET OUR PRODUCT LINES", "Follow us on Instagram".
   Measured on the live store, that class plus the theme's own h1-h6 rules
   compute to PF Agora Sans Pro / 33.44px / 900 / lh 38.456px / uppercase /
   rgb(117, 91, 166) / letter-spacing -0.3px. Nothing here re-states any of
   those numbers: restating one is how the next drift starts.

   THIS OVERRIDES THE PASS-3 DECISION, deliberately. Pass 3 made the heading
   24px/700/sentence-case/black, reasoning from the measured Judge.me
   control's own 20px/400 line. That reasoning is retired: the brief is no
   longer "replicate the control", it is "be the site". Where the site and
   the control disagree about this heading, the site wins. Do not restore a
   type declaration to this rule.

   WHAT IS LEFT IS LAYOUT ONLY. `margin: 0` because the heading is a grid
   item and the summary grid's row-gap owns the space under it (and because
   the theme's shared reset otherwise puts 1rem under every heading);
   `grid-area` lives in the 768px block further down.

   THE EXTENSION PUTS THE TYPE BACK -- 2026-09-07. Pass 5's reasoning was "be
   the site", and the way it did that was to borrow the theme's own
   `section__title-text` class. An app block cannot borrow a theme class: the
   extension ships to three storefronts on two different themes, and a class it
   does not own is a class that may not exist. So the declarations come back, as
   the SITE'S OWN MEASURED VALUES rather than an invention: 33.44px / 900 /
   uppercase / rgb(117,91,166) / letter-spacing -0.3px, measured on the live
   Spain store. Two of them are parameterised instead of pinned, because they
   are the two that must differ per store: the colour is the block's own heading
   setting, and the case is the `heading_style` select (a store whose section
   titles are sentence case would otherwise get a shouting heading). The family
   is `inherit`: whatever the host theme sets on the page is closer to "be the
   site" than any name we could hardcode, and hardcoding PF Agora Sans Pro would
   ship a font Poland's theme does not load. The size is a clamp rather than the
   measured 33.44px for the same reason: 33px is the Spain theme's own H2 at
   1440px and a guess at any other width. */
.digx-reviews__heading {
  margin: 0;
  font-family: inherit;
  font-weight: 900;
  font-size: clamp(24px, 2.4vw, 32px);
  line-height: 1.15;
  color: var(--digx-heading, #755BA6);
  letter-spacing: 0.02em;
}

/* Case is a per-store choice, not a per-widget one, so it rides on the root's
   data attribute rather than on a second class. Sentence case is the other
   option and needs no rule: it is what the markup already carries. */
.digx-reviews-root[data-heading="uppercase"] .digx-reviews__heading {
  text-transform: uppercase;
}

/* Empty state has no summary grid to give the heading its spacing, so the
   heading carries its own there. Scoped through .digx-reviews (0,2,0) so it
   cannot lose a source-order coin toss with the theme's own
   `.section__title-text { margin: 0 }` (0,1,0), which the markup now also
   carries. */
.digx-reviews .digx-reviews__heading--solo {
  margin-bottom: 24px;
}

.digx-reviews {
  /* --digx-star: the one color token this component still needs of its own
     -- neither --color--headings' hex value nor the carousel's amber is a
     drop-in match for "whatever the PDP control's own star color is"; it
     happens to equal --color--headings today (#755BA6) but is named
     separately so a future carousel-only palette change can't silently
     drag this component's stars along with it. */
  --digx-star: var(--digx-brand, #755BA6);

  /* The header's shared geometry, as tokens, so a variant changes ONE value
     instead of re-declaring four rules. --digx-rating-line is the single
     box height every child of .digx-reviews__rating is forced to, and it is
     what makes defect (a) impossible to reintroduce: equal boxes on one
     flex line have equal bottom edges by construction. */
  --digx-rating-line: 32px;
  --digx-avg-size: 30px;
  --digx-summary-star: 24px;

  /* THE READING MEASURE, and the arithmetic is the point. `1ch` in this font
     at 16px measures 8.93px on the real page, so 624 / 8.93 = 69.9ch, the
     top of the 65-to-70 target the round-3 variants were built against and
     inside the canon's 45-to-75 band. It is also 39 steps of the 16px body
     size, so it does not drift off the type rhythm. In REAL Spanish letters
     it is about 89, not 70: PF Agora averages 7.01px per glyph against the
     `0` glyph's 8.93. Both numbers are true and 27 percent apart -- the
     value is left at the number Compact was judged and picked at rather than
     quietly re-tuned afterwards.

     It caps three things, and they must stay in step or the list loses its
     left rail: the review card, the load-more button and the load-more
     status line. */
  --digx-measure: 624px;

  /* THE MUTED GREY, AND WHY IT IS NOT THE CONTROL'S rgb(123,123,123).
     CONTROL-SPEC-REVIEWS.md records the control's muted text as
     rgb(123,123,123). Measured against white that is 4.23:1, under the
     4.5:1 AA body floor, and it is carried by real content: the review
     date and the lightbox's photo counter, both at 14px, neither of them
     large text under WCAG. Pass 3 already refused to introduce a THIRD
     instance of the value for the same reason (see .digx-reviews__dist-count
     below, which went black) and left the existing two "called out in the
     pass report rather than changed here". Two passes deferring one defect
     is how it never gets fixed.
     rgb(117,117,117) is 4.54:1 -- over the floor, and six points of grey
     away from the measured value, which is below the threshold at which
     anyone can see a difference. The design canon is a hard workspace rule
     and the control does not get to overrule it; a 6-point darkening is the
     smallest change that satisfies both. Declared once, as a token, so the
     overlay in assets/digx-reviews-lightbox.css inherits the same value
     instead of copying the number.

     MOVED TO .digx-reviews-root (2026-09-07): declared here it would outrank
     the block root's inline style for every consumer inside .digx-reviews,
     which is every consumer there is, so the colour setting would have been a
     picker that changed nothing. The value did not change. */

  /* DEFECT (b): literal px here too, so .digx-reviews__summary and
     .digx-reviews__controls inherit 16/24 rather than the theme's 15.2 /
     27.36. Nothing in this component computes a font-size from `em`. */
  font-size: 16px;
  line-height: 24px;
  /* The base text colour, parameterised 2026-09-07 so a store whose body copy
     is not black can say so once. Default unchanged. */
  color: var(--digx-text, rgb(0, 0, 0));

  /* THE ANCHOR TARGET'S OWN OFFSET. This element is `id="digx-reviews"`, and
     snippets/pdp-block-rating.liquid now links to it from the star cluster
     under the price. The page's own sticky header is a single element
     measuring 73px tall, so without this the heading arrives underneath it.
     96px is the only value on the {4,8,12,16,24,32,48,64,96,128} scale that
     clears 73, and it is the SAME number the sticky summary uses for its own
     `top`, so the jump and the sticky column agree about where the top of
     the page is. */
  scroll-margin-top: 96px;
}

/* Fallback only. The theme already ships .visually-hidden (the filter and
   sort labels have used it since pass 1); this scoped copy means the
   distribution's per-bar accessible names cannot silently become visible
   text if that theme utility is ever renamed. */
.digx-reviews .visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

.digx-reviews__empty {
  margin: 0;
  padding: 32px 0;
  color: var(--digx-muted, #6B6B6B);
  font-size: 16px;
}

/* ---- star rows -------------------------------------------------------- */

/* Summary: a SINGLE star icon, not a 5-star row -- confirmed against
   control-summary.png. PASS 3 made it an inline SVG instead of the U+2605
   glyph it was: a glyph's drawn box depends on the font's own metrics, so
   its rendered top and bottom edges are not knowable from CSS, and defect
   (a) is a measurement of exactly those edges. An SVG's box is the box we
   declare, and it scales with --digx-summary-star when a variant changes
   the band.

   DEFECT (a), part 1 of 3: this box is var(--digx-rating-line) TALL, not
   var(--digx-summary-star) -- the icon is 24px, the box it lives in is the
   full 32px band, and the icon is centred inside it. The other two children
   of .digx-reviews__rating declare the same height. Equal boxes on one flex
   line have equal bottom edges, whatever `align-items` says. */
.digx-reviews__summary-stars {
  /* inline-block, NOT inline-flex, and this is load bearing. A flex item
     with no text has a SYNTHESISED baseline, and Chrome synthesises a flex
     container's from its first child's BORDER-box bottom, which ignores the
     negative margin below and left the star 3.49px above the line (measured
     on the live page, both ways). An inline-block synthesises from its own
     bottom MARGIN edge, so the margin counts and the star lands on the
     baseline to within 0.01px. Measured, not reasoned: five candidate rules
     were rendered on the real page and this is the one that returned 0. */
  display: inline-block;
  flex: 0 0 auto;
  width: var(--digx-summary-star);
  /* BASELINE, NOT EQUAL BOXES -- 2026-08-30. Nikita: "align to the baseline
     when text layers are near each other." The old rule made all three
     children var(--digx-rating-line) tall so their BOTTOM edges lined up,
     which is a different thing: measured on the live page, "27 resenas" sat
     3.5px above the baseline of "4.9" and the star's feet 1.34px above it.
     The row is now align-items: baseline, so this box hugs its icon and
     stops imposing a 32px band on the line. */
  height: auto;
  color: var(--digx-star);
}

/* DEFECT (a) HAS A SECOND HALF, AND IT IS OPTICAL. PASS 5, 2026-08-29.

   Pass 3 equalised the BOXES: the star box, the average and the count are
   all exactly var(--digx-rating-line) tall, so their top and bottom edges
   measure a 0.00px delta. That is still true and nothing below changes it.
   Nikita's crop still shows the star sitting visibly lower than "4.9",
   because equal boxes are not equal INK: a 24px star centred in a 32px band
   centres on the band, while digits centre on their own cap band, which
   sits above the band's middle by half the descender.

   THE ARITHMETIC, from the font's own metrics rather than from taste.
   PF Agora Sans Pro (assets/PFAgoraSansPro-*.ttf, read out of the head /
   hhea / OS-2 tables): unitsPerEm 1000, ascent 750, descent 250, capHeight
   693 in the UltraBlack face -- which is the face that renders here, since
   the theme declares only weights 400 and 900 and CSS font matching sends
   font-weight: 700 to 900.

     line box              L = var(--digx-rating-line) = 32px
     average size          S = var(--digx-avg-size)    = 30px
     content area          = (750 + 250) / 1000 x S    = S exactly
     half-leading          = (L - S) / 2               = 1px
     baseline from box top = 1 + 0.750 x 30            = 23.5px
     cap top               = 23.5 - 0.693 x 30         = 2.71px
     DIGITS' OPTICAL CENTRE = (2.71 + 23.5) / 2        = 13.105px

   And the star's ink, which is not centred in its own viewBox either: the
   path spans y 2.4 to 20.51 of a 0 0 24 24 box, so its ink centre sits at
   11.455/24 = 0.47729 of the icon, not 0.5.

     STAR INK CENTRE = L/2 + I x (0.47729 - 0.5)       = 15.455px

   15.455 - 13.105 = 2.35px too low, which is the offset in the crop.

   THE FIX moves the INK, never the box: the <svg> is translated up inside a
   box that keeps its 32px height and its shared edges, so every box-edge
   measurement still reads 0.00px while the drawn star lines up with the
   digits. Written as a calc off the two tokens so it stays correct if the
   average size or the icon size ever changes -- note that L cancels out of
   the derivation entirely, so the band height is free to move:

     lift = 0.0965 x S - 0.02271 x I
          = 0.0965 x 30 - 0.02271 x 24 = 2.895 - 0.545 = 2.35px

   where 0.0965 = 0.750 - 0.5 - 0.693/2 (ascent, half-leading, half cap) and
   0.02271 = 0.5 - 11.455/24 (the path's own bias inside its viewBox).

   This is a typographic correction measured in sub-pixels, not a layout
   space, so the 4/8/12/16/24 spacing scale does not apply to it -- the
   canon's scale governs gaps, padding and margins, and snapping an optical
   correction to 4px would put the star 1.65px wrong on purpose. */
.digx-reviews__summary-stars svg {
  display: block;
  width: var(--digx-summary-star);
  height: var(--digx-summary-star);
  /* A replaced element has no text baseline, so flexbox synthesises one from
     its BOTTOM MARGIN EDGE. The star path bottoms out at 20.51 of the
     24-unit viewBox, leaving 14.54% of the icon box empty underneath, so
     without this the synthesised baseline sits 3.49px below the glyph's own
     feet and the star floats. Pulling the box up by exactly that strip puts
     the star's feet ON the line that "4.9" and "27 resenas" sit on.
     0.1454 = 1 - (20.51 / 24), read off this file's own <path>. This is a
     typographic correction in sub-pixels, not a layout gap, so the
     4/8/12/16/24 spacing scale does not govern it. */
  margin-bottom: calc(var(--digx-summary-star) * -0.1454);
}

/* Per-review row: 5 stars, 136x24 total (control-review-row.png). Still
   rendered via the shared digx-review-stars snippet (byte-parity contract
   with lib/reviews/fragments.ts's reviewProductItemHtml(), see the Liquid
   snippet's own header comment) -- only the box this component gives that
   markup changes here. Explicit width/height lock the box to the measured
   control size regardless of glyph metrics; font-size/letter-spacing make
   the 5 glyphs actually fill it. */
.digx-stars,
.digx-review__stars {
  display: inline-block;
  line-height: 1;
  letter-spacing: 4px;
}

.digx-review__stars {
  width: 136px;
  height: 24px;
  overflow: hidden;
  color: var(--digx-star);
  font-size: 24px;
  line-height: 24px;
}

.digx-stars__label {
  margin-left: 8px;
  color: var(--digx-muted, #6B6B6B);
  font-size: 14px;
}

/* ---- badges (Verificado pills) -------------------------------------------
   The summary pill (filled, mint) and the per-review pill (outline, black)
   no longer share sizing -- the control renders them at different weights/
   line-heights/padding, so only the truly shared properties stay on the
   base .digx-badge rule. */

.digx-badge {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  font-family: inherit;
  white-space: nowrap;
}

.digx-badge__icon {
  width: 11px;
  height: 11px;
}

/* ONE VERIFIED PILL, IN THE BRAND PURPLE (2026-08-29).

   Nikita: "You have two different pills for verified purchase, has to be in
   brand color." He is right, and the reason is uncomfortable: the two styles
   were a faithful replication. Judge.me itself ships TWO verified badges on
   the same page -- `jm-verified-badge`, a mint pill on rgb(156,242,231), in
   the summary, and `jm-verified-buyer-badge__text`, a black outline pill, on
   each review row. Both were copied exactly, so we inherited its
   inconsistency along with its measurements. Neither is a FIZI colour.

   Both modifiers now resolve to the same treatment: the site's own heading
   purple on a 12 percent tint of itself. Measured 4.70:1, over the 4.5:1 AA
   text floor. `--filled` and `--outline` are kept as separate selectors only
   because two renderers emit those class names (this file's Liquid and
   lib/reviews/fragments.ts), and collapsing the markup would break the
   byte-parity contract with the load-more endpoint for no visual gain.

   Sizes stay at the control's measurements. What changed is colour, not
   geometry. */
.digx-badge--filled,
.digx-badge--outline {
  padding: 3px 9px;
  border: 1px solid transparent;
  border-radius: 24px;
  background: rgba(117, 91, 166, 0.12);
  color: rgb(117, 91, 166);
  font-weight: 500;
  font-size: 12px;
  line-height: 18px;
}

.digx-badge--filled .digx-badge__icon,
.digx-badge--outline .digx-badge__icon {
  color: rgb(117, 91, 166);
}

/* The per-review pill's geometry, kept from control-deep.txt
   (jm-verified-buyer-badge__text: 12px/500/lh18px, padding 3px 9px, radius
   24px). 3px/9px is off the 4/8/12 spacing scale on purpose: it is a literal
   control measurement, not a spacing decision. Colour is set above, shared
   with the summary pill. */

/* ---- summary row ---------------------------------------------------------*/

/* The header is ONE grid over four children in one fixed DOM order:
   heading, rating, dist, controls. Nothing moves in the markup, so keyboard
   order always matches visual order and the SSR contract is untouched.

   Mobile-first: no template at all below 768px, just a single column in
   source order with a 16px gap. Below that width the distribution stacks
   full width under the rating and the controls sit under it, which is the
   only shape a 128px-wide bar chart and a 192px control cluster can share
   on a 375px screen. */
.digx-reviews__summary {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: 16px;
  padding-bottom: 24px;
  margin-bottom: 24px;
  border-bottom: 1px solid rgba(0, 0, 0, 0.1);
}

/* THE HEADER FROM 768px UP -- TWO ROWS, THREE COLUMNS. PASS 5, 2026-08-29.

   WHAT WAS WRONG, MEASURED AT 1440px. The heading's bottom edge sat at
   -1192.6 and the rating's top edge at -1064.6: 128px of dead air between a
   section title and the number it introduces. That gap is what Nikita's
   "still feels badly aligned ... badly designed still" is pointing at, and
   it was structural, not a spacing value anyone could have tuned:

     grid-template-areas: "heading heading heading"
                          "rating  dist    controls";

   gave the heading a full-width row of its own, then put the rating in a
   SECOND row whose height is set by the 136px distribution beside it. With
   `align-items: end` the 32px rating fell to the bottom of that 136px row,
   so the space under the heading was row-gap 24 + (136 - 32) = 128. The
   number is exactly reproducible from the template; no amount of gap
   tuning could have reached it.

   THE FIX IS THE TEMPLATE. The distribution now SPANS both rows, and the
   heading and the rating share the left column as the natural stack they
   always read as:

     grid-template-columns: auto minmax(240px, 1fr) auto;
     grid-template-areas:  "heading dist controls"
                           "rating  dist controls";

   Left column: title, then the rating line under it, 12px apart. Middle:
   the five-bar breakdown, full height. Right: filter and sort, on the
   bottom rail. Two things stacked against a chart and a control cluster --
   which is what the header was always trying to be.

   `grid-template-rows: auto 1fr` IS LOAD-BEARING, not decoration. With two
   `auto` rows, CSS grid splits a spanning item's extra height EQUALLY
   across the rows it spans, so the 136px distribution would have pushed
   ~20.8px into the heading's own row and floated the heading down off the
   top edge. `auto 1fr` pins row 1 to the heading's own height and hands
   every remaining pixel to row 2, so the heading's top edge is the header's
   top edge, by construction.

   THE ROW MATHS AT 1440px, which is the thing to re-measure:
     row 1  = the heading, 38.456px (the site's own H2 line-height)
     gap    = 12px
     row 2  = 1fr = 136 - 38.456 - 12 = 85.544px
     total  = 136px, set by the distribution (5 x 24 + 4 x 4)
     heading   top 0,      bottom 38.456
     rating    top 50.456, bottom 82.456   (align-self: start)
     controls  top 88,     bottom 136      (align-self: end, 48px tall)
     dist      top 0,      bottom 136
   Heading bottom to rating top is therefore exactly the row-gap, 12px,
   at every viewport and in every modifier -- it cannot drift, because the
   two edges are the two sides of one gap.

   WHAT SURVIVES FROM PASS 4, UNCHANGED:
     - `align-items: end` on the container, so .digx-reviews__controls stays
       on the bottom rail with the distribution. That was Nikita's explicit
       ask and it still measures a 0.00px delta against the distribution's
       bottom edge: the distribution is the tallest item, so its bottom edge
       IS the row's bottom edge, which is where `end` puts the cluster.
     - `align-self: end` restated on the cluster itself, so a later change
       to the container cannot move it without anyone noticing.
     - The star / average / count baseline. That is a flex rule INSIDE
       .digx-reviews__rating and is independent of where the element sits.

   THE TRACKS. `auto` for the left column so it sizes to its own content,
   `minmax(240px, 1fr)` for the distribution so it takes every pixel the
   other two do not, `auto` for the controls. 240px is the floor at which a
   bar track still reads as a bar. The left column is now the WIDER of the
   heading and the rating rather than the rating alone, so at the 768px
   breakpoint it can ask for more room than it used to; `auto` shrinks
   toward min-content under pressure and the heading wraps to two lines
   before anything overflows (row 1 then grows and row 2 absorbs the rest,
   which is exactly what `auto 1fr` is for). */
@media screen and (min-width: 768px) {
  .digx-reviews__summary {
    grid-template-columns: auto minmax(240px, 1fr) auto;
    grid-template-rows: auto 1fr;
    grid-template-areas:
      "heading dist controls"
      "rating  dist controls";
    column-gap: 48px;
    /* 12px, not the 24 it was: the heading and the rating are one unit now
       (Gestalt proximity), and 48px of column gap is what separates that
       unit from the chart. Both values are on the 4/8/12/16/24/32/48 scale. */
    row-gap: 12px;
    align-items: end;
  }

  /* A MISSING CHILD IS NOT A MISSING TRACK. grid-template-areas reserves
     all three columns whether or not every area has an occupant, so a shop
     owner switching off the breakdown or both controls would leave the
     header holding an empty 240px or 192px track -- defect (c) again, this
     time with a setting to blame for it. CSS cannot select "my sibling is
     absent", so snippets/digx-reviews-widget.liquid resolves the two cases
     into modifier classes (its note B) and they redeclare the template.
     All three keep the two-row shape, so the heading/rating stack survives
     every setting combination; only the columns change. */
  .digx-reviews__summary--no-dist {
    grid-template-columns: minmax(0, 1fr) auto;
    grid-template-areas:
      "heading controls"
      "rating  controls";
    column-gap: 32px;
  }

  .digx-reviews__summary--no-controls {
    grid-template-columns: auto minmax(240px, 1fr);
    grid-template-areas:
      "heading dist"
      "rating  dist";
  }

  .digx-reviews__summary--no-dist.digx-reviews__summary--no-controls {
    grid-template-columns: minmax(0, 1fr);
    grid-template-areas:
      "heading"
      "rating";
  }

  .digx-reviews__heading { grid-area: heading; }
  .digx-reviews__dist { grid-area: dist; }

  .digx-reviews__rating {
    grid-area: rating;
    /* TOP of row 2, which is 12px under the heading. NOT `end`: `end` would
       drop it to the bottom of a row that the 136px distribution stretches,
       which is the 128px defect this pass exists to remove. The heading is
       the top rail, the rating hangs directly off it, and the row's own
       bottom rail belongs to the chart and the controls. */
    align-self: start;
  }

  .digx-reviews__controls {
    grid-area: controls;
    /* THE JOB-2 CONTRACT, restated on the element the test measures instead
       of inherited from the container. A later change to the summary's own
       `align-items` must not be able to move this cluster off the bottom
       rail without anyone noticing. */
    align-self: end;
  }
}

/* DEFECT (a). Read the three height declarations below as one rule:
   the star box, the average and the count are ALL exactly
   var(--digx-rating-line) tall. When every flex item on a line shares a
   cross size equal to the line's own cross size, `align-items: center`
   resolves to a zero offset for all of them, so
   star.bottom === average.bottom === count.bottom === row.bottom, exactly,
   at every viewport and in every header variant. The pass-2 bug was that
   the star box was 24px and the average box was 45px inside a `center`
   row, which is (45 - 24) / 2 = 10.5px of offset -- the measured 11px.

   The verified pill is deliberately NOT forced to the band height: a pill
   is a shape, not a line of type, and it reads correctly centred at its own
   22px. It is not part of the star/number alignment claim. */
.digx-reviews__rating {
  display: flex;
  flex-direction: row;
  align-items: baseline;
  flex-wrap: wrap;
  gap: 8px;
  min-width: 0;
}

/* The verified pill is a SHAPE, not a text layer: baseline-aligning a
   padded pill hangs it below the line the three text layers share. It
   centres on the big number instead. */
.digx-reviews__rating > .digx-badge {
  align-self: center;
}

.digx-reviews__summary-avg {
  display: block;
  height: auto;
  margin: 0;
  color: rgb(0, 0, 0);
  font-family: inherit;
  font-weight: 700;
  font-size: var(--digx-avg-size);
  line-height: var(--digx-rating-line);
}

.digx-reviews__summary-count {
  display: block;
  height: auto;
  margin: 0;
  color: rgb(0, 0, 0);
  font-weight: 400;
  font-size: 16px;
  line-height: var(--digx-rating-line);
}

/* ---- rating distribution (the 5 bars) -------------------------------------
   The data was already in the snapshot (`snap.dist`, index 0 = 1 star) and
   already rendered -- buried inside the collapsed filter panel, where it is
   invisible until a shopper opens a funnel button. Surfacing it in the
   header is what lets Breakdown and Banner spend defect (c)'s 952px on real
   information instead of decoration.

   ALWAYS RENDERED NOW (pass 4). Breakdown is the shipping header, so this
   block is `display: flex` with no attribute and no picker in front of it.
   The one switch left is the shop owner's own `show_distribution` setting,
   and that one removes the <ul> from the SERVED HTML rather than hiding it
   here -- a `display: none` element is still in the accessibility tree,
   still a payload byte, and still a lie about what the setting does.

   THESE BARS ARE DISPLAY ONLY, NOT CONTROLS. The interactive rating filter
   stays exactly where it is, in the funnel <details> panel, because
   assets/digx-reviews.js binds its rows by querying inside
   [data-digx-filter-panel] -- and that file is not in this pass's scope.
   Making these bars clickable without touching that file would ship a dead
   control, which is a hard block here. So they are <li> elements, not
   buttons, and they claim no interactive affordance.

   ACCESSIBILITY: each row carries a visually hidden accessible name of the
   form "5 estrellas: 4 reseñas" (rating plus count, built from the locale
   keys the filter panel already uses), and the count is ALSO printed as
   visible text next to the bar -- so neither the bar's colour nor its
   length is the only carrier of the value. */
.digx-reviews__dist {
  display: flex;
  flex-direction: column;
  gap: 4px;
  min-width: 0;
  margin: 0;
  padding: 0;
  list-style: none;
}

.digx-reviews__dist-row {
  display: flex;
  align-items: center;
  gap: 8px;
  height: 24px;
  color: rgb(0, 0, 0);
  font-size: 14px;
  line-height: 24px;
}

.digx-reviews__dist-num {
  flex: 0 0 8px;
  text-align: right;
}

.digx-reviews__dist-star {
  display: inline-flex;
  flex: 0 0 12px;
  align-items: center;
  justify-content: center;
  height: 24px;
  color: var(--digx-star);
}

.digx-reviews__dist-star svg {
  display: block;
  width: 12px;
  height: 12px;
}

.digx-reviews__dist-track {
  flex: 1 1 auto;
  min-width: 64px;
  height: 8px;
  overflow: hidden;
  border-radius: 4px;
  background: rgba(0, 0, 0, 0.08);
}

.digx-reviews__dist-fill {
  display: block;
  height: 100%;
  border-radius: 4px;
  background: var(--digx-star);
}

/* ---- THE CHART IS THE FILTER -- 2026-08-30 -----------------------------
   Each row is a <button> that filters the list to its own star rating, and
   pressing the active row again clears it. A row whose count is 0 ships
   `disabled`: filtering to a rating with no reviews would empty the list and
   read as a broken widget, which is the dead-control class this workspace
   hard-blocks on.

   The row keeps the exact geometry it had as a static <li> child -- same
   24px height, same 8px gap, same track and fill -- so nothing about the
   chart moves when it becomes interactive. What is added is the affordance:
   a pointer cursor, a hover wash, a real focus ring, and a pressed state
   that fills the row so "you are looking at 5 stars only" is visible without
   reading the list. */
.digx-reviews__dist-row {
  /* The negative margin pulls the hover wash out to the chart's own edges
     without moving the bars: the row grows sideways into its own padding, so
     the numbers and the track stay exactly where the static version put
     them. */
  width: calc(100% + 16px);
  margin: 0 -8px;
  padding: 0 8px;
  border: 0;
  border-radius: 6px;
  background: transparent;
  color: inherit;
  font: inherit;
  text-align: left;
  cursor: pointer;
  transition: background-color 0.15s ease;
}

.digx-reviews__dist-row:hover:not(:disabled) {
  background: rgba(117, 91, 166, 0.08);
}

.digx-reviews__dist-row:focus-visible {
  outline: 2px solid var(--digx-star);
  outline-offset: 2px;
}

.digx-reviews__dist-row[aria-pressed="true"] {
  background: rgba(117, 91, 166, 0.16);
}

/* Never colour alone: the pressed row also carries the only bold weight in
   the chart, so the active filter still reads without hue. */
.digx-reviews__dist-row[aria-pressed="true"] .digx-reviews__dist-num,
.digx-reviews__dist-row[aria-pressed="true"] .digx-reviews__dist-count {
  font-weight: 700;
}

.digx-reviews__dist-row:disabled {
  cursor: default;
  /* Not a dead control: a 0-review row has nothing to filter to, and WCAG
     1.4.11 exempts an inactive component from the 3:1 floor. It still prints
     its own "0" at full contrast, so the data is never dimmed -- only the
     affordance is. */
  opacity: 0.55;
}

/* The reset. Hidden until a filter is actually on, so the chart carries no
   spare chrome in its resting state. assets/digx-reviews.js toggles
   `hidden`, and `hidden` alone is not enough here: the flex display below
   would override it. */
.digx-reviews__dist-clear {
  align-self: flex-start;
  margin-top: 4px;
  padding: 4px 8px;
  border: 0;
  border-radius: 6px;
  background: transparent;
  color: var(--digx-star);
  font-family: inherit;
  font-size: 14px;
  font-weight: 700;
  line-height: 24px;
  cursor: pointer;
}

.digx-reviews__dist-clear[hidden] {
  display: none;
}

.digx-reviews__dist-clear:hover {
  background: rgba(117, 91, 166, 0.08);
}

.digx-reviews__dist-clear:focus-visible {
  outline: 2px solid var(--digx-star);
  outline-offset: 2px;
}

.digx-reviews__dist-count {
  flex: 0 0 24px;
  text-align: right;
  /* Black, not the component's rgb(123,123,123) muted token. That token
     measures 4.23:1 against white, under the 4.5:1 body floor, and this is
     NEW text -- introducing another instance of a known-failing value is
     not something a redesign pass gets to do. (The existing instances, the
     review date and the filter-panel numbers, are called out in the pass
     report rather than changed here: they are measured control values and
     nobody asked for them.) */
  color: rgb(0, 0, 0);
}

/* ---- summary-row controls: filter button + sort <select> ------------------
   CONTROL-SPEC-REVIEWS.md line 38 + 76 and control-filters.png: the
   control's filter button (funnel icon) and its sort dropdown ARE two
   separate elements side by side -- kept as two elements here, not merged.
   What was wrong in the rejected build was their SIZE: the whole cluster
   measures 178x48 total, right-aligned, gap 8px, align-items: stretch so
   both controls share the exact same 48px height and matching border
   radius/colour -- that equal-height rule is the actual fix for the
   "misaligned buttons" defect. */

/* The theme has no global border-box reset, so every fixed height in this
   file was growing by its own padding plus border: the filter button measured
   66px against a declared 48px (48 + 8*2 + 1*2), and the sort select grew by a
   different amount because its padding differs. Two controls, two heights,
   which is the misalignment in Nikita's screenshot. Scope border-box to this
   widget rather than resetting the theme. */
.digx-reviews *,
.digx-reviews *::before,
.digx-reviews *::after {
  box-sizing: border-box;
}

.digx-reviews__controls {
  display: flex;
  align-items: stretch;
  justify-content: flex-end;
  gap: 8px;
  width: 100%;
}

@media screen and (min-width: 480px) {
  .digx-reviews__controls {
    /* 192px, not the control's measured 178px, and the 14px is not a
       styling opinion. `feedback_design_dropdown_chevron_padding` is a hard
       rule in this workspace and the sort select was breaking it: 12px of
       chevron sitting 12px from the right edge against 24px of text padding
       left EXACTLY zero clearance between the longest label and the glyph.
       Fixing that costs the label 8px of room, and "Mejor valoradas" at
       12px/500 already needed about 87 of the 95px it had. So the 8px is
       given back to the control (40 filter + 8 gap + 144 sort = 192)
       instead of taken out of the label, which keeps the label space at
       the control's own value rather than truncating a real option. */
    /* 144px, was 192px. The 192 was "40 filter + 8 gap + 144 sort"; the
       filter button is gone (see the note further down), so the cluster is
       the sort control and nothing else. */
    width: 144px;
    /* Right-aligns the cluster in BOTH layouts with one declaration: as an
       auto margin in the stacked 480-767px column, and as the same auto
       margin inside its own grid track from 768px up. No justify-self
       needed. */
    margin-left: auto;
  }
}

/* ---- THE FILTER DROPDOWN IS GONE -- 2026-08-30 -------------------------
   Nikita: "Filters button does not work, and what are you filtering? People
   should be able to click on the review bar and once it is clicked that
   particular filter is applied."

   Both halves were true. The funnel opened a panel that measured 34px wide
   against a 244px tall menu (measured on the live page), so the rows were an
   unreadable sliver -- the click handler worked, the box did not. And the
   panel's five rows were a SECOND copy of the distribution chart already
   drawn 16px above it, so the control asked the shopper to open a menu to
   reach a duplicate of what they were already looking at.

   The chart IS the control now. Every rule for .digx-reviews__filter,
   __filter-btn, __filter-menu, __filter-row, __filter-num, __filter-track,
   __filter-fill and __filter-count was deleted rather than fixed: there is
   no second copy left to style. The interactive states live with the chart
   itself, on .digx-reviews__dist-row above. */

.digx-reviews__sort {
  flex: 1 1 auto;
  min-width: 0;
}

@media screen and (min-width: 480px) {
  /* 144px, was 128px. The 16px is the chevron-clearance fix's bill, paid by
     the cluster instead of by the label -- see the .digx-reviews__controls
     width note above for the arithmetic. */
  .digx-reviews__sort {
    flex: 0 0 144px;
  }
}

.digx-reviews__sort-select {
  width: 100%;
  height: 48px;
  /* The theme gives every <select> a 12px bottom margin. With the cluster on
     `align-items: stretch` that margin made the whole control row 60px while
     the filter button stayed 48px, so the two controls sat at different
     heights: the exact misalignment Nikita photographed. */
  margin: 0;
  /* Padding was the control's own literal measurement (control-deep.txt:
     "pad 6px 24px 6px 9px"). The RIGHT value is now 32px, and this is the
     one place in this file where a hard workspace rule beats a measured
     control value.
     THE DEFECT: the chevron is 12px wide drawn 12px in from the right edge,
     so it occupies the band from 12px to 24px. A 24px right padding put the
     longest label's last glyph at exactly 24px. Zero clearance -- the text
     touched the glyph, which is what
     `feedback_design_dropdown_chevron_padding` (HARD) forbids.
     32px puts 8px of air between the label and the chevron. 9px/6px stay
     the control's literal values. */
  padding: 6px 32px 6px 9px;
  border: 1px solid rgb(0, 0, 0);
  border-radius: 8px;
  background-color: #FFFFFF;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20' width='12' height='12'%3E%3Cpath d='M5 7l5 6 5-6' fill='none' stroke='%23000000' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 12px center;
  color: rgb(0, 0, 0);
  font-family: inherit;
  font-weight: 500;
  font-size: 12px;
  appearance: none;
  cursor: pointer;
}

/* Hover was missing: the select looked identical whether or not the pointer
   was on it, so it read as a label rather than a control. */
.digx-reviews__sort-select:hover {
  background-color: rgba(0, 0, 0, 0.05);
}

.digx-reviews__sort-select:focus-visible {
  outline: 2px solid var(--digx-heading, #755BA6);
  outline-offset: 2px;
}

/* ---- THE WIDGET IS TWO COLUMNS FROM 1024px UP -- PASS 6, 2026-08-29 -------
   Nikita, picking Compact: "make it so this part was fixed on the top and be
   in one column (left) while reviews are on the right".

   WHAT IT BUYS. Compact was measured leaving about 500px of empty page to
   the right of a 624px list inside the 1136px frame. That void is where the
   summary lives now, so the same density Nikita picked also keeps the
   average, the breakdown and the two controls on screen while he reads down
   the list, instead of scrolling away after the first row.

   EVERY CHILD OF THE ROOT IS PLACED BY HAND. The root has four in-flow
   children in the populated branch (summary, list, load-more button,
   load-more status) and two in the empty one (the solo heading, the empty
   line). Auto-placement over a two-track template would drop the load-more
   button into column 1, under the summary, the moment a product passes 10
   reviews -- a state no local fixture has and nobody would see until it
   shipped. So nothing is left to it. Rows 2 and 3 collapse to zero height
   when the button is absent, because this component has no row-gap anywhere:
   every vertical gap in it is a margin.

   .digx-lightbox IS NOT A GRID ITEM AND MUST NEVER BECOME ONE. It is
   `position: fixed` (assets/digx-reviews-lightbox.css), and an out-of-flow
   child of a grid container is not a grid item at all, so the placement
   below changes nothing today. It is written down anyway: if that element
   ever loses its fixed position it would otherwise claim a track and shove
   the entire list sideways. Placed across both columns on row 1, so the
   worst case it can ever produce is an overlay, never a reflow.

   THE COLUMNS: 384px + 48px + whatever is left.
   384 = 3 x 128, off the spacing scale's own top step, and it is read from
   the measured content rather than chosen by eye:
     - the rating line measures 24 star + 8 + 52 average + 8 + 74 count + 8 +
       82 verified pill = 256px, so it stays on ONE line. That is what keeps
       the star / average / count baseline contract alive in a narrow column;
       .digx-reviews__rating wraps, and a wrap is what would break it.
     - the five-bar breakdown keeps 384 - 68 = 316px of track, well over the
       240px floor at which a bar still reads as a bar.
     - the 192px filter-plus-sort cluster fits with room to spare.
   48px is the column gap the summary's own header grid already used.
   At a 1440px viewport the section is 1200px wide with 32px of padding, so
   the frame is 1136px and the right column is 1136 - 384 - 48 = 704px. The
   review card stops at --digx-measure (624px), which leaves 80px of trailing
   air: a right margin, not the 500px void Compact carried. At exactly 1024px
   the frame is 960px and the right column is 528px, which the card fills
   completely.

   `align-self: start` IS LOAD-BEARING, NOT TIDINESS. A grid item left on the
   container's default `stretch` is exactly as tall as its row, and a sticky
   element that is as tall as its containing block has nowhere to travel --
   the stickiness would look like a no-op and nobody would know why. It is
   declared on the container AND restated on the summary itself so a later
   change to the container cannot silently kill it.

   THE TALL-SUMMARY GUARD IS A HEIGHT QUERY, NOT AN INTERNAL SCROLLER. A
   summary taller than the viewport sticks at a position the shopper can
   never scroll past. The obvious fix -- `max-height` plus `overflow-y: auto`
   -- is WRONG HERE: it would make the summary a scroll container and clip
   the filter panel, which is a `position: absolute` menu hanging off
   .digx-reviews__filter, so the funnel button would open onto a cut-off
   list. A dead-looking control is a hard block in this workspace, so the
   stickiness itself is gated on viewport height instead, in its own query
   below. The summary measures about 380px at this column width (heading up
   to two lines at ~77 + 12 + rating 32 + 16 + chart 136 + 16 + controls 48,
   plus slack); at 640px of viewport there are 640 - 96 = 544px of room for
   it, a 164px margin. Under 640px tall the block is an ordinary, scrolling
   part of the page.

   THE SUMMARY'S OWN DIVIDER GOES. Its border-bottom used to run the full
   1136px and part the header from the list. Under a 384px column the same
   hairline separates nothing from nothing and reads as a leftover; the 48px
   column gap is what parts the two now.
   -------------------------------------------------------------------------*/

@media screen and (min-width: 1024px) {
  .digx-reviews {
    display: grid;
    grid-template-columns: 384px minmax(0, 1fr);
    column-gap: 48px;
    /* Zero, deliberately. Every vertical gap in this component is a margin
       (the list's own row dividers, the load-more's 32px top margin), so a
       row-gap here would double them AND stop the empty explicit rows above
       from collapsing to nothing when there is no load-more button. */
    row-gap: 0;
    align-items: start;
  }

  /* Column 1, spanning every row the right column can produce, so the sticky
     summary can travel the whole length of the list rather than stopping at
     the bottom of row 1. */
  .digx-reviews__summary {
    grid-column: 1;
    grid-row: 1 / span 3;
    align-self: start;
    /* See the note above: a full-width hairline has nothing left to separate
       once the header is a column of its own. */
    padding-bottom: 0;
    margin-bottom: 0;
    border-bottom: 0;
  }

  /* THE SUMMARY RESTACKS TO ONE COLUMN. From 768px up it is a two-row,
     three-column grid (heading and rating stacked left, the chart spanning
     both rows in the middle, the controls on the bottom right rail). None of
     that fits 384px, so the template is REPLACED rather than squeezed: one
     column, source order, 16px apart.

     ALL FOUR SELECTORS ARE LISTED, and that is not belt-and-braces. A media
     query adds no specificity of its own, and
     .digx-reviews__summary--no-dist.digx-reviews__summary--no-controls is a
     0,2,0 compound declared earlier in this file -- a plain
     .digx-reviews__summary here (0,1,0) would lose to it and a shop with
     both switches off would keep a three-column template in a 384px box. */
  .digx-reviews__summary,
  .digx-reviews__summary--no-dist,
  .digx-reviews__summary--no-controls,
  .digx-reviews__summary--no-dist.digx-reviews__summary--no-controls {
    grid-template-columns: minmax(0, 1fr);
    grid-template-rows: auto;
    grid-template-areas: none;
    column-gap: 0;
    row-gap: 16px;
    align-items: stretch;
  }

  /* The four named areas do not exist any more, so the names have to go with
     them. Liquid still renders the same four children in the same DOM order
     and a single-column grid places them in exactly that order. */
  .digx-reviews__heading,
  .digx-reviews__rating,
  .digx-reviews__dist,
  .digx-reviews__controls {
    grid-area: auto;
  }

  /* The cluster was right-aligned against the chart's right edge while the
     header was wide. In a 384px column the whole summary reads as one left
     rail -- heading, rating line, chart, controls -- so the auto margin goes.
     The width stays the measured 192px: stretching a 12px label's select to
     384px would scale a control well past its own content for nothing. */
  .digx-reviews__controls {
    margin-left: 0;
  }

  /* Column 2, one explicit row each. */
  .digx-reviews__list {
    grid-column: 2;
    grid-row: 1;
  }

  .digx-reviews__load-more {
    grid-column: 2;
    grid-row: 2;
  }

  .digx-reviews__load-more-status {
    grid-column: 2;
    grid-row: 3;
  }

  /* The empty branch has no summary and no list -- only these two children
     exist there. Both span the frame and stack in source order, which is
     exactly what they render as today. Declared after the grid-area reset
     above, because .digx-reviews__heading--solo also carries
     .digx-reviews__heading and the two selectors are the same specificity. */
  .digx-reviews__heading--solo,
  .digx-reviews__empty {
    grid-column: 1 / -1;
  }

  /* The guard described above. Fixed elements are not grid items, so this is
     inert today and exists only so it can never become a track. */
  .digx-lightbox {
    grid-column: 1 / -1;
    grid-row: 1;
  }
}

/* THE STICKINESS, AND THE ONLY PLACE IT IS DECLARED. Split out of the block
   above so the height guard is impossible to lose in an edit: a viewport
   shorter than 640px never gets a summary that can pin itself somewhere the
   shopper cannot scroll past. 96px clears the page's own 73px sticky header
   and is the same offset .digx-reviews carries as scroll-margin-top. */
@media screen and (min-width: 1024px) and (min-height: 640px) {
  .digx-reviews__summary {
    position: sticky;
    top: 96px;
  }
}

/* ---- review list -----------------------------------------------------------
   CONTROL-SPEC-REVIEWS.md line 59: each row gets its own bottom border and
   bottom padding, plus a 24px top margin between rows -- the divider our
   pass-1 version was missing entirely. */

.digx-reviews__list {
  display: flex;
  flex-direction: column;
  margin: 0;
  padding: 0;
  list-style: none;
}

/* COMPACT'S ROW BOX. 16px of bottom padding and 16px between rows, down from
   24 and 24: the density position Nikita picked, both values on the
   {4,8,12,16,24,32,48,64,96,128} scale.

   THE CARD STOPS AT THE MEASURE, AND SO DOES ITS DIVIDER. A dense row running
   the full frame would print 127ch per line, which is worse than what the
   block shipped with -- the layout would answer the height question by making
   the width question worse. Capping the <li> rather than only the paragraph
   is what keeps the divider, the star row and the helpful cluster on the same
   right edge as the last word: a hairline running past the end of the text is
   the giveaway that a column was capped as an afterthought.

   NO `display` HERE, EVER. The filter hides a row with `li.hidden = true`
   (assets/digx-reviews.js), which relies on the UA stylesheet's
   `[hidden] { display: none }`. An author-origin `display` on this element
   would beat that and the funnel would silently stop hiding anything. That is
   also why the Compact grid below goes on .digx-review__card, the <article>
   inside this <li>, and not here. */
.digx-review {
  max-width: var(--digx-measure);
  padding: 0 0 16px;
  margin-top: 16px;
  border-style: solid;
  border-width: 0 0 1px;
  border-color: rgba(0, 0, 0, 0.2);
}

.digx-reviews__list > .digx-review:first-child {
  margin-top: 0;
}

.digx-review__header {
  display: flex;
  align-items: center;
  gap: 8px;
  margin: 16px 0 0;
}

/* 32px, not the control's 44px. The avatar is what sets the height of the
   merged identity line, so leaving it at 44 would mean building a dense row
   and then refusing to let it be dense. On the spacing scale, and it still
   holds a 16px/700 initial with room on every side. */
.digx-review__avatar {
  display: flex;
  flex: 0 0 auto;
  align-items: center;
  justify-content: center;
  width: 32px;
  height: 32px;
  border-radius: 50%;
  /* Control's own literal measurement (color(srgb .494 .443 .8 / .1)) --
     see the file header note: this is NOT --color--headings, it is a
     slightly different purple the control itself uses only here. */
  background: rgba(126, 113, 204, 0.1);
  color: rgb(0, 0, 0);
  font-family: inherit;
  font-weight: 700;
  font-size: 16px;
}

/* Name, verified pill and date on ONE line, not stacked. `baseline` rather
   than `center` because these are two different type sizes (16px name, 14px
   date) and centring their boxes would leave them visibly off each other's
   baseline -- the same class of defect the summary row's --digx-rating-line
   token exists to prevent. `wrap` is the narrow-viewport guard: a long
   Spanish name plus a pill plus a date drops the date onto its own line
   rather than pushing anything out of the card, and `overflow-wrap` catches
   the one case wrapping cannot, a single unbroken word with no space in it. */
.digx-review__identity {
  display: flex;
  flex-direction: row;
  align-items: baseline;
  flex-wrap: wrap;
  gap: 8px;
  min-width: 0;
  overflow-wrap: break-word;
}

.digx-review__name-row {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  /* 6px is off the 4/8/12 spacing scale on purpose -- CONTROL-SPEC-
     REVIEWS.md line 65 measures this gap at exactly 6px; the "control
     wins" exception named in this rebuild's brief. */
  gap: 6px;
}

.digx-review__author {
  font-weight: 700;
  font-size: 16px;
  color: rgb(0, 0, 0);
}

/* Zero, not 4px. That margin existed to part the date from the name row it
   sat UNDER; on the same line it is just a 4px push out of alignment. */
.digx-review__date {
  margin-top: 0;
  /* See --digx-muted above: 4.54:1, not the control's failing 4.23:1. */
  color: var(--digx-muted);
  font-weight: 400;
  font-size: 14px;
}

.digx-review__title {
  margin: 0 0 8px;
  color: rgb(0, 0, 0);
  font-family: inherit;
  /* Same assets/theme.css !important h1-h6 rule as .digx-reviews__heading
     above applies here too -- this element is an <h3>. Not present in any
     control sample review, so sized off the shared 16px body scale rather
     than a measured control value. */
  font-weight: 700 !important;
  font-size: 16px;
  text-transform: none !important;
  letter-spacing: normal;
}

/* THE ONE <p> LEFT IN THIS COMPONENT, and the only one whose line-height
   and bottom margin this file depends on. It cannot become a <span> or a
   <div>: the tag is frozen by the byte-parity contract with
   lib/reviews/fragments.ts's reviewProductItemHtml(), which re-renders this
   exact element for AJAX load-more pages, and that file is outside this
   pass's scope.

   So it is pinned with `!important` instead, and that is not a coin flip:
   the theme's inline rule is `body p { ... !important }` at specificity
   (0,0,2); this rule is (0,1,0). Between two `!important` author
   declarations the higher specificity wins, so these two land and the
   theme's 1.5 line-height and 1.375em (22px) phantom bottom margin do not.
   Without the second one, the Ledger grid below inherits a 22px bottom
   margin on the body that grid layout will NOT collapse away, and every
   review row grows by 22px of dead space above its useful row. */
.digx-review__body {
  margin-top: 16px;
  margin-bottom: 0 !important;
  color: rgb(0, 0, 0);
  font-weight: 400;
  font-size: 16px;
  line-height: 24px !important;
  /* Redundant while .digx-review carries the same cap, and kept on purpose:
     it is the floor that survives if the card cap is ever raised, so the
     paragraph can never go back to the 109ch line the block shipped with.
     Pass 1's note here said "no max-width cap, runs the full row width" --
     that was written when the row WAS the frame. It is not any more. */
  max-width: var(--digx-measure);
}

.digx-review__media {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin-top: 12px;
}

/* 128px, TWICE THE 64px THIS SHIPPED AT. Nikita: "I would increase the size
   of images like 2x."

   THE SIZE HAS TO COME FROM CSS. The <img> inside carries width="64"
   height="64" as HTML attributes, and that markup is frozen by the
   byte-parity contract with lib/reviews/fragments.ts, which re-renders every
   load-more row and cannot be taught about a change made here. BOTH
   dimensions are declared on this anchor and BOTH are declared on the image
   below, because a single dimension would let the attributes' intrinsic 1:1
   aspect ratio decide the other one.

   NOTHING UPSCALES, AND IT MUST STAY THAT WAY. The thumbnail sources this
   store serves measure 375x500 and 500x281. `object-fit: cover` on a 128px
   square scales by the SHORT side, so the crop needs 128 of 375 and 128 of
   281 -- both about a third of the source. Even on a 2x DPR screen it needs
   256 of 375 and 256 of 281, still inside both. Raising this box past 281
   CSS px would start upscaling the landscape source at 1x, and past 140 at
   2x; either is a hard block under the no-upscale rule. Re-measure the
   sources before changing this number. */
.digx-review__photo {
  display: block;
  width: 128px;
  height: 128px;
  overflow: hidden;
  border-radius: 8px;
}

/* Both states were missing. A 64px thumbnail that opens a full-size photo
   had nothing on hover and no ring on Tab, so a keyboard user walking a
   review with four photos could not tell which one was about to open.
   box-shadow rather than a border for the hover ring: a border would change
   the box and nudge the row. */
.digx-review__photo:hover {
  box-shadow: 0 0 0 2px var(--digx-heading, #755BA6);
}

.digx-review__photo:focus-visible {
  outline: 2px solid var(--digx-heading, #755BA6);
  outline-offset: 2px;
}

/* zoom-in ONLY when the overlay is actually wired. With the lightbox
   setting off the anchor is a plain link to the image and the ordinary
   pointer is the truthful cursor for that. The flag is written by
   snippets/digx-reviews-widget.liquid onto the widget root. */
[data-digx-reviews][data-lightbox="true"] .digx-review__photo {
  cursor: zoom-in;
}

/* BOTH dimensions, and that is the point. The <img> carries width="64"
   height="64" attributes this file cannot remove; with only one of the two
   set here, the browser would keep honouring that 1:1 intrinsic ratio and the
   thumbnail would not follow the anchor to 128px. `cover` keeps every photo a
   square crop whatever the source aspect is. */
.digx-review__photo img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.digx-review__media video {
  display: block;
  max-width: 100%;
  height: auto;
  border-radius: 8px;
}

/* ---- useful / vote row -----------------------------------------------------
   KEPT (corrected mid-build): control-review-row.png shows "¿Útil? 👍0 👎0"
   on every row, so this is a faithful copy of the control, not an
   invention. Restyled to the control's own measurements
   (control-deep.txt jm-voting-controls block): label + both buttons in the
   flat control-deep.txt jm-voting-controls block): label + both buttons in the
   flat "muted colour" rgb(123,123,123), NOT brand purple; icons 20x20 (was
   16x16); label+count text ~14px regular, consistent with the date line;
   gap 16px between the label and each button, matching the control's own
   jm-voting-controls cluster measurement (33 + 16 + 37 + 16 + 37 = 139,
   the exact width control-deep.txt records for that cluster). Hover/active
   states are our own addition (the control is a static screenshot, no
   interaction state was measured) and shift toward brand purple for
   affordance -- this does not contradict any measured value. */

.digx-review__useful {
  display: flex;
  align-items: center;
  gap: 16px;
  /* Measured off the control, not read off a screenshot: the row is 40px tall,
     sits 16px under the body, and its type is 16px/400 in black. An earlier
     pass styled it 14px muted grey from a screenshot reading and it was wrong
     on all three counts. */
  height: 40px;
  margin-top: 16px;
  font-size: 16px;
  line-height: 24px;
  color: rgb(0, 0, 0);
}

.digx-review__useful-label {
  color: rgb(0, 0, 0);
  font-weight: 400;
  font-size: 16px;
  line-height: 24px;
}

.digx-review__vote-btn {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 4px 8px;
  border: 0;
  border-radius: 8px;
  background: none;
  /* WAS rgb(123, 123, 123), and that was wrong twice over.
     1. It contradicted the measurement this whole file is built on:
        CONTROL-SPEC-REVIEWS.md line 138 records the control's vote row at
        "type 16px / 400, colour rgb(0,0,0)". The parent .digx-review__useful
        rule already sets black; only the button opted out.
     2. rgb(123,123,123) on white computes 4.23:1, under the 4.5:1 AA body
        floor, and the vote count is real content, not decoration.
     Black fixes both and moves TOWARD the control, not away from it. */
  color: rgb(0, 0, 0);
  font-family: inherit;
  font-weight: 400;
  font-size: 14px;
  cursor: pointer;
}

/* Hover and pressed used to share one declaration block, so a button the
   shopper had actually pressed looked exactly like one their cursor
   happened to be over -- and since the vote is per-browser and persists
   across reloads, that is the state that most needs to be readable.
   Hover is a neutral grey field; pressed is a purple field with purple
   type (5.5:1 on white, 4.8:1 on its own tint, both over the AA floor). */
.digx-review__vote-btn:hover {
  background: rgba(0, 0, 0, 0.05);
}

.digx-review__vote-btn.is-active {
  background: rgba(126, 113, 204, 0.12);
  color: var(--digx-heading, #755BA6);
}

.digx-review__vote-btn:focus-visible {
  outline: 2px solid var(--digx-heading, #755BA6);
  outline-offset: 2px;
}

.digx-review__vote-icon {
  width: 20px;
  height: 20px;
}

.digx-review__vote-icon--down {
  transform: rotate(180deg);
}

/* ---- review row: COMPACT (the default body layout, promoted 2026-08-29) ---
   Nikita picked Compact out of the round-3 picker ("I like compact"), so
   every rule that carried the harness's layout attribute moved here and lost
   it. There is nothing to set: this IS the layout. Measure, Stacked and
   Columns are deleted, and so are the picker's stylesheet, its script and the
   two asset tags in sections/digx-reviews.liquid that loaded them.

   IT REPLACES LEDGER, the round-1 pick, which pinned the reviewer identity in
   a fixed 128px left rail. That rail is GONE, not overridden -- the variants
   file had to neutralise it with a `grid-column: 1 / -1` catch-all because it
   was layered on top of a shipping rule, and there is nothing to neutralise
   here.

   WHAT COMPACT IS. Avatar, name, verified pill and date on ONE line with the
   five stars pinned right; the text directly under it; and the photo strip
   sharing its line with the helpful row instead of each claiming a band of
   its own. Three of Ledger's six blocks each held a full band; two of the
   three are merged away. Measured on the real store at 1440px before the
   promotion: 133px per row and a 1344px list, against Ledger's 225px per row
   and 1912px list.

   THE GRID GOES ON .digx-review__card (the <article>), NOT ON THE <li>. The
   <li> owns the row divider and the filter's `hidden` attribute and has to
   keep its normal block display, or the UA stylesheet's
   `[hidden] { display: none }` stops hiding filtered rows.

   480px, NOT 768px. At 320px the content box is 288px and the star row alone
   is a fixed 136px, which would leave 152px for an avatar, a name, a verified
   pill and a date. Below 480px the card falls back to block flow and keeps
   only the density -- 32px avatar, one-line identity, tighter row padding --
   which is the honest answer rather than shrinking a line until it wraps into
   a mess.

   ROWS ARE ASSIGNED EXPLICITLY rather than left to auto-placement, because
   the title and the media block are both optional. An empty explicit row
   collapses to zero height (there is no row-gap in this component: every gap
   here is a margin), whereas auto-placement would reshuffle the right-hand
   track every time a review has no photo. */

@media screen and (min-width: 480px) {
  .digx-review__card {
    display: grid;
    /* Two tracks: everything flexible on the left, the fixed 136px star row
       and the helpful cluster pinned right. `minmax(0, 1fr)` rather than
       `1fr` so a single unbreakable word in a name cannot widen the track
       past the card. */
    grid-template-columns: minmax(0, 1fr) auto;
    /* Vertical only: this is what sits the 24px star row against the 32px
       avatar. It does not touch the text blocks, which span both tracks and
       stretch horizontally as normal (that is `justify-items`, left at its
       default). */
    align-items: center;
  }

  /* A GUARD, NOT A FIX. All six blocks below are placed by hand, so nothing
     needs this today. It is here so a seventh block added later lands full
     width instead of colliding with the star track. Keep it FIRST: it has the
     same specificity as the placement rules under it, so source order is the
     only thing making those win. */
  .digx-review__card > * {
    grid-column: 1 / -1;
  }

  /* Line 1, left: avatar, name, verified pill, date. Zero margin because the
     header is the first thing in the card here, where in block flow it sits
     under the stars and needs 16px. */
  .digx-review__header {
    grid-column: 1;
    grid-row: 1;
    margin: 0;
  }

  /* Line 1, right. The stars move visually but NOT in the DOM, and that is
     safe in a way a hoisted photo strip would not be: this element is a <div>
     of five glyphs carrying an aria-label and no tab stop at all, so no focus
     order changes and a screen reader still reads the rating before the name,
     exactly as it does today. */
  .digx-review__stars {
    grid-column: 2;
    grid-row: 1;
    justify-self: end;
  }

  /* Rows 2 and 3 span both tracks: the text is the card, not a column of it.
     Both margins are stated in full because grid items never collapse
     margins, so an inherited bottom margin here would reopen the band this
     layout closes. 8px rather than 16px is the density position. */
  .digx-review__title {
    grid-column: 1 / -1;
    grid-row: 2;
    margin: 8px 0 0;
  }

  .digx-review__body {
    grid-column: 1 / -1;
    grid-row: 3;
    margin-top: 8px;
  }

  /* Line 4, shared. The photo strip and the helpful row are the two bands
     this layout merges, so they take the same explicit row with the same
     explicit top margin -- if the two margins differed, the taller one would
     size the row and the shorter block would float inside it.

     A review with no photos leaves this row holding only the helpful cluster,
     right-aligned on a line of its own. A shop that switches the helpful row
     off leaves only the thumbnails. Both are correct and neither needs a rule
     of its own, because an explicit grid row with no items in it collapses to
     zero height when there is no row-gap. */
  .digx-review__media {
    grid-column: 1;
    grid-row: 4;
    margin-top: 12px;
  }

  /* `end`, overriding the card's own `center`, and this changed WITH the 2x
     photos rather than before them. Against a 48px thumbnail a centred 40px
     cluster read as level with it; against a 128px one it floats in the
     middle of the photo band with 44px of air above and below. The bottom
     rail puts it level with the last thing in the review. */
  .digx-review__useful {
    grid-column: 2;
    grid-row: 4;
    justify-self: end;
    align-self: end;
    margin-top: 12px;
  }
}

/* ---- load more (Task 16, 2026-08-27) --------------------------------------
   No control equivalent exists to match (the Judge.me control was not
   observed paginating in the captured viewport) -- Nikita has not objected
   to this control, so it stays, restyled onto this file's literal-px scale
   instead of the old rem-based font-size.

   Server-rendered `hidden` by default (snippets/digx-reviews-widget.liquid)
   and only ever unhidden by assets/digx-reviews.js once a click handler is
   actually wired -- so a no-JS visitor never sees a dead control. The
   `[hidden]` rule below is declared explicitly (not left to the UA
   stylesheet): author-origin CSS always outranks the UA default regardless
   of selector specificity. */

/* CAPPED AT THE SAME MEASURE AS THE LIST, and this is part of the Compact
   promotion rather than a style choice. Once .digx-review stops at 624px the
   button is the only thing left running the full frame, so it would hang off
   the right of every row above it. */
.digx-reviews__load-more {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  max-width: var(--digx-measure);
  min-height: 48px;
  margin-top: 32px;
  padding: 12px 24px;
  border: 1.5px solid var(--digx-heading, #755BA6);
  border-radius: 999px;
  background: #FFFFFF;
  color: var(--digx-heading, #755BA6);
  font-family: inherit;
  font-weight: 700;
  font-size: 16px;
  line-height: 24px;
  cursor: pointer;
}

@media screen and (min-width: 768px) {
  .digx-reviews__load-more {
    width: auto;
    min-width: 240px;
    /* 0, not the `auto` it was. Centring made sense while the list ran the
       full frame; against a 624px list it would sit the button 40px right of
       every row's left edge at 1440px and 256px right of it at 1023px. The
       button belongs on the list's own left rail. */
    margin-inline: 0;
  }
}

.digx-reviews__load-more:hover {
  background: rgba(0, 0, 0, 0.05);
}

.digx-reviews__load-more:focus-visible {
  outline: 2px solid var(--digx-heading, #755BA6);
  outline-offset: 2px;
}

.digx-reviews__load-more.is-loading,
.digx-reviews__load-more:disabled {
  cursor: default;
  opacity: 0.7;
}

/* The hover fill has to go while the button is loading, or a pointer left
   resting on it after the click makes a disabled control look pressable. */
.digx-reviews__load-more:disabled:hover {
  background: #FFFFFF;
}

.digx-reviews__load-more[hidden] {
  display: none;
}

/* Same cap as the button it reports on, so the centred text is centred over
   the button rather than over the whole column. */
.digx-reviews__load-more-status {
  max-width: var(--digx-measure);
  margin: 12px 0 0;
  color: var(--digx-muted, #6B6B6B);
  font-size: 14px;
  text-align: center;
}

/* One <div> carries two very different messages: "loading" and "that
   failed, press again". They looked identical. The error gets full-strength
   black and a heavier weight -- NOT a red, because this component has no
   red and the design canon is brand palette only; introducing one hue for
   one line of text is not a trade worth making. */
.digx-reviews__load-more-status.is-error {
  color: rgb(0, 0, 0);
  font-weight: 500;
}

.digx-reviews__load-more-status:empty {
  display: none;
}


/* ---- the product page's star cluster, as a link to this block -------------
   PASS 6, 2026-08-29. Nikita, with a screenshot of the stars and the "(8)"
   under the price: "Also this part has to be clickable with anchor link to
   this block as well".

   snippets/pdp-block-rating.liquid does the wrapping. It puts a real
   <a href="#digx-reviews"> around the whole cluster -- the .rating div, the
   .rating-text line and the .rating-count line -- and only when the product
   actually has a review to jump to. A real anchor, not a scroll handler:
   it works with JavaScript off, it is focusable and it activates on Enter for
   free, and none of that has to be written or tested.

   THE RULES LIVE IN THIS FILE because this component is what the link points
   at, and the two numbers have to agree: .digx-reviews carries
   scroll-margin-top: 96px and the sticky summary carries top: 96px, both
   clearing the page's own 73px sticky header. Splitting them across two
   stylesheets is how they drift apart.

   `display: inline-block`, AND IT IS THE FOCUS RING THAT DECIDES IT. The
   three wrapped elements sit in normal inline flow inside a
   <div style="text-align: ..."> (the review-stars block in
   sections/main-product.liquid), and .rating and .rating-count are both
   inline-block. An `inline` anchor draws its outline around the FONT's own
   line box rather than around those two boxes, which is a ring that misses
   the stars. inline-block keeps the anchor inline-level, so the block's
   text-align still places the cluster exactly where it sits today, and gives
   the outline a real content box to wrap.

   THE RING CARRIES SOME AIR UNDER IT, DELIBERATELY. .rating-count is a <p>,
   so the theme's inline `body p { margin-bottom: 1.375em !important }` puts a
   phantom bottom margin inside this box. Resetting it here would work (a
   0,2,0 class selector beats the theme's 0,0,2 between two !important
   declarations) but it would also silently retighten the live product page's
   own spacing, on a snippet shared with the live theme, for a change nobody
   asked for. A slightly generous ring is the cheaper of the two.
   -------------------------------------------------------------------------*/

.digx-pdp-rating-link {
  display: inline-block;
  /* The cluster keeps the colours the theme already gives it: .rating-count
     has its own `color` at 0,1,0 and the stars are a gradient clipped to
     transparent text, so an inherited link colour would change nothing
     visible and an underline would be the only thing that landed. Both are
     switched off here so the rest state looks exactly like today. */
  color: inherit;
  text-decoration: none;
  border-radius: 4px;
}

/* Hover lands on the count, because it is the only part of the cluster
   carrying its own ink. 0,3,0 against theme.css's own `.rating-count` at
   0,1,0, so it wins without !important. */
.digx-pdp-rating-link:hover .rating-count {
  color: var(--digx-heading, #755BA6);
  text-decoration: underline;
}

.digx-pdp-rating-link:focus-visible {
  outline: 2px solid var(--digx-heading, #755BA6);
  outline-offset: 2px;
}

/* ---- merchant reply (2026-09-07) -------------------------------------------
   New markup, so nothing here can regress a measured value. The card renders it
   between the media block and the helpful row (byte-parity contract with
   lib/reviews/fragments.ts's productReplyHtml), and the rail plus the tint is
   the shape every storefront already uses for "the shop answered this": an
   indented quote, not a second review.

   PLACEMENT AT 480px AND UP. The Ledger card is an explicit 4-row grid whose
   row 4 deliberately MERGES the photo strip (column 1) and the helpful cluster
   (column 2) into one band. A block that sits between those two in the DOM
   cannot sit between them on screen while they share a row, so the reply takes
   a row of its own under that band and spans both tracks. Reading order stays
   review, photos, reply; only the right-rail vote cluster reads above it, and
   it is a control cluster rather than content.

   Colours: the rail and the label are the block's brand token, so a reply on
   the Polish store is ink green without a second stylesheet. The tint is
   rgba(0,0,0,0.04) rather than a named grey so it works on any card background
   the host theme paints. Spacing is on the {4, 8, 12, 16} scale. */
.digx-review__reply {
  margin-top: 12px;
  padding: 12px 16px;
  border-left: 4px solid var(--digx-brand, #755BA6);
  background: rgba(0, 0, 0, 0.04);
  border-radius: 8px;
}

.digx-review__reply-label {
  display: block;
  font-size: 12px;
  font-weight: 700;
  color: var(--digx-brand, #755BA6);
  margin-bottom: 4px;
}

/* `white-space: pre-wrap` so a merchant's own line breaks survive: the admin
   textarea accepts them and escaping alone would collapse them into one run.
   The `!important` on line-height and margin is the same theme trap the rest of
   this file works around -- the Spain theme ships an inline
   `body p { line-height: 1.5 !important; margin-bottom: 1.375em !important }`
   that no class selector can outrank, and this element is a <p> because its tag
   is frozen by the byte-parity contract. */
.digx-review__reply-body {
  margin: 0 !important;
  line-height: 24px !important;
  white-space: pre-wrap;
}

@media screen and (min-width: 480px) {
  .digx-review__reply {
    grid-column: 1 / -1;
    grid-row: 5;
  }
}
