/* =================================================================
   REVIEWS - /reviews/ Velvet Cinema destination
   Page-scoped sheet, auto-loaded by _main.php (css/reviews.css).
   All values from design-tokens.css. Themed via tokens (light + dark).
   ================================================================= */

/* Phosphor icons: the project base .ph-icon sets no intrinsic size, so an
   inline SVG with only a viewBox collapses to 0x0. Size each star icon
   explicitly here, scoped to this component only. */
.review-badge__star.ph-icon {
  width: 1.1em;
  height: 1.1em;
}

/* -----------------------------------------------------------------
   REVIEWS HERO
   DOMINANT MOMENT: Oversized display headline over a refined
   platform-rating badge with warm rose stars - a trust signal
   elevated to editorial object. - .reviews-hero__title
   ----------------------------------------------------------------- */

.reviews-hero {
  position: relative;
  isolation: isolate;
  overflow: hidden;
  background:
    radial-gradient(ellipse 80% 60% at 50% 0%,
      color-mix(in srgb, var(--color-accent-glow) 7%, transparent) 0%, transparent 65%),
    linear-gradient(to bottom, var(--color-bg) 0%, var(--color-bg-alt) 100%);
  /* Tightened so the whole hero (title + badge + credibility + lede + CTA)
     sits comfortably in one viewport with nothing below the fold - including
     short laptop heights. The longer H1 needs a contained max size (below)
     so width-driven scaling doesn't push content past the fold. */
  /* svh, not vw - same reason as .chero and .team-hero. The failure axis is
     viewport HEIGHT, so width-based padding charged a 720px-tall laptop the
     same ~101px as a 1080p screen. Caps match the old vw maxima, so tall
     screens are unchanged; at 720 this reclaims the last 9px that the lede and
     stat-label trims could not reach. */
  padding: clamp(1.5rem, 5.5svh, 3.5rem) 0 clamp(1.25rem, 4.5svh, 3rem);
  /* The fold is the viewport MINUS the sticky header, never a bare vh unit.
     This was min(82vh, 660px), which is where "nothing below the fold" above
     stopped being true: 82vh of an 800px viewport is 656px, but the first fold
     is only 800 - 157 = 643px, so the hero's own floor pushed it 13px under.
     Measured on staging at 1280x800 before this change: +13px past the fold.
     --hero-h carries the subtraction and tracks every breakpoint (88/98/157),
     so this now lands at exactly 0. Same drift family as the hero offsets and
     the sticky offsets - see reference_header_height_css_variable.
     The 660px ceiling is unchanged and still wins on tall viewports. */
  min-height: min(var(--hero-h), 660px);
  display: flex;
  align-items: center;
  text-align: center;
}

.reviews-hero__inner {
  position: relative;
  z-index: 1;
  width: 100%;
  max-width: 52rem;
  margin-inline: auto;
  padding-inline: var(--container-padding);
}

.reviews-hero__title {
  /* Velvet Cinema editorial serif hero (matches .svcs-hero__title). */
  font-family: var(--font-serif);
  font-optical-sizing: auto;
  font-size: clamp(2.4rem, 1.5rem + 4vw, 4.25rem);
  font-weight: 350;
  line-height: 1.04;
  letter-spacing: -0.015em;
  color: var(--color-heading);
  text-wrap: balance;
  margin: 0 0 clamp(1.25rem, 3vw, 2rem);
}

/* Rose-deep serif-italic accent on "K Bella" - matches the pillar hero em. */
.reviews-hero__accent {
  font-style: italic;
  font-weight: 480;
  color: var(--color-rose-deep);
}

/* Trust stat rail - three distinct facts under the rating badge. Serif oversized
   numbers (shared recipe with .careers-stat) read as an editorial closing note to
   the hero, not a second card competing with the rating badge above.
   DOMINANT MOMENT stays the title + rating badge; this rail is quiet support. */
.reviews-hero__stats {
  list-style: none;
  padding: 0;
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  align-items: flex-start;
  gap: clamp(1.5rem, 5vw, 3.5rem);
  /* fit-content + margin auto centers the row against the global p/ul caps. */
  width: fit-content;
  max-width: 100%;
  margin: clamp(1.5rem, 3.5vw, 2.25rem) auto 0;
}

.reviews-hero__stat {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.3em;
  text-align: center;
}

/* Hairline divider between stats on wider screens (sits in the flex gap). */
@media (min-width: 560px) {
  .reviews-hero__stat + .reviews-hero__stat::before {
    content: "";
    position: absolute;
    left: calc(clamp(1.5rem, 5vw, 3.5rem) / -2);
    top: 0.15em;
    width: 1px;
    height: 2.75rem;
    background: var(--color-border);
  }
}

.reviews-hero__stat-num {
  font-family: var(--font-serif);
  font-optical-sizing: auto;
  font-weight: 300;
  font-size: clamp(2.5rem, 1.9rem + 2.6vw, 3.5rem);
  line-height: 0.9;
  letter-spacing: -0.03em;
  color: var(--color-heading);
  font-variant-numeric: lining-nums;
}

.reviews-hero__stat-label {
  font-family: var(--font-body);
  font-size: var(--text-sm);
  font-weight: var(--weight-regular);
  line-height: 1.4;
  color: var(--color-muted);
  max-width: 15ch;
}

@media (min-width: 768px) {
  .reviews-hero__title {
    /* Contained max (was --text-4xl at up to 5rem) - the 7-word H1 wrapped to
       4 large lines and overflowed short laptop viewports. This caps it so the
       full hero fits the fold while still reading as a confident display H1. */
    font-size: clamp(2.25rem, 1.4rem + 2.1vw, 3.5rem);
  }
}

/* Badge container - single badge now, side-by-side in Task 3 */
.reviews-hero__badges {
  display: flex;
  justify-content: center;
  gap: var(--space-lg);
  flex-wrap: wrap;
}

/* -----------------------------------------------------------------
   REVIEW BADGE - platform trust signal as a refined design element
   ----------------------------------------------------------------- */

.review-badge {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex-wrap: wrap; /* meta drops below the rating+stars on narrow screens instead of overlapping */
  gap: 0.4em var(--space-sm);
  padding: var(--space-md) var(--space-lg);
  background: var(--color-bg-card);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-xl);
  text-decoration: none;
  box-shadow: var(--shadow-md);
}

@media (min-width: 480px) {
  .review-badge {
    flex-wrap: nowrap;
    padding: var(--space-md) var(--space-xl);
  }
}

@media (prefers-reduced-motion: no-preference) {
  .review-badge {
    transition: box-shadow var(--transition-base), border-color var(--transition-base), transform var(--transition-fast);
  }
}

@media (hover: hover) {
  .review-badge:hover {
    border-color: var(--color-border-hover);
    box-shadow: var(--shadow-lg);
    transform: translateY(-2px);
  }
}

.review-badge:focus-visible {
  outline: 2px solid var(--color-focus-ring);
  outline-offset: 3px;
}

/* Large display rating number */
.review-badge__rating {
  font-family: var(--font-display);
  font-size: var(--text-2xl);
  font-weight: var(--weight-bold);
  line-height: 1;
  color: var(--color-heading);
  letter-spacing: -0.01em;
}

/* Star row */
.review-badge__stars {
  display: flex;
  align-items: center;
  gap: 0.1em;
  color: var(--color-rose);
  font-size: 1.1rem;
}

/* Review count meta label */
.review-badge__meta {
  font-family: var(--font-body);
  font-size: var(--text-sm);
  font-weight: var(--weight-medium);
  color: var(--color-muted);
  white-space: nowrap;
}

/* -----------------------------------------------------------------
   DARK THEME OVERRIDES
   Token-driven: most values adjust automatically via [data-theme="dark"]
   on <html>. Only overrides that need non-token adjustments live here.
   ----------------------------------------------------------------- */

[data-theme="dark"] .review-badge {
  background: var(--color-bg-elevated);
}

[data-theme="dark"] .review-badge__stars {
  /* rose token is already warm in dark mode - no override needed */
  color: var(--color-rose);
}

/* -----------------------------------------------------------------
   REVIEWS HERO - LEDE + CTA CLUSTER
   DOMINANT MOMENT: Confident editorial lead sentence above a pill
   button that reads as the singular conversion action. - .btn--cta
   ----------------------------------------------------------------- */

/* Supporting paragraph beneath the badge - comfortable measure,
   muted body tone, light weight for editorial restraint */
.reviews-hero__lede {
  margin: clamp(1rem, 2.5vw, 1.75rem) auto clamp(1.5rem, 3vw, 2.25rem);
  max-width: 46rem;
  font-family: var(--font-body);
  font-size: var(--text-lg);
  font-weight: var(--weight-light);
  line-height: 1.55;
  color: var(--color-body);
  text-wrap: pretty;
}

/* CTA cluster: primary pill button + subdued secondary line */
.reviews-hero__cta {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-md);
}

@media (min-width: 480px) {
  .reviews-hero__cta {
    flex-direction: row;
    justify-content: center;
    flex-wrap: wrap;
  }
}

/* Ensure the primary button meets 44px tap target */
.reviews-hero__cta .btn--cta {
  min-height: 44px;
  display: inline-flex;
  align-items: center;
  gap: 0.5em;
}

/* Secondary "or leave one on Yelp / Facebook" line */
.reviews-hero__cta-secondary {
  font-family: var(--font-body);
  font-size: var(--text-sm);
  font-weight: var(--weight-regular);
  color: var(--color-muted);
  display: inline-flex;
  align-items: center;
  gap: 0.4em;
  flex-wrap: wrap;
  justify-content: center;
}

.reviews-hero__cta-secondary a {
  color: var(--color-link);
  text-decoration: underline;
  text-underline-offset: 2px;
  /* "Yelp" is only 27px wide and 21px tall - the smallest tap target on the
     site, and it is a review-capture link, so a missed tap costs a review.
     WCAG 2.5.8 arguably exempts it (these links sit in a sentence), but the
     parent is inline-flex, which blockifies the anchors, so a tool testing the
     inline exemption via computed display cannot see the exemption either.
     Cheaper to fix than to argue.
     Width AND height both need lifting here - most expanders on this site are
     height-only - so the pseudo is inset negatively on all four sides. */
  --hit-expander: 1;
  position: relative;
}

/* Invisible tap expander -> 44x44. The visible text is untouched, so the
   sentence keeps its rhythm. 0.7em per side takes the narrowest link (Yelp,
   27px) past 44px wide while staying inside the ~24px gap to the next link, so
   the two zones abut rather than overlap - overlapping zones are worse than a
   small target, since the later element in DOM order wins the tap. Vertically
   the nearest target above is the Google CTA at 16px, and a centred 44px zone
   reaches only 11.5px up. */
.reviews-hero__cta-secondary a::after {
  content: "";
  position: absolute;
  left: -0.7em;
  right: -0.7em;
  top: 50%;
  transform: translateY(-50%);
  height: 44px;
}

@media (hover: hover) {
  @media (prefers-reduced-motion: no-preference) {
    .reviews-hero__cta-secondary a {
      transition: color var(--transition-base), opacity var(--transition-fast);
    }
    .reviews-hero__cta-secondary a:hover {
      opacity: 0.75;
    }
  }
}

.reviews-hero__cta-secondary a:focus-visible {
  outline: 2px solid var(--color-focus-ring);
  outline-offset: 2px;
  border-radius: 2px;
}

/* Dark theme: secondary link uses the dark-mode link token automatically
   (--color-link is already brighter teal in dark context via design-tokens.css).
   Muted text adapts via --color-muted dark override. No manual override needed. */

/* -----------------------------------------------------------------
   WALL INTRO - keyword-aware lead-in directly under the "In Our Guests'
   Words" heading, above the review content it describes. Carries the
   location (incl. Brighton for local SEO) + service-line keywords without
   a floating standalone band.
   ----------------------------------------------------------------- */

.reviews-wall__intro {
  max-width: 52rem;
  margin: 0 auto clamp(2rem, 4vw, 3rem);
  text-align: center;
  font-family: var(--font-body);
  font-size: var(--text-base);
  font-weight: var(--weight-regular);
  line-height: 1.7;
  color: var(--color-muted);
  text-wrap: pretty;
}

/* -----------------------------------------------------------------
   FEATURED PULL-QUOTES
   DOMINANT MOMENT: Large editorial quotes - standout longform reviews
   elevated above the wall. Generous type, refined cite line, warm
   star color. Section uses .section--cream for rhythm against hero.
   ----------------------------------------------------------------- */

.reviews-featured {
  padding-block: var(--space-section);
}

.reviews-featured__title {
  font-family: var(--font-serif);
  font-optical-sizing: auto;
  /* Larger than the wall title (--text-2xl) so Five-Star Stories reads as the
     dominant section and the two headings carry real hierarchy, not equal weight. */
  font-size: var(--text-3xl);
  font-weight: 350;
  letter-spacing: -0.015em;
  line-height: 1.05;
  color: var(--color-heading);
  text-align: center;
  margin: 0 0 clamp(2.5rem, 5vw, 4rem);
}
.reviews-featured__title em { font-style: italic; font-weight: 480; color: var(--color-rose-deep); }

/* Homepage-style featured layout: one full-width lead pull-quote, then a row of
   up to three compact supporting cards below it. */
.reviews-featured__lead {
  margin-bottom: var(--space-xl);
}

.reviews-featured__row {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--space-lg);
  align-items: stretch;
}
/* Straight from 1-col (phones) to 3-col at tablet width. A 2-col step would
   orphan the third card (2 + 1) through the whole tablet range. 800px catches
   iPad portrait (834) with a comfortable ~245px card. */
@media (min-width: 800px) {
  .reviews-featured__row { grid-template-columns: repeat(3, 1fr); }
}

/* Compact supporting card - mirrors the homepage's three smaller review cards:
   stars, quote, hairline divider, monogram + reviewer + Google mark, chips. */
.featured-mini {
  display: flex;
  flex-direction: column;
  gap: var(--space-sm);
  padding: var(--space-lg) var(--space-lg) var(--space-md);
  background: var(--color-bg-card);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-card);
}
.featured-mini__stars {
  display: flex;
  gap: 0.125rem;
  color: var(--color-rose);
}
.featured-mini__star.ph-icon { width: 1.05em; height: 1.05em; flex-shrink: 0; }
.featured-mini__quote { margin: 0; flex: 1; }
.featured-mini__quote p {
  margin: 0;
  font-family: var(--font-body);
  font-size: var(--text-base);
  font-weight: var(--weight-light);
  color: var(--color-body);
  line-height: 1.7;
}
.featured-mini__footer {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-sm);
  margin-top: auto;
  padding-top: var(--space-md);
  border-top: 1px solid var(--color-border);
}
.featured-mini__author { display: flex; align-items: center; gap: 0.625rem; }
.featured-mini__initial {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 2.25rem;
  height: 2.25rem;
  flex-shrink: 0;
  border-radius: var(--radius-full);
  background: color-mix(in srgb, var(--color-accent) 12%, transparent);
  color: var(--color-accent);
  font-family: var(--font-display);
  font-size: var(--text-sm);
  font-weight: var(--weight-bold);
  line-height: 1;
}
.featured-mini__meta { display: flex; flex-direction: column; }
.featured-mini__name {
  font-family: var(--font-display);
  font-size: var(--text-sm);
  font-weight: var(--weight-semibold);
  color: var(--color-heading);
  font-style: normal;
}
.featured-mini__date {
  font-family: var(--font-body);
  font-size: var(--text-xs);
  color: var(--color-muted);
}
.featured-mini__badge.ph-icon {
  width: 1.1em;
  height: 1.1em;
  color: var(--color-muted);
  opacity: 0.5;
  flex-shrink: 0;
}
.featured-mini__tags {
  display: flex;
  flex-wrap: wrap;
  column-gap: 0.4em;
  /* Same .featured-quote__tag chips as the main quote, so the same pitch floor
     and the same value - see .featured-quote__tags for the reasoning. This
     container is a separate rule and was missed when that fix landed, which is
     why the tags in the mini cards still wrapped at a 33px pitch. */
  row-gap: 1.15rem;
  margin-top: var(--space-sm);
}

@media (prefers-reduced-motion: no-preference) {
  @media (hover: hover) {
    .featured-mini {
      transition: border-color var(--transition-base), box-shadow var(--transition-base), transform var(--transition-fast);
    }
    .featured-mini:hover {
      border-color: var(--color-border-hover);
      box-shadow: var(--shadow-md);
      transform: translateY(-2px);
    }
  }
}

/* -----------------------------------------------------------------
   FEATURED QUOTE CARD - mirrors the homepage featured review:
   editorial quote (left) | attribution rail (right) with the oversized
   Kb monogram watermark. Self-contained here so the home section (the
   .reviews__ selectors in style.css) stays untouched.
   DOMINANT MOMENT: the Kb monogram watermark bleeding off the rail -
   .featured-quote__mark
   ----------------------------------------------------------------- */

.featured-quote {
  position: relative;
  margin: 0;
  padding: var(--space-lg);
  background: var(--color-bg-card);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-xl);
  box-shadow: var(--shadow-card);
  overflow: hidden;
  display: flex;
  flex-direction: column;
  gap: var(--space-md);
}

/* LEFT: the testimonial (rides above the watermark) */
.featured-quote__body {
  margin: 0;
  font-family: var(--font-display);
  font-size: var(--text-lg);
  font-weight: var(--weight-regular);
  line-height: 1.55;
  color: var(--color-heading);
  text-wrap: pretty;
  position: relative;
  z-index: 1;
}

/* RIGHT: attribution rail */
.featured-quote__rail {
  position: relative;
  z-index: 1;
  display: flex;
  flex-direction: column;
  gap: var(--space-sm);
  margin-top: var(--space-md);
  padding-top: var(--space-md);
  border-top: 1px solid var(--color-border);
}

/* Watermark only earns its space at tablet+ (see media query below) */
.featured-quote__mark { display: none; }

.featured-quote__stars {
  display: flex;
  align-items: center;
  gap: 0.15em;
  color: var(--color-rose);
}
.featured-quote__star.ph-icon {
  width: 1.15em;
  height: 1.15em;
  flex-shrink: 0;
}

.featured-quote__verified {
  display: inline-flex;
  align-items: center;
  align-self: flex-start;
  gap: 0.4rem;
  padding: 0.32rem 0.72rem;
  border: 1px solid var(--color-border);
  border-radius: var(--radius-full);
  background: var(--color-bg-alt);
  font-family: var(--font-body);
  font-size: var(--text-xs);
  font-weight: var(--weight-medium);
  letter-spacing: 0.02em;
  color: var(--color-body);
}
.featured-quote__google.ph-icon {
  width: 1em;
  height: 1em;
  color: var(--color-muted);
  flex-shrink: 0;
}

.featured-quote__attr {
  display: flex;
  align-items: center;
  gap: 0.625rem;
}
.featured-quote__initial {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 2.25rem;
  height: 2.25rem;
  flex-shrink: 0;
  border-radius: var(--radius-full);
  background: color-mix(in srgb, var(--color-accent) 12%, transparent);
  border: 1px solid var(--color-border);
  font-family: var(--font-display);
  font-size: var(--text-base);
  line-height: 1;
  color: var(--color-heading);
}
.featured-quote__meta {
  display: flex;
  flex-direction: column;
}
.featured-quote__author {
  font-family: var(--font-body);
  font-size: var(--text-sm);
  font-weight: var(--weight-semibold);
  color: var(--color-body);
  font-style: normal;
  letter-spacing: 0.01em;
}
.featured-quote__time {
  font-family: var(--font-body);
  font-size: var(--text-xs);
  font-weight: var(--weight-regular);
  color: var(--color-muted);
}

.featured-quote__tags {
  display: flex;
  flex-wrap: wrap;
  /* Row gap split out from the shared 0.4em. These pills are 27px at 320 and
     29px at 768, and when the tag row wraps the two rows sat only 33px / 36px
     apart - so a 44px hit-expander here would overlap the neighbouring row and
     let the lower pill steal taps meant for the upper one (the failure mode
     already hit on .footer-band__links a). Raising the pitch instead is what
     makes the target reachable without an expander: 27 + 18.4 = 45.
     Row gap only applies once the row actually wraps, so this is inert at
     widths where the tags fit on one line.
     Column gap stays 0.4em to keep the horizontal rhythm unchanged. */
  column-gap: 0.4em;
  row-gap: 1.15rem;
}

/* Stylist / service tag: pill link */
.featured-quote__tag {
  display: inline-block;
  font-family: var(--font-body);
  font-size: var(--text-xs);
  font-weight: var(--weight-medium);
  letter-spacing: 0;
  color: var(--color-link);
  background: color-mix(in srgb, var(--color-accent) 10%, transparent);
  border: 1px solid color-mix(in srgb, var(--color-accent) 25%, transparent);
  border-radius: var(--radius-full);
  padding: 0.2em 0.75em;
  text-decoration: none;
  line-height: 1.8;
}

.featured-quote__tag:focus-visible {
  outline: 2px solid var(--color-focus-ring);
  outline-offset: 2px;
}

@media (prefers-reduced-motion: no-preference) {
  @media (hover: hover) {
    .featured-quote__tag {
      transition: background var(--transition-base), border-color var(--transition-base), color var(--transition-fast);
    }
    .featured-quote__tag:hover {
      background: color-mix(in srgb, var(--color-accent) 18%, transparent);
      border-color: color-mix(in srgb, var(--color-accent) 40%, transparent);
      color: var(--color-accent-hover);
    }
  }
}

/* Tablet+: split the card into quote | rail, and reveal the Kb watermark */
@media (min-width: 768px) {
  .featured-quote {
    display: grid;
    grid-template-columns: minmax(0, 1.55fr) minmax(220px, 1fr);
    column-gap: clamp(2rem, 4.5vw, 4rem);
    align-items: center;
    padding: var(--space-xl);
  }
  .featured-quote__rail {
    margin-top: 0;
    padding-top: 0;
    padding-left: clamp(2rem, 4.5vw, 4rem);
    border-top: none;
    border-left: 1px solid var(--color-border);
    align-self: stretch;
    justify-content: center;
    gap: var(--space-md);
  }
  /* Kb monogram (no ring), oversized + faint, bleeding off the top-right corner
     and clipped by the card's overflow:hidden. Masked so it picks up rose in
     both themes. Matches the homepage featured card's watermark. */
  .featured-quote__mark {
    display: block;
    position: absolute;
    top: clamp(-3rem, -3.5vw, -1.5rem);
    right: clamp(-2.5rem, -2.5vw, -1rem);
    width: clamp(10rem, 15vw, 15rem);
    height: clamp(10rem, 15vw, 15rem);
    background: var(--color-rose);
    -webkit-mask: url(../images/k-bella-kb-no-ring-mono.svg) center / contain no-repeat;
    mask: url(../images/k-bella-kb-no-ring-mono.svg) center / contain no-repeat;
    opacity: 0.16;
    pointer-events: none;
    user-select: none;
    z-index: 0;
  }
}

/* -----------------------------------------------------------------
   DARK THEME - FEATURED PULL-QUOTES
   .section--cream re-maps its tokens for dark via
   [data-theme="dark"] .section--cream in style.css. Card, verified pill,
   and tags use the remapped tokens; only targeted overrides here.
   ----------------------------------------------------------------- */

[data-theme="dark"] .featured-quote {
  background: var(--color-bg-elevated);
  border-color: var(--color-border);
}

[data-theme="dark"] .featured-quote__body {
  color: var(--color-heading);
}

[data-theme="dark"] .featured-quote__verified {
  background: var(--color-bg-card);
}

[data-theme="dark"] .featured-quote__mark {
  opacity: 0.2;
}

[data-theme="dark"] .featured-quote__tag {
  background: color-mix(in srgb, var(--color-accent) 14%, transparent);
  border-color: color-mix(in srgb, var(--color-accent) 28%, transparent);
  color: var(--color-link);
}

[data-theme="dark"] .featured-mini {
  background: var(--color-bg-elevated);
  border-color: var(--color-border);
}
[data-theme="dark"] .featured-mini__name {
  color: var(--color-heading);
}

/* Dark theme depth: carry the hero's glow down into the two body sections so
   they aren't near-flat black slabs. Featured gets a top teal wash; the wall
   gets a soft rose glow at its base + warmer elevated card fills so the dense
   grid layers off the field instead of sitting flat on it. */
[data-theme="dark"] .reviews-featured {
  background-image: radial-gradient(ellipse 72% 42% at 50% 0%,
    color-mix(in srgb, var(--color-accent-glow) 11%, transparent) 0%, transparent 60%);
}
[data-theme="dark"] .reviews-wall {
  background-image: radial-gradient(ellipse 60% 34% at 50% 100%,
    rgba(212, 160, 160, 0.055) 0%, transparent 60%);
}
[data-theme="dark"] .review-card {
  background: var(--color-bg-elevated);
}

/* -----------------------------------------------------------------
   REVIEW WALL
   Archive-density grid: lighter, denser than featured marquee above.
   Featured = editorial; wall = the full record.
   ----------------------------------------------------------------- */

.reviews-wall {
  padding-block: var(--space-section);
  background: var(--color-bg);
}

.reviews-wall__title {
  font-family: var(--font-serif);
  font-optical-sizing: auto;
  font-size: var(--text-2xl);
  font-weight: 350;
  letter-spacing: -0.015em;
  line-height: 1.06;
  color: var(--color-heading);
  text-align: center;
  /* Tightened: the wall intro paragraph now follows the heading */
  margin: 0 0 clamp(0.75rem, 2vw, 1.25rem);
}
.reviews-wall__title em { font-style: italic; font-weight: 480; color: var(--color-rose-deep); }

/* Empty state - centered across the full wall width. column-span:all gives it
   the full multicol width; margin-inline:auto centers the box, which the global
   `p { max-width: 70ch }` otherwise leaves left-aligned (same root cause as the
   hero credibility row - text was centering within a left-anchored 70ch box). */
.reviews-wall__empty {
  color: var(--color-muted);
  font-size: var(--text-base);
  text-align: center;
  padding: var(--space-xl);
  column-span: all;
  margin-inline: auto;
}

/* -----------------------------------------------------------------
   WALL GRID - full-text MASONRY, 1 -> 2 -> 3 col.
   CSS multi-column so reviews of varying length tile with no ragged
   gaps and read as editorial rhythm. Dropped from 4 cols (too busy).
   Cards break-inside:avoid so none split across a column boundary.
   ----------------------------------------------------------------- */

.reviews-wall__grid {
  column-count: 1;
  column-gap: var(--space-lg);
}

@media (min-width: 560px) {
  .reviews-wall__grid {
    column-count: 2;
  }
}

@media (min-width: 1000px) {
  .reviews-wall__grid {
    column-count: 3;
  }
}

/* -----------------------------------------------------------------
   REVIEW CARD
   Compact: lighter padding, smaller type, clamped body. Clearly a
   step below the featured pull-quotes in visual weight.
   ----------------------------------------------------------------- */

.review-card {
  background: var(--color-bg-card);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-card);
  padding: var(--space-lg);
  display: flex;
  flex-direction: column;
  gap: var(--space-sm);
  box-shadow: var(--shadow-card);
  /* Masonry: keep a card whole within its column + provide row rhythm */
  break-inside: avoid;
  margin-bottom: var(--space-lg);
}

@media (prefers-reduced-motion: no-preference) {
  .review-card {
    transition: box-shadow var(--transition-base), border-color var(--transition-base), transform var(--transition-fast);
  }
}

@media (prefers-reduced-motion: no-preference) {
  @media (hover: hover) {
    .review-card:hover {
      border-color: var(--color-border-hover);
      box-shadow: var(--shadow-card-hover);
      transform: translateY(-2px);
    }
  }
}

/* Stars row - same rose token as featured, smaller size */
.review-card__stars {
  display: flex;
  align-items: center;
  gap: 0.1em;
  color: var(--color-rose);
  font-size: var(--text-sm);
}

/* Explicit star size - base .ph-icon has no intrinsic dimensions */
.review-card__star.ph-icon {
  width: 1em;
  height: 1em;
  flex-shrink: 0;
}

/* Headline quote - display face, the card's typographic lead */
.review-card__headline {
  margin: 0;
  font-family: var(--font-display);
  font-size: var(--text-base);
  font-weight: var(--weight-semibold);
  line-height: 1.35;
  letter-spacing: -0.01em;
  color: var(--color-heading);
  text-wrap: balance;
}

/* Body: shown IN FULL by default (no clamp). Only the rare >=600-char
   review is excerpted server-side with a Read-more control. */
.review-card__body {
  margin: 0;
  font-family: var(--font-body);
  font-size: var(--text-base);
  font-weight: var(--weight-regular);
  line-height: 1.6;
  color: var(--color-body);
  text-wrap: pretty;
}

/* "Read full review" control - only on excerpted long reviews */
.review-card__more {
  align-self: flex-start;
  display: inline-flex;
  align-items: center;
  gap: 0.35em;
  padding: 0;
  margin-top: calc(var(--space-xs) * -1);
  background: none;
  border: 0;
  cursor: pointer;
  font-family: var(--font-body);
  font-size: var(--text-xs);
  font-weight: var(--weight-semibold);
  letter-spacing: 0.02em;
  color: var(--color-link);
}

.review-card__more-icon.ph-icon {
  width: 0.95em;
  height: 0.95em;
  flex-shrink: 0;
}

.review-card__more:focus-visible {
  outline: 2px solid var(--color-focus-ring);
  outline-offset: 3px;
  border-radius: 3px;
}

@media (prefers-reduced-motion: no-preference) {
  @media (hover: hover) {
    .review-card__more {
      transition: color var(--transition-fast);
    }
    .review-card__more:hover {
      color: var(--color-accent-hover);
    }
    .review-card__more:hover .review-card__more-icon {
      transform: translateX(2px);
    }
    .review-card__more-icon {
      transition: transform var(--transition-fast);
    }
  }
}

/* Card footer: author + time + tag chips, wrapping */
.review-card__foot {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  column-gap: 0.55em;
  /* Tap targets: .review-card__tag is ~24px tall (320) to ~27px (768). Only the
     3-4 cards whose footer wraps to a second row have a chip directly below
     another chip, but where they do, the neighbour is 4.8px away - too close for
     a hit-expander. 19.75px row-gap gives those rows a >=44px pitch. Cards that
     do not wrap are unaffected, since row-gap only applies between flex lines. */
  row-gap: 19.75px;
  border-top: 1px solid var(--color-border);
  padding-top: var(--space-sm);
  margin-top: auto;
}

.review-card__author {
  font-family: var(--font-body);
  font-size: var(--text-xs);
  font-weight: var(--weight-semibold);
  color: var(--color-body);
  letter-spacing: 0.01em;
}

.review-card__time {
  font-family: var(--font-body);
  font-size: var(--text-xs);
  font-weight: var(--weight-regular);
  color: var(--color-muted);
}

/* Tag chips: subtle pill links (staff or service). Natural case - names are
   proper case, services are title case; uppercasing them read shouty. */
.review-card__tag {
  display: inline-block;
  font-family: var(--font-body);
  font-size: var(--text-xs);
  font-weight: var(--weight-medium);
  letter-spacing: 0;
  color: var(--color-link);
  background: color-mix(in srgb, var(--color-accent) 8%, transparent);
  border: 1px solid color-mix(in srgb, var(--color-accent) 20%, transparent);
  border-radius: var(--radius-full);
  padding: 0.2em 0.7em;
  text-decoration: none;
  line-height: 1.6;
}

.review-card__tag:focus-visible {
  outline: 2px solid var(--color-focus-ring);
  outline-offset: 2px;
}

@media (prefers-reduced-motion: no-preference) {
  @media (hover: hover) {
    .review-card__tag {
      transition: background var(--transition-base), border-color var(--transition-base), color var(--transition-fast);
    }
    .review-card__tag:hover {
      background: color-mix(in srgb, var(--color-accent) 16%, transparent);
      border-color: color-mix(in srgb, var(--color-accent) 35%, transparent);
      color: var(--color-accent-hover);
    }
  }
}

/* -----------------------------------------------------------------
   DARK THEME - WALL + CARDS
   ----------------------------------------------------------------- */

[data-theme="dark"] .reviews-wall {
  background: var(--color-bg);
}

[data-theme="dark"] .review-card {
  background: var(--color-bg-card);
  border-color: var(--color-border);
}

[data-theme="dark"] .review-card__tag {
  background: color-mix(in srgb, var(--color-accent) 12%, transparent);
  border-color: color-mix(in srgb, var(--color-accent) 24%, transparent);
  color: var(--color-link);
}

/* -----------------------------------------------------------------
   FILTER + SORT TOOLBAR
   Positioned between the "Every review" H2 and the wall grid.
   Chips are real <a href> links - no-JS fallback, full accessibility.
   Two facet dimensions wrapped in native <details> disclosure groups:
   stylist (teal accent) and service (rose accent).
   Sort is a compact paired text-link control, right-aligned on desktop.
   ----------------------------------------------------------------- */

.reviews-toolbar {
  display: flex;
  flex-direction: column;
  gap: var(--space-md);
  margin-bottom: clamp(1.75rem, 3.5vw, 2.75rem);
}

@media (min-width: 768px) {
  .reviews-toolbar {
    flex-direction: row;
    align-items: flex-start;
    justify-content: space-between;
    gap: var(--space-lg);
  }
}

/* Filter groups row: two disclosure groups side by side on desktop.
   position:relative makes THIS the anchor for both overlay panels (below),
   so a wide panel opens as a left-aligned dropdown under the summary row and
   can never run off either viewport edge - per-group left/right anchoring was
   the overflow bug. */
.reviews-toolbar__filters {
  position: relative;
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-sm);
  flex: 1;
}

/* -----------------------------------------------------------------
   DISCLOSURE GROUP - the <details> wrapper
   ----------------------------------------------------------------- */

.filter-group {
  /* static: the panel anchors to .reviews-toolbar__filters (the positioned
     ancestor), not to each group - that is what keeps a wide panel on-screen. */
  position: static;
}

/* Remove default browser disclosure triangle */
.filter-group__summary {
  list-style: none;
}

.filter-group__summary::-webkit-details-marker {
  display: none;
}

/* Summary pill: looks like a refined button control */
.filter-group__summary {
  display: inline-flex;
  align-items: center;
  gap: 0.35em;
  min-height: 44px;
  padding: 0.45em 0.85em 0.45em 1em;
  font-family: var(--font-body);
  font-size: var(--text-sm);
  font-weight: var(--weight-medium);
  color: var(--color-body);
  background: var(--color-bg-card);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-button);
  cursor: pointer;
  user-select: none;
  white-space: nowrap;
  line-height: 1.2;
}

@media (prefers-reduced-motion: no-preference) {
  .filter-group__summary {
    transition:
      background var(--transition-base),
      border-color var(--transition-base),
      color var(--transition-fast),
      box-shadow var(--transition-fast);
  }
}

@media (hover: hover) {
  .filter-group__summary:hover {
    background: var(--color-bg-alt);
    border-color: var(--color-border-hover);
    color: var(--color-heading);
  }
}

.filter-group__summary:focus-visible {
  outline: 2px solid var(--color-focus-ring);
  outline-offset: 2px;
}

/* "Stylist" label - muted weight, acts as a prefix */
.filter-group__label {
  font-weight: var(--weight-regular);
  color: var(--color-muted);
}

/* Active value text - bolder */
.filter-group__value {
  font-weight: var(--weight-semibold);
  color: var(--color-heading);
}

/* Caret icon - sized and animated */
.filter-group__caret.ph-icon {
  width: 1em;
  height: 1em;
  flex-shrink: 0;
  color: var(--color-muted);
}

@media (prefers-reduced-motion: no-preference) {
  .filter-group__caret {
    transition: transform var(--transition-base);
  }
}

details[open] .filter-group__caret {
  transform: rotate(180deg);
}

/* Active filter engaged state - teal accent border + shadow */
.filter-group__summary.is-filtered {
  border-color: var(--color-accent);
  box-shadow: 0 0 0 1px var(--color-accent);
  color: var(--color-heading);
  background: color-mix(in srgb, var(--color-accent) 8%, var(--color-bg-card));
}

/* Service group active state uses rose */
details[data-facet="service"] .filter-group__summary.is-filtered {
  border-color: var(--color-rose);
  box-shadow: 0 0 0 1px var(--color-rose);
  background: color-mix(in srgb, var(--color-rose) 10%, var(--color-bg-card));
}

/* Panel: floating OVERLAY chip list. Absolutely positioned against the
   .reviews-toolbar__filters container (both panels share that anchor) so
   opening one never pushes the grid or the sibling summary - no layout jump.
   It opens as a LEFT-aligned dropdown directly under the summary row; the
   max-width is viewport-clamped so a wide service list can never run off
   either edge at any width or zoom. Scrolls internally if the list is tall. */
.filter-group__panel {
  position: absolute;
  top: calc(100% + var(--space-xs));
  left: 0;
  z-index: 30;
  display: flex;
  flex-wrap: wrap;
  align-content: flex-start;
  gap: var(--space-xs) var(--space-sm);
  width: max-content;
  max-width: min(34rem, calc(100vw - 2 * var(--container-padding)));
  max-height: min(60vh, 26rem);
  overflow-y: auto;
  /* premium thin scrollbar (standard model - does not inherit, so set here;
     Chrome themed globally via ::-webkit-scrollbar in style.css) */
  scrollbar-width: thin;
  padding: var(--space-md);
  background: var(--color-bg-card);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-lg);
}

/* Sort: compact segmented link pair, left on mobile, right-aligned on desktop.
   overflow: clip (not hidden) - clips to border-box without creating a scroll container,
   so :focus-visible outlines on .sort-link are not clipped. */
.reviews-toolbar__sort {
  display: flex;
  align-items: center;
  gap: 0;
  flex-shrink: 0;
  border: 1px solid var(--color-border);
  border-radius: var(--radius-button);
  overflow: clip;
  align-self: flex-start;
}

/* -----------------------------------------------------------------
   FILTER CHIPS - stylist dimension (default accent: teal/muted)
   ----------------------------------------------------------------- */

.filter-chip {
  display: inline-flex;
  align-items: center;
  gap: 0.45em;
  min-height: 44px;
  /* Tighter + uniform padding (was 0.4em/1em - lopsided); min-height 36->44 for tap floor (Phase 2 polish) */
  padding: 0.45em 0.7em;
  font-family: var(--font-body);
  font-size: var(--text-sm);
  font-weight: var(--weight-medium);
  color: var(--color-body);
  background: var(--color-bg-card);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-button);
  text-decoration: none;
  white-space: nowrap;
  line-height: 1.2;
}

/* Review-count badge on each chip - typographically secondary */
.filter-chip__count {
  font-size: var(--text-2xs);
  font-weight: var(--weight-regular);
  color: var(--color-muted);
  font-variant-numeric: tabular-nums;
}

.filter-chip.is-active .filter-chip__count {
  color: var(--color-body);
}

@media (prefers-reduced-motion: no-preference) {
  .filter-chip {
    transition:
      background var(--transition-base),
      border-color var(--transition-base),
      color var(--transition-fast),
      box-shadow var(--transition-fast);
  }
}

@media (hover: hover) {
  .filter-chip:hover {
    background: var(--color-bg-alt);
    border-color: var(--color-border-hover);
    color: var(--color-heading);
  }
}

.filter-chip:focus-visible {
  outline: 2px solid var(--color-focus-ring);
  outline-offset: 2px;
}

/* Active stylist chip: teal outline + heading text */
.filter-chip.is-active {
  color: var(--color-heading);
  background: color-mix(in srgb, var(--color-accent) 12%, var(--color-bg-card));
  border-color: var(--color-accent);
  font-weight: var(--weight-semibold);
  box-shadow: 0 0 0 1px var(--color-accent);
}

/* -----------------------------------------------------------------
   SERVICE CHIPS - visually distinct: rose tint
   Keeps the two facet dimensions (stylist vs service) readable
   without being noisy. Same pill geometry, different accent hue.
   ----------------------------------------------------------------- */

.filter-chip--service {
  color: var(--color-eyebrow);
  background: color-mix(in srgb, var(--color-rose) 8%, var(--color-bg-card));
  border-color: color-mix(in srgb, var(--color-rose) 25%, transparent);
}

@media (hover: hover) {
  .filter-chip--service:hover {
    background: color-mix(in srgb, var(--color-rose) 16%, var(--color-bg-card));
    border-color: color-mix(in srgb, var(--color-rose) 40%, transparent);
    color: var(--color-heading);
  }
}

/* Active service chip: rose outline */
.filter-chip--service.is-active {
  color: var(--color-heading);
  background: color-mix(in srgb, var(--color-rose) 16%, var(--color-bg-card));
  border-color: var(--color-rose);
  box-shadow: 0 0 0 1px var(--color-rose);
}

/* -----------------------------------------------------------------
   SORT LINKS - segmented control pair
   ----------------------------------------------------------------- */

.sort-link {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: 44px;
  padding: 0 var(--space-md);
  font-family: var(--font-body);
  font-size: var(--text-sm);
  font-weight: var(--weight-medium);
  color: var(--color-muted);
  text-decoration: none;
  background: var(--color-bg-card);
  white-space: nowrap;
  /* Dividing line between the two sort links */
  border-right: 1px solid var(--color-border);
}

.sort-link:last-child {
  border-right: none;
}

@media (prefers-reduced-motion: no-preference) {
  .sort-link {
    transition: background var(--transition-base), color var(--transition-fast);
  }
}

@media (hover: hover) {
  .sort-link:hover {
    background: var(--color-bg-alt);
    color: var(--color-heading);
  }
}

.sort-link:focus-visible {
  outline: 2px solid var(--color-focus-ring);
  outline-offset: -2px;
}

.sort-link.is-active {
  color: var(--color-heading);
  background: var(--color-bg-alt);
  font-weight: var(--weight-semibold);
}

/* -----------------------------------------------------------------
   "WITH PHOTOS" TOGGLE
   Binary filter pill (not a disclosure) in the filters row. Same pill
   geometry as the facet summaries; OFF = neutral outline, ON = solid
   teal fill so a switched-on toggle reads differently from the
   outline-tinted facet "engaged" states. Only rendered when photo
   reviews exist (guarded server-side).
   ----------------------------------------------------------------- */

.filter-toggle {
  display: inline-flex;
  align-items: center;
  gap: 0.4em;
  min-height: 44px;
  padding: 0.45em 0.9em;
  font-family: var(--font-body);
  font-size: var(--text-sm);
  font-weight: var(--weight-medium);
  color: var(--color-body);
  background: var(--color-bg-card);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-button);
  text-decoration: none;
  white-space: nowrap;
  line-height: 1.2;
}

.filter-toggle__icon.ph-icon {
  width: 1.1em;
  height: 1.1em;
  flex-shrink: 0;
  color: var(--color-muted);
}

.filter-toggle__count {
  font-size: var(--text-2xs);
  font-weight: var(--weight-regular);
  color: var(--color-muted);
  font-variant-numeric: tabular-nums;
}

@media (prefers-reduced-motion: no-preference) {
  .filter-toggle {
    transition:
      background var(--transition-base),
      border-color var(--transition-base),
      color var(--transition-fast),
      box-shadow var(--transition-fast);
  }
}

@media (hover: hover) {
  .filter-toggle:hover {
    background: var(--color-bg-alt);
    border-color: var(--color-border-hover);
    color: var(--color-heading);
  }
}

.filter-toggle:focus-visible {
  outline: 2px solid var(--color-focus-ring);
  outline-offset: 2px;
}

/* ON: solid teal fill - clearly distinct from the outlined facet states */
.filter-toggle.is-active {
  color: var(--color-btn-primary-text);
  background: var(--color-accent);
  border-color: var(--color-accent);
  font-weight: var(--weight-semibold);
}

.filter-toggle.is-active .filter-toggle__icon,
.filter-toggle.is-active .filter-toggle__count {
  color: inherit;
}

[data-theme="dark"] .filter-toggle {
  background: var(--color-bg-card);
  border-color: var(--color-border);
  color: var(--color-body);
}

[data-theme="dark"] .filter-toggle.is-active {
  color: var(--color-btn-primary-text);
  background: var(--color-accent);
  border-color: var(--color-accent);
}

/* -----------------------------------------------------------------
   DARK THEME - TOOLBAR
   Tokens mostly handle it; a few targeted overrides for sufficient
   contrast on the chips and disclosure groups.
   ----------------------------------------------------------------- */

[data-theme="dark"] .filter-group__summary {
  background: var(--color-bg-card);
  border-color: var(--color-border);
  color: var(--color-body);
}

[data-theme="dark"] .filter-group__summary:hover {
  background: var(--color-bg-elevated);
  border-color: var(--color-border-hover);
  color: var(--color-heading);
}

[data-theme="dark"] .filter-group__summary.is-filtered {
  background: color-mix(in srgb, var(--color-accent) 12%, var(--color-bg-card));
  border-color: var(--color-accent);
  box-shadow: 0 0 0 1px var(--color-accent);
  color: var(--color-heading);
}

[data-theme="dark"] details[data-facet="service"] .filter-group__summary.is-filtered {
  background: color-mix(in srgb, var(--color-rose) 14%, var(--color-bg-card));
  border-color: var(--color-rose);
  box-shadow: 0 0 0 1px var(--color-rose);
}

[data-theme="dark"] .filter-group__panel {
  background: var(--color-bg-elevated);
  border-color: var(--color-border);
  box-shadow: var(--shadow-md);
}

[data-theme="dark"] .filter-chip {
  background: var(--color-bg-card);
  border-color: var(--color-border);
  color: var(--color-body);
}

[data-theme="dark"] .filter-chip.is-active {
  background: color-mix(in srgb, var(--color-accent) 16%, var(--color-bg-card));
  border-color: var(--color-accent);
  box-shadow: 0 0 0 1px var(--color-accent);
  color: var(--color-heading);
}

[data-theme="dark"] .filter-chip--service {
  color: var(--color-eyebrow);
  background: color-mix(in srgb, var(--color-rose) 10%, var(--color-bg-card));
  border-color: color-mix(in srgb, var(--color-rose) 20%, transparent);
}

[data-theme="dark"] .filter-chip--service.is-active {
  background: color-mix(in srgb, var(--color-rose) 18%, var(--color-bg-card));
  border-color: var(--color-rose);
  box-shadow: 0 0 0 1px var(--color-rose);
  color: var(--color-heading);
}

[data-theme="dark"] .reviews-toolbar__sort {
  border-color: var(--color-border);
}

[data-theme="dark"] .sort-link {
  background: var(--color-bg-card);
  border-right-color: var(--color-border);
  color: var(--color-muted);
}

[data-theme="dark"] .sort-link.is-active {
  background: var(--color-bg-elevated);
  color: var(--color-heading);
}

/* -----------------------------------------------------------------
   PAGINATION
   Centered row below the grid. Tap targets >= 44px. Current item
   highlighted with rose accent underline + heading color.
   ----------------------------------------------------------------- */

.reviews-pager {
  margin-top: clamp(2.5rem, 5vw, 4rem);
}

.reviews-pager ul {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  justify-content: center;
  align-items: center;
  flex-wrap: wrap;
  gap: var(--space-xs);
}

.reviews-pager li {
  display: flex;
}

.reviews-pager a,
.reviews-pager li > span.is-current {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 44px;
  min-height: 44px;
  padding: 0 var(--space-sm);
  font-family: var(--font-body);
  font-size: var(--text-sm);
  font-weight: var(--weight-medium);
  color: var(--color-body);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  text-decoration: none;
  background: var(--color-bg-card);
}

.reviews-pager li > span.is-current {
  color: var(--color-heading);
  font-weight: var(--weight-bold);
  background: var(--color-bg-alt);
  border-color: var(--color-rose);
  box-shadow: 0 0 0 1px var(--color-rose);
}

.reviews-pager a:focus-visible {
  outline: 2px solid var(--color-focus-ring);
  outline-offset: 2px;
}

@media (prefers-reduced-motion: no-preference) {
  @media (hover: hover) {
    .reviews-pager a {
      transition: background var(--transition-base), border-color var(--transition-base), color var(--transition-fast);
    }
    .reviews-pager a:hover {
      background: var(--color-bg-alt);
      border-color: var(--color-border-hover);
      color: var(--color-heading);
    }
  }
}

/* Dark theme pager */
[data-theme="dark"] .reviews-pager a,
[data-theme="dark"] .reviews-pager li > span.is-current {
  background: var(--color-bg-card);
  border-color: var(--color-border);
  color: var(--color-body);
}

[data-theme="dark"] .reviews-pager li > span.is-current {
  color: var(--color-heading);
  border-color: var(--color-rose);
  box-shadow: 0 0 0 1px var(--color-rose);
  background: var(--color-bg-elevated);
}

@media (prefers-reduced-motion: no-preference) {
  @media (hover: hover) {
    [data-theme="dark"] .reviews-pager a:hover {
      background: var(--color-bg-elevated);
      border-color: var(--color-border-hover);
      color: var(--color-heading);
    }
  }
}

/* -----------------------------------------------------------------
   FETCH-AND-SWAP LOADING STATE
   Subtle opacity fade on the card grid while a swap is in-flight.
   Reduced-motion guard: transition only fires when motion is OK.
   ----------------------------------------------------------------- */

#reviews-wall-grid[aria-busy="true"] {
  opacity: 0.6;
}

@media (prefers-reduced-motion: no-preference) {
  #reviews-wall-grid {
    transition: opacity 0.15s ease;
  }
}

/* -----------------------------------------------------------------
   CLOSING CTA BAND
   Centered, generous rhythm, sits below the wall as a confident close.
   .section--cream tokens handle background + base text in both themes.
   ----------------------------------------------------------------- */

.reviews-cta {
  padding-block: clamp(3.5rem, 6vw, 6rem);
  text-align: center;
}

.reviews-cta__inner {
  max-width: 44rem;
  margin-inline: auto;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 1.5rem;
}

.reviews-cta__title {
  font-family: var(--font-serif);
  font-optical-sizing: auto;
  font-size: var(--text-3xl);
  font-weight: 350;
  color: var(--color-heading);
  line-height: 1.08;
  letter-spacing: -0.015em;
}
.reviews-cta__title em { font-style: italic; font-weight: 480; color: var(--color-rose-deep); }

.reviews-cta__lede {
  font-size: clamp(1rem, 0.9rem + 0.5vw, 1.15rem);
  color: var(--color-body);
  max-width: 34rem;
  line-height: 1.6;
}

/* Button pair - stacked on mobile, side by side at 480px+ */
.reviews-cta__actions {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.875rem;
  width: 100%;
}

@media (min-width: 480px) {
  .reviews-cta__actions {
    flex-direction: row;
    justify-content: center;
    flex-wrap: wrap;
  }
}

/* Tap target floor - both buttons at least 44px tall */
.reviews-cta__actions .btn {
  min-height: 44px;
  min-width: 200px;
}

/* Secondary line - Yelp / Facebook */
.reviews-cta__secondary {
  font-size: var(--text-sm, 0.875rem);
  color: var(--color-muted);
  line-height: 1.5;
}

/* Keep "Yelp or Facebook." together on one line. At 320 this sentence wraps, and
   it used to break BETWEEN the two links - Yelp ending line 1, Facebook opening
   line 2, a 19.42px line pitch apart. That made the obvious fix (a 44px hit
   expander, as used on .reviews-hero__cta-secondary) actively harmful: two 44px
   zones 19.42px apart overlap by ~25px and the later element in DOM order wins,
   so a tap aimed at Yelp would open Facebook. Same failure already documented on
   .footer-band__links and .post-author-card__link.
   Holding the pair on one line means the expander below only ever overlaps plain
   text on the line above, which steals nothing - text is not a competing target.
   The phrase is ~110px at 320, so it cannot overflow the viewport. */
.reviews-cta__pair {
  white-space: nowrap;
}

.reviews-cta__secondary a {
  color: var(--color-link);
  text-underline-offset: 0.2em;
  /* "Yelp" is 25.6x16 here - the twin of the hero CTA link, missed in the first
     pass because the sweep's unclassed-anchor bucket reported only its first
     instance and a prose link masked this one. Needs width AND height, so the
     pseudo is inset on all four sides. 0.72em per side is sized off the NARROW
     link: (44 - 25.6) / 2 = 9.2px at the 12.96px font of the 320 breakpoint.
     0.5em was tried first and left Yelp at 39.75px wide. The " or " between the
     two links is ~20px, so 2 x 9.3px of expansion still leaves the zones
     abutting rather than overlapping - verified by each link still owning its
     own centre at every width. */
  --hit-expander: 1;
  position: relative;
}

.reviews-cta__secondary a::after {
  content: "";
  position: absolute;
  left: -0.72em;
  right: -0.72em;
  top: 50%;
  transform: translateY(-50%);
  height: 44px;
}

@media (prefers-reduced-motion: no-preference) {
  @media (hover: hover) {
    .reviews-cta__secondary a:hover {
      color: var(--color-accent-hover);
    }
  }
}

/* -----------------------------------------------------------------
   CLOSING CTA - PAIRED BUTTONS (item 8)
   The primary .btn--cta is a rose/teal pill; the secondary .btn--outline
   default geometry did not match. Give both the same pill shape, height,
   padding rhythm and display type so they read as a deliberate pair.
   .btn--cta keeps its own rose/teal background (never recolored).
   ----------------------------------------------------------------- */

.reviews-cta__actions .btn {
  box-sizing: border-box;
  padding: 16px 32px;
  min-height: 0;
  border-radius: var(--radius-full);
  font-family: var(--font-display);
  font-size: 14px;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  white-space: nowrap;
}

/* Icon sizing inside the CTA button (matches the global .btn--cta icon rule) */
.reviews-cta__actions .btn .btn__icon.ph-icon,
.reviews-cta__actions .btn .ph-icon {
  width: 1.1em;
  height: 1.1em;
  flex-shrink: 0;
}

/* -----------------------------------------------------------------
   READ-MORE MODAL (item 4)
   Centered dialog on desktop, full-height scrollable bottom-sheet on
   mobile. Focus-trapped + scroll-locked + Esc/backdrop/close dismiss in
   reviews.js. ZERO grid reflow - the whole reason this is a modal, not an
   inline expand. Built once and appended to <body> by JS.
   ----------------------------------------------------------------- */

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

.review-modal {
  position: fixed;
  inset: 0;
  z-index: 1000;
  display: flex;
  justify-content: center;
  align-items: flex-end; /* mobile: bottom sheet */
}

@media (min-width: 600px) {
  .review-modal {
    align-items: center;
    padding: var(--space-xl);
  }
}

.review-modal__backdrop {
  position: absolute;
  inset: 0;
  background: rgba(0, 0, 0, 0.55);
}

@supports (backdrop-filter: blur(2px)) {
  .review-modal__backdrop {
    backdrop-filter: blur(2px);
  }
}

.review-modal__dialog {
  position: relative;
  display: flex;
  flex-direction: column;
  width: 100%;
  max-width: 40rem;
  max-height: 85vh;
  overflow: hidden; /* content is the scroll container so the close button stays pinned */
  background: var(--color-bg-card);
  color: var(--color-body);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-xl) var(--radius-xl) 0 0; /* bottom sheet: round top only */
  box-shadow: var(--shadow-xl);
}

@media (min-width: 600px) {
  .review-modal__dialog {
    border-radius: var(--radius-xl);
    max-height: min(85vh, 44rem);
  }
}

[data-theme="dark"] .review-modal__dialog {
  background: var(--color-bg-elevated);
}

.review-modal__close {
  position: absolute;
  top: 0.75rem;
  right: 0.75rem;
  z-index: 2;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 44px;
  height: 44px;
  background: var(--color-bg-card);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-full);
  color: var(--color-body);
  cursor: pointer;
}

[data-theme="dark"] .review-modal__close {
  background: var(--color-bg-card);
}

.review-modal__close-icon.ph-icon {
  width: 1.15rem;
  height: 1.15rem;
}

.review-modal__close:focus-visible {
  outline: 2px solid var(--color-focus-ring);
  outline-offset: 2px;
}

@media (prefers-reduced-motion: no-preference) {
  @media (hover: hover) {
    .review-modal__close {
      transition: background var(--transition-base), color var(--transition-fast);
    }
    .review-modal__close:hover {
      background: var(--color-bg-alt);
      color: var(--color-heading);
    }
  }
}

.review-modal__content {
  /* Vertical only - see .post-toc__sticky in inspiration.css. */
  overflow-x: hidden;
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
  scrollbar-width: thin; /* premium thin scrollbar (standard model) */
  padding: clamp(1.75rem, 4vw, 2.5rem);
}

/* Cloned card sub-parts, scaled up for the dialog reading context */
.review-modal__content .review-card__stars {
  font-size: var(--text-base);
  margin-bottom: var(--space-sm);
}

.review-modal__content .review-card__headline {
  font-size: var(--text-lg);
  margin-bottom: var(--space-sm);
}

.review-card__full-body {
  margin: 0 0 var(--space-lg);
  font-family: var(--font-body);
  font-size: var(--text-base);
  line-height: 1.7;
  color: var(--color-body);
  white-space: pre-line; /* keep the paragraph breaks Google stores */
}

.review-modal__content .review-card__foot {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.35em 0.6em;
  border-top: 1px solid var(--color-border);
  padding-top: var(--space-md);
}

/* Scroll-lock the page behind the modal OR the lightbox. Two classes so a
   lightbox opened from inside the read-more modal keeps the lock when it
   closes (the modal class is still present). */
html.review-modal-open,
html.review-modal-open body,
html.review-lightbox-open,
html.review-lightbox-open body {
  overflow: hidden;
}

@media (prefers-reduced-motion: no-preference) {
  .review-modal__backdrop {
    animation: review-modal-fade 0.2s ease;
  }
  .review-modal__dialog {
    animation: review-modal-slide 0.28s cubic-bezier(0.16, 1, 0.3, 1);
  }
  @keyframes review-modal-fade {
    from { opacity: 0; }
    to   { opacity: 1; }
  }
  @keyframes review-modal-slide {
    from { opacity: 0; transform: translateY(24px); }
    to   { opacity: 1; transform: none; }
  }
}

/* -----------------------------------------------------------------
   REVIEW PHOTOS - thumbnail strip (item: client-attached review photos)
   DOMINANT MOMENT: a compact row of square photo thumbnails in the card
   foot that turns a text review into proof-with-pictures. - .review-photos
   Uniform cover-cropped thumbs (UGC of mixed aspect ratios); the lightbox
   shows each photo whole. Guarded server-side: no markup when no photos.
   ----------------------------------------------------------------- */

.review-photos {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-xs);
}

.review-photos__item {
  display: flex;
}

.review-photos__thumb {
  --thumb-size: 56px;
  width: var(--thumb-size);
  height: var(--thumb-size);
  flex: 0 0 auto;
  padding: 0;
  border: 1px solid var(--color-border);
  border-radius: var(--radius-sm);
  overflow: hidden; /* contains the hover zoom */
  cursor: pointer;
  background: var(--color-bg-alt);
}

.review-photos__thumb img {
  width: 100%;
  height: 100%;
  object-fit: cover; /* uniform strip - the lightbox shows the uncropped image */
  object-position: center;
}

.review-photos__thumb:focus-visible {
  outline: 2px solid var(--color-focus-ring);
  outline-offset: 2px;
}

@media (prefers-reduced-motion: no-preference) {
  @media (hover: hover) {
    .review-photos__thumb {
      transition: border-color var(--transition-base), box-shadow var(--transition-fast), transform var(--transition-fast);
    }
    .review-photos__thumb img {
      transition: transform var(--transition-base);
    }
    .review-photos__thumb:hover {
      border-color: var(--color-border-hover);
      box-shadow: var(--shadow-md);
      transform: translateY(-2px);
    }
    .review-photos__thumb:hover img {
      transform: scale(1.06);
    }
  }
}

/* Larger thumbs inside the read-more modal reading context */
.review-modal__content .review-photos {
  margin-top: var(--space-md);
}

.review-modal__content .review-photos__thumb {
  --thumb-size: 76px;
}

/* Featured pull-quotes: slightly larger thumbs to match the editorial scale */
.featured-quote .review-photos__thumb {
  --thumb-size: 72px;
}

/* -----------------------------------------------------------------
   PHOTO LIGHTBOX (item: review photos)
   Built once and appended to <body> by reviews.js, mirroring the
   read-more modal pattern: focus-trapped, scroll-locked, Esc/backdrop/
   close dismiss, focus returns to the trigger thumb. Sits ABOVE the
   read-more modal (z 1100 > 1000) so photos opened from inside the
   modal layer correctly. Image is shown UNCROPPED (object-fit: contain).
   Backdrop is intentionally dark in BOTH themes, so the chrome uses
   fixed white-on-translucent values (token heading colors would be
   wrong against a permanently-dark backdrop) - justified exception.
   ----------------------------------------------------------------- */

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

.review-lightbox {
  position: fixed;
  inset: 0;
  z-index: 1100;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: clamp(1rem, 4vw, 2.5rem);
}

.review-lightbox__backdrop {
  position: absolute;
  inset: 0;
  background: rgba(0, 0, 0, 0.8);
}

@supports (backdrop-filter: blur(4px)) {
  .review-lightbox__backdrop {
    backdrop-filter: blur(4px);
  }
}

.review-lightbox__figure {
  position: relative;
  z-index: 1;
  margin: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-md);
  max-width: 100%;
  max-height: 100%;
}

.review-lightbox__img {
  display: block;
  width: auto;
  height: auto;
  max-width: min(92vw, 1100px);
  max-height: 78vh;
  object-fit: contain; /* whole image, never cropped */
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-xl);
  background: var(--color-bg-card);
}

.review-lightbox__caption {
  max-width: min(92vw, 40rem);
  text-align: center;
  font-family: var(--font-body);
  font-size: var(--text-sm);
  line-height: 1.5;
  color: rgba(255, 255, 255, 0.85); /* on permanently-dark backdrop, both themes */
  text-wrap: pretty;
}

/* Close + prev/next chrome: white-on-translucent, theme-independent */
.review-lightbox__close,
.review-lightbox__nav {
  position: absolute;
  z-index: 2;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 44px;
  height: 44px;
  background: rgba(0, 0, 0, 0.45);
  border: 1px solid rgba(255, 255, 255, 0.28);
  border-radius: var(--radius-full);
  color: #fff;
  cursor: pointer;
}

.review-lightbox__close svg,
.review-lightbox__nav svg {
  width: 22px;
  height: 22px;
  fill: none;
  stroke: currentColor;
  stroke-width: 2;
  stroke-linecap: round;
  stroke-linejoin: round;
}

.review-lightbox__close {
  top: clamp(0.75rem, 2vw, 1.5rem);
  right: clamp(0.75rem, 2vw, 1.5rem);
}

.review-lightbox__nav {
  top: 50%;
  transform: translateY(-50%);
}

.review-lightbox__nav--prev {
  left: clamp(0.5rem, 2vw, 1.5rem);
}

.review-lightbox__nav--next {
  right: clamp(0.5rem, 2vw, 1.5rem);
}

.review-lightbox__counter {
  position: absolute;
  z-index: 2;
  top: clamp(0.75rem, 2vw, 1.5rem);
  left: 50%;
  transform: translateX(-50%);
  font-family: var(--font-body);
  font-size: var(--text-xs);
  font-variant-numeric: tabular-nums;
  color: rgba(255, 255, 255, 0.85);
  background: rgba(0, 0, 0, 0.45);
  padding: 0.25em 0.7em;
  border-radius: var(--radius-full);
}

.review-lightbox__close:focus-visible,
.review-lightbox__nav:focus-visible {
  outline: 2px solid #fff;
  outline-offset: 2px;
}

@media (prefers-reduced-motion: no-preference) {
  @media (hover: hover) {
    .review-lightbox__close,
    .review-lightbox__nav {
      transition: background var(--transition-base), border-color var(--transition-base);
    }
    .review-lightbox__close:hover,
    .review-lightbox__nav:hover {
      background: rgba(0, 0, 0, 0.7);
      border-color: rgba(255, 255, 255, 0.5);
    }
  }
}

@media (prefers-reduced-motion: no-preference) {
  .review-lightbox__backdrop {
    animation: review-modal-fade 0.2s ease;
  }
  .review-lightbox__figure {
    animation: review-lightbox-zoom 0.26s cubic-bezier(0.16, 1, 0.3, 1);
  }
  @keyframes review-lightbox-zoom {
    from { opacity: 0; transform: scale(0.94); }
    to   { opacity: 1; transform: none; }
  }
}
