/* WHAT THE BLOCK SAYS — slice 2, 2026-08-11.
 *
 * A real stylesheet rather than an inline <style>, and that is not taste: an
 * inline block in <head> parsed fine, matched the element, and did not apply —
 * dc-runtime rewrites the document and something about that sheet stops
 * counting. Every other rule on this page arrives through a <link>, so this
 * does too. Measured, not guessed.
 *
 * TWO THINGS MAKE THIS APPLY, and both were found by asking the browser which
 * rules matched rather than by reading:
 *
 *   1. It is LINKED LAST. Linked first, its rules lost every equal-specificity
 *      contest to the sheets after it and the photo tiles rendered at 24px.
 *   2. The `display` rule is scoped `.reviews-live .reviews-photos` (0,2,0),
 *      because the skin neutralizer `.skin-home ul { display: revert }` is
 *      (0,1,1) and outranks a bare `.reviews-photos`. That neutralizer is the
 *      `all: unset` family CLAUDE.md documents for every `.skin-*` wrapper;
 *      anything setting `display` on a plain element inside this page has to
 *      clear it.
 *
 * AMENDED 2026-08-12. Point 2 used to end "Only `display` needs the extra
 * weight, so the rest stay flat." That was true and it was still a mistake:
 * "the rest" were then surviving on document order alone, so re-ordering one
 * <link> would have taken the section's layout with it. Every photo-grid rule
 * below is now scoped under `.reviews-live` too. Point 1 stays true and stays
 * required for the few unscoped rules above; it is no longer load-bearing for
 * the grid.
 */
  .reviews-agg { margin-top: 6px; font-size: .84rem; color: #A8A6A2; }
  .reviews-agg a { color: #E8A33A; }
  /* THE WHOLE CARD IS A LINK, and that is the finding behind this change
     rather than a stray decoration rule: every card wraps its stars, body and
     attribution in one <a>, so the "underlined middle card" was this file's
     :hover rule underlining the SENTENCE — on whichever card the cursor
     happened to be. Confirmed by reading the renderer, not inferred.

     The affordance moves to the CARD (slice 3b2): the sentence is never
     styled, the card takes a gold outline on hover and on keyboard focus.
     :focus-visible is on the anchor because that is the focusable thing;
     :has() puts the mark on the card around it, and the plain :hover rule
     below is the fallback for engines without :has(). */
  .review-card > a.review-link { color: inherit; text-decoration: none; display: block; }
  .review-card > a.review-link:hover .review-quote,
  .review-card > a.review-link:focus .review-quote { text-decoration: none; }
  .review-when { display: block; margin-top: 6px; font-size: .76rem; color: #A8A6A2; }
  /* EVERY RULE BELOW IS SCOPED UNDER .reviews-live, and that is a repair to this
     file's own foundation rather than a style choice. The header above records
     that these rules only worked because the sheet is LINKED LAST — they were
     winning equal-specificity contests on document order alone. A section that
     is one <link> reorder away from losing its whole layout is not a section
     that can be trusted on a customer-facing page, and the failure mode is not
     subtle: with this sheet neutralised the four tiles stop being a grid, go to
     their natural heights and stack full-width. Measured, 2026-08-12, by
     serving an empty reviews.css to the live page. Scoping lifts every rule to
     (0,2,x), so link order stops being load-bearing. */

  /* The 40px top margin: the tiles are a separate thought from the cards above
     them, and 18px read as a grid that had come apart. Measured on screen, not
     chosen from a scale. */
  .reviews-live .reviews-photos { list-style: none; margin: 40px 0 0; padding: 0;
    display: grid; grid-template-columns: repeat(auto-fit, minmax(120px, 1fr)); gap: 10px;
    /* NOTHING MAY ESCAPE THE ROW, UPWARD OR DOWNWARD. Explicit start alignment
       instead of the default, because `align-items: end` inherited from
       anywhere would bottom-align the tiles and leave ragged tops — which is
       exactly the shape of the defect reported on 2026-08-12. There is no fixed
       height here on purpose: a grid with no height always grows to hold its
       rows, so the cards above and the @smashtimebx line below cannot be
       overlapped by a tall photo.
       `stretch` rather than `start` — both defeat an inherited `end`, but
       stretch also gives every tile in a row the SAME height, which start does
       not: the Francisco Javier Soto Santos credit wraps to two lines and left
       the row 15px ragged along the bottom. Measured at 1280 and 1067. */
    align-items: stretch; align-content: start; }

  /* THE min-width: auto BLOWOUT, the one CLAUDE.md records from the checkout.
     Grid items refuse to shrink below min-content, so one long unbroken word in
     a credit would push its column — and every ancestor — wider than the page.
     This is the fix for a bug that has not happened here yet and would be
     invisible until it did. */
  .reviews-live .reviews-photos > li { min-width: 0; display: flex; flex-direction: column; }

  /* CONTAINMENT, NOT A DIAGNOSIS — Director's ruling 2026-08-13, and the
     honest framing matters: three fixes negotiated with the IMG (aspect-ratio
     on it, height:auto on it, flex-basis on it), all three measured clean
     against stand-ins, and all three failed on the real page, where exactly
     one portrait-source tile blew out its column by a mechanism still unnamed.
     So the image loses its vote entirely:

     - THE SHAPE LIVES HERE, on the link box the grid sizes. aspect-ratio on a
       grid-tracked, definite-width container is resolved by the browser from
       the track alone; nothing about the photograph participates.
     - overflow:hidden means an image that still insists on being enormous gets
       CLIPPED at this box's edge. The overlap of the cards above and the
       caption below becomes structurally impossible whatever the mechanism
       turns out to be.
     - The credit is this box's SIBLING (li > a > img, then span), so the clip
       can never cut the licence line off.
     - position:relative so that if the runaway ever turns out to be
       absolutely-positioned, its containing block is this clipped box and not
       an ancestor it can escape through.
     - The background moves here from the img: the neutral right-shaped floor
       must exist even while the image inside is missing or mid-flight. */
  .reviews-live .reviews-photos > li > a { display: block; min-width: 0;
    aspect-ratio: 4 / 3; overflow: hidden; position: relative;
    border-radius: 10px; background: #141210; }
  /* :empty, NOT [hidden] — and the reason is measured. dc-runtime rebuilds
     this element from its template and STRIPS the hidden attribute (it keeps
     class and data-*, and adds its own data-dc-tpl). A hidden attribute here
     is silently discarded, so the grid rendered as an empty block. :empty
     needs no attribute and says the true thing anyway: a photo grid with no
     photos in it does not exist. */
  .reviews-live .reviews-photos:empty { display: none; }
  /* The img carries NO sizing opinion of its own any more — it fills the fixed
     box above and object-fit crops it there. width and height are 100% OF A
     CONTAINER WHOSE SIZE THE IMAGE CANNOT INFLUENCE, which is the whole point:
     even if this element still computes some enormous box on the broken
     machine, the parent's overflow:hidden bounds what can ever paint.

     Kept as an <img> rather than background-image, deliberately. A background
     cannot overflow at all, but it costs the accessibility story: the alt
     ("Photo from the Google listing, by <uploader>") is composed by
     lib/places.ts and is part of this section's provenance honesty, and a
     background would push that naming onto the link + credit and drop native
     lazy-loading. The clip above already delivers the same cannot-escape
     guarantee a background would, so the a11y price would buy nothing. */
  .reviews-live .reviews-photos img { width: 100%; height: 100%;
    object-fit: cover; display: block; }

  /* THE CREDIT IS THE LICENCE, so it has to be readable and it has to stay
     inside its tile.
     UNDER the photograph, never over it — which is what makes "legible on a
     bright photo AND a dark one" true by construction rather than by tuning: it
     never sits on a photograph at all, it sits on the section's own near-black
     ground, where #C2BCB4 measures about 11:1. Overlaying it would mean finding
     one colour that survives both a white plate and a black bowl, and this
     project already carries the scar tissue on that problem.
     overflow-wrap:anywhere is not decoration: "Photo by Francisco Javier Soto
     Santos on Google" is the longest real credit on this listing and it wraps to
     two lines in a narrow column. It has to wrap INSIDE the tile. */
  .reviews-live .reviews-photo-by { display: block; margin-top: 6px; font-size: .7rem;
    color: #C2BCB4; line-height: 1.35; overflow-wrap: anywhere; }

  /* THE CARDS ABOVE. They are already equal height — the row stretches them and
     `align-content: start` packs each one's content to the top — but they carry
     the same min-width:auto exposure as the tiles, and a card cannot clip text
     it is allowed to wrap. Hardened here rather than in demo-only.css so the
     whole section's behaviour reads in one file. */
  .reviews-live .reviews-grid > li { min-width: 0; }
  .reviews-live .review-card, .reviews-live .review-quote { overflow-wrap: anywhere; }
