/* ===========================================================================
   REVIEWS + RATINGS
   Stars use the single brand accent, not a second amber hue — this system
   allows exactly one accent, and introducing gold here would break every
   other chapter's restraint.
   =========================================================================== */

/* ---- star row -------------------------------------------------------------
   Two identical layers; the fill is absolutely positioned and width-clipped,
   so fractional ratings are exact and no clip-path IDs can collide. */
.stars { position: relative; display: inline-flex; flex-shrink: 0; line-height: 0; }
.stars__track, .stars__fill { display: inline-flex; gap: var(--p-space-px); }
.stars__track { color: color-mix(in oklab, var(--foreground) 16%, transparent); }
.stars__fill {
  position: absolute; inset: 0 auto 0 0; overflow: hidden;
  color: var(--brand); white-space: nowrap;
}
.stars__i { width: 1rem; height: 1rem; flex-shrink: 0; }
.stars--xs .stars__i { width: 0.75rem; height: 0.75rem; }
.stars--sm .stars__i { width: 0.875rem; height: 0.875rem; }
.stars--lg .stars__i { width: 1.375rem; height: 1.375rem; }

/* ---- buy-box rating line --------------------------------------------------- */
.ratingline {
  display: inline-flex; align-items: center; gap: var(--p-space-2);
  text-decoration: none; width: fit-content;
  transition: opacity 150ms var(--ease-out-quart);
}
.ratingline:hover { opacity: 0.72; }
.ratingline__avg {
  font-family: var(--font-mono), ui-monospace, monospace;
  font-size: var(--p-text-13); font-weight: 600; font-variant-numeric: tabular-nums;
  color: var(--foreground);
}
.ratingline__count {
  font-size: var(--p-text-13); color: var(--ink-3);
  text-decoration: underline; text-underline-offset: 2px;
  text-decoration-color: color-mix(in oklab, var(--ink-3) 35%, transparent);
}

/* ---- card rating (PLP / related) ------------------------------------------- */
.ratingmini { display: inline-flex; align-items: center; gap: var(--p-space-1-5); }
.ratingmini__n {
  font-family: var(--font-mono), ui-monospace, monospace;
  font-size: var(--p-text-11); font-weight: 600; font-variant-numeric: tabular-nums;
  color: var(--ink-2);
}
.ratingmini__n span { color: var(--ink-4); font-weight: 400; }

/* ---- the chapter -----------------------------------------------------------
   FIGURE-GROUND, NOT DECORATION. The old chapter drew white cards, a white
   summary band and transparent chips on a 42%-tinted white ground: five
   different components at one visual weight, on a ground barely distinct from
   any of them. Nothing in the most-read section of the page had hierarchy, and
   the highest-contrast object on screen was a distribution ladder whose bottom
   three rows read zero.

   Two moves fix it. The summary becomes the ink band this system already
   reserves for surfaces that carry data (see pdp.css: "dark is only ever used
   where it carries data" — an average and a distribution are exactly that),
   and the CARD EDGE is what separates a review from the ground.

   Not a tinted ground. Tinting the chapter was the first attempt and it was
   wrong twice over: the skincare vertical deliberately flattens tint bands
   here ("one ground, hairlines for division"), so it lost the cascade and
   shipped white-on-white anyway — and even unopposed it fixes the symptom at
   the wrong layer. The actual defect was the hairline: `--border` is #ECF3FC
   against a #FFFFFF ground, which is not an edge, it is a rumour. */
.pdp-chapter--reviews { border-top: 1px solid var(--border); }
.reviews__head { max-width: 46rem; margin: 0 0 var(--p-space-8); }
.reviews__lead { margin: var(--p-space-4) 0 0; color: var(--ink-2); max-width: 58ch; }

/* ---- the verdict band ------------------------------------------------------
   The chapter's one anchor: score, distribution and customer photos on a deep
   ground, so the eye lands here before it lands anywhere in the wall below. */
.reviews__verdict {
  display: grid; gap: var(--p-space-8);
  margin: 0 0 var(--p-space-6);
  padding: var(--p-space-7);
  border-radius: var(--radius-xl);
  background: var(--ink-band);
  color: var(--brand-foreground);
  box-shadow: var(--elevation-pop);
}
@media (min-width: 720px) {
  .reviews__verdict { grid-template-columns: auto minmax(13rem, 1fr); align-items: center; gap: var(--p-space-10); padding: var(--p-space-8) var(--p-space-9); }
}
@media (min-width: 1080px) {
  .reviews__verdict { grid-template-columns: auto minmax(13rem, 1fr) minmax(0, 21rem); gap: var(--p-space-12); }
}

/* Stars and bars keep the brand hue on the dark ground — the soft step, which
   clears 4.5:1 on the ink band where the 500 would sit at 1.6:1 and vanish. */
.reviews__verdict .stars__track { color: color-mix(in oklab, var(--brand-foreground) 18%, transparent); }
.reviews__verdict .stars__fill  { color: var(--brand-soft); }

.verdict__score { display: flex; flex-direction: column; gap: var(--p-space-2); align-items: flex-start; }
.verdict__avg {
  display: flex; align-items: baseline; gap: var(--p-space-0-5); margin: 0;
  font-family: var(--font-mono), ui-monospace, monospace;
  font-size: calc(var(--p-text-48) * 1.28); line-height: 1; font-weight: 600;
  font-variant-numeric: tabular-nums; letter-spacing: var(--p-tracking-n30);
  color: var(--brand-foreground);
}
.verdict__of { font-size: var(--p-text-20); font-weight: 400; color: color-mix(in oklab, var(--brand-foreground) 52%, transparent); }
.verdict__count {
  margin: 0; font-family: var(--font-mono), ui-monospace, monospace;
  font-size: var(--p-text-11); letter-spacing: var(--p-tracking-6); text-transform: uppercase;
  color: color-mix(in oklab, var(--brand-foreground) 66%, transparent);
}
/* The one derived number in the chapter, and it is derived from the rating
   counts Woo maintains for EVERY review on the product — not the page's worth
   we happened to render. */
.verdict__stat {
  margin: var(--p-space-1-5) 0 0; padding: var(--p-space-1-5) var(--p-space-3);
  border-radius: var(--p-radius-pill);
  background: color-mix(in oklab, var(--brand-soft) 20%, transparent);
  font-size: var(--p-text-12); font-weight: 600; line-height: 1.3;
  color: var(--brand-foreground);
}

/* ---- distribution, as filters ----------------------------------------------
   Rows are buttons. A ratings distribution is the one summary element visitors
   reliably try to click, and most implementations draw it inert. */
.verdict__dist { display: flex; flex-direction: column; gap: var(--p-space-1); min-width: 0; }
.distrow {
  display: grid; grid-template-columns: 2.25rem minmax(0, 1fr) 1.75rem;
  align-items: center; gap: var(--p-space-3);
  width: 100%; padding: var(--p-space-1) var(--p-space-2);
  border: 0; border-radius: var(--radius-md); background: transparent;
  color: inherit; cursor: pointer; text-align: left;
  transition: background-color 140ms var(--ease-out-quart);
}
.distrow[disabled] { cursor: default; opacity: 0.42; }
@media (hover: hover) and (pointer: fine) {
  .distrow:not([disabled]):hover { background: color-mix(in oklab, var(--brand-foreground) 8%, transparent); }
}
.distrow[aria-pressed="true"] { background: color-mix(in oklab, var(--brand-foreground) 13%, transparent); }
.distrow:focus-visible { outline: 2px solid var(--brand-soft); outline-offset: 2px; }
.distrow__k {
  display: inline-flex; align-items: center; gap: var(--p-space-0-5);
  font-family: var(--font-mono), ui-monospace, monospace;
  font-size: var(--p-text-12); font-variant-numeric: tabular-nums;
  color: color-mix(in oklab, var(--brand-foreground) 78%, transparent);
}
.distrow__k span { color: color-mix(in oklab, var(--brand-foreground) 40%, transparent); font-size: var(--p-text-10); }
.distrow__track {
  position: relative; height: 0.5rem; border-radius: var(--p-radius-pill);
  background: color-mix(in oklab, var(--brand-foreground) 12%, transparent); overflow: hidden;
}
.distrow__bar {
  position: absolute; inset: 0 auto 0 0; border-radius: var(--p-radius-pill);
  background: var(--brand-soft);
}
.distrow__n {
  font-family: var(--font-mono), ui-monospace, monospace;
  font-size: var(--p-text-12); font-variant-numeric: tabular-nums; text-align: right;
  color: color-mix(in oklab, var(--brand-foreground) 78%, transparent);
}

/* ---- the pooled photo gallery ---------------------------------------------
   Photo reviews are the strongest proof this page holds, and they were
   previously reachable only by scrolling until you hit a card that had one. */
.reviews__gallery { min-width: 0; }
.reviews__galleryk {
  margin: 0 0 var(--p-space-3);
  font-family: var(--font-mono), ui-monospace, monospace;
  font-size: var(--p-text-11); letter-spacing: var(--p-tracking-6); text-transform: uppercase;
  color: color-mix(in oklab, var(--brand-foreground) 66%, transparent);
}

/* ---- the control rail ------------------------------------------------------ */
.reviews__rail {
  display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between;
  gap: var(--p-space-3) var(--p-space-5);
  margin: 0 0 var(--p-space-6);
}
.reviews__filters { display: flex; flex-wrap: wrap; gap: var(--p-space-2); margin: 0; }
.reviews__chip {
  display: inline-flex; align-items: center; gap: var(--p-space-1-5);
  padding: var(--p-space-2) var(--p-space-3-5);
  border: 1px solid var(--border-strong);
  border-radius: var(--p-radius-pill);
  background: var(--card);
  color: var(--ink-2);
  font-size: var(--p-text-13); font-weight: 500;
  cursor: pointer;
  transition: border-color 140ms var(--ease-out-quart), color 140ms var(--ease-out-quart);
}
.reviews__chip:hover { border-color: var(--border-hover); color: var(--foreground); }
.reviews__chip:focus-visible { outline: 2px solid var(--brand); outline-offset: 2px; }
.reviews__chip.is-on {
  background: var(--foreground); color: var(--brand-foreground); border-color: var(--foreground);
}
.reviews__chipn {
  font-family: var(--font-mono, ui-monospace, monospace);
  font-size: var(--p-text-11); font-variant-numeric: tabular-nums; opacity: .62;
}
.reviews__sort { display: inline-flex; align-items: center; gap: var(--p-space-2); }
.reviews__sortk {
  font-family: var(--font-mono), ui-monospace, monospace;
  font-size: var(--p-text-10); letter-spacing: var(--p-tracking-6); text-transform: uppercase; color: var(--ink-3);
}
.reviews__sortsel { font-size: var(--p-text-13); padding: var(--p-space-2) var(--p-space-3); }

/* ---- the wall --------------------------------------------------------------
   Grid, not multi-column: CSS columns fill DOWN each column before moving
   right and balance heights, so four reviews landed 2/2/0. `align-items:start`
   keeps every card at its natural height, so rows stay ragged rather than
   stretching to the tallest card. */
.reviews__grid {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--p-space-5);
  align-items: start;
}
@media (min-width: 700px)  { .reviews__grid { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (min-width: 1100px) { .reviews__grid { grid-template-columns: repeat(3, minmax(0, 1fr)); } }

/* ---- masonry ---------------------------------------------------------------
   A grid row is as tall as its tallest cell, so one review carrying a
   full-width photograph — around 800px — left the two text cards beside it
   sitting over 600px of white. `align-items: start` made that worse, not
   better: it stopped the short cards stretching, which is correct, but the
   ROW still reserved the tall card's height.

   The fix is the row-span technique: rows become 1px, the visible gap moves to
   a margin so the span arithmetic stays exact, and each card spans as many
   1px rows as it is tall. `dense` lets a short card backfill the hole a tall
   neighbour left, which is what makes it pack rather than merely stagger.

   PROGRESSIVE. The class is added by storefront.js only once it has measured,
   so with no JS the wall renders as the plain grid above — ragged, but never
   broken. It is also switched off at one column, where there is nothing to
   pack and the spans would only round every card up to a whole pixel. */
.reviews__grid.is-masonry {
  grid-auto-flow: row dense;
  grid-auto-rows: 1px;
  row-gap: 0;
}
.reviews__grid.is-masonry > .review {
  grid-row-end: span var(--rows, 1);
  margin-bottom: var(--p-space-5);
}

.review {
  display: block;
  padding: var(--p-space-5) var(--p-space-5) var(--p-space-4-5);
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-xl);
  background: var(--card);
  box-shadow: var(--elevation-card);
  transition: box-shadow 220ms var(--ease-out-quart), transform 220ms var(--ease-out-quart), border-color 220ms var(--ease-out-quart);
}
@media (hover: hover) and (pointer: fine) {
  .review:hover { box-shadow: var(--elevation-lift); border-color: var(--border-hover); transform: translateY(-2px); }
}

/* Verdict line: the rating and WHEN, together. The date used to sit orphaned
   below the footer rule, in the palest tone on the card, which is exactly
   backwards — recency is a trust signal, not a filing detail. */
.review__verdict {
  display: flex; align-items: center; justify-content: space-between;
  gap: var(--p-space-3); margin: 0 0 var(--p-space-3);
}
.review__score {
  margin-right: auto;
  font-family: var(--font-mono), ui-monospace, monospace;
  font-size: var(--p-text-12); font-weight: 600; font-variant-numeric: tabular-nums;
  color: var(--ink-3);
}
.review__date {
  font-family: var(--font-mono), ui-monospace, monospace;
  font-size: var(--p-text-11); letter-spacing: var(--p-tracking-4);
  color: var(--ink-3); white-space: nowrap;
}

/* The reviewer's own first sentence, promoted. Nothing here is authored by the
   store — see ms_review_split(). */
.review__headline {
  margin: 0 0 var(--p-space-2);
  font-family: var(--font-display);
  font-size: var(--p-text-17); line-height: 1.3; font-weight: 600;
  letter-spacing: var(--p-tracking-n10); color: var(--foreground); text-wrap: balance;
}

/* Full ink, not the muted tone. These words are the only thing on this page a
   visitor came to this chapter for; they were previously set lighter than the
   chrome around them. */
.review__body { color: var(--foreground); font-size: var(--p-text-15); line-height: 1.62; }
.review__body p { margin: 0 0 var(--p-space-2-5); }
.review__body p:last-child { margin-bottom: 0; }

.review__foot {
  display: flex; flex-wrap: wrap; align-items: center; gap: var(--p-space-2) var(--p-space-3);
  margin-top: var(--p-space-4); padding-top: var(--p-space-3-5); border-top: 1px solid var(--border);
}
.review__who { display: inline-flex; align-items: center; gap: var(--p-space-2); min-width: 0; }
.review__initial {
  display: grid; place-items: center; flex-shrink: 0;
  width: 1.75rem; height: 1.75rem; border-radius: var(--p-radius-pill);
  background: var(--brand-muted); color: var(--brand-hover);
  font-size: var(--p-text-11); font-weight: 700; letter-spacing: var(--p-tracking-4);
}
.review__name { font-size: var(--p-text-13); font-weight: 600; color: var(--foreground); }
.review__verified {
  display: inline-flex; align-items: center; gap: var(--p-space-1);
  padding: var(--p-space-1) var(--p-space-2);
  border-radius: var(--p-radius-pill);
  background: var(--brand-muted);
  font-family: var(--font-mono), ui-monospace, monospace;
  font-size: var(--p-text-10); font-weight: 600; letter-spacing: var(--p-tracking-6); text-transform: uppercase;
  color: var(--brand-hover);
}
.review__verified svg { color: currentColor; }

/* ---- the spotlight ---------------------------------------------------------
   A wall of six identical rectangles has no first read. One review is promoted
   ahead of the grid at a size that is actually inviting, with its photo laid
   alongside rather than shrunk into the strip. */
.review--spot {
  margin: 0 0 var(--p-space-5);
  padding: var(--p-space-6);
  border-left: 3px solid var(--brand);
  box-shadow: var(--elevation-lift);
}
@media (min-width: 860px) {
  .review--spot { padding: var(--p-space-7); }
  /* Two columns only when there IS a photo — the modifier is set server-side.
     Keyed off `:empty` instead, a spotlight with no photos would still reserve
     the 20rem media track and squeeze the text into the remainder. */
  .review--spotmedia {
    display: grid; grid-template-columns: minmax(0, 22rem) minmax(0, 1fr);
    align-items: center; gap: var(--p-space-8);
  }
}
.review--spot .review__main { min-width: 0; }
.review--spot .review__headline { font-size: var(--p-text-24); line-height: 1.22; letter-spacing: var(--p-tracking-n14); }
.review--spot .review__body { font-size: var(--p-text-17); line-height: 1.6; }
.review--spot .review__score { font-size: var(--p-text-13); }
.review__spotmedia:empty { display: none; }

/* ---- closing band ----------------------------------------------------------
   The chapter used to end at the deepest point anyone scrolls on this page
   with nothing to do next. */
.reviews__close {
  display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between;
  gap: var(--p-space-5) var(--p-space-8);
  margin: var(--p-space-10) 0 var(--p-space-8);
  padding: var(--p-space-7) var(--p-space-8);
  border-radius: var(--radius-xl);
  border: 1px solid var(--border-strong);
  background: var(--card);
  box-shadow: var(--elevation-card);
}
.reviews__closetitle { margin: 0; }
.reviews__closesub { margin: var(--p-space-2) 0 0; color: var(--ink-2); max-width: 46ch; }
/* Trailing glyph in its own well rather than naked beside the label — the
   button reads as one machined object instead of text with an arrow after it. */
.reviews__closecta { display: inline-flex; align-items: center; gap: var(--p-space-3); }
.reviews__closearrow {
  display: grid; place-items: center;
  width: 1.75rem; height: 1.75rem; border-radius: var(--p-radius-pill);
  background: color-mix(in oklab, var(--brand-foreground) 18%, transparent);
  transition: translate 220ms var(--ease-out-quart);
}
@media (hover: hover) and (pointer: fine) {
  .reviews__closecta:hover .reviews__closearrow { translate: 0.1875rem 0; }
}

.reviews__more, .reviews__empty {
  margin: var(--p-space-6) 0 0;
  font-family: var(--font-mono), ui-monospace, monospace;
  font-size: var(--p-text-11); letter-spacing: var(--p-tracking-6); text-transform: uppercase; color: var(--ink-3);
}
.reviews__empty[hidden] { display: none; }
.review[hidden] { display: none; }

/* ---- empty state ------------------------------------------------------------ */
.reviews__none { max-width: 40rem; margin-inline: auto; text-align: center; }
.reviews__nonesub { margin: var(--p-space-3-5) auto var(--p-space-7); color: var(--ink-2); max-width: 46ch; }
.reviews__none .rform { margin-inline: auto; text-align: left; }

/* ---- the write-a-review disclosure ------------------------------------------ */
.rform { max-width: 34rem; }
.rform__summary {
  display: inline-flex; align-items: center; gap: 0.4375rem; cursor: pointer;
  padding: var(--p-space-2-5) var(--p-space-4-5); list-style: none;
  border: 1px solid var(--border-strong); border-radius: var(--radius-lg);
  background: var(--background);
  font-size: var(--p-text-14); font-weight: 600; color: var(--foreground);
  transition: border-color 160ms var(--ease-out-quart), background-color 160ms var(--ease-out-quart);
}
.rform__summary::-webkit-details-marker { display: none; }
.rform__summary:hover { border-color: color-mix(in oklab, var(--foreground) 28%, transparent); }
.rform__summary:active { transform: scale(0.98); }
.rform__chev { transition: transform 200ms var(--ease-out-quart); }
.rform[open] .rform__chev { transform: rotate(180deg); }
.reviews__act .rform { max-width: none; }
.reviews__act .rform__panel { max-width: 34rem; }
.rform__panel {
  margin-top: var(--p-space-4); padding: var(--p-space-5);
  border: 1px solid var(--border); border-radius: var(--radius-xl); background: var(--card);
}
.rform__row { display: flex; flex-direction: column; gap: var(--p-space-1-5); margin-bottom: var(--p-space-3-5); }
.rform__label {
  font-family: var(--font-mono), ui-monospace, monospace;
  font-size: var(--p-text-10); letter-spacing: var(--p-tracking-6); text-transform: uppercase; color: var(--ink-3);
}
.rform__hint { font-size: var(--p-text-12); color: var(--ink-4); }
.rform__area { min-height: 7rem; resize: vertical; padding: var(--p-space-2-5) var(--p-space-3); line-height: 1.55; }
.rform__panel .comment-form-cookies-consent { display: flex; align-items: center; gap: var(--p-space-2); margin-bottom: var(--p-space-3-5); font-size: var(--p-text-13); color: var(--ink-3); }
.rform__panel .form-submit { margin: 0; }
.rform__panel .logged-in-as { margin: 0 0 var(--p-space-3-5); font-size: var(--p-text-13); color: var(--ink-3); }


/* ===========================================================================
   REVIEW PHOTOS
   Customer images are the one thing on this page we did not write, so they get
   no frame, no caption furniture and no accent — a hairline square and the
   photograph. The card grid is already `align-items: start` with natural
   heights, so a strip simply makes its card taller and the rows stay ragged.
   =========================================================================== */

.review__shots {
  display: flex; flex-wrap: wrap; gap: var(--p-space-1-5);
  margin: var(--p-space-3-5) 0 0; padding: 0; list-style: none;
}
/* Every photo is in the DOM so the viewer can page the whole set; the ones
   past the fold are hidden here rather than omitted server-side. */
.review__shots .is-overflow { display: none; }

.review__shot {
  position: relative; display: block; overflow: hidden;
  width: 3.25rem; height: 3.25rem; flex: none; padding: 0;
  border: 1px solid var(--border); border-radius: var(--radius-md);
  background: var(--surface-2); cursor: pointer;
  transition: border-color 160ms var(--ease-out-quart);
}
.review__shot img { display: block; width: 100%; height: 100%; object-fit: cover; }
/* The independent `scale` property, not `transform` — a shared reveal utility
   on an ancestor rewrites `transform` wholesale and would erase this. */
.review__shot img { transition: scale 300ms var(--ease-out-quart); }
@media (hover: hover) and (pointer: fine) {
  .review__shot:hover { border-color: var(--border-strong); }
  .review__shot:hover img { scale: 1.04; }
}
.review__shot:active { scale: .97; }
.review__shot:focus-visible { outline: 2px solid var(--brand); outline-offset: 2px; }

/* Hero strip — the spotlight review lays its first frame alongside the text at
   a size worth looking at, with the rest as a row beneath it. */
/* THE LEAD PHOTO SPANS ITS CARD. It used to be a 3.25rem square in a rail —
   a customer photograph, the most persuasive object in the chapter, rendered
   at the size of a favicon. It now takes the full width of whatever column it
   is in, at its OWN proportions: no aspect-ratio and no crop, because these
   are real uploads and a fixed landscape box guillotines a portrait photo
   (every one of ours is 3:4) while a fixed portrait box does the same to a
   landscape one. wp_get_attachment_image() supplies the intrinsic width and
   height, so the browser reserves the exact box and nothing shifts on load. */
.review__shots > li:first-child { flex: 1 0 100%; }
.review__shot--lead {
  width: 100%; height: auto;
  border-radius: var(--radius-lg);
}
.review__shot--lead img { width: 100%; height: auto; object-fit: fill; }
/* A corner chip, not the full-cover scrim the small thumbs use: at lead size
   that scrim would black out the photograph it is counting. */
.review__shot--lead .review__shotmore {
  inset: auto var(--p-space-2) var(--p-space-2) auto;
  padding: var(--p-space-1) var(--p-space-2-5);
  border-radius: var(--p-radius-pill);
  background: color-mix(in oklab, var(--foreground) 76%, transparent);
}

/* Pooled gallery — every photo on the product, on the verdict band's dark
   ground, so the hairline and fill invert against it. */
.reviews__wall { display: flex; flex-wrap: wrap; gap: var(--p-space-2); margin: 0; padding: 0; list-style: none; }
.reviews__wall .is-overflow { display: none; }
.review__shot--wall {
  width: 4rem; height: 4rem;
  border-color: color-mix(in oklab, var(--brand-foreground) 20%, transparent);
  background: color-mix(in oklab, var(--brand-foreground) 8%, transparent);
}
@media (hover: hover) and (pointer: fine) {
  .review__shot--wall:hover { border-color: color-mix(in oklab, var(--brand-foreground) 46%, transparent); }
}

.review__shotmore {
  position: absolute; inset: 0; display: grid; place-items: center;
  background: color-mix(in oklab, var(--foreground) 62%, transparent);
  color: var(--brand-foreground);
  font-family: var(--font-mono), ui-monospace, monospace;
  font-size: var(--p-text-11); font-weight: 600; font-variant-numeric: tabular-nums;
}

/* ---- the viewer ------------------------------------------------------------
   A native <dialog> opened with showModal(): the focus trap, the inert
   background and Escape-to-close come from the platform. Transform-origin
   stays centre — this is a modal, not a popover anchored to its trigger. */
.rlb {
  position: fixed; inset: 0;
  width: 100vw; max-width: 100vw;
  height: 100vh; max-height: 100vh;
  height: 100dvh; max-height: 100dvh;
  margin: 0; padding: 0; border: 0; overflow: hidden;
  background: transparent; color: var(--brand-foreground);
  opacity: 0; scale: .96;
  /* Exit is quicker than entry: the visitor has already decided to leave. */
  transition:
    opacity 150ms var(--ease-out-quart),
    scale   150ms var(--ease-out-quart),
    display 150ms allow-discrete,
    overlay 150ms allow-discrete;
}
.rlb[open] { opacity: 1; scale: 1; transition-duration: 200ms; }
@starting-style { .rlb[open] { opacity: 0; scale: .96; } }

.rlb::backdrop { background: rgba(22, 25, 28, .9); }
.rlb::backdrop { background: color-mix(in oklab, var(--foreground) 90%, transparent); }

/* showModal() makes the page inert but does not stop it scrolling behind the
   backdrop, which reads as the viewer having come loose from the page. */
html.ms-lb-open { overflow: hidden; }

.rlb__inner {
  display: grid; grid-template-columns: auto minmax(0, 1fr) auto;
  align-items: center; gap: clamp(.25rem, 2vw, 1.25rem);
  width: 100%; height: 100%;
  padding: clamp(1rem, 4vw, 2.5rem);
}

.rlb__fig {
  display: flex; flex-direction: column; align-items: center; gap: var(--p-space-4);
  margin: 0; min-width: 0;
}
.rlb__img {
  display: block; max-width: 100%; max-height: 74dvh;
  object-fit: contain; border-radius: var(--radius-md);
}
.rlb__cap {
  display: flex; flex-wrap: wrap; justify-content: center; align-items: baseline;
  gap: var(--p-space-1) var(--p-space-3);
  font-family: var(--font-mono), ui-monospace, monospace;
  font-size: var(--p-text-11); letter-spacing: var(--p-tracking-6); text-transform: uppercase;
}
.rlb__count { font-variant-numeric: tabular-nums; opacity: .55; }
.rlb__by { opacity: .8; letter-spacing: var(--p-tracking-6); text-transform: none; font-size: var(--p-text-12); }

.rlb__nav, .rlb__x {
  display: grid; place-items: center; flex: none; padding: 0; cursor: pointer;
  width: 2.75rem; height: 2.75rem; border-radius: var(--radius-circle);
  color: inherit;
  border: 1px solid color-mix(in oklab, var(--surface) 22%, transparent);
  background: color-mix(in oklab, var(--surface) 8%, transparent);
  transition:
    background-color 160ms var(--ease-out-quart),
    border-color 160ms var(--ease-out-quart);
}
@media (hover: hover) and (pointer: fine) {
  .rlb__nav:hover, .rlb__x:hover {
    background: color-mix(in oklab, var(--surface) 16%, transparent);
    border-color: color-mix(in oklab, var(--surface) 38%, transparent);
  }
}
.rlb__nav:active, .rlb__x:active { scale: .97; }
.rlb__nav:focus-visible, .rlb__x:focus-visible { outline: 2px solid var(--surface); outline-offset: 2px; }
.rlb__nav--prev svg { scale: -1 1; }
.rlb__nav[hidden] { display: none; }

.rlb__x {
  position: absolute; top: clamp(1rem, 4vw, 2.5rem); right: clamp(1rem, 4vw, 2.5rem);
  z-index: 1;
}
@media (max-width: 559px) {
  .rlb__nav, .rlb__x { width: 2.25rem; height: 2.25rem; }
  .rlb__inner { gap: var(--p-space-1); }
}

/* ---- uploader --------------------------------------------------------------
   A plain multiple file input behind a styled label: the picker opens and the
   files post with no JavaScript at all. Previews, drag-and-drop and per-file
   removal are the enhancement, never the mechanism. */
.rform__row--files { gap: var(--p-space-2); }
.rform__opt {
  font-family: var(--font-mono), ui-monospace, monospace;
  font-size: .5625rem; letter-spacing: .1em; color: var(--ink-4);
}
/* Positioned so the clipped input below anchors here rather than escaping to
   whatever ancestor happens to be positioned. */
.rform__pick { position: relative; display: flex; flex-wrap: wrap; align-items: center; gap: var(--p-space-2-5) var(--p-space-3-5); }
/* Clipped, not display:none — it must stay focusable and keep its label. */
.rform__file {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: calc(var(--p-space-px) * -1);
  overflow: hidden; clip-path: inset(50%); white-space: nowrap; border: 0;
}
.rform__pickbtn { cursor: pointer; }
.rform__file:focus-visible + .rform__pickbtn { outline: 2px solid var(--brand); outline-offset: 2px; }
.rform__meta {
  font-family: var(--font-mono), ui-monospace, monospace;
  font-size: var(--p-text-10); letter-spacing: var(--p-tracking-6); text-transform: uppercase; color: var(--ink-4);
}

/* Drag target is the whole panel — a dashed dropzone would be a second, weaker
   affordance sitting next to a perfectly good button. */
.rform__panel {
  transition:
    border-color 160ms var(--ease-out-quart),
    background-color 160ms var(--ease-out-quart);
}
.rform__panel.is-dragover {
  border-color: var(--brand);
  background: color-mix(in oklab, var(--brand) 5%, var(--card));
}

.rform__previews {
  display: flex; flex-wrap: wrap; gap: var(--p-space-2);
  margin: var(--p-space-1) 0 0; padding: 0; list-style: none;
}
.rform__previews[hidden] { display: none; }
.rform__preview {
  position: relative; overflow: hidden;
  width: 4rem; height: 4rem;
  border: 1px solid var(--border); border-radius: var(--radius-md);
  background: var(--surface-2);
  /* Animation + `translate`, never transition + transform: this element also
     carries a hover scale, and a shorthand here would reset it. */
  animation: ms-preview-in 220ms var(--ease-out-quart) both;
  animation-delay: calc(var(--i, 0) * 40ms);
}
@keyframes ms-preview-in {
  from { opacity: 0; translate: 0 6px; }
  to   { opacity: 1; translate: none; }
}
.rform__preview img { display: block; width: 100%; height: 100%; object-fit: cover; }
.rform__drop {
  position: absolute; top: .1875rem; right: .1875rem;
  display: grid; place-items: center; padding: 0; cursor: pointer;
  width: 1.25rem; height: 1.25rem; border-radius: var(--radius-circle);
  border: 0; background: color-mix(in oklab, var(--foreground) 72%, transparent);
  color: var(--brand-foreground);
  transition: background-color 140ms var(--ease-out-quart);
}
.rform__drop svg { width: .75rem; height: .75rem; }
@media (hover: hover) and (pointer: fine) {
  .rform__drop:hover { background: var(--foreground); }
}
.rform__drop:active { scale: .94; }
.rform__drop:focus-visible { outline: 2px solid var(--brand); outline-offset: 2px; }

.rform__fileerr {
  margin: 0; font-size: var(--p-text-12); line-height: 1.5;
  color: color-mix(in oklab, var(--foreground) 70%, transparent);
}
.rform__fileerr[hidden] { display: none; }

.rform__as { margin: 0 0 var(--p-space-3-5); font-size: var(--p-text-13); color: var(--ink-3); }
.rform__gate { margin: 0; font-size: var(--p-text-14); color: var(--ink-2); }
.rform__consent {
  display: flex; align-items: center; gap: var(--p-space-2);
  margin: 0 0 var(--p-space-3-5); font-size: var(--p-text-13); color: var(--ink-3);
}
/* Off-screen rather than display:none, which bots detect and skip. */
.rform__hp {
  position: absolute; left: -9999px; width: 1px; height: 1px; overflow: hidden;
}

/* ---- submission outcome ---------------------------------------------------- */
.rnotice {
  display: flex; align-items: flex-start; gap: var(--p-space-2);
  margin: 0 0 var(--p-space-4); padding: var(--p-space-3) var(--p-space-3-5);
  border: 1px solid var(--border); border-radius: var(--radius-lg);
  background: var(--card);
  font-size: var(--p-text-14); line-height: 1.5; color: var(--ink-2);
}
.rnotice__i { flex: none; margin-top: var(--p-space-0-5); color: var(--brand); }
.rnotice--err { border-color: color-mix(in oklab, var(--foreground) 22%, transparent); }
.rnotice--err .rnotice__i { color: var(--foreground); }

@media (prefers-reduced-motion: reduce) {
  .rlb, .rlb[open] { scale: 1; }
  .rlb { transition-property: opacity, display, overlay; }
  .review__shot img, .review__shot:active,
  .rlb__nav:active, .rlb__x:active, .rform__drop:active { scale: 1; transition: none; }
  .rform__preview { animation: none; }
}

