/* ==========================================================================
   Elimination Station — Design tokens + base styles
   ========================================================================== */

:root {
  --sage: #7A8B6F;
  --sage-dark: #5C6E52;
  --cream: #F7F4EE;
  --charcoal: #2B2B2B;
  --blush: #E8D5C4;
  /* Warm gold for headings on the dark footer. Sits with the blush/cream side
     of the palette and lifts off the near-black at 8.4:1. */
  --gold: #D4AF6A;
  /* Deeper member of --blush's family (hue 28deg vs 24deg) -- used for the
     Instagram button so it differs from the sage one without leaving the
     palette. White on it measures 5.2:1. */
  --terracotta: #9A5F3C;
  /* Deep forest green -- the darkest step of the sage family (hue 104 vs sage's
     96), used for the Reviews heading. 8.7:1 on the cream ground. */
  --forest: #3A4A34;
  /* Star gold, shared by the review-card ratings and the Google score badge. */
  --star-gold: #D9A441;
  --terracotta-dark: #85502F;
  --deep-charcoal: #1A1A1A;
  --white: #FFFFFF;

  --font-heading: 'Playfair Display', Georgia, serif;
  /* Elegant serif used for accent headings and the hero brand name. */
  --font-accent: 'Cormorant Garamond', 'Playfair Display', Georgia, serif;
  --font-body: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif;

  --radius-sm: 6px;
  --radius-md: 12px;
  --radius-lg: 20px;
  /* Single source of truth for button corners, site-wide. */
  --radius-btn: 10px;

  --shadow-card: 0 6px 24px rgba(43, 43, 43, 0.08);
  --shadow-lift: 0 12px 32px rgba(43, 43, 43, 0.14);

  --max-width: 1180px;
}

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

html {
  scroll-behavior: smooth;
  /* Needed alongside the body rule: when <html> is the scroll container,
     clipping only on <body> still leaves a horizontal scrollbar. */
  overflow-x: hidden;
  max-width: 100%;
}

body {
  margin: 0;
  overflow-x: hidden;
  overflow-wrap: break-word;
  font-family: var(--font-body);
  background: var(--cream);
  color: var(--charcoal);
  line-height: 1.65;
  -webkit-font-smoothing: antialiased;
}

h1, h2, h3, h4 {
  font-family: var(--font-heading);
  font-weight: 700;
  line-height: 1.2;
  margin: 0 0 0.6em;
  color: var(--charcoal);
}

h1 { font-size: clamp(2rem, 4vw, 3.2rem); }
h2 { font-size: clamp(1.6rem, 3vw, 2.3rem); }
h3 { font-size: clamp(1.2rem, 2vw, 1.5rem); }

p { margin: 0 0 1em; }

a { color: var(--sage-dark); text-decoration: none; }
a:hover { text-decoration: underline; }

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

/* Third-party embeds (Square scheduler, Google Map) inject their own markup
   and can be wider than the viewport, so constrain them defensively. */
iframe, video, embed, object { max-width: 100%; }
table { max-width: 100%; display: block; overflow-x: auto; }

/* Accent headings ("Free ♡ Consultations", "Real words.", "Reviews").
   Matches the hero brand lockup so the site uses one accent face throughout. */
.script-accent {
  font-family: var(--font-accent);
  font-style: italic;
  font-weight: 600;
  color: var(--sage-dark);
}

/* Book Now tab-panel intros (deposit policy, consultation blurb). Centred and
   semibold; pulled out of inline/utility classes so the responsive layer can
   override text-align -- an inline rule would have won outright. */
.panel-intro {
  text-align: center;
}

/* Upright, bold variant of the accent face. Same Cormorant family, size and
   sage colour -- only the slant and weight change. Book Now's font request was
   italic-only (ital,wght@1,…), so the upright 600/700 weights were added there
   too; without them font-style:normal would have quietly fallen back to
   Playfair. Scoped as a modifier so the other .script-accent uses (Results'
   "Real words" and "Reviews") keep their italics. */
.script-accent--upright {
  font-style: normal;
  font-weight: 700;
}

/* Results hero heading. Cormorant Garamond sets noticeably smaller on the body
   than Playfair Display does at the same font-size, so the accent half read as
   shrunken rather than deliberately different. Scaling it up brings the two
   x-heights into line and lets weight and colour carry the contrast instead of
   an accidental size difference. Scoped to this heading so the other
   .script-accent uses (Reviews, Free Consultations) are unaffected. */
.results-title {
  text-wrap: balance;
}
.results-title .script-accent {
  font-size: 1.12em;
  margin-left: 0.08em;
  letter-spacing: 0.005em;
}

.eyebrow {
  text-transform: uppercase;
  letter-spacing: 0.12em;
  font-size: 0.8rem;
  font-weight: 600;
  color: var(--sage-dark);
  margin: 0 0 0.5em;
}

/* Never use the padding shorthand here: elements combine `.container` with
   `.section`/`.hero`, and a shorthand would reset their vertical padding. */
.container {
  max-width: var(--max-width);
  margin: 0 auto;
  padding-left: 24px;
  padding-right: 24px;
}

/* Adjacent sections each contribute their own padding, so these values are
   roughly half the gap between two cards. At 64/40 that produced 104-128px
   voids between sections; 44/32 keeps clear separation at ~64-76px. */
.section {
  padding-top: 44px;
  padding-bottom: 44px;
}

.section--tight { padding-top: 32px; padding-bottom: 32px; }

/* How It Works: one spacing value for every gap on the page.
   It mixed .section (44+44) with .section--tight (32+32), and the two cards in
   #science were separated by .card + .card (24px), so the gaps ran
   24 / 44 / 64 / 76px. Putting 24px on both edges of every block makes each
   adjacent pair sum to exactly 48px, and #immune gets the full 48 in one go
   because it is a sibling card inside #science, not a section of its own.
   The inline padding-bottom/margin-top that used to sit on the hero and #immune
   were removed in the markup -- inline styles outrank this rule. */
.page-hiw .section,
.page-hiw .section--tight { padding-top: 24px; padding-bottom: 24px; }
.page-hiw .hero { padding-bottom: 24px; }
.page-hiw #immune { margin-top: 48px; }
/* The h1's own bottom margin sits inside the hero's padding and stacks on top
   of it, which measured 94px against everything else's 64px. */
.page-hiw .hero h1 { margin-bottom: 0; }
/* The banner is the one block with a background, so its padding is inside the
   coloured band rather than whitespace. Margins supply its half of the gap. */
.page-hiw .section--sage { margin-top: 24px; margin-bottom: 24px; }

/* Small standalone strip sitting just under the sage banner. Deliberately
   understated so it doesn't compete with the heading above it. Only top
   padding is needed here -- the following section supplies its own. */
.tagline-band {
  padding-top: 26px;
  text-align: center;
}
.tagline-strip {
  display: inline-block;
  margin: 0;
  padding: 9px 24px;
  background: var(--blush);
  border: 1px solid var(--sage);
  border-radius: 999px;
  color: var(--sage-dark);
  font-size: 0.78rem;
  font-weight: 600;
  line-height: 1.4;
  text-transform: uppercase;
  letter-spacing: 0.14em;
}

.section--sage {
  background: var(--sage);
  color: var(--white);
}
.section--sage h2, .section--sage h3 { color: var(--white); }

.section--charcoal {
  background: var(--deep-charcoal);
  color: var(--cream);
}

.card {
  background: var(--white);
  border-radius: var(--radius-lg);
  padding: 32px;
  box-shadow: var(--shadow-card);
}

/* Safety net: stacked cards must never butt together, whatever the page does. */
.card + .card { margin-top: 24px; }

/* Two equal-width cards side by side. Grid `gap` handles the spacing, so the
   stacked-card margin above has to be cancelled or it double-spaces them. */
.card-duo {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 24px;
  align-items: stretch;   /* both cards match the taller one */
}
.card-duo .card + .card { margin-top: 0; }

/* Text card beside a photo, equal columns. */
.text-media {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 28px;
  align-items: stretch;
}
/* Image column that always matches the height of the text column beside it.
   The image is taken out of flow so it contributes no height of its own: the
   text card alone sizes the grid row, and the stretched frame follows it. That
   means the image shrinks and grows with the text -- including as a
   "Read more" toggle expands or collapses -- with no leftover gap under the
   shorter column in any state. Cropping (cover) keeps it undistorted. */
.media-frame {
  position: relative;
  margin: 0;
  min-height: 0;
  border-radius: var(--radius-lg);
  overflow: hidden;
  box-shadow: var(--shadow-card);
}
.media-frame img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center top;
}
/* No trailing gap under the final paragraph inside the card. */
.text-media .card > p:last-child { margin-bottom: 0; }

/* Aftercare tips: text beside a photo, both columns the same height. */
.aftercare-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 28px;
  align-items: stretch;
}
.aftercare-grid .card > p:last-child { margin-bottom: 0; }
/* Was a .faq-question button; matches its 1.05rem so the question reads the
   same as before, just without the toggle. */
.aftercare-q {
  font-size: 1.05rem;
  margin: 22px 0 10px;
}
/* The image is taken out of flow so it contributes no height of its own: the
   text card alone sizes the grid row and the stretched figure follows it, which
   is what keeps the two columns exactly level. min-height: 0 defeats the grid
   item's automatic minimum size, which would otherwise floor the row at the
   image's intrinsic height. */
.aftercare-media {
  position: relative;
  margin: 0;
  min-height: 0;
  border-radius: var(--radius-lg);
  overflow: hidden;
  box-shadow: var(--shadow-card);
}
.aftercare-media img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  /* cover crops rather than distorting as the row height changes. */
  object-fit: cover;
  object-position: center;
}
/* Lighter than the site's 700 heading default, but still clearly a heading
   (Playfair 500 is loaded, so this is a real weight, not synthesised). */
.text-media .card h2 { font-weight: 500; }

.card--paper {
  background: var(--white);
  background-image:
    radial-gradient(rgba(122, 139, 111, 0.05) 1px, transparent 1px);
  background-size: 14px 14px;
}

/* Buttons
   ========================================================================== */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  /* ~46px tall on one line (11+11 padding + 20.5px line + 4px border). The old
     14px made a single-line button 52px and left two-line labels looking hollow. */
  padding: 11px 24px;
  border-radius: var(--radius-btn);
  font-weight: 600;
  font-size: 0.95rem;
  border: 2px solid transparent;
  cursor: pointer;
  transition: transform 0.15s ease, background 0.2s ease, color 0.2s ease, box-shadow 0.2s ease;
  text-decoration: none;
  text-align: center;
  max-width: 100%;
  line-height: 1.35;
}

.btn:hover { text-decoration: none; transform: translateY(-2px); }

.btn-primary {
  background: var(--sage);
  color: var(--white);
  box-shadow: var(--shadow-card);
}
.btn-primary:hover { background: var(--sage-dark); box-shadow: var(--shadow-lift); }

.btn-secondary {
  background: transparent;
  color: var(--sage-dark);
  border-color: var(--sage);
}
.btn-secondary:hover { background: var(--blush); }

.btn-block { width: 100%; }

/* Header
   ========================================================================== */

.site-header {
  position: sticky;
  top: 0;
  z-index: 100;
  background: rgba(26, 26, 26, 0.92);
  backdrop-filter: blur(10px);
  color: var(--cream);
}

.top-strip {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  padding: 3px 24px;
  max-width: var(--max-width);
  margin: 0 auto;
  font-size: 0.7rem;
  /* This element is centred at max-width, so a plain background would paint only
     the middle 1180px and leave the header's charcoal showing either side. The
     shadow spreads the fill to the viewport edges and the clip-path trims it back
     to the strip's own height -- neither affects layout or the scroll width. */
  background: var(--sage-dark);
  box-shadow: 0 0 0 100vmax var(--sage-dark);
  clip-path: inset(0 -100vmax);
}

/* Marquee. The track holds N identical copies (cloned in marquee.js) and slides
   left by exactly one copy width, so the animation's restart is invisible.
   Only transform is animated, which the compositor handles without repainting
   text every frame -- important on phones. */
.marquee {
  flex: 1;
  min-width: 0;
  overflow: hidden;
  /* Soft edges so the line fades in and out instead of being sliced off. */
  -webkit-mask-image: linear-gradient(to right, transparent 0, #000 20px, #000 calc(100% - 20px), transparent 100%);
  mask-image: linear-gradient(to right, transparent 0, #000 20px, #000 calc(100% - 20px), transparent 100%);
}
.marquee-track {
  display: flex;
  width: max-content;
}
.marquee-track > * {
  flex: 0 0 auto;
  white-space: nowrap;
  padding-right: 3rem;   /* the gap between repeats; part of the measured shift */
}
.marquee-track.is-running {
  animation: marquee-scroll var(--marquee-duration, 14s) linear infinite;
  will-change: transform;
}
@keyframes marquee-scroll {
  from { transform: translateX(0); }
  to   { transform: translateX(calc(var(--marquee-shift, 0px) * -1)); }
}
/* Nice-to-have: hold it still to read. focus-within covers keyboard users
   reaching the phone link. */
.marquee:hover .marquee-track,
.marquee:focus-within .marquee-track { animation-play-state: paused; }
@media (prefers-reduced-motion: reduce) {
  .marquee-track.is-running { animation: none; }
}

.top-strip .tagline {
  margin: 0;
  font-style: italic;
  /* Full opacity on the sage ground: at 0.85 the cream measured 4.2:1, just
     under the 4.5 this type size needs. */
  opacity: 1;
}
.top-strip .tagline a {
  color: var(--cream);
  font-weight: 600;
  font-style: normal;
}

.main-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 24px;
  max-width: var(--max-width);
  margin: 0 auto;
  padding: 13px 24px;
}

.site-logo {
  display: flex;
  align-items: center;
  color: var(--cream);
  flex-shrink: 0;
}
.site-logo:hover { text-decoration: none; }

/* Single combined lockup (emblem + wordmark). Sized by height so the 5.6:1
   artwork scales predictably; at 34px it lands at ~191px wide, near enough the
   same footprint as the old 34px mark plus the text span it replaced. The source
   is 128px tall, so this stays ~3.7x oversampled and sharp on retina. */
.logo-lockup {
  display: block;
  height: 34px;
  width: auto;
  flex-shrink: 0;
}

.site-nav {
  display: flex;
  gap: 20px;
  flex: 1;
  justify-content: center;
}

.site-nav a {
  color: var(--cream);
  font-weight: 500;
  font-size: 0.92rem;
  padding: 6px 2px;
  border-bottom: 2px solid transparent;
}
/* Uppercase the six nav items. Slightly smaller with a little tracking so
   the row stays the same overall width as it was in sentence case. */
.site-nav a:not(.nav-cta):not(.nav-phone) {
  text-transform: uppercase;
  font-size: 0.84rem;
  letter-spacing: 0.05em;
}
.site-nav a:hover,
.site-nav a[aria-current="page"] {
  color: var(--blush);
  border-bottom-color: var(--sage);
  text-decoration: none;
}

/* Trimmed below the base .btn (14px 28px) so it reads as part of the header row
   rather than the page's primary action. Desktop/tablet only -- hidden at 800px,
   where .site-nav .nav-cta takes over inside the menu. */
.header-cta { flex-shrink: 0; padding: 9px 20px; font-size: 0.85rem; white-space: nowrap; }

/* Mobile-menu-only items (revealed inside the slide-in nav) */
.nav-cta,
.nav-phone { display: none; }

.nav-toggle {
  display: none;
  flex-direction: column;
  gap: 5px;
  background: none;
  border: none;
  cursor: pointer;
  padding: 8px;
}
.nav-toggle span {
  width: 24px;
  height: 2px;
  background: var(--cream);
  border-radius: 2px;
}

/* Hero
   ========================================================================== */

/* Full-bleed hero photo. The image is weighted to the right (eucalyptus and
   candle) with open cream space on the left, so it's anchored right-of-centre
   and a cream scrim keeps the charcoal heading readable on top of it. */
.hero-bg {
  position: relative;
  display: flex;
  align-items: center;
  min-height: 460px;
  background-image: url('../images/hero/hero-background.jpg?v=46');
  background-size: cover;
  background-position: 70% center;
  background-repeat: no-repeat;
}
.hero-bg::before {
  content: '';
  position: absolute;
  inset: 0;
  background: linear-gradient(
    to right,
    rgba(247, 244, 238, 0.93) 0%,
    rgba(247, 244, 238, 0.88) 50%,
    rgba(247, 244, 238, 0.66) 100%
  );
  pointer-events: none;
}
.hero-bg > .hero {
  position: relative;
  z-index: 1;
  width: 100%;
}

.hero {
  padding-top: 56px;
  padding-bottom: 56px;
  text-align: center;
}

.hero h1 { max-width: 760px; margin-left: auto; margin-right: auto; }

/* Homepage hero lockup: brand name on line 1 (larger, italic serif), the
   service line beneath it (smaller). Sized with clamp() so it scales down
   cleanly on phones instead of wrapping mid-phrase. */
.hero-title {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 2px;
}
/* Matched to the nav/footer logo artwork: that wordmark is an upright, bold,
   high-contrast display serif -- Playfair Display 700, which is already loaded.
   Colour stays sage-dark: the logo reads cream only because it sits on the near
   black bar, and cream on this light hero would be invisible. */
.hero-brand {
  font-family: var(--font-heading);
  font-style: normal;
  font-weight: 700;
  font-size: clamp(2.1rem, 8vw, 4.4rem);
  line-height: 1.08;
  color: var(--sage-dark);
}
.hero-tagline {
  font-size: clamp(1.05rem, 3.4vw, 1.85rem);
  font-weight: 700;
  line-height: 1.25;
  color: var(--charcoal);
}
.hero .lede {
  max-width: 620px;
  margin: 0 auto 28px;
  font-size: 1.1rem;
  color: #4a4a4a;
}

.hero-actions {
  display: flex;
  gap: 16px;
  justify-content: center;
  flex-wrap: wrap;
}

/* Split media/text layouts
   ========================================================================== */

.split-media {
  display: grid;
  grid-template-columns: 1.2fr 1fr;
  gap: 32px;
  align-items: center;
}
/* Top-anchored media column. The figure keeps the image's natural proportions
   and sits flush with the top of the row, so expanding the "Read more" text
   just makes the text column taller -- the image never stretches, shifts or
   leaves a gap in either toggle state. */
/* Columns stretch to equal height; pair with a .media-frame image column. */
.split-media--match { align-items: stretch; }

/* Image column sits at the top at its own natural height, rather than being
   stretched to match the text beside it. */
.split-media--top { align-items: start; }

/* The Science diagram. Scaled down as a whole via max-height with width:auto,
   so the aspect ratio is preserved and every panel, label and icon stays
   visible -- it is never cropped to fit a container. */
.science-figure {
  margin: 0;
}
.science-figure img {
  width: auto;
  height: auto;
  max-width: 100%;
  max-height: 460px;
  /* Centred in its column, so the slack is shared either side instead of all
     sitting to the right. `text-align: center` on the figure did nothing here --
     the global `img { display: block }` makes this a block box, and text-align
     cannot move one, which is why it had been pinned hard left. */
  margin-left: auto;
  margin-right: auto;
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-card);
}

/* Studio product shot (Astanza Duality). object-fit: contain with a natural
   height means the whole machine stays visible -- the laser arm at the top and
   the wheels at the base are never cropped. Keeps the previous right alignment
   and rounded corners. */
/* Studio product shot: sized from its own proportions, not forced to match the
   old image's dimensions or the height of the text column. width:auto with a
   max-height scales the whole thing down proportionally, so the laser arm at
   the top and the wheels at the base always stay in frame. */
.product-figure {
  margin: 0;
  text-align: center;
}
.product-figure img {
  display: inline-block;
  width: auto;
  height: auto;
  max-width: 100%;
  max-height: 380px;
  object-fit: contain;
  border-radius: var(--radius-md);
}

/* Vertically stacked CTA pair. align-items:stretch makes both buttons share the
   same width whatever their label length, capped so the longer one doesn't run
   the full column width on desktop. */
.stacked-actions {
  display: flex;
  flex-direction: column;
  align-items: stretch;
  gap: 12px;
  margin-top: 22px;
  max-width: 420px;
}

/* Intro block: portrait beside the heading and opening lines. Replaces the old
   .portrait-row, where the photo sat alone in its own band of cream above the
   bio card and introduced Rochelle twice -- once visually, once in text. */
.about-intro {
  display: grid;
  grid-template-columns: minmax(0, 0.38fr) minmax(0, 0.62fr);
  gap: 32px;
  align-items: center;
  margin-bottom: 28px;
}
.about-portrait {
  margin: 0;
  border-radius: var(--radius-lg);
  overflow: hidden;
  box-shadow: var(--shadow-card);
}
.about-portrait img { width: 100%; }
.about-intro-copy > :last-child { margin-bottom: 0; }

/* Brand green rather than the default near-black, with a touch of tracking so
   the serif reads as a deliberate display line. No rule beneath it. */
.about-intro h1 {
  color: var(--sage-dark);
  letter-spacing: 0.022em;
}


/* Social CTA closing the bio rather than interrupting it before the reader
   knows who Rochelle is. The rule separates it from the last paragraph. */
.about-follow {
  margin-top: 32px;
  padding-top: 26px;
  border-top: 1px solid rgba(43, 43, 43, 0.1);
  text-align: center;
}
.about-follow .eyebrow { margin-bottom: 0.35em; }
.about-follow-note { margin: 0 0 16px; }
/* Both social links are buttons, sitting side by side. wrap lets them stack on
   narrow phones rather than squeezing. */
.about-follow-actions {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  align-items: stretch;
  gap: 12px;
}
/* Same filled treatment as .btn-primary, in the terracotta drawn from the
   promise boxes' tan. The two greens read as one colour at a glance; this gives
   the pair a real distinction while staying earthy. */
.btn-terracotta {
  background: var(--terracotta);
  color: var(--white);
  box-shadow: var(--shadow-card);
}
.btn-terracotta:hover {
  background: var(--terracotta-dark);
  color: var(--white);
  box-shadow: var(--shadow-lift);
}

/* About page: paragraph grouping + promise list
   ========================================================================== */


.promise-list {
  list-style: none;
  padding: 0;
  margin: 0 auto;
  max-width: 640px;
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 16px;
}
.promise-list li {
  background: var(--blush);
  border-radius: var(--radius-md);
  padding: 16px 20px;
}
/* Four boxes in an even 2x2, all the same size. The fifth promise sits below as
   a closing line rather than a lone full-width box. */
.promise-list { grid-auto-rows: 1fr; }
.promise-note {
  max-width: 640px;
  margin: 18px auto 0;
  text-align: center;
  font-size: 0.95rem;
  font-weight: 600;
  color: var(--sage-dark);
}

/* Feature image
   ========================================================================== */

.feature-photo {
  position: relative;
  border-radius: var(--radius-lg);
  overflow: hidden;
  box-shadow: var(--shadow-card);
  margin: 32px 0;
}
.feature-photo img { width: 100%; }

/* Cards grid
   ========================================================================== */

.cards-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 24px;
}

.quick-link-card {
  display: block;
  background: var(--white);
  border-radius: var(--radius-lg);
  padding: 32px 24px;
  text-align: center;
  box-shadow: var(--shadow-card);
  transition: transform 0.2s ease, box-shadow 0.2s ease;
  color: var(--charcoal);
}
.quick-link-card:hover {
  transform: translateY(-4px);
  box-shadow: var(--shadow-lift);
  text-decoration: none;
}
.quick-link-card h3 { color: var(--sage-dark); }

/* FAQ accordion
   ========================================================================== */

.faq-list { display: flex; flex-direction: column; gap: 12px; }

/* Two independent columns rather than one grid of items: each column is its own
   flex list, so opening an accordion only grows that column and can't leave a
   gap beside the item across from it. */
.faq-columns {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 12px 24px;
  align-items: start;
}

.faq-item {
  background: var(--white);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-card);
  overflow: hidden;
}

.faq-question {
  width: 100%;
  text-align: left;
  background: none;
  border: none;
  padding: 20px 24px;
  font-family: var(--font-heading);
  font-size: 1.05rem;
  font-weight: 700;
  cursor: pointer;
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 16px;
  color: var(--charcoal);
}

.faq-question .icon {
  flex-shrink: 0;
  width: 20px;
  height: 20px;
  position: relative;
}
.faq-question .icon::before,
.faq-question .icon::after {
  content: '';
  position: absolute;
  background: var(--sage-dark);
  border-radius: 2px;
  transition: transform 0.2s ease;
}
.faq-question .icon::before { width: 100%; height: 2px; top: 9px; left: 0; }
.faq-question .icon::after { width: 2px; height: 100%; top: 0; left: 9px; }
.faq-item.is-open .faq-question .icon::after { transform: rotate(90deg); opacity: 0; }

.faq-answer {
  display: none;
  padding: 0 24px 22px;
  color: #4a4a4a;
}
.faq-item.is-open .faq-answer {
  display: block;
}

/* Anchored sub-nav
   ========================================================================== */

.subnav {
  position: sticky;
  top: var(--header-h, 104px);
  z-index: 50;
  background: var(--cream);
  border-bottom: 1px solid rgba(43, 43, 43, 0.08);
  padding: 12px 24px;
  display: flex;
  gap: 24px;
  justify-content: center;
  flex-wrap: wrap;
  font-size: 0.88rem;
  font-weight: 600;
}
.subnav a { color: var(--sage-dark); }

/* Gallery
   ========================================================================== */

/* Results video
   ========================================================================== */

/* Text left, video right. `align-items: start` is deliberate: the video keeps
   its own natural height and stays at the top of its column. It must NOT be
   stretched to match the text -- doing that elsewhere previously blew the
   media up well past its natural proportions. */
/* One card, not two boxes. The video floats top-right so the copy wraps beside
   it and then runs the card's full width once it clears the video's bottom
   edge. flow-root contains the float so it cannot escape the card's padding. */
.results-intro {
  display: flow-root;
}
/* Block boxes do not wrap around a float -- only their line boxes shorten, so
   the callout's tan background would slide underneath the video. Making it its
   own formatting context keeps it clear of the float instead. */
.results-intro .callout {
  display: flow-root;
}
.results-intro > p:first-of-type { margin-top: 0; }
.results-intro > :last-child { margin-bottom: 0; }

.results-video {
  float: right;
  width: 47%;
  margin: 0 0 22px 28px;
  max-width: 100%;
  border-radius: var(--radius-lg);
  overflow: hidden;
  box-shadow: var(--shadow-card);
  background: var(--charcoal);
  scroll-margin-top: calc(var(--header-h, 104px) + 16px);
}
.results-video video {
  display: block;
  width: 100%;
  height: auto;        /* natural 16:9 aspect, never distorted */
  max-height: 420px;
  object-fit: contain;
}

/* Carousel (Results before/after slideshow)
   ========================================================================== */

.carousel-thumbs {
  display: flex;
  gap: 10px;
  overflow-x: auto;
  padding-bottom: 12px;
  margin-bottom: 16px;
  scrollbar-width: thin;
}

.carousel-thumb {
  flex: 0 0 90px;
  height: 66px;
  padding: 0;
  border: 2px solid transparent;
  border-radius: var(--radius-sm);
  overflow: hidden;
  cursor: pointer;
  background: none;
  opacity: 0.6;
  transition: opacity 0.2s ease, border-color 0.2s ease;
}
.carousel-thumb img { width: 100%; height: 100%; object-fit: cover; }
.carousel-thumb[aria-selected="true"] {
  border-color: var(--sage);
  opacity: 1;
}
.carousel-thumb:hover { opacity: 1; }

.carousel-viewer {
  position: relative;
  overflow: hidden;
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-card);
  background: var(--charcoal);
}

.carousel-track {
  display: flex;
  transition: transform 0.5s ease;
}

.carousel-slide {
  flex: 0 0 100%;
  margin: 0;
  height: 380px;
}
.carousel-slide img { width: 100%; height: 100%; object-fit: contain; background: var(--charcoal); }

.carousel-arrow {
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
  z-index: 2;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 44px;
  height: 44px;
  border-radius: 50%;
  border: none;
  background: rgba(26, 26, 26, 0.55);
  color: var(--white);
  font-size: 1.6rem;
  line-height: 1;
  cursor: pointer;
}
.carousel-arrow:hover { background: rgba(26, 26, 26, 0.8); }
.carousel-arrow--prev { left: 14px; }
.carousel-arrow--next { right: 14px; }
.carousel-arrow[disabled] { opacity: 0.28; cursor: default; }

/* Reviews slider (site-wide, above the footer)
   ========================================================================== */

/* Results only: the "Kind Words" card and the carousel under it read as one
   block, so they sit closer than two independent sections would. Scoped by id so
   the carousel on every other page keeps its normal section spacing. */
#reviews { padding-bottom: 16px; }
#reviews + .reviews-section { padding-top: 16px; }

.reviews-heading {
  font-size: clamp(1.15rem, 2vw, 1.5rem);
  text-align: center;
  text-transform: uppercase;
  letter-spacing: 0.09em;
  margin-bottom: 22px;
  /* Deep forest green instead of the h2 default near-black. Only the five pages
     that use this class are affected -- Results has its own "Reviews" heading
     and does not carry it. */
  color: var(--forest);
}

/* Star rating. Two stacked layers: a grey row underneath and a gold row on top
   clipped to a percentage width, which gives exact half (or any fraction)
   stars without needing separate half-star glyphs. */
.star-rating {
  position: relative;
  display: inline-block;
  margin: 0 0 8px;
  font-size: 0.95rem;
  line-height: 1;
  letter-spacing: 2px;
  white-space: nowrap;
}
.star-rating-base { color: #d9d5cc; }
.star-rating-fill {
  position: absolute;
  top: 0;
  left: 0;
  overflow: hidden;
  white-space: nowrap;
  color: var(--star-gold);
}

/* Arrows live in their own grid columns either side of the track, so they sit
   in the gutters and can never overlap a card or its text. */
.reviews-carousel {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr) auto;
  grid-template-areas: "prev track next";
  align-items: center;
  gap: 14px;
}
/* These arrows sit on the cream page rather than over a photo, so the gallery's
   dark translucent treatment reads as a flat grey dot here. Paper-white disc with
   a warm diagonal gradient and a two-layer shadow, filling solid sage on hover. */
.reviews-carousel .carousel-arrow {
  position: static;      /* override the overlay positioning used by the gallery */
  transform: none;
  flex-shrink: 0;
  width: 44px;
  height: 44px;
  background: linear-gradient(135deg, #ffffff 0%, #f3f1e9 100%);
  border: 1px solid rgba(0, 0, 0, 0.06);
  color: #7a8b6f;
  line-height: 1;
  padding: 0;
  box-shadow: 0 2px 6px rgba(0, 0, 0, 0.08), 0 6px 16px rgba(0, 0, 0, 0.06);
  transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);
}
/* Drawn chevron rather than the ‹ › text glyphs these used to carry: those are
   font-dependent, sit slightly off-centre, and render as a thin hairline at any
   size. Stroked with round caps and joins so the arrow keeps a defined shape. */
.reviews-carousel .carousel-arrow svg {
  width: 17px;
  height: 17px;
  display: block;
}
.reviews-carousel .carousel-arrow:hover:not([disabled]) {
  /* Shorthand, so it clears the gradient set above rather than layering on it. */
  background: #7a8b6f;
  border-color: #7a8b6f;
  color: #ffffff;
  transform: translateY(-3px);
  box-shadow: 0 4px 10px rgba(122, 139, 111, 0.3), 0 10px 22px rgba(122, 139, 111, 0.18);
}
.reviews-carousel .carousel-arrow:active:not([disabled]) {
  transform: translateY(0);
  box-shadow: 0 2px 6px rgba(122, 139, 111, 0.22);
}
.reviews-carousel .carousel-arrow:focus-visible {
  outline: 2px solid var(--sage-dark);
  outline-offset: 3px;
}
/* At the ends, stay fully visible but clearly inert -- the gallery's 0.28 opacity
   left barely anything on a light background. */
.reviews-carousel .carousel-arrow[disabled] {
  opacity: 1;
  background: var(--cream);
  border-color: rgba(122, 139, 111, 0.22);
  color: rgba(122, 139, 111, 0.55);
  box-shadow: none;
}
@media (prefers-reduced-motion: reduce) {
  .reviews-carousel .carousel-arrow,
  .reviews-carousel .carousel-arrow:hover:not([disabled]),
  .reviews-carousel .carousel-arrow:active:not([disabled]) {
    transition: background-color 0.2s ease, color 0.2s ease;
    transform: none;
  }
}
.reviews-carousel .carousel-arrow--prev { grid-area: prev; }
.reviews-carousel .carousel-arrow--next { grid-area: next; }

.reviews-track {
  grid-area: track;
  align-items: stretch;   /* every card matches the tallest in the row */
  display: flex;
  gap: 20px;
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  scroll-behavior: smooth;
  -webkit-overflow-scrolling: touch;
  scrollbar-width: none;          /* the arrows are the affordance */
  padding-bottom: 4px;
}
.reviews-track::-webkit-scrollbar { display: none; }
.reviews-track:focus-visible { outline: 2px solid var(--sage); outline-offset: 4px; }
.reviews-track > .testimonial-card {
  flex: 0 0 calc((100% - 40px) / 3);
  scroll-snap-align: start;
}
/* Nothing to scroll: drop the arrows rather than showing dead controls. */
.reviews-carousel.is-static .carousel-arrow { display: none; }
@media (prefers-reduced-motion: reduce) {
  .reviews-track { scroll-behavior: auto; }
}

.carousel-playpause {
  position: absolute;
  top: 14px;
  left: 14px;
  z-index: 2;
  border: none;
  border-radius: var(--radius-btn);
  padding: 8px 16px;
  font-size: 0.8rem;
  font-weight: 600;
  background: rgba(26, 26, 26, 0.55);
  color: var(--white);
  cursor: pointer;
}
.carousel-playpause:hover { background: rgba(26, 26, 26, 0.8); }

/* Testimonials
   ========================================================================== */

.testimonial-grid {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 20px;
  margin: 32px 0;
  align-items: stretch;   /* every card in a row matches the tallest */
}
.testimonial-grid .testimonial-card.is-hidden { display: none; }

.testimonial-card {
  background: var(--white);
  border-radius: var(--radius-md);
  padding: 24px;
  box-shadow: var(--shadow-card);
  /* Flex column so the card body fills the stretched height instead of
     leaving the background short of its neighbour. No `height: 100%` here:
     against an auto-height flex row that percentage is indeterminate and
     stops the card stretching, which left short reviews sitting shorter than
     their neighbours. */
  display: flex;
  flex-direction: column;
}
.testimonial-card p:last-child { margin-bottom: 0; }

/* Reviews in the carousel: every card the same height. The review text is
   clamped to a fixed number of lines so all cards match when collapsed, and
   the collapsible fills the remaining space so the "Read more" toggle always
   sits at the bottom edge rather than floating mid-card. */
/* A floor so a row of only-short reviews still has presence; stretch then keeps
   every card level with the tallest, including ones with no "Read more". */
.reviews-track .testimonial-card { min-height: 300px; }
.reviews-track .review-collapsible {
  display: flex;
  flex-direction: column;
  flex: 1;
}
.reviews-track .review-collapsible.is-collapsed .collapsible-text {
  max-height: 9.9em;   /* ~6 lines; overrides the 5em site default */
}
/* Pushes the toggle to the bottom edge of the card rather than leaving it
   floating directly under a short review. */
.reviews-track .collapsible-toggle { margin-top: auto; padding-top: 10px; }

/* Results: the gallery CTA sat ~104px above the reviews block, well beyond the
   spacing used between the other sections on this page. */
#before-after { padding-bottom: 24px; }
.testimonial-card .name {
  font-family: var(--font-heading);
  font-weight: 700;
  color: var(--sage-dark);
  margin-bottom: 8px;
}

/* Content has to fit the circle's inscribed square (~0.7 x diameter), not its
   full width, so keep the line-height tight and the star row narrow. */
.rating-badge {
  display: inline-flex;
  flex-direction: column;
  align-items: center;
  gap: 2px;
  border: 2px solid var(--sage);
  border-radius: 50%;
  width: 130px;
  height: 130px;
  flex-shrink: 0;
  justify-content: center;
  margin: 24px auto;
  padding: 8px;
  text-align: center;
  line-height: 1.25;
}
.rating-badge .stars { color: var(--star-gold); font-size: 0.82rem; letter-spacing: 1px; }
.rating-badge .score { font-family: var(--font-heading); font-size: 2rem; font-weight: 700; }
.rating-badge .rating-label { font-size: 0.7rem; }

/* Quote / callout
   ========================================================================== */

.callout {
  border-left: 4px solid var(--sage);
  background: var(--blush);
  border-radius: 0 var(--radius-md) var(--radius-md) 0;
  padding: 20px 24px;
  font-style: italic;
  margin: 24px 0;
}

/* Collapsible long-form text. The full text always stays in the DOM (so search
   engines and screen readers get it); only the visible height is clamped.
   max-height is used rather than -webkit-line-clamp so a group of several
   paragraphs collapses just as reliably as a single one. Clamping is applied by
   JS via .is-collapsed, so with JS off the text shows in full instead of being
   permanently clipped with no way to open it. */
.collapsible-text {
  margin: 0;
  overflow: hidden;
  /* Animating the height means the image column beside it (which stretches to
     match) grows and shrinks smoothly rather than snapping. */
  transition: max-height 0.35s ease;
}
.collapsible-text > p:last-child { margin-bottom: 0; }
.collapsible.is-collapsed .collapsible-text {
  max-height: 5em;   /* ~3 lines at the body line-height */
}
@media (prefers-reduced-motion: reduce) {
  .collapsible-text { transition: none; }
}

.collapsible-toggle {
  display: none;
  margin-top: 10px;
  padding: 0;
  background: none;
  border: 0;
  font-family: var(--font-body);
  font-size: 0.88rem;
  font-style: normal;
  font-weight: 600;
  color: var(--sage-dark);
  text-decoration: underline;
  cursor: pointer;
}
.collapsible.is-ready .collapsible-toggle { display: inline-block; }

/* Blocks that only clamp on narrow screens. The JS clears the classes itself,
   but stating it in CSS too means the wide layout never flashes clamped text
   before the script runs. Matches the (min-width: 901px) query in collapsible.js. */
@media (min-width: 901px) {
  .collapsible[data-collapse-mobile-only].is-collapsed .collapsible-text { max-height: none; }
  .collapsible[data-collapse-mobile-only] .collapsible-toggle { display: none; }
}

/* Keep a button that follows a collapsible off the "Read more" link. */
.collapsible + .btn { margin-top: 18px; }
.collapsible-toggle:hover { color: var(--charcoal); }
.collapsible-toggle:focus-visible { outline: 2px solid var(--sage); outline-offset: 2px; }

/* Steps
   ========================================================================== */

.steps-list {
  counter-reset: step;
  list-style: none;
  padding: 0;
  margin: 24px 0;
}
.steps-list li {
  counter-increment: step;
  position: relative;
  padding-left: 52px;
  margin-bottom: 20px;
}
.steps-list li::before {
  content: counter(step);
  position: absolute;
  left: 0;
  top: 0;
  width: 36px;
  height: 36px;
  border-radius: 50%;
  background: var(--sage);
  color: var(--white);
  display: flex;
  align-items: center;
  justify-content: center;
  font-family: var(--font-heading);
  font-weight: 700;
}

/* Downloads grid
   ========================================================================== */

.downloads-grid {
  display: grid;
  /* All four across one row. minmax(0, …) lets the columns shrink below the
     longest form name instead of overflowing the card. */
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 16px;
  margin: 32px 0;
}

.download-card {
  display: flex;
  align-items: center;
  /* Tighter than the 20px/16px used at two-across -- four columns leave each
     card ~271px, so the padding and icon give the label the room instead. */
  gap: 12px;
  background: var(--white);
  border-radius: var(--radius-md);
  padding: 16px 14px;
  box-shadow: var(--shadow-card);
}
.download-card .icon {
  flex-shrink: 0;
  width: 34px;
  height: 34px;
  color: var(--sage);
}
.download-card h4 { margin: 0 0 4px; font-family: var(--font-heading); font-size: 0.95rem; }
/* Inline glyph in front of the label, inheriting the link's colour. */
.download-file {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  /* 14px exactly -- the stated floor for these labels. */
  font-size: 0.875rem;
}
.download-file .dl-icon {
  flex-shrink: 0;
  width: 14px;
  height: 14px;
}

/* Tabs (Book Now)
   ========================================================================== */

.tabs {
  display: flex;
  gap: 8px;
  margin-bottom: 32px;
  border-bottom: 2px solid rgba(122, 139, 111, 0.2);
}
.tab-btn {
  background: none;
  border: none;
  padding: 14px 22px;
  font-family: var(--font-heading);
  font-size: 1.05rem;
  font-weight: 700;
  color: #8a8a8a;
  cursor: pointer;
  border-bottom: 3px solid transparent;
  margin-bottom: -2px;
}
.tab-btn[aria-selected="true"] {
  color: var(--sage-dark);
  border-bottom-color: var(--sage);
}
.tab-panel { display: none; }
.tab-panel.is-active { display: block; }

.map-embed {
  border-radius: var(--radius-md);
  overflow: hidden;
  box-shadow: var(--shadow-card);
  margin-top: 24px;
}
.map-embed iframe { width: 100%; height: 360px; border: 0; display: block; }

/* No min-height: Square injects either a 500px-min iframe (which sizes itself)
   or, on narrow screens, just a small button - and a min-height here left a
   tall empty white box under that button. */
.scheduler-embed {
  max-width: 100%;
  overflow-x: auto;
  background: var(--white);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-card);
  padding: 24px;
}

/* Forms
   ========================================================================== */

.form-note { font-size: 0.85rem; color: #6a6a6a; margin-bottom: 20px; }
.required-flag { color: #b5544b; }

.form-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 20px;
}
.form-grid .full-width { grid-column: 1 / -1; }

.field { display: flex; flex-direction: column; gap: 6px; margin-bottom: 20px; }
.field label { font-weight: 600; font-size: 0.9rem; }
.field .hint { font-size: 0.78rem; color: #8a8a8a; }

input[type="text"],
input[type="email"],
input[type="tel"],
input[type="file"],
select,
textarea {
  font-family: var(--font-body);
  font-size: 0.95rem;
  padding: 12px 14px;
  border: 1px solid rgba(43, 43, 43, 0.18);
  border-radius: var(--radius-sm);
  background: var(--white);
  color: var(--charcoal);
  width: 100%;
  max-width: 100%;
}
textarea { resize: vertical; min-height: 120px; }
input:focus, select:focus, textarea:focus {
  outline: 2px solid var(--sage);
  outline-offset: 1px;
}

.form-status {
  margin-top: 16px;
  padding: 14px 18px;
  border-radius: var(--radius-sm);
  font-size: 0.9rem;
  display: none;
}
.form-status.is-success { display: block; background: #e4ede0; color: var(--sage-dark); }
.form-status.is-error { display: block; background: #f6e2df; color: #a3392f; }

/* Footer
   ========================================================================== */

.site-footer {
  background: var(--deep-charcoal);
  color: var(--cream);
  /* 56px top was set when a text heading led the footer. The lockup leads it now,
     and the extra height plus a left-aligned logo made the top read as a separate
     band. Tightened so the centred lockup sits with the content, not above it. */
  /* Bottom padding also keeps the copyright clear of the fixed "Text us" button,
     which sits 20px off the bottom-right and stands ~52px tall. */
  padding: 28px 0 32px;
}

.footer-inner {
  max-width: var(--max-width);
  margin: 0 auto;
  padding: 0 24px;
  display: grid;
  /* Three columns: logo + blurb | Quick Links | business info with "Follow
     along" stacked beneath it. minmax(0, …) stops any column being forced wider
     than its share by content that will not wrap. */
  grid-template-columns:
    minmax(0, 1.3fr) minmax(0, 0.8fr) minmax(0, 1.15fr);
  gap: 32px;
  align-items: start;
}

.footer-logo:hover { text-decoration: none; }
/* Sized by width, not height, so it scales down with its column instead of
   overflowing on narrower desktops. 202px is the 36px-tall rendering. */
.footer-logo img { display: block; width: 100%; max-width: 202px; height: auto; }

/* Business info with "Follow along" stacked under it, sharing one column at
   every width now -- so this is a real box, not `display: contents`. The gap
   matches the 24px the footer already uses between stacked blocks. */
.footer-contact {
  display: flex;
  flex-direction: column;
  gap: 24px;
}

/* Column 1: the lockup with the blurb stacked directly beneath it. It spans the
   full width only on mobile -- see the responsive layer. */
.footer-about {
  display: flex;
  flex-direction: column;
  gap: 14px;
}
.footer-blurb {
  /* align-items: flex-start on the parent shrink-wraps its children, so without
     this the paragraph box stops at its text rather than spanning the row. */
  align-self: stretch;
  margin: 0;
  font-size: 0.88rem;
  line-height: 1.6;
  opacity: 0.8;
}

/* Warm gold: brighter and more distinct against the cream body text than either
   the old blush (which read washed-out) or a sage tint (too close to the icon
   discs). Measures 8.4:1 on the footer's near-black. */
.footer-heading {
  font-family: var(--font-heading);
  font-weight: 700;
  /* Pinned rather than inherited: the size used to come from whichever column
     the heading sat in (0.9rem under .footer-social, 0.9rem via .footer-brand p,
     but 1rem under the new Quick Links wrapper), so the three did not match. */
  font-size: 0.9rem;
  margin-bottom: 12px;
  color: var(--gold);
}

.footer-brand p:not(.footer-heading) { margin: 0 0 6px; opacity: 0.85; font-size: 0.9rem; }
/* The email is 28 characters in a quarter-width column; `anywhere` lets the
   column shrink below its length instead of overflowing. */
.footer-brand a { overflow-wrap: anywhere; }
.footer-brand a, .footer-nav a, .footer-social a { color: var(--cream); opacity: 0.85; }

.footer-nav { display: flex; flex-direction: column; gap: 4px; font-size: 0.9rem; }
.footer-social { display: flex; flex-direction: column; gap: 8px; font-size: 0.9rem; }

/* Social + email as icon buttons, matching the disc treatment the top bar used:
   a tinted circle with a cream glyph. 38px keeps them comfortably tappable. */
.footer-icons {
  display: flex;
  gap: 10px;
}
.footer-icons a {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 38px;
  height: 38px;
  border-radius: 50%;
  background: var(--sage);
  color: var(--cream);
  opacity: 1;   /* overrides the 0.85 shared by the footer's text links */
  transition: background 0.18s ease;
}
.footer-icons a:hover { background: var(--sage-dark); text-decoration: none; }
.footer-icons a:focus-visible { outline: 2px solid var(--sage); outline-offset: 2px; }
.footer-icons svg { width: 17px; height: 17px; fill: currentColor; }

.footer-copy {
  text-align: center;
  margin: 40px 0 0;
  font-size: 0.78rem;
  opacity: 0.55;
}

/* SMS widget
   ========================================================================== */

.sms-widget {
  position: fixed;
  right: 20px;
  bottom: 20px;
  z-index: 200;
  display: inline-flex;
  align-items: center;
  gap: 10px;
  /* Deeper than the page's sage CTAs: it sits over photos and cream alike, and
     white on --sage-dark measures 5.1:1 against 3.7:1 on plain sage. */
  background: var(--sage-dark);
  color: var(--white);
  padding: 13px 22px;
  /* Hairline in the cream family so the edge stays defined over a pale photo. */
  border: 1px solid rgba(247, 244, 238, 0.22);
  /* Same token as every .btn on the site -- keep them in step. */
  border-radius: var(--radius-btn);
  font-weight: 600;
  font-size: 0.9rem;
  letter-spacing: 0.012em;
  box-shadow: var(--shadow-card);
  transition: background 0.2s ease, transform 0.2s ease, box-shadow 0.2s ease;
}
/* Slow ripple so the button reads as live without nagging. Transform + opacity
   only, so it runs on the compositor and never triggers layout. */
.sms-widget::after {
  content: "";
  position: absolute;
  inset: -1px;
  border-radius: inherit;
  border: 2px solid var(--sage);
  pointer-events: none;
  opacity: 0;
  animation: sms-ripple 3.4s ease-out infinite;
}
@keyframes sms-ripple {
  0%   { transform: scale(1);   opacity: 0.5; }
  55%  { transform: scale(1.3); opacity: 0; }
  100% { transform: scale(1.3); opacity: 0; }
}
.sms-widget:hover {
  background: var(--forest);
  transform: translateY(-2px);
  box-shadow: var(--shadow-lift);
  text-decoration: none;
}
.sms-widget:focus-visible {
  outline: 2px solid var(--sage);
  outline-offset: 3px;
}
/* Line icon: stroke and the dot fills come from the markup, so only size here. */
.sms-widget svg { width: 22px; height: 22px; flex-shrink: 0; }
@media (prefers-reduced-motion: reduce) {
  .sms-widget { transition: background 0.2s ease; }
  .sms-widget:hover { transform: none; }
  .sms-widget::after { animation: none; }
}

/* Scroll reveal
   ========================================================================== */

[data-reveal] {
  opacity: 0;
  transform: translateY(16px);
  transition: opacity 0.6s ease, transform 0.6s ease;
}
[data-reveal].is-visible {
  opacity: 1;
  transform: translateY(0);
}
@media (prefers-reduced-motion: reduce) {
  [data-reveal] { opacity: 1; transform: none; transition: none; }
}

/* Utility
   ========================================================================== */

.text-center { text-align: center; }
.nowrap { white-space: nowrap; }
.mt-0 { margin-top: 0; }
.visually-hidden {
  position: absolute;
  width: 1px; height: 1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
}

.skip-link {
  position: absolute;
  left: -999px;
  top: 0;
  background: var(--sage);
  color: var(--white);
  padding: 12px 20px;
  z-index: 1000;
  border-radius: 0 0 var(--radius-sm) 0;
}
.skip-link:focus { left: 0; }
