/* ==========================================================================
   Papakura Acupuncture Clinic
   Rebuilt to match the live Squarespace 7.1 site.

   1. Site tokens (palette, fonts, type scale)
   2. Section colour themes
   3. Base
   4. Fluid-engine grid
   5. Sections
   6. Buttons
   7. Header
   8. Reviews carousel
   9. Footer section
  10. Media placeholders
   ========================================================================== */

/* 1. Site tokens ----------------------------------------------------------- */

:root {
  /* Site palette, taken verbatim from the live site styles */
  --white-hsl:        44, 38%, 94%;   /* warm cream  */
  --black-hsl:       148, 19%, 15%;   /* deep green  */
  --accent-hsl:      102, 23%, 32%;   /* olive       */
  --lightAccent-hsl:  78, 25%, 78%;   /* pale sage   */
  --darkAccent-hsl:   27, 31%, 24%;   /* warm brown  */

  --safeLightAccent-hsl:        44, 38%, 94%;
  --safeDarkAccent-hsl:        102, 23%, 32%;
  --safeInverseAccent-hsl:      44, 38%, 94%;
  --safeInverseDarkAccent-hsl:  44, 38%, 94%;
  --safeInverseLightAccent-hsl:148, 19%, 15%;

  /* Fonts. The live site pairs Georgia headings with SF Pro Text body copy
     and Almarai buttons; the body stack falls back to the platform UI face. */
  --heading-font: Georgia, "Times New Roman", Times, serif;
  --body-font: -apple-system, BlinkMacSystemFont, "SF Pro Text", "Segoe UI",
    Roboto, "Helvetica Neue", Helvetica, Arial, sans-serif;
  --button-font: "Almarai", var(--body-font);

  --heading-font-line-height: 1.2em;
  --heading-font-letter-spacing: -0.02em;
  /* Unitless so it re-resolves against each element's own size on the way
     down - an em here would inherit as a fixed pixel value and break any
     text that is resized, such as the review captions. */
  --body-font-line-height: 1.5;

  /* Type scale values, fed through the responsive size formula below */
  --heading-1-size-value: 4;
  --heading-2-size-value: 2.8;
  --heading-3-size-value: 2.2;
  --heading-4-size-value: 1.6;
  --large-text-size-value: 1.4;
  --normal-text-size-value: 1;
  --small-text-size-value: 0.9;

  --maxPageWidth: 2560px;
  --pagePadding: 3vw;
  --sqs-site-max-width: var(--maxPageWidth);
  --sqs-site-gutter: var(--pagePadding);
  --sqs-mobile-site-gutter: 6vw;

  /* One radius for every panel on the page - review cards, photos, map. */
  --panel-radius: 8px;

  --header-logo-height: 41px;
  --header-vert-padding: 0.8vw;
  --mobile-header-vert-padding: 6vw;
}

/* The responsive type formula the live site uses. Each element sets --v to
   its scale value; the size grows with the viewport, then locks at the page
   max width. */
.fs {
  font-size: calc((var(--v) - 1) * calc(0.012 * min(100vh, 900px)) + 1rem);
}

@media screen and (min-width: 768px), screen and (orientation: landscape) {
  .fs {
    font-size: min(
      calc((var(--v) - 1) * 1.2vw + 1rem),
      max(
        calc((var(--v) - 1) * 0.012 * var(--maxPageWidth) + 1rem),
        calc(var(--v) * 1rem)
      )
    );
  }
}

/* 2. Section colour themes ------------------------------------------------- */

[data-section-theme="white"] {
  --bg: hsl(var(--white-hsl));
  --text: hsl(var(--black-hsl));
  --btn-bg: hsl(var(--safeDarkAccent-hsl));
  --btn-text: hsl(var(--safeInverseDarkAccent-hsl));
  --rule: hsla(var(--black-hsl), 0.15);
  --rule-strong: hsla(var(--black-hsl), 0.55);
}

[data-section-theme="light"] {
  --bg: hsl(var(--lightAccent-hsl));
  --text: hsl(var(--black-hsl));
  --btn-bg: hsl(var(--safeDarkAccent-hsl));
  --btn-text: hsl(var(--safeInverseDarkAccent-hsl));
  --rule: hsla(var(--black-hsl), 0.15);
  --rule-strong: hsla(var(--black-hsl), 0.55);
}

[data-section-theme="bright"] {
  --bg: hsl(var(--accent-hsl));
  --text: hsl(var(--safeInverseAccent-hsl));
  --btn-bg: hsl(var(--safeInverseAccent-hsl));
  --btn-text: hsl(var(--accent-hsl));
  --rule: hsla(var(--safeInverseAccent-hsl), 0.25);
  --rule-strong: hsla(var(--safeInverseAccent-hsl), 0.65);
}

/* 3. Base ------------------------------------------------------------------ */

*,
*::before,
*::after { box-sizing: border-box; }

html { -webkit-text-size-adjust: 100%; }

body {
  margin: 0;
  background: hsl(var(--white-hsl));
  color: hsl(var(--black-hsl));
  font-family: var(--body-font);
  font-weight: 400;
  line-height: var(--body-font-line-height);
  -webkit-font-smoothing: antialiased;
  padding-top: calc(var(--header-logo-height) + var(--header-vert-padding) * 2);
}

h1, h2, h3, h4 {
  font-family: var(--heading-font);
  font-weight: 400;
  font-style: normal;
  letter-spacing: var(--heading-font-letter-spacing);
  margin: 0;
}

/* Headings tighten as they get larger. The live site derives each level's
   line-height from the global size value, not from any per-block override,
   so a resized heading keeps its level's leading. */
h1 { --v: var(--heading-1-size-value); }
h2 { --v: var(--heading-2-size-value); }
h3 { --v: var(--heading-3-size-value); }
h4 { --v: var(--heading-4-size-value); }

h1 {
  line-height: calc(
    var(--heading-font-line-height) * (1 + (1 - var(--heading-1-size-value)) / 25)
  );
}
h2 {
  line-height: calc(
    var(--heading-font-line-height) * (1 + (1 - var(--heading-2-size-value)) / 25)
  );
}
h3 {
  line-height: calc(
    var(--heading-font-line-height) * (1 + (1 - var(--heading-3-size-value)) / 25)
  );
}
h4 {
  line-height: calc(
    var(--heading-font-line-height) * (1 + (1 - var(--heading-4-size-value)) / 25)
  );
}

p { --v: var(--normal-text-size-value); margin: 0; }
p + p { margin-top: 1em; }

a { color: inherit; }

.rte a {
  color: inherit;
  text-decoration: underline;
  text-decoration-thickness: 1px;
  text-underline-offset: 0.2em;
}

img {
  display: block;
  max-width: 100%;
}

figure { margin: 0; }

ul[data-rte-list] {
  margin: 1em 0 0;
  padding-left: 1.2em;
}
ul[data-rte-list] li + li { margin-top: 0.9em; }

:focus-visible {
  outline: 2px solid currentColor;
  outline-offset: 3px;
}

.skip-link {
  position: absolute;
  left: -9999px;
  top: 0;
  z-index: 100;
  background: hsl(var(--accent-hsl));
  color: hsl(var(--safeInverseAccent-hsl));
  padding: 0.75rem 1.25rem;
  text-decoration: none;
}
.skip-link:focus { left: 1rem; top: 1rem; }

/* 4. Fluid-engine grid ----------------------------------------------------- */
/* 8 columns on mobile, 24 on desktop, an 11px gutter either way, and rows
   sized as a fraction of the container - the live layout engine's grid. */

.fluid {
  display: grid;
  position: relative;
  --grid-gutter: calc(var(--sqs-mobile-site-gutter) - 11px);
  /* Size the cell against whichever is smaller, the site max width or the
     viewport (less its gutters), so the 8 columns fit the phone screen
     instead of being laid out against 2560px and sheared by overflow. */
  --container-width: min(
    var(--sqs-site-max-width),
    calc(100vw - var(--sqs-mobile-site-gutter) * 2)
  );
  --cell-max-width: calc((var(--container-width) - (11px * 7)) / 8);
  grid-template-columns:
    minmax(var(--grid-gutter), 1fr)
    repeat(8, minmax(0, var(--cell-max-width)))
    minmax(var(--grid-gutter), 1fr);
  grid-auto-rows: minmax(24px, auto);
  row-gap: 11px;
  column-gap: 11px;
  overflow-x: clip;
}

@media (min-width: 768px) {
  .fluid {
    --grid-gutter: calc(var(--sqs-site-gutter) - 11px);
    --cell-max-width: calc((var(--sqs-site-max-width) - (11px * 23)) / 24);
    --container-width: min(
      var(--sqs-site-max-width),
      calc(100vw - var(--sqs-site-gutter) * 2)
    );
    grid-template-columns:
      minmax(var(--grid-gutter), 1fr)
      repeat(24, minmax(0, var(--cell-max-width)))
      minmax(var(--grid-gutter), 1fr);
    grid-auto-rows: minmax(calc(var(--container-width) * 0.0215), auto);
  }
}

/* Every block is a flex column so it can sit middle- or top-aligned across
   the rows it spans, the way the layout engine aligns its blocks. */
.fb {
  display: flex;
  flex-direction: column;
  justify-content: center;
  min-width: 0;
}
.fb--top { justify-content: flex-start; }

/* 5. Sections -------------------------------------------------------------- */

.page-section {
  background: var(--bg);
  color: var(--text);
  position: relative;
}

.section-height--small  { min-height: 33vh; }
.section-height--medium { min-height: 66vh; }

.section-height--small  > .content-wrapper { padding-block: 3.3vmax; }
.section-height--medium > .content-wrapper { padding-block: 6.6vmax; }

/* About page: tighter vertical rhythm. The sections carry less padding around
   their text and are not forced to two-thirds of the viewport, so the space
   below each paragraph before the next section's border is smaller. Change the
   padding here to retune how much air sits around the about-page copy. */
.page-about .section-height--medium { min-height: 0; }
.page-about .section-height--medium > .content-wrapper { padding-block: 7.2vmax; }

/* Homepage Services section: same vertical rhythm as the about-page sections,
   so the space around its content matches. (The reviews block below uses the
   same 7.2vmax on its own inner padding.) */
.page-home .section-height--medium { min-height: 0; }
.page-home .section-height--medium > .content-wrapper { padding-block: 7.2vmax; }

/* Hero */
.b-hero-image   { grid-area: 1 / 2 / 7 / 10; }
.b-hero-eyebrow { grid-area: 8 / 2 / 10 / 10; }
.b-hero-title   { grid-area: 10 / 2 / 13 / 10; }
.b-hero-button  { grid-area: 13 / 2 / 15 / 10; }
.b-hero-phones  { grid-area: 15 / 2 / 16 / 10; }

/* The eyebrow is tinted warm brown on the live site. It is a paragraph rather
   than a heading - it labels the headline below it, it does not title a
   section - but it is set exactly as the h3 it replaced, down to the leading
   the heading scale would have given it. */
.eyebrow {
  --v: var(--heading-3-size-value);
  align-self: center;
  font-family: var(--heading-font);
  letter-spacing: var(--heading-font-letter-spacing);
  line-height: calc(
    var(--heading-font-line-height) * (1 + (1 - var(--heading-3-size-value)) / 25)
  );
  color: hsl(var(--darkAccent-hsl));
  margin: 0;
}

/* Services. The copy is one block on a single row that grows to fit it, so
   the spacing inside comes from the rules below rather than from which grid
   rows each heading happened to land on. */
.b-services-image { grid-area: 1 / 4 / 10 / 10; }
.b-services-copy  { grid-column: 2 / 10; grid-row: 11; }

/* Footer section. The three columns live in a wrapper so their spacing is set
   once here rather than falling out of the page grid. On mobile the wrapper
   fills the inner 8-cell band and stacks its children one under the other. */
.footer-grid { grid-column: 2 / 10; grid-row: 1; }
.b-footer-hours   { margin-top: 2.75rem; }
.b-footer-contact { margin-top: 2.75rem; }

/* About page. Each section is one block holding a heading stacked directly
   above its body text. The block reuses the site's column grid only to sit in
   the right place and width; inside, the heading and body are two rows that
   flow one under the other, so the heading-to-text gap is a single row-gap
   value (below) rather than something that falls out of per-element row spans.

   Mobile: the content fills the inner 8-cell band (columns 2 - 10). */
.about-block {
  display: grid;
  grid-template-columns:
    minmax(var(--grid-gutter), 1fr)
    repeat(8, minmax(0, var(--cell-max-width)))
    minmax(var(--grid-gutter), 1fr);
  --grid-gutter: calc(var(--sqs-mobile-site-gutter) - 11px);
  --container-width: min(
    var(--sqs-site-max-width),
    calc(100vw - var(--sqs-mobile-site-gutter) * 2)
  );
  --cell-max-width: calc((var(--container-width) - (11px * 7)) / 8);
  column-gap: 11px;
  row-gap: 2rem;
  max-width: var(--maxPageWidth);
  margin-inline: auto;
}
.about-heading,
.about-body { grid-column: 2 / 10; }

/* The normal text size resolves to a flat 1rem at every width, because the
   scale formula's variable part falls to zero at a size value of 1. These are
   long passages read end to end, so they run one pixel up from that - change
   the 1px to retune. */
.about-body p { font-size: calc(1rem + 1px); }

@media (min-width: 768px) {
  /* Hero: a full-width banner image with the copy stacked beneath it */
  .b-hero-image   { grid-area: 1 / 2 / 10 / 26; }
  .b-hero-eyebrow { grid-area: 10 / 3 / 12 / 18; }
  .b-hero-title   { grid-area: 12 / 3 / 14 / 18; }
  .b-hero-button  { grid-area: 14 / 3 / 16 / 8; }
  .b-hero-phones  { grid-area: 16 / 3 / 17 / 8; }

  /* Services: image on the left, the three treatments listed on the right.
     Both sit on a single auto-height row so the section grows to fit the copy
     and no empty grid rows are reserved beneath it - that reserved space was
     making the bottom gap larger than the top. The image stretches to the row
     height so it stays as tall as the copy beside it. */
  .b-services-image { grid-column: 4 / 11;  grid-row: 1; align-self: stretch; }
  .b-services-copy  { grid-column: 12 / 25; grid-row: 1; }

  /* Footer: map and address left, hours centre, contact right.

     The three columns share the full inner band (grid lines 2 - 26, i.e. 24
     cells) as their own three-track grid rather than each taking a fixed cell
     span. This lets the gap between them be narrower than a whole grid step
     while the columns take up the width that frees: the outer edges stay on
     lines 2 and 26, so the section looks the same at the default width, but the
     text columns are wider and the space between them smaller.

     Each grid cell is (container - 23 gutters) / 24 wide; the gap here is two
     of those cells plus the one 11px gutter that sits between them - narrower
     than the previous three-cell gap. The 1fr columns split whatever is left,
     so all three stay equal. */
  .footer-grid {
    display: grid;
    grid-column: 2 / 26;
    grid-row: 1;
    grid-template-columns: repeat(3, 1fr);
    column-gap: calc(
      2 * ((var(--container-width) - 23 * 11px) / 24) + 11px
    );
  }
  .b-footer-location,
  .b-footer-hours,
  .b-footer-contact { grid-row: 1; margin-top: 0; }

  /* About page: on desktop the same block switches to the 24-column band and
     its heading and body sit right of centre, in columns 9 - 19, exactly where
     the old per-element grid placed them. */
  .about-block {
    --grid-gutter: calc(var(--sqs-site-gutter) - 11px);
    --cell-max-width: calc((var(--sqs-site-max-width) - (11px * 23)) / 24);
    grid-template-columns:
      minmax(var(--grid-gutter), 1fr)
      repeat(24, minmax(0, var(--cell-max-width)))
      minmax(var(--grid-gutter), 1fr);
  }
  .about-heading,
  .about-body { grid-column: 9 / 19; }
}

/* "Expert Care, Tailored to You" is scaled text on the live site: the heading
   is forced onto a single line and scaled so that line exactly fills its
   column. Solving that against the grid gives the sizes below.

   The string measures 12.0031em wide in Georgia at -0.02em tracking. On
   desktop it sits in 8 of the 24 columns, so the column is
   (0.94vw_total - 253px) / 3 + 77px, and dividing by 12.0031 gives
   2.611vw - 0.611px. It stops growing once the page hits its 2560px max,
   where the column is 846px and the text 70.5px. On mobile the block spans
   the full content width, which is 0.88 of the viewport, giving 7.33vw. */
.scaled-text {
  white-space: nowrap;
  line-height: 1;
  font-size: 7.33vw;
}

@media (min-width: 768px) {
  .scaled-text { font-size: min(calc(2.611vw - 0.611px), 70.5px); }
}

/* The map is sized by its own aspect ratio rather than by the grid rows it
   spans, so it keeps its shape wherever the footer column falls. On mobile it
   fills the footer column; on desktop it sits back to 70% of the wider column. */
.map-frame {
  aspect-ratio: 4 / 3;
  border-radius: var(--panel-radius);
  overflow: hidden;
}

@media (min-width: 768px) {
  .map-frame {
    aspect-ratio: 16 / 9;
    /* Roughly 30% smaller than the full footer column; the aspect ratio keeps
       the height in step, so the whole map shrinks proportionally. */
    max-width: 70%;
  }
}

.map-embed {
  border: 0;
  width: 100%;
  height: 100%;
  min-height: 200px;
  display: block;
}

/* Services copy ------------------------------------------------------------ */

.b-services-copy { gap: clamp(1.5rem, 2.4vw, 2.5rem); }

/* A little more air under the section heading than between the treatments. */
.b-services-copy > h2 { margin-bottom: 0.35rem; }

.service h4 { margin-bottom: 0.5em; }

/* Description text sits a touch above the shared body size - between the base
   size and the slightly larger size it carried before. */
.service p { --v: calc(var(--normal-text-size-value) + 0.075); }

/* Footer spacing ----------------------------------------------------------- */

.footer-heading { margin-bottom: 1.1rem; }

.b-footer-location .footer-body { margin-top: 1.4rem; }

/* 6. Buttons --------------------------------------------------------------- */
/* Solid pill, Almarai, 1.25rem - the site's primary button style. */

.btn {
  --v: 1.25;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-family: var(--button-font);
  font-weight: 400;
  font-style: normal;
  line-height: 1.2em;
  letter-spacing: 0;
  text-align: center;
  text-decoration: none;
  padding: 1rem 1.3rem;
  border: 0;
  border-radius: 300px;
  background: var(--btn-bg);
  color: var(--btn-text);
  transition: opacity 0.15s ease;
}
.btn:hover { opacity: 0.82; }

/* The header call-to-action has its own size token on the live site (1rem),
   rather than the 1.25rem in-page primary buttons use. */
.header-actions .btn,
.header-menu .btn { --v: 1; }

/* The hero call to action carries more weight than the in-page buttons,
   so it sits a little taller than the shared 1rem block padding, and stands
   off the headline by more than the grid row gap alone would give it. */
.b-hero-button { margin-top: 1.25rem; }

.b-hero-button .btn {
  width: 100%;
  padding-block: 1.3rem;
}

/* 7. Header ---------------------------------------------------------------- */
/* Solid, fixed, "scroll back": it hides on the way down and returns on the
   way up. Title left, navigation centred, booking button right. */

.site-header {
  position: fixed;
  inset: 0 0 auto;
  z-index: 60;
  background: hsl(var(--white-hsl));
  color: hsl(var(--black-hsl));
  --btn-bg: hsl(var(--safeDarkAccent-hsl));
  --btn-text: hsl(var(--safeInverseDarkAccent-hsl));
  transition: transform 0.28s ease;
}
.site-header.is-hidden { transform: translateY(-100%); }

.header-inner {
  max-width: var(--maxPageWidth);
  margin-inline: auto;
  padding-inline: var(--sqs-site-gutter);
  padding-block: var(--header-vert-padding);
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  align-items: center;
  gap: 1rem;
  min-height: calc(var(--header-logo-height) + var(--header-vert-padding) * 2);
}

.site-title {
  --v: 1.5;
  font-family: var(--heading-font);
  font-weight: 400;
  line-height: var(--heading-font-line-height);
  letter-spacing: var(--heading-font-letter-spacing);
  color: hsl(var(--black-hsl));
  text-decoration: none;
  justify-self: start;
}

.header-nav {
  display: flex;
  align-items: center;
  gap: 2.2rem;
  justify-self: center;
}
.header-nav a {
  --v: calc(var(--normal-text-size-value) + 0.08);
  font-family: var(--body-font);
  color: hsl(var(--black-hsl));
  text-decoration: none;
  padding-block: 0.25rem;
}
.header-nav a[aria-current="page"],
.header-nav a:hover {
  text-decoration: underline;
  text-underline-offset: 0.35em;
  text-decoration-thickness: 1px;
}

.header-actions { justify-self: end; }

.header-burger {
  display: none;
  background: none;
  border: 0;
  padding: 0.6rem;
  cursor: pointer;
  color: inherit;
  justify-self: end;
}
.burger-box {
  display: block;
  width: 26px;
  height: 13px;
  position: relative;
}
.burger-box span {
  position: absolute;
  left: 0;
  width: 100%;
  height: 1px;
  background: currentColor;
  transition: transform 0.22s ease, opacity 0.22s ease;
}
.burger-box span:first-child { top: 0; }
.burger-box span:last-child  { bottom: 0; }

.site-header.menu-open .burger-box span:first-child {
  transform: translateY(6px) rotate(45deg);
}
.site-header.menu-open .burger-box span:last-child {
  transform: translateY(-6px) rotate(-45deg);
}

/* Full-screen overlay menu, the site's mobile navigation */
.header-menu {
  position: fixed;
  inset: 0;
  z-index: 55;
  background: hsl(var(--white-hsl));
  --btn-bg: hsl(var(--safeDarkAccent-hsl));
  --btn-text: hsl(var(--safeInverseDarkAccent-hsl));
  padding: calc(var(--mobile-header-vert-padding) * 2 + 40px)
    var(--sqs-mobile-site-gutter) var(--sqs-mobile-site-gutter);
  display: flex;
  flex-direction: column;
  gap: 1.5rem;
  opacity: 0;
  visibility: hidden;
  transition: opacity 0.2s ease, visibility 0.2s ease;
}
.header-menu[hidden] { display: none; }
.header-menu.is-open { opacity: 1; visibility: visible; }
.header-menu a {
  --v: var(--heading-4-size-value);
  font-family: var(--heading-font);
  letter-spacing: var(--heading-font-letter-spacing);
  color: hsl(var(--black-hsl));
  text-decoration: none;
}
.header-menu .btn {
  align-self: flex-start;
  font-family: var(--button-font);
  letter-spacing: 0;
}

@media (max-width: 767px) {
  body {
    padding-top: calc(30px + var(--mobile-header-vert-padding) * 2);
  }
  .header-inner {
    grid-template-columns: 1fr auto;
    padding-inline: var(--sqs-mobile-site-gutter);
    padding-block: var(--mobile-header-vert-padding);
    min-height: 0;
  }
  .site-title { --v: 1.2; }
  .header-nav,
  .header-actions { display: none; }
  .header-burger { display: block; }
}

/* 8. Reviews carousel ------------------------------------------------------ */
/* A scroll-snap row of cards: three fit on desktop, one on mobile, and the
   arrows page through by a card at a time. The quotes are set in the body
   sans, not the Georgia used elsewhere, so they read as spoken voice rather
   than as site copy.

   The cards are filled in the pale sage of the services section above, so the
   two bands read as one family without repeating a full-width colour. */

.reviews-section {
  --review-gap: 24px;
  --review-quote-size: 1.05rem;
}

.reviews-inner {
  max-width: var(--maxPageWidth);
  margin-inline: auto;
  /* Same vertical rhythm as the about-page sections and the services block. */
  padding-block: 7.2vmax;
  padding-inline: var(--pagePadding);
}

.reviews-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1.5rem;
  margin-bottom: 40px;
}

.reviews-title {
  --v: var(--heading-2-size-value);
  font-family: var(--heading-font);
  font-weight: 400;
  line-height: var(--heading-font-line-height);
  letter-spacing: var(--heading-font-letter-spacing);
  margin: 0;
}

.reviews-nav {
  display: flex;
  gap: 10px;
  flex-shrink: 0;
}

/* An outline, but a firm one - the hairline this started as all but
   disappeared against the cream. */
.reviews-arrow {
  width: 48px;
  height: 48px;
  display: grid;
  place-items: center;
  padding: 0;
  border: 1.5px solid var(--rule-strong);
  border-radius: 300px;
  background: none;
  color: inherit;
  cursor: pointer;
  transition: background-color 0.18s ease, border-color 0.18s ease,
    opacity 0.18s ease;
}
.reviews-arrow svg {
  width: 20px;
  height: 20px;
  fill: none;
  stroke: currentColor;
  stroke-width: 2;
  stroke-linecap: round;
  stroke-linejoin: round;
}
.reviews-arrow:hover {
  border-color: currentColor;
  background: hsla(var(--black-hsl), 0.06);
}

/* Spent, not disabled: the button stays focusable so keyboard users can tell
   they have reached the end rather than losing the control entirely. */
.reviews-arrow.is-spent { opacity: 0.3; }
.reviews-arrow.is-spent:hover { background: none; border-color: var(--rule-strong); }

.reviews-track {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: 86%;
  column-gap: var(--review-gap);
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  scroll-behavior: smooth;
  scrollbar-width: none;
  overscroll-behavior-x: contain;
}
.reviews-track::-webkit-scrollbar { display: none; }
.reviews-track:focus-visible { outline-offset: 6px; }

.review-card {
  scroll-snap-align: start;
  display: flex;
  flex-direction: column;
  min-width: 0;
  background: hsl(var(--lightAccent-hsl));
  border-radius: var(--panel-radius);
  padding: 2.2rem 2rem;
}

.review-quote {
  font-family: var(--body-font);
  font-size: var(--review-quote-size);
  line-height: 1.65;
  margin: 0 0 auto;
}

.review-name {
  font-family: var(--button-font);
  font-size: 0.8rem;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: hsl(var(--accent-hsl));
  margin: 1.6rem 0 0;
}

.review-source {
  font-family: var(--body-font);
  font-size: 0.8rem;
  opacity: 0.7;
  margin: 0.35rem 0 0;
}

@media (min-width: 768px) {
  .reviews-section { --review-gap: 28px; --review-quote-size: 1.0625rem; }
  .reviews-track {
    grid-auto-columns: calc((100% - var(--review-gap) * 2) / 3);
  }
}

.review-quote::before {
  content: "\201C";
  display: block;
  font-family: var(--heading-font);
  font-size: 3.2rem;
  line-height: 0.6;
  margin-bottom: 1.1rem;
  color: hsl(var(--accent-hsl));
}

/* 9. Footer section -------------------------------------------------------- */

.site-footer { display: block; }

/* 10. Media placeholders --------------------------------------------------- */
/* Drop real photos into /images and the frames fill automatically. Until
   then .is-missing keeps the layout looking deliberate. */

/* The frame fills whatever grid area it is placed in, and the photo is taken
   out of flow so it crops to that area. Sizing the image with height:100%
   in flow instead makes its height depend on a row that is itself sized by
   its contents, which is a cycle the browser cannot resolve. */
.media-frame {
  position: relative;
  overflow: hidden;
  border-radius: var(--panel-radius);
  background: hsla(var(--black-hsl), 0.08);
  min-height: 0;
}

.media-frame > img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.media-frame.is-missing > img { display: none; }

.media-frame.is-missing::after {
  content: attr(data-placeholder);
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 1.5rem;
  text-align: center;
  font-size: 0.85rem;
  color: hsla(var(--black-hsl), 0.45);
}

/* Motion preferences ------------------------------------------------------- */

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    transition-duration: 0.01ms !important;
  }
}
