/* ==========================================================================
   Iyesha Leanne SPMU & Beauty
   Core stylesheet - tokens, base, components
   Do not redefine custom properties outside the :root block below.
   ========================================================================== */

/* --------------------------------------------------------------------------
   1. Fonts
   -------------------------------------------------------------------------- */

@font-face {
  font-family: "Bodoni Moda";
  src: url("/assets/fonts/bodoni-moda-400.woff2") format("woff2");
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}

@font-face {
  font-family: "Bodoni Moda";
  src: url("/assets/fonts/bodoni-moda-400-italic.woff2") format("woff2");
  font-weight: 400;
  font-style: italic;
  font-display: swap;
}

@font-face {
  font-family: "Jost";
  src: url("/assets/fonts/jost-300.woff2") format("woff2");
  font-weight: 300;
  font-style: normal;
  font-display: swap;
}

@font-face {
  font-family: "Jost";
  src: url("/assets/fonts/jost-400.woff2") format("woff2");
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}

@font-face {
  font-family: "Jost";
  src: url("/assets/fonts/jost-500.woff2") format("woff2");
  font-weight: 500;
  font-style: normal;
  font-display: swap;
}

/* --------------------------------------------------------------------------
   2. Tokens
   -------------------------------------------------------------------------- */

:root {
  /* Colour. Ratios noted are against the surface each colour is used on. */
  --c-bone: #f3f1ec;          /* page ground */
  --c-shell: #eae4dc;         /* alternate section */
  --c-blush: #f0e6e2;         /* soft tint section */
  --c-espresso: #26211e;      /* footer, dark panels */

  --c-ink: #1a1816;           /* 15.68:1 on bone */
  --c-muted: #55504b;         /* 7.06:1 on bone, 6.31:1 on shell */
  --c-rose: #7e5049;          /* 5.94:1 on bone, 5.31:1 on shell */
  --c-rose-deep: #6f4640;     /* 7.08:1 on bone - hover state */
  --c-rose-light: #c99a90;    /* 6.45:1 on espresso - footer accent only */

  --c-border: #7f766b;        /* 3.95:1 non-text - form controls */
  --c-hairline: #ddd6cc;      /* decorative rules only, never a control edge */
  --c-error: #8e2a2a;         /* 7.40:1 on bone */
  --c-success: #2f6b4f;       /* 5.58:1 on bone */

  --c-on-dark: #f3f1ec;       /* 14.11:1 on espresso */
  --c-on-dark-muted: #bdb2a6; /* 7.65:1 on espresso */

  /* Hero wash. Measured against the shipped crops: ink clears 6.08:1 minimum
     at every breakpoint. Rose and muted both FAIL over the hero - ink only. */
  --wash-h: linear-gradient(
    to right,
    rgba(243, 241, 236, 0.97) 0%,
    rgba(243, 241, 236, 0.95) 32%,
    rgba(243, 241, 236, 0.82) 50%,
    rgba(243, 241, 236, 0.34) 68%,
    rgba(243, 241, 236, 0) 86%
  );
  /* Phones and tablets get an even veil, not a gradient. Any ramp leaves one
     end of the section bare and the other flat bone, which reads as dead
     space. A flat 0.60 shows the picture at 40 per cent across the full
     height and measures 5.60:1 on ink on the phone crop, 5.59:1 on the
     tablet crop. Desktop keeps the horizontal wash, where the copy sits
     beside the picture rather than over it. */
  --wash-veil: linear-gradient(
    rgba(243, 241, 236, 0.6),
    rgba(243, 241, 236, 0.6)
  );

  /* Typography */
  --ff-display: "Bodoni Moda", Georgia, "Times New Roman", serif;
  --ff-body: "Jost", -apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial, sans-serif;

  --fs-xs: clamp(0.75rem, 0.735rem + 0.08vw, 0.8125rem);
  --fs-sm: clamp(0.875rem, 0.86rem + 0.08vw, 0.9375rem);
  --fs-base: clamp(1rem, 0.97rem + 0.15vw, 1.0625rem);
  --fs-md: clamp(1.0625rem, 1.01rem + 0.28vw, 1.1875rem);
  --fs-lg: clamp(1.1875rem, 1.09rem + 0.45vw, 1.4375rem);
  --fs-xl: clamp(1.4375rem, 1.25rem + 0.9vw, 2rem);
  --fs-2xl: clamp(1.75rem, 1.43rem + 1.6vw, 2.75rem);
  --fs-3xl: clamp(2.125rem, 1.6rem + 2.6vw, 3.5rem);
  --fs-4xl: clamp(2.5rem, 1.75rem + 3.75vw, 4.375rem);

  --lh-tight: 1.12;
  --lh-snug: 1.3;
  --lh-body: 1.75;

  --ls-caps: 0.16em;
  --ls-caps-wide: 0.28em;
  --ls-display: -0.005em;

  /* Spacing */
  --sp-1: 0.25rem;
  --sp-2: 0.5rem;
  --sp-3: 0.75rem;
  --sp-4: 1rem;
  --sp-5: 1.5rem;
  --sp-6: 2rem;
  --sp-7: 2.5rem;
  --sp-8: 3rem;
  --sp-9: 4rem;
  --sp-10: 5rem;
  --sp-11: 6.5rem;
  --sp-12: 8rem;

  --sp-section: clamp(3.5rem, 2rem + 7.5vw, 7.5rem);
  --gutter: clamp(1.25rem, 0.9rem + 1.75vw, 2.5rem);

  /* Layout
     --w-wide is fluid above about 1476px. A fixed 1240 grows its margin
     linearly once the viewport passes it: 140px at 1440, but 380px at 1920,
     which strands the content in the middle of a large monitor. The clamp
     minimum keeps 1440 and below exactly as they were. */
  --w-wide: clamp(1240px, 84vw, 2000px);
  --w-default: 1100px;
  --w-prose: 68ch;
  --w-narrow: 720px;

  /* Effects */
  --radius-sm: 2px;
  --radius: 3px;
  --radius-pill: 999px;
  --shadow-sm: 0 1px 2px rgba(26, 24, 22, 0.06), 0 2px 8px rgba(26, 24, 22, 0.04);
  --shadow-md: 0 2px 4px rgba(26, 24, 22, 0.06), 0 12px 32px rgba(26, 24, 22, 0.08);
  --ease: cubic-bezier(0.4, 0, 0.2, 1);
  --ease-out: cubic-bezier(0.16, 1, 0.3, 1);
  --dur: 220ms;
  --dur-slow: 600ms;

  --header-h: 64px;
  --callbar-h: 62px;
}

@media (min-width: 64em) {
  :root {
    --header-h: 76px;
  }
}

/* --------------------------------------------------------------------------
   3. Reset and base
   -------------------------------------------------------------------------- */

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

* {
  margin: 0;
}

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
  scroll-padding-top: calc(var(--header-h) + var(--sp-4));
}

body {
  background-color: var(--c-bone);
  color: var(--c-ink);
  font-family: var(--ff-body);
  font-size: var(--fs-base);
  font-weight: 400;
  line-height: var(--lh-body);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-rendering: optimizeLegibility;
  overflow-x: hidden;
}

img,
picture,
video,
svg {
  display: block;
  max-width: 100%;
  height: auto;
}

input,
button,
textarea,
select {
  font: inherit;
  color: inherit;
}

h1,
h2,
h3,
h4 {
  font-family: var(--ff-display);
  font-weight: 400;
  line-height: var(--lh-tight);
  letter-spacing: var(--ls-display);
  text-wrap: balance;
}

h1 {
  font-size: var(--fs-3xl);
}

h2 {
  font-size: var(--fs-2xl);
}

h3 {
  font-size: var(--fs-xl);
  line-height: var(--lh-snug);
}

h4 {
  font-size: var(--fs-lg);
  line-height: var(--lh-snug);
}

p {
  text-wrap: pretty;
}

p + p {
  margin-top: var(--sp-4);
}

/* A heading needs air beneath it, not just above. Written with :where() so
   it carries zero specificity and any component that sets its own spacing
   still wins. */
:where(h1, h2, h3, h4) + p,
:where(h1, h2, h3, h4) + ul,
:where(h1, h2, h3, h4) + ol,
:where(h1, h2, h3, h4) + .lead {
  margin-top: var(--sp-5);
}

a {
  color: var(--c-rose);
  text-decoration: underline;
  text-underline-offset: 0.18em;
  text-decoration-thickness: 1px;
  transition: color var(--dur) var(--ease);
}

a:hover {
  color: var(--c-rose-deep);
  text-decoration-thickness: 2px;
}

ul,
ol {
  padding-left: 1.25em;
}

li + li {
  margin-top: var(--sp-2);
}

strong {
  font-weight: 500;
}

hr {
  border: 0;
  border-top: 1px solid var(--c-hairline);
  margin: var(--sp-8) 0;
}

::selection {
  background-color: var(--c-rose);
  color: var(--c-bone);
}

/* --------------------------------------------------------------------------
   4. Focus
   Never remove an outline without replacing it.
   -------------------------------------------------------------------------- */

:focus-visible {
  outline: 3px solid var(--c-rose);
  outline-offset: 3px;
  border-radius: var(--radius-sm);
}

.site-footer :focus-visible,
.panel-dark :focus-visible {
  outline-color: var(--c-rose-light);
}

/* --------------------------------------------------------------------------
   5. Skip link
   -------------------------------------------------------------------------- */

.skip-link {
  position: fixed;
  top: var(--sp-2);
  left: var(--sp-2);
  z-index: 300;
  padding: var(--sp-3) var(--sp-5);
  background-color: var(--c-ink);
  color: var(--c-bone);
  font-size: var(--fs-sm);
  font-weight: 500;
  letter-spacing: var(--ls-caps);
  text-transform: uppercase;
  text-decoration: none;
  border-radius: var(--radius);
  transform: translateY(-200%);
  transition: transform var(--dur) var(--ease);
}

.skip-link:focus-visible {
  transform: translateY(0);
  color: var(--c-bone);
}

/* --------------------------------------------------------------------------
   6. Layout
   -------------------------------------------------------------------------- */

.container {
  width: 100%;
  max-width: var(--w-default);
  margin-inline: auto;
  padding-inline: var(--gutter);
}

.container--wide {
  max-width: var(--w-wide);
}

/* Full-bleed inset used by the header and the hero. A fixed max-width
   container grows its margin linearly above about 1500px, which leaves the
   content stranded in the middle of a large monitor. This tracks the
   viewport instead: 101px at 1440, 134px at 1920, capped at 160px. */
.container--fluid {
  max-width: none;
}

@media (min-width: 64em) {
  .container--fluid {
    padding-inline: clamp(2.5rem, 7vw, 10rem);
  }
}

.container--narrow {
  max-width: var(--w-narrow);
}

.section {
  padding-block: var(--sp-section);
}

.section--tight {
  padding-block: clamp(2.5rem, 1.5rem + 5vw, 5rem);
}

.section--shell {
  background-color: var(--c-shell);
}

.section--blush {
  background-color: var(--c-blush);
}

.panel-dark {
  background-color: var(--c-espresso);
  color: var(--c-on-dark);
}

.panel-dark h1,
.panel-dark h2,
.panel-dark h3 {
  color: var(--c-on-dark);
}

.panel-dark p {
  color: var(--c-on-dark-muted);
}

/* :not(.btn) is load bearing. A bare ".panel-dark a" scores (0,1,1) and
   beats .btn--light at (0,1,0), which paints a button's label the same
   colour as its own background. Excluding buttons lets them keep their own
   colours instead. Same applies to .panel-rose and .site-footer below. */
.panel-dark a:not(.btn) {
  color: var(--c-rose-light);
}

/* The closing CTA sat on espresso, the same colour as the footer directly
   beneath it, so the two read as one block. Rose is the accent and has not
   been used as a ground anywhere else. Bone on rose measures 5.94:1, and
   body copy is held at 88% opacity, which still clears at 5.04:1. */
.panel-rose {
  background-color: var(--c-rose);
  color: var(--c-bone);
}

.panel-rose h2,
.panel-rose h3 {
  color: var(--c-bone);
}

.panel-rose p {
  color: rgba(243, 241, 236, 0.88);
}

.panel-rose .eyebrow {
  color: rgba(243, 241, 236, 0.88);
}

.panel-rose a:not(.btn) {
  color: var(--c-bone);
}

.panel-rose .btn--outline {
  border-color: var(--c-bone);
  color: var(--c-bone);
}

.panel-rose :focus-visible {
  outline-color: var(--c-bone);
}

.prose {
  max-width: var(--w-prose);
}

.prose h2,
.prose h3 {
  margin-top: var(--sp-7);
  margin-bottom: var(--sp-4);
}

.prose h2:first-child,
.prose h3:first-child {
  margin-top: 0;
}

.prose ul,
.prose ol {
  margin-top: var(--sp-4);
}

.stack > * + * {
  margin-top: var(--sp-4);
}

.split {
  display: grid;
  gap: clamp(2rem, 1rem + 5vw, 5rem);
  align-items: center;
}

@media (min-width: 64em) {
  .split {
    grid-template-columns: 1fr 1fr;
  }

  .split--reverse > :first-child {
    order: 2;
  }
}

.grid {
  display: grid;
  gap: var(--sp-5);
}

@media (min-width: 40em) {
  .grid--2,
  .grid--3 {
    grid-template-columns: repeat(2, 1fr);
  }
}

@media (min-width: 40em) {
  .grid--4 {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}

@media (min-width: 64em) {
  .grid--3 {
    grid-template-columns: repeat(3, 1fr);
  }

  .grid--4 {
    grid-template-columns: repeat(4, minmax(0, 1fr));
  }
}

/* --------------------------------------------------------------------------
   7. Type helpers
   -------------------------------------------------------------------------- */

/* 12px, not 16. The eyebrow is a label attached to the heading below it, so
   it should sit closer to the heading than the heading sits to the body. */
.eyebrow {
  display: block;
  margin-bottom: var(--sp-3);
  color: var(--c-rose);
  font-family: var(--ff-body);
  font-size: var(--fs-xs);
  font-weight: 500;
  letter-spacing: var(--ls-caps-wide);
  line-height: 1.4;
  text-transform: uppercase;
}

.panel-dark .eyebrow {
  color: var(--c-rose-light);
}

.lead {
  color: var(--c-muted);
  font-size: var(--fs-md);
  font-weight: 300;
  line-height: 1.65;
}

.script {
  font-family: var(--ff-display);
  font-style: italic;
  font-weight: 400;
}

.muted {
  color: var(--c-muted);
}

.section-head {
  margin-bottom: clamp(2rem, 1.25rem + 3vw, 3.5rem);
}

.section-head--centred {
  max-width: 46rem;
  margin-inline: auto;
  text-align: center;
}

.section-head p {
  max-width: 52ch;
  margin-top: var(--sp-5);
}

.section-head--centred p {
  margin-inline: auto;
}

.rule {
  width: 3.5rem;
  height: 1px;
  margin-block: var(--sp-5);
  background-color: var(--c-rose);
  border: 0;
}

.section-head--centred .rule {
  margin-inline: auto;
}

.visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

/* --------------------------------------------------------------------------
   8. Buttons
   -------------------------------------------------------------------------- */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--sp-2);
  min-height: 48px;
  padding: var(--sp-3) var(--sp-6);
  border: 1px solid transparent;
  border-radius: var(--radius);
  background-color: var(--c-ink);
  color: var(--c-bone);
  font-family: var(--ff-body);
  font-size: var(--fs-sm);
  font-weight: 500;
  letter-spacing: var(--ls-caps);
  line-height: 1.2;
  text-align: center;
  text-decoration: none;
  text-transform: uppercase;
  cursor: pointer;
  transition: background-color var(--dur) var(--ease),
    color var(--dur) var(--ease), border-color var(--dur) var(--ease),
    transform var(--dur) var(--ease);
}

.btn:active {
  transform: translateY(0);
}

.btn--primary {
  background-color: var(--c-rose);
}

.btn--outline {
  background-color: transparent;
  border-color: var(--c-ink);
  color: var(--c-ink);
}

.panel-dark .btn--outline {
  border-color: var(--c-on-dark);
  color: var(--c-on-dark);
}

.btn--light {
  background-color: var(--c-bone);
  color: var(--c-ink);
}

/* Hover only where there is a real pointer. iOS leaves the hover state stuck
   after a tap, which was filling the outline button solid black on touch. */
@media (hover: hover) and (pointer: fine) {
  .btn:hover {
    background-color: var(--c-rose);
    color: var(--c-bone);
    transform: translateY(-1px);
  }

  .btn--primary:hover {
    background-color: var(--c-rose-deep);
  }

  .btn--outline:hover {
    background-color: var(--c-ink);
    color: var(--c-bone);
  }

  .panel-dark .btn--outline:hover {
    background-color: var(--c-on-dark);
    color: var(--c-espresso);
  }

  .btn--light:hover {
    background-color: var(--c-rose-light);
    color: var(--c-espresso);
  }
}

.btn--sm {
  min-height: 42px;
  padding: var(--sp-2) var(--sp-5);
  font-size: var(--fs-xs);
}

.btn--full {
  width: 100%;
}

.btn-row {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--sp-4) var(--sp-6);
  margin-top: var(--sp-6);
}

.section-head--centred .btn-row {
  justify-content: center;
}

.link-arrow {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-2);
  font-size: var(--fs-sm);
  font-weight: 500;
  letter-spacing: var(--ls-caps);
  text-transform: uppercase;
  text-decoration: none;
}

.link-arrow::after {
  content: "";
  width: 1.5rem;
  height: 1px;
  background-color: currentcolor;
  transition: width var(--dur) var(--ease);
}

.link-arrow:hover::after {
  width: 2.25rem;
}

/* --------------------------------------------------------------------------
   9. Trust strip
   -------------------------------------------------------------------------- */

.trust {
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-3) var(--sp-6);
  margin-top: var(--sp-6);
  padding: 0;
  list-style: none;
  color: var(--c-muted);
  font-size: var(--fs-xs);
  letter-spacing: var(--ls-caps);
  text-transform: uppercase;
}

.trust li {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  margin-top: 0;
}

.trust li::before {
  content: "";
  flex: none;
  width: 5px;
  height: 5px;
  background-color: var(--c-rose);
  border-radius: 50%;
}

.panel-dark .trust {
  color: var(--c-on-dark-muted);
}

.panel-dark .trust li::before {
  background-color: var(--c-rose-light);
}

/* Fixed 2x2 shape rather than a flex wrap, so it cannot land on an odd
   2-then-1 break as the container width changes. Columns are content sized,
   not 1fr: equal fractions would push column two out to the halfway point
   and leave a dead gap after the shorter labels. auto lets the text wrap
   rather than overflow if the block is ever too narrow. */
.trust--grid {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: var(--sp-3) var(--sp-6);
  justify-content: start;
}

@media (min-width: 48em) {
  .trust--grid {
    grid-template-columns: repeat(2, auto);
    justify-items: start;
  }
}

/* --------------------------------------------------------------------------
   10. Header
   Hides on scroll down past 120px, returns immediately on scroll up.
   -------------------------------------------------------------------------- */

.site-header {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  z-index: 100;
  background-color: var(--c-bone);
  border-bottom: 1px solid transparent;
  transform: translateY(0);
  transition: transform 320ms var(--ease),
    border-color var(--dur) var(--ease),
    box-shadow var(--dur) var(--ease);
}

/* Hairline and shadow only appear once the page has moved, so the header
   reads as one continuous field with the hero at rest. */
.site-header.is-stuck {
  border-bottom-color: var(--c-hairline);
  box-shadow: var(--shadow-sm);
}

.site-header.is-hidden {
  transform: translateY(-100%);
}

.site-header__inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-4);
  min-height: var(--header-h);
}

.site-header__logo {
  flex: none;
  line-height: 0;
  text-decoration: none;
}

.site-header__logo img {
  width: auto;
  height: 34px;
}

@media (min-width: 26em) {
  .site-header__logo img {
    height: 40px;
  }
}

/* Offset the page content by the fixed header */
.page {
  padding-top: var(--header-h);
}

/* --------------------------------------------------------------------------
   11. Navigation
   Below 64em the nav is a full-viewport overlay, not a dropdown strip.
   -------------------------------------------------------------------------- */

.nav-toggle {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex: none;
  width: 48px;
  height: 48px;
  padding: 0;
  background: none;
  border: 1px solid var(--c-border);
  border-radius: var(--radius);
  cursor: pointer;
  transition: background-color var(--dur) var(--ease),
    border-color var(--dur) var(--ease);
}

.nav-toggle:hover {
  background-color: var(--c-shell);
  border-color: var(--c-ink);
}

.nav-toggle__bars {
  position: relative;
  display: block;
  width: 20px;
  height: 1.5px;
  background-color: var(--c-ink);
  transition: background-color var(--dur) var(--ease);
}

.nav-toggle__bars::before,
.nav-toggle__bars::after {
  content: "";
  position: absolute;
  left: 0;
  width: 20px;
  height: 1.5px;
  background-color: var(--c-ink);
  transition: transform var(--dur) var(--ease), top var(--dur) var(--ease);
}

.nav-toggle__bars::before {
  top: -6px;
}

.nav-toggle__bars::after {
  top: 6px;
}

.nav-toggle[aria-expanded="true"] .nav-toggle__bars {
  background-color: transparent;
}

.nav-toggle[aria-expanded="true"] .nav-toggle__bars::before {
  top: 0;
  transform: rotate(45deg);
}

.nav-toggle[aria-expanded="true"] .nav-toggle__bars::after {
  top: 0;
  transform: rotate(-45deg);
}

.site-nav {
  position: fixed;
  top: var(--header-h);
  left: 0;
  right: 0;
  z-index: 99;
  display: flex;
  flex-direction: column;
  height: calc(100vh - var(--header-h));
  height: calc(100dvh - var(--header-h));
  padding: clamp(1.5rem, 1rem + 3vw, 3.5rem) var(--gutter) var(--sp-8);
  background-color: var(--c-bone);
  overflow-y: auto;
  opacity: 0;
  visibility: hidden;
  transform: translateY(-10px);
  transition: opacity 260ms var(--ease), transform 260ms var(--ease),
    visibility 260ms var(--ease);
}

.site-nav.is-open {
  opacity: 1;
  visibility: visible;
  transform: translateY(0);
}

.site-nav__list {
  padding: 0;
  margin: 0;
  list-style: none;
}

.site-nav__list > li {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  margin-top: 0;
  border-bottom: 1px solid var(--c-hairline);
  opacity: 0;
  transform: translateY(14px);
  transition: opacity 420ms var(--ease), transform 420ms var(--ease);
}

.site-nav.is-open .site-nav__list > li {
  opacity: 1;
  transform: translateY(0);
}

.site-nav.is-open .site-nav__list > li:nth-child(1) { transition-delay: 70ms; }
.site-nav.is-open .site-nav__list > li:nth-child(2) { transition-delay: 125ms; }
.site-nav.is-open .site-nav__list > li:nth-child(3) { transition-delay: 180ms; }
.site-nav.is-open .site-nav__list > li:nth-child(4) { transition-delay: 235ms; }
.site-nav.is-open .site-nav__list > li:nth-child(5) { transition-delay: 290ms; }

.site-nav__list > li > a {
  flex: 1;
  display: flex;
  align-items: baseline;
  gap: var(--sp-4);
  padding-block: clamp(0.75rem, 0.5rem + 1.2vw, 1.25rem);
  color: var(--c-ink);
  font-family: var(--ff-display);
  font-size: clamp(1.625rem, 1.2rem + 2.4vw, 2.5rem);
  font-weight: 400;
  line-height: 1.1;
  text-decoration: none;
  transition: color var(--dur) var(--ease);
}

.site-nav__list > li > a::before {
  content: counter(nav-index, decimal-leading-zero);
  flex: none;
  color: var(--c-rose);
  font-family: var(--ff-body);
  font-size: var(--fs-xs);
  font-weight: 500;
  letter-spacing: 0.1em;
}

.site-nav__list {
  counter-reset: nav-index;
}

.site-nav__list > li {
  counter-increment: nav-index;
}

.site-nav__list > li > a:hover,
.site-nav__list > li > a[aria-current="page"] {
  color: var(--c-rose);
}

/* --------------------------------------------------------------------------
   11a. Treatments submenu
   Disclosure pattern. The parent stays a real link to /services/ and the
   chevron is a separate button, so the state is announced properly and
   keyboard users are not forced through a hover-only menu.
   -------------------------------------------------------------------------- */

.nav-sub-toggle {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex: none;
  width: 44px;
  height: 44px;
  padding: 0;
  background: none;
  border: 0;
  border-radius: var(--radius);
  color: var(--c-rose);
  cursor: pointer;
  transition: background-color var(--dur) var(--ease),
    color var(--dur) var(--ease);
}

.nav-sub-toggle:hover {
  background-color: var(--c-shell);
  color: var(--c-rose-deep);
}

.nav-sub-toggle svg {
  width: 20px;
  height: 20px;
  fill: none;
  stroke: currentcolor;
  stroke-width: 1.75;
  stroke-linecap: round;
  stroke-linejoin: round;
  transition: transform var(--dur) var(--ease);
}

.nav-sub-toggle[aria-expanded="true"] svg {
  transform: rotate(180deg);
}

/* Mobile and tablet: an accordion. 0fr to 1fr animates the height without
   needing a measured pixel value. visibility keeps the closed links out of
   the tab order and the accessibility tree. */
.site-nav__sub {
  display: grid;
  grid-template-rows: 0fr;
  flex-basis: 100%;
  visibility: hidden;
  transition: grid-template-rows 300ms var(--ease),
    visibility 300ms var(--ease);
}

.site-nav__list > li.is-open .site-nav__sub {
  grid-template-rows: 1fr;
  visibility: visible;
}

.site-nav__sub-list {
  min-height: 0;
  padding: 0 0 0 var(--sp-6);
  margin: 0;
  overflow: hidden;
  list-style: none;
}

.site-nav__sub-list li {
  margin-top: 0;
}

.site-nav__sub-list li + li {
  border-top: 1px solid var(--c-hairline);
}

.site-nav__sub-list a {
  display: block;
  padding-block: var(--sp-3);
  color: var(--c-muted);
  font-family: var(--ff-body);
  font-size: var(--fs-base);
  font-weight: 400;
  letter-spacing: 0.02em;
  text-decoration: none;
  transition: color var(--dur) var(--ease);
}

.site-nav__sub-list a:hover,
.site-nav__sub-list a[aria-current="page"] {
  color: var(--c-rose);
}

.site-nav__foot {
  margin-top: auto;
  padding-top: var(--sp-8);
  opacity: 0;
  transform: translateY(14px);
  transition: opacity 420ms var(--ease) 340ms, transform 420ms var(--ease) 340ms;
}

.site-nav.is-open .site-nav__foot {
  opacity: 1;
  transform: translateY(0);
}

.site-nav__meta {
  padding: 0;
  margin: 0 0 var(--sp-6);
  list-style: none;
  color: var(--c-muted);
  font-size: var(--fs-sm);
}

.site-nav__meta li + li {
  margin-top: var(--sp-2);
}

.site-nav__meta a {
  color: var(--c-ink);
  text-decoration: none;
}

.site-nav__meta a:hover {
  color: var(--c-rose);
  text-decoration: underline;
}

body.nav-open {
  overflow: hidden;
}

@media (min-width: 64em) {
  .nav-toggle {
    display: none;
  }

  .site-nav {
    position: static;
    flex-direction: row;
    align-items: center;
    gap: var(--sp-7);
    height: auto;
    padding: 0;
    background: none;
    overflow: visible;
    opacity: 1;
    visibility: visible;
    transform: none;
    transition: none;
  }

  .site-nav__list {
    display: flex;
    align-items: center;
    gap: var(--sp-6);
  }

  .site-nav__list > li {
    position: relative;
    flex-wrap: nowrap;
    gap: var(--sp-1);
    border-bottom: 0;
    opacity: 1;
    transform: none;
    transition: none;
  }

  .site-nav__list > li > a {
    position: relative;
    display: block;
    flex: none;
    padding-block: var(--sp-2);
    font-family: var(--ff-body);
    font-size: var(--fs-xs);
    font-weight: 500;
    letter-spacing: var(--ls-caps);
    text-transform: uppercase;
  }

  .site-nav__list > li > a::before {
    content: none;
  }

  .site-nav__list > li > a::after {
    content: "";
    position: absolute;
    left: 0;
    bottom: 0;
    width: 0;
    height: 1px;
    background-color: var(--c-rose);
    transition: width var(--dur) var(--ease);
  }

  .site-nav__list > li > a:hover::after,
  .site-nav__list > li > a[aria-current="page"]::after {
    width: 100%;
  }

  .nav-sub-toggle {
    width: 28px;
    height: 28px;
  }

  .nav-sub-toggle svg {
    width: 15px;
    height: 15px;
  }

  /* Desktop: a floating panel rather than an accordion */
  .site-nav__sub {
    position: absolute;
    top: 100%;
    left: calc(var(--sp-4) * -1);
    z-index: 10;
    display: block;
    min-width: 15.5rem;
    margin-top: var(--sp-3);
    background-color: var(--c-bone);
    border: 1px solid var(--c-hairline);
    border-radius: var(--radius);
    box-shadow: var(--shadow-md);
    opacity: 0;
    visibility: hidden;
    transform: translateY(-6px);
    transition: opacity var(--dur) var(--ease),
      transform var(--dur) var(--ease), visibility var(--dur) var(--ease);
  }

  /* Bridges the gap between the trigger and the panel so the menu does not
     close while the pointer travels across it */
  .site-nav__sub::before {
    content: "";
    position: absolute;
    top: calc(var(--sp-3) * -1);
    left: 0;
    right: 0;
    height: var(--sp-3);
  }

  .site-nav__list > li.is-open .site-nav__sub {
    opacity: 1;
    visibility: visible;
    transform: translateY(0);
  }

  .site-nav__sub-list {
    padding: var(--sp-2) 0;
    overflow: visible;
  }

  .site-nav__sub-list li + li {
    border-top: 0;
  }

  .site-nav__sub-list a {
    padding: var(--sp-2) var(--sp-5);
    font-size: var(--fs-sm);
  }

  .site-nav__sub-list a:hover {
    background-color: var(--c-shell);
    color: var(--c-rose);
  }

  .site-nav__foot {
    display: none;
  }

  .site-nav__cta {
    display: inline-flex;
  }
}

.site-nav__cta {
  width: 100%;
}

/* The direct child is the desktop bar button. The overlay has its own copy
   inside .site-nav__foot, so only one is ever visible. */
.site-nav > .site-nav__cta {
  display: none;
}

@media (min-width: 64em) {
  .site-nav > .site-nav__cta {
    display: inline-flex;
    width: auto;
  }
}

/* --------------------------------------------------------------------------
   12. Hero
   Light treatment. Bone wash over the photograph, ink type.
   ONLY --c-ink clears 4.5:1 across the wash. Rose and muted both fail.
   -------------------------------------------------------------------------- */

/* Full bleed at every width. On a phone the copy is full width, so it has
   to sit over the photograph rather than beside it. The hero fills the
   viewport and the copy is bottom aligned, which leaves clean photograph
   above it instead of the wash covering the whole frame. */
.hero {
  position: relative;
  display: flex;
  /* Centred, not bottom aligned. Bottom aligning pushes all the slack to the
     top of the screen, which is what made it read as bottom heavy. */
  align-items: center;
  min-height: max(30rem, calc(100vh - var(--header-h)));
  min-height: max(30rem, calc(100svh - var(--header-h)));
  padding-block: var(--sp-8);
  background-color: var(--c-shell);
  overflow: hidden;
}

.hero__media {
  position: absolute;
  inset: 0;
}

/* The <img> is wrapped in <picture>, and the reset gives picture height:auto.
   Without this, height:100% on the img resolves against an indefinite height,
   falls back to auto, and object-fit never engages: the photograph renders at
   its natural ratio and stops short of the section. */
.hero__media picture {
  display: block;
  width: 100%;
  height: 100%;
}

.hero__media img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center 40%;
}

.hero__media::after {
  content: "";
  position: absolute;
  inset: 0;
  background-image: var(--wash-veil);
}

/* .hero__body is the centring container. .hero__inner is the text block
   inside it. Keeping them separate matters: putting .container and a
   max-width on the same element centres the text block in the viewport. */
.hero__body {
  position: relative;
  z-index: 1;
  width: 100%;
}

.hero__inner .eyebrow {
  color: var(--c-ink);
}

.hero__inner .lead {
  max-width: 34rem;
  margin-top: var(--sp-5);
  color: var(--c-ink);
  font-size: var(--fs-md);
}

.hero__inner .trust {
  color: var(--c-ink);
}

.hero__inner .trust li::before {
  background-color: var(--c-ink);
}

/* Tablet: fills the screen, same as a phone. A fixed clamp left the hero
   stopping well short of the fold with dead space beneath it. Inherits the
   centred copy and the even veil from the base. */
@media (min-width: 48em) {
  .hero {
    min-height: max(34rem, calc(100vh - var(--header-h)));
    min-height: max(34rem, calc(100svh - var(--header-h)));
    padding-block: var(--sp-9);
  }

  .hero__media img {
    object-position: center 42%;
  }
}

/* --------------------------------------------------------------------------
   12b. Tablet type
   fs-3xl is driven by viewport width, and a portrait tablet is narrow but
   very tall. It ends up with a smaller headline than a laptop in a box that
   is 40 per cent taller, which is what makes the block read as undersized.
   This gives the hero its own step between 48em and 64em only.
   -------------------------------------------------------------------------- */

@media (min-width: 48em) and (max-width: 63.99em) {
  .hero__inner h1 {
    /* Tops out at 4.5rem, which is the last size that holds two lines */
    font-size: clamp(4rem, 0.5rem + 7.6vw, 4.5rem);
  }

  .hero__inner .lead {
    /* 40rem, not 34rem: at the larger size the sentence runs to three lines
       in a 34rem measure */
    max-width: 40rem;
    font-size: var(--fs-lg);
  }

  .hero .trust {
    font-size: var(--fs-sm);
    /* Tracking comes down as the size goes up. At 0.16em the two columns
       need 715px and overflow a 712px block at 768. */
    letter-spacing: 0.1em;
  }
}

@media (min-width: 64em) {
  .hero {
    align-items: center;
    /* Fill the viewport below the header, capped so it does not run away
       on very tall monitors. svh keeps mobile browser chrome out of it. */
    min-height: clamp(34rem, calc(100vh - var(--header-h)), 56rem);
    min-height: clamp(34rem, calc(100svh - var(--header-h)), 56rem);
  }

  .hero__media img {
    object-position: 42% center;
  }

  .hero__media::after {
    background-image: var(--wash-h);
  }

  /* 42rem, not 40rem: the icons add 32px to each trust item and the 2x2
     grid needs 644px, which overflows a 640px block by 4px. */
  .hero__inner {
    max-width: 42rem;
  }

  .hero__inner .lead {
    font-size: var(--fs-lg);
  }
}

/* --------------------------------------------------------------------------
   12a. Hero budget on phones
   The first screen on a 390x844 handset is 611px once the header is off.
   The full desktop copy is 540px, which is 88% of it. Three things buy the
   photograph its space back: the call bar tucks away while the hero is on
   screen (section 21), the buttons pair up with shorter labels, and the
   lead drops the feature list that the eyebrow already carries.
   -------------------------------------------------------------------------- */

.btn__long,
.lead__long {
  display: none;
}

@media (min-width: 40em) {
  .btn__short {
    display: none;
  }

  .btn__long {
    display: inline;
  }
}

@media (min-width: 48em) {
  .lead__short {
    display: none;
  }

  .lead__long {
    display: inline;
  }
}

/* Equal halves rather than auto widths, so the pair reads as one control */
.hero .btn-row .btn {
  flex: 1 1 auto;
  padding-inline: var(--sp-4);
}

@media (min-width: 40em) {
  .hero .btn-row .btn {
    flex: 0 1 auto;
    padding-inline: var(--sp-6);
  }
}

/* An icon per point in place of the rose dot, at every width. The dot rule
   stays on .trust generally so other sections can still use it. */
.trust__icon {
  display: none;
}

.hero .trust li {
  display: flex;
  align-items: center;
  gap: var(--sp-3);
}

.hero .trust li::before {
  display: none;
}

.hero .trust__icon {
  display: block;
  flex: none;
  width: 20px;
  height: 20px;
  fill: none;
  stroke: var(--c-rose);
  stroke-width: 1.5;
  stroke-linecap: round;
  stroke-linejoin: round;
}

/* Phones additionally get hairline rules, because the list is a single
   column there. On a tablet it is a 2x2 grid and rules would fight it. */
@media (max-width: 47.99em) {
  .hero .trust {
    gap: 0;
  }

  .hero .trust li {
    padding-block: var(--sp-3);
  }

  .hero .trust li + li {
    border-top: 1px solid rgba(26, 24, 22, 0.16);
  }
}

/* Short handsets only. iOS Safari reports the SMALL viewport height here, so
   an iPhone 15 reports about 675px, not 844. The threshold has to sit below
   that or this fires on every phone. An SE reports about 527px. */
@media (max-width: 47.99em) and (max-height: 600px) {
  .hero .trust li:nth-child(n + 3) {
    display: none;
  }
}

.hero--page {
  min-height: clamp(16rem, 12rem + 14vw, 24rem);
}

/* Above 1440 the headline stops growing and the block starts to look
   stranded on a large monitor. The clamp minimum matches the value
   fs-3xl already reaches at 1440, so nothing jumps at the breakpoint. */
@media (min-width: 90em) {
  .hero__inner {
    max-width: 46rem;
  }

  .hero__inner h1 {
    font-size: clamp(3.5rem, 0.875rem + 2.92vw, 4.375rem);
  }

  .hero__inner .lead {
    max-width: 36rem;
  }
}

/* --------------------------------------------------------------------------
   12b-i. Hero entrance
   Pure CSS so it runs on parse with no flash and no dependency on the script.
   The photograph settles rather than fades: it is the LCP element, and an
   opacity animation on it would delay the metric. Transform does not.
   -------------------------------------------------------------------------- */

@keyframes hero-rise {
  from {
    opacity: 0;
    transform: translateY(20px);
  }
}

@keyframes hero-settle {
  from {
    transform: scale(1.06);
  }
}

.hero__media img {
  animation: hero-settle 1800ms var(--ease-out) both;
}

.hero__inner > * {
  animation: hero-rise 700ms var(--ease-out) both;
}

.hero__inner > *:nth-child(1) { animation-delay: 100ms; }
.hero__inner > *:nth-child(2) { animation-delay: 190ms; }
.hero__inner > *:nth-child(3) { animation-delay: 280ms; }
.hero__inner > *:nth-child(4) { animation-delay: 370ms; }
.hero__inner > *:nth-child(5) { animation-delay: 460ms; }

/* --------------------------------------------------------------------------
   12c. Feature
   An asymmetric split where the image runs off the left edge of the viewport.
   A plain two column grid with a boxed image is the default preset on every
   site builder going, so this breaks the container instead.
   -------------------------------------------------------------------------- */

.feature {
  display: grid;
  gap: var(--sp-7);
}

.feature .media {
  max-width: 32rem;
  margin-inline: auto;
}

/* Tablet gets its own idea rather than a default stack. The split cannot
   hold here, since a 363px text column wraps the headline to four lines, but
   the plain stack centres a capped image above left aligned copy and the two
   share no edge. So the image runs the full width of the viewport as a
   landscape band, which keeps the container-breaking move from desktop and
   gives the copy a clean edge to sit under. */
@media (min-width: 48em) and (max-width: 63.99em) {
  .feature {
    gap: var(--sp-8);
  }

  .feature .media {
    max-width: none;
    margin-inline: calc(-1 * (max((100vw - var(--w-wide)) / 2, 0px) + var(--gutter)));
    border-radius: 0;
  }

  .feature .media img {
    aspect-ratio: 21 / 10;
    object-fit: cover;
    /* Biased up the frame so the band keeps both the mirror and her face */
    object-position: center 22%;
  }
}

@media (min-width: 64em) {
  .feature {
    grid-template-columns: 0.95fr 1fr;
    gap: clamp(3rem, 0.5rem + 5vw, 6rem);
    /* stretch, not center: the image fills the row so it can then be pulled
       out past the section padding */
    align-items: stretch;
  }

  .feature__body {
    order: 2;
    align-self: center;
  }

  /* The column grows with the container on a large monitor, so the measure
     is capped here rather than left to run to 100 characters a line. */
  .feature__body p {
    max-width: 60ch;
  }

  .feature .media {
    order: 1;
    max-width: none;
    margin-inline: 0;
    /* Reaches the viewport edge: half the leftover gutter plus the container
       padding. max() keeps it at just the padding below the container width. */
    margin-left: calc(-1 * (max((100vw - var(--w-wide)) / 2, 0px) + var(--gutter)));
    /* And cancels the section padding, so it meets the top and bottom edges
       too. Bleeding on one side only reads as a mistake. */
    margin-block: calc(-1 * var(--sp-section));
    border-radius: 0;
  }

  .feature .media img {
    height: 100%;
    object-fit: cover;
  }

  /* Mirrored: copy on the left, image running off the right edge instead */
  .feature--mirror .feature__body {
    order: 1;
  }

  .feature--mirror .media {
    order: 2;
    margin-left: 0;
    margin-right: calc(-1 * (max((100vw - var(--w-wide)) / 2, 0px) + var(--gutter)));
  }
}

/* A single line lifted out of the copy, set in the display italic with a
   rose rule above it. The strongest thing she said, given room to land. */
.statement {
  position: relative;
  margin-top: var(--sp-7);
  padding-top: var(--sp-6);
  font-family: var(--ff-display);
  font-style: italic;
  font-size: var(--fs-xl);
  line-height: 1.35;
  text-wrap: balance;
}

.statement::before {
  content: "";
  position: absolute;
  top: 0;
  left: 0;
  width: 3.5rem;
  height: 1px;
  background-color: var(--c-rose);
}

.statement + p {
  margin-top: var(--sp-6);
}

/* --------------------------------------------------------------------------
   12c. Media
   Image wrapper for split sections. figure carries a default margin, so it
   is zeroed here rather than relying on the global reset alone.
   -------------------------------------------------------------------------- */

.media {
  margin: 0;
  overflow: hidden;
  background-color: var(--c-bone);
  border-radius: var(--radius);
}

.media img {
  width: 100%;
  height: auto;
}

/* When a split stacks, the image would otherwise run the full container
   width. On an 834 tablet that is a 776px block, which dominates the copy
   and needs a 1552px source. Capped and centred instead, so one 1200px
   file covers every viewport at 2x. */
.split .media {
  max-width: 32rem;
  margin-inline: auto;
}

@media (min-width: 64em) {
  .split .media {
    max-width: none;
    margin-inline: 0;
  }
}

/* --------------------------------------------------------------------------
   11b. Breadcrumbs
   These went missing when section 11 was rewritten for the nav dropdown,
   which left them rendering as a raw numbered list.
   -------------------------------------------------------------------------- */

.breadcrumbs {
  margin-bottom: var(--sp-6);
  font-size: var(--fs-xs);
  letter-spacing: 0.06em;
}

.breadcrumbs ol {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--sp-2) var(--sp-3);
  padding: 0;
  margin: 0;
  list-style: none;
}

.breadcrumbs li {
  display: flex;
  align-items: center;
  gap: var(--sp-3);
  margin-top: 0;
  color: var(--c-muted);
}

/* A short rule rather than a slash, picking up the flanking dashes in the
   logo */
.breadcrumbs li + li::before {
  content: "";
  flex: none;
  width: 14px;
  height: 1px;
  background-color: var(--c-border);
}

.breadcrumbs a {
  color: var(--c-muted);
  text-decoration: none;
}

.breadcrumbs a:hover {
  color: var(--c-rose);
  text-decoration: underline;
}

/* --------------------------------------------------------------------------
   12c-ii. Treatment block
   Its own layout rather than the generic split. On a phone the image sits
   between the heading and the detail, which reads better than dumping it
   above or below the whole block. From 48em it goes two column, so tablet
   never hits the stacked-and-centred problem.
   -------------------------------------------------------------------------- */

.treatment {
  display: grid;
  gap: var(--sp-5);
}

.treatment__media {
  aspect-ratio: 3 / 2;
}

.treatment__media img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

@media (min-width: 48em) {
  .treatment {
    grid-template-columns: 1fr 1fr;
    grid-template-areas:
      "title media"
      "body  media";
    align-items: start;
    gap: var(--sp-5) clamp(2rem, 0.5rem + 4vw, 4rem);
  }

  .treatment__title {
    grid-area: title;
  }

  .treatment__body {
    grid-area: body;
  }

  .treatment__media {
    grid-area: media;
    aspect-ratio: 1 / 1;
  }

  .treatment--reverse {
    grid-template-areas:
      "media title"
      "media body";
  }
}

/* --------------------------------------------------------------------------
   12c-iii. Credentials
   A spec list rather than bullets. Issuer above, subject below, hairline
   between each. Three of the four are safety qualifications, which in this
   trade is the differentiator worth setting properly.
   -------------------------------------------------------------------------- */

.creds {
  display: grid;
  padding: 0;
  margin-top: var(--sp-7);
  list-style: none;
  border-top: 1px solid var(--c-hairline);
}

.creds li {
  margin-top: 0;
  padding-block: var(--sp-5);
  border-bottom: 1px solid var(--c-hairline);
}

@media (min-width: 48em) {
  .creds {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    column-gap: var(--sp-8);
  }
}

.creds__issuer {
  display: block;
  color: var(--c-rose);
  font-size: var(--fs-xs);
  font-weight: 500;
  letter-spacing: var(--ls-caps);
  text-transform: uppercase;
}

.creds__subject {
  display: block;
  margin-top: var(--sp-2);
  font-family: var(--ff-display);
  font-size: var(--fs-lg);
  line-height: var(--lh-snug);
}

/* --------------------------------------------------------------------------
   12c-iv. Steps
   A numbered sequence for a process. Number in a fixed left column spanning
   both rows, so the headings and descriptions stay on one vertical line
   regardless of how long the numbers get.
   -------------------------------------------------------------------------- */

.steps {
  max-width: 48rem;
  padding: 0;
  margin-top: var(--sp-7);
  list-style: none;
  counter-reset: step;
}

.steps li {
  counter-increment: step;
  display: grid;
  gap: var(--sp-2);
  padding-block: var(--sp-6);
  margin-top: 0;
  border-top: 1px solid var(--c-hairline);
}

.steps li:last-child {
  border-bottom: 1px solid var(--c-hairline);
}

.steps li::before {
  content: counter(step, decimal-leading-zero);
  color: var(--c-rose);
  font-size: var(--fs-xs);
  font-weight: 500;
  letter-spacing: 0.1em;
}

.steps h3 {
  font-size: var(--fs-lg);
}

.steps p {
  color: var(--c-muted);
}

@media (min-width: 40em) {
  .steps li {
    grid-template-columns: 3.5rem minmax(0, 1fr);
    column-gap: var(--sp-5);
  }

  .steps li::before {
    grid-row: 1 / span 2;
    padding-top: 0.35em;
  }
}

/* Same hairline separated list without the numbering, for things that are a
   set rather than a sequence */
.steps--plain li::before {
  content: none;
}

.steps--plain p + p {
  margin-top: var(--sp-4);
}

@media (min-width: 40em) {
  .steps--plain li {
    grid-template-columns: minmax(0, 1fr);
  }
}

/* --------------------------------------------------------------------------
   12c-v. Legal contents
   Sticky table of contents for the long legal pages, sharing the two column
   layout used by the FAQ and the credentials block.
   -------------------------------------------------------------------------- */

.legal-toc ul {
  padding: 0;
  margin-top: var(--sp-4);
  list-style: none;
  border-top: 1px solid var(--c-hairline);
}

.legal-toc li {
  margin-top: 0;
  border-bottom: 1px solid var(--c-hairline);
}

.legal-toc a {
  display: block;
  padding-block: var(--sp-3);
  color: var(--c-muted);
  font-size: var(--fs-sm);
  text-decoration: none;
}

.legal-toc a:hover {
  color: var(--c-rose);
}

.legal-updated {
  margin-top: var(--sp-5);
  color: var(--c-muted);
  font-size: var(--fs-sm);
}

.prose h2 {
  font-size: var(--fs-xl);
}

/* --------------------------------------------------------------------------
   12c-vi. Standalone pages
   404 and thank you. No breadcrumb, no page header, just a centred block
   with room around it.
   -------------------------------------------------------------------------- */

.standalone {
  display: flex;
  align-items: center;
  min-height: max(28rem, calc(100vh - var(--header-h) - 6rem));
  min-height: max(28rem, calc(100svh - var(--header-h) - 6rem));
  padding-block: var(--sp-section);
}

.standalone__inner {
  width: 100%;
  max-width: 34rem;
  margin-inline: auto;
  text-align: center;
}

.standalone__mark {
  width: auto;
  height: 56px;
  margin-inline: auto;
  margin-bottom: var(--sp-6);
}

.standalone .btn-row {
  justify-content: center;
}

/* A plain list of onward links under the buttons */
.elsewhere {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: var(--sp-3) var(--sp-5);
  padding: 0;
  margin-top: var(--sp-8);
  list-style: none;
  font-size: var(--fs-sm);
}

.elsewhere li {
  margin-top: 0;
}

.elsewhere a {
  color: var(--c-muted);
  text-decoration: none;
}

.elsewhere a:hover {
  color: var(--c-rose);
  text-decoration: underline;
}

/* --------------------------------------------------------------------------
   12c-vii. Third party embeds
   The GoHighLevel script sets the iframe height itself once it loads.
   min-height reserves roughly the right space beforehand so the page does
   not jump, and it is deliberately conservative: too generous and the
   script leaves dead space beneath a shorter widget.
   -------------------------------------------------------------------------- */

.embed {
  width: 100%;
  overflow: hidden;
  background-color: var(--c-bone);
  border-radius: var(--radius);
}

.embed iframe {
  display: block;
  width: 100%;
  border: 0;
}

.embed--calendar iframe {
  min-height: 44rem;
}

.embed--form iframe {
  min-height: 50rem;
}

.embed__note {
  margin-top: var(--sp-4);
  color: var(--c-muted);
  font-size: var(--fs-sm);
}

/* --------------------------------------------------------------------------
   12d. Page header
   Inner pages get a quiet type-only header rather than a photographic hero.
   The hero is the home page's statement, and repeating it on every page both
   dilutes it and costs another crop per page.
   -------------------------------------------------------------------------- */

.page-header {
  padding-block: clamp(2rem, 1rem + 4vw, 4rem) clamp(2.5rem, 1.5rem + 5vw, 5rem);
  background-color: var(--c-shell);
}

.page-header h1 {
  max-width: 20ch;
}

.page-header .lead {
  max-width: 56ch;
  margin-top: var(--sp-5);
  color: var(--c-muted);
}

/* --------------------------------------------------------------------------
   12e. Prices
   Rows rather than a bordered card, so they sit inside a treatment block
   without adding a second frame around content that is already in one.
   -------------------------------------------------------------------------- */

.prices {
  margin-top: var(--sp-6);
  border-top: 1px solid var(--c-hairline);
}

.prices__row {
  display: flex;
  align-items: baseline;
  gap: var(--sp-4);
  padding-block: var(--sp-3);
  border-bottom: 1px solid var(--c-hairline);
}

.prices__row dt {
  flex: 1;
  font-size: var(--fs-sm);
}

.prices__row dd {
  margin: 0;
  font-family: var(--ff-display);
  font-size: var(--fs-lg);
  white-space: nowrap;
}

.prices__was {
  margin-right: var(--sp-2);
  color: var(--c-muted);
  font-family: var(--ff-body);
  font-size: var(--fs-sm);
  text-decoration: line-through;
}

.prices__note {
  margin-top: var(--sp-4);
  color: var(--c-rose);
  font-size: var(--fs-sm);
  font-weight: 500;
}

/* --------------------------------------------------------------------------
   13. Cards
   -------------------------------------------------------------------------- */

.card {
  position: relative;
  display: flex;
  flex-direction: column;
  height: 100%;
  background-color: var(--c-bone);
  border: 1px solid var(--c-hairline);
  border-radius: var(--radius);
  overflow: hidden;
  transition: border-color var(--dur) var(--ease),
    box-shadow var(--dur) var(--ease), transform var(--dur) var(--ease);
}

.card:hover,
.card:focus-within {
  border-color: var(--c-rose);
  box-shadow: var(--shadow-md);
  transform: translateY(-3px);
}

/* 3:2. Portrait made the image 65% of a phone screen. The files are cut to
   this ratio at source, so object-fit never has to crop and each focal point
   is placed once rather than guessed by the browser. */
.card__media {
  aspect-ratio: 3 / 2;
  background-color: var(--c-shell);
}

.card__media img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.card__body {
  display: flex;
  flex-direction: column;
  flex: 1;
  padding: var(--sp-5) var(--sp-5) var(--sp-6);
}

.card__body h3 {
  margin-bottom: var(--sp-3);
}

.card__body p {
  color: var(--c-muted);
  font-size: var(--fs-sm);
}

.card__price {
  display: block;
  margin-top: var(--sp-3);
  color: var(--c-ink);
  font-family: var(--ff-display);
  font-size: var(--fs-lg);
}

.card__body .link-arrow {
  margin-top: auto;
  padding-top: var(--sp-5);
}

/* Cards want a tighter heading rhythm than the 24px base */
.card__body h3 + p {
  margin-top: var(--sp-3);
}

.card__link {
  color: inherit;
  text-decoration: none;
}

.card__link::after {
  content: "";
  position: absolute;
  inset: 0;
}

/* --------------------------------------------------------------------------
   14. Price list
   -------------------------------------------------------------------------- */

.pricelist {
  padding: var(--sp-6);
  background-color: var(--c-bone);
  border: 1px solid var(--c-hairline);
  border-radius: var(--radius);
}

.pricelist h3 {
  padding-bottom: var(--sp-4);
  border-bottom: 1px solid var(--c-hairline);
}

.pricelist__note {
  margin-top: var(--sp-2);
  color: var(--c-muted);
  font-size: var(--fs-sm);
}

.pricelist dl {
  margin: var(--sp-5) 0 0;
}

.pricelist__row {
  display: flex;
  align-items: baseline;
  gap: var(--sp-3);
  padding-block: var(--sp-3);
  border-bottom: 1px solid var(--c-hairline);
}

.pricelist__row dt {
  flex: 1;
}

.pricelist__row dd {
  margin: 0;
  font-family: var(--ff-display);
  font-size: var(--fs-lg);
  white-space: nowrap;
}

.pricelist__was {
  margin-right: var(--sp-2);
  color: var(--c-muted);
  font-family: var(--ff-body);
  font-size: var(--fs-sm);
  text-decoration: line-through;
}

.pricelist .btn {
  margin-top: var(--sp-6);
}

/* --------------------------------------------------------------------------
   15. FAQ
   -------------------------------------------------------------------------- */

/* Head on the left, questions on the right, rather than one centred column
   of accordion rows. The numbers pick up the same device as the mobile nav. */
.faq-layout {
  display: grid;
  gap: var(--sp-7);
}

@media (min-width: 64em) {
  .faq-layout {
    grid-template-columns: 0.8fr 1.2fr;
    gap: clamp(3rem, 1rem + 5vw, 6rem);
    align-items: start;
  }

  .faq-layout__head {
    position: sticky;
    top: calc(var(--header-h) + var(--sp-8));
  }
}

.faq {
  counter-reset: faq-index;
}

.faq__item {
  counter-increment: faq-index;
}

.faq__item {
  border-bottom: 1px solid var(--c-hairline);
}

.faq__item summary {
  display: flex;
  align-items: flex-start;
  gap: var(--sp-4);
  padding-block: var(--sp-5);
  font-family: var(--ff-display);
  font-size: var(--fs-lg);
  line-height: var(--lh-snug);
  cursor: pointer;
  list-style: none;
  transition: color var(--dur) var(--ease);
}

.faq__item summary::-webkit-details-marker {
  display: none;
}

.faq__item summary:hover {
  color: var(--c-rose);
}

.faq__item summary::before {
  content: counter(faq-index, decimal-leading-zero);
  flex: none;
  width: 1.75rem;
  padding-top: 0.5em;
  color: var(--c-rose);
  font-family: var(--ff-body);
  font-size: var(--fs-xs);
  font-weight: 500;
  letter-spacing: 0.1em;
}

.faq__icon {
  position: relative;
  flex: none;
  width: 16px;
  height: 16px;
  margin-top: 0.45em;
  margin-left: auto;
}

.faq__icon::before,
.faq__icon::after {
  content: "";
  position: absolute;
  top: 50%;
  left: 0;
  width: 16px;
  height: 1.5px;
  background-color: var(--c-rose);
  transform: translateY(-50%);
  transition: transform var(--dur) var(--ease);
}

.faq__icon::after {
  transform: translateY(-50%) rotate(90deg);
}

.faq__item[open] .faq__icon::after {
  transform: translateY(-50%) rotate(0deg);
}

.faq__answer {
  padding-bottom: var(--sp-5);
  padding-left: calc(1.75rem + var(--sp-4));
  color: var(--c-muted);
  max-width: var(--w-prose);
}

.closing-call {
  margin-top: var(--sp-6);
  font-size: var(--fs-sm);
}

.site-footer__hours {
  margin-top: var(--sp-5);
  font-size: var(--fs-sm);
}

.site-footer__reviews {
  margin-top: var(--sp-5);
  font-size: var(--fs-sm);
}

.site-footer__reviews a {
  text-decoration: underline;
  text-underline-offset: 0.18em;
}

/* --------------------------------------------------------------------------
   16. Reviews
   -------------------------------------------------------------------------- */

/* Shell, not bone. The section sits on bone so the cards need to lift off
   it, and it stops these reading as the treatment cards a screen earlier. */
.review {
  display: flex;
  flex-direction: column;
  height: 100%;
  padding: var(--sp-6);
  background-color: var(--c-shell);
  border-radius: var(--radius);
}

.review__stars {
  display: flex;
  gap: 3px;
  margin-bottom: var(--sp-4);
  color: var(--c-rose);
}

.review__stars svg {
  width: 84px;
  height: 16px;
  fill: currentcolor;
}

.review blockquote {
  flex: 1;
  margin: 0;
  font-family: var(--ff-display);
  font-size: var(--fs-md);
  line-height: 1.6;
}

.review__author {
  margin-top: var(--sp-5);
  color: var(--c-ink);
  font-size: var(--fs-xs);
  font-weight: 500;
  letter-spacing: var(--ls-caps);
  text-transform: uppercase;
}

.review__meta {
  display: block;
  margin-top: var(--sp-1);
  color: var(--c-muted);
  font-size: var(--fs-xs);
  font-weight: 400;
  letter-spacing: 0.04em;
  text-transform: none;
}

/* --------------------------------------------------------------------------
   17. Gallery
   -------------------------------------------------------------------------- */

.gallery-filter {
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-3);
  justify-content: center;
  margin-bottom: var(--sp-7);
}

.gallery-filter__btn {
  min-height: 44px;
  padding: var(--sp-2) var(--sp-5);
  background: none;
  border: 1px solid var(--c-border);
  border-radius: var(--radius-pill);
  color: var(--c-ink);
  font-size: var(--fs-xs);
  font-weight: 500;
  letter-spacing: var(--ls-caps);
  text-transform: uppercase;
  cursor: pointer;
  transition: background-color var(--dur) var(--ease),
    border-color var(--dur) var(--ease), color var(--dur) var(--ease);
}

.gallery-filter__btn:hover {
  border-color: var(--c-rose);
  color: var(--c-rose);
}

.gallery-filter__btn[aria-pressed="true"] {
  background-color: var(--c-ink);
  border-color: var(--c-ink);
  color: var(--c-bone);
}

/* Explicit columns rather than auto-fill. With 33 square images, auto-fill
   drops to a single column on a phone and makes the page enormous. */
.gallery-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--sp-3);
  padding: 0;
  list-style: none;
}

@media (min-width: 48em) {
  .gallery-grid {
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: var(--sp-4);
  }
}

@media (min-width: 64em) {
  .gallery-grid {
    grid-template-columns: repeat(4, minmax(0, 1fr));
  }
}

/* A six image teaser rather than the full set. Capped at three columns so it
   lands as two clean rows instead of four across and two stranded. */
@media (min-width: 48em) {
  .gallery-grid--strip {
    grid-template-columns: repeat(3, minmax(0, 1fr));
  }
}

.gallery-grid--strip img {
  width: 100%;
  aspect-ratio: 1 / 1;
  object-fit: cover;
  background-color: var(--c-shell);
  border-radius: var(--radius);
}

.gallery-item {
  margin-top: 0;
}

/* The tile is a button so it is reachable by keyboard and announces itself
   as something that opens */
.gallery-item__btn {
  display: block;
  width: 100%;
  padding: 0;
  background: none;
  border: 0;
  border-radius: var(--radius);
  overflow: hidden;
  cursor: pointer;
}

.gallery-item__btn img {
  width: 100%;
  aspect-ratio: 1 / 1;
  object-fit: cover;
  background-color: var(--c-shell);
  transition: transform var(--dur-slow) var(--ease);
}

@media (hover: hover) and (pointer: fine) {
  .gallery-item__btn:hover img {
    transform: scale(1.04);
  }
}

/* --------------------------------------------------------------------------
   17b. Lightbox
   Native <dialog>, which brings the focus trap, the Escape handler and the
   backdrop with it rather than needing any of that written by hand.
   -------------------------------------------------------------------------- */

/* position, inset and margin are all set here rather than left to the
   browser. A modal dialog is centred by the UA rule margin:auto against
   inset:0, and the global * { margin: 0 } reset at the top of this file
   wipes that out, which pins the dialog to the top left corner. */
.lightbox {
  position: fixed;
  inset: 0;
  width: min(94vw, 58rem);
  max-width: none;
  max-height: 94vh;
  margin: auto;
  padding: 0;
  background-color: var(--c-bone);
  border: 0;
  border-radius: var(--radius);
}

.lightbox::backdrop {
  background-color: rgba(26, 24, 22, 0.9);
}

.lightbox__figure {
  margin: 0;
}

.lightbox__figure img {
  display: block;
  width: 100%;
  height: auto;
  max-height: 74vh;
  object-fit: contain;
  background-color: var(--c-shell);
}

.lightbox__bar {
  display: flex;
  align-items: center;
  gap: var(--sp-4);
  padding: var(--sp-4) var(--sp-5);
}

.lightbox__caption {
  flex: 1;
  color: var(--c-muted);
  font-size: var(--fs-sm);
}

.lightbox__count {
  flex: none;
  color: var(--c-muted);
  font-size: var(--fs-xs);
  letter-spacing: var(--ls-caps);
  white-space: nowrap;
}

.lightbox__nav {
  display: flex;
  flex: none;
  gap: var(--sp-2);
}

.lightbox__btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 44px;
  height: 44px;
  padding: 0;
  background: none;
  border: 1px solid var(--c-border);
  border-radius: var(--radius);
  cursor: pointer;
  transition: background-color var(--dur) var(--ease),
    border-color var(--dur) var(--ease);
}

@media (hover: hover) and (pointer: fine) {
  .lightbox__btn:hover {
    background-color: var(--c-shell);
    border-color: var(--c-ink);
  }
}

.lightbox__btn svg {
  width: 18px;
  height: 18px;
  fill: none;
  stroke: var(--c-ink);
  stroke-width: 1.75;
  stroke-linecap: round;
  stroke-linejoin: round;
}

@media (max-width: 39.99em) {
  .lightbox__bar {
    flex-wrap: wrap;
  }

  .lightbox__caption {
    order: 3;
    flex-basis: 100%;
  }
}

.gallery-item figcaption {
  position: absolute;
  left: var(--sp-3);
  bottom: var(--sp-3);
  padding: var(--sp-2) var(--sp-4);
  background-color: rgba(26, 24, 22, 0.86);
  border-radius: var(--radius-pill);
  color: var(--c-on-dark);
  font-size: var(--fs-xs);
  letter-spacing: var(--ls-caps);
  text-transform: uppercase;
}

.gallery-empty {
  padding: var(--sp-8) 0;
  color: var(--c-muted);
  text-align: center;
}

/* --------------------------------------------------------------------------
   18. Forms
   -------------------------------------------------------------------------- */

.form {
  max-width: 36rem;
}

.field + .field {
  margin-top: var(--sp-5);
}

.field label {
  display: block;
  margin-bottom: var(--sp-2);
  font-size: var(--fs-sm);
  font-weight: 500;
  letter-spacing: 0.04em;
}

.field__hint {
  display: block;
  margin-top: -0.25rem;
  margin-bottom: var(--sp-2);
  color: var(--c-muted);
  font-size: var(--fs-xs);
}

.field input,
.field select,
.field textarea {
  width: 100%;
  min-height: 48px;
  padding: var(--sp-3) var(--sp-4);
  background-color: var(--c-bone);
  border: 1px solid var(--c-border);
  border-radius: var(--radius);
  font-size: var(--fs-base);
  transition: border-color var(--dur) var(--ease),
    box-shadow var(--dur) var(--ease);
}

.field textarea {
  min-height: 9rem;
  resize: vertical;
}

.field input:hover,
.field select:hover,
.field textarea:hover {
  border-color: var(--c-ink);
}

.field input:focus,
.field select:focus,
.field textarea:focus {
  border-color: var(--c-rose);
  box-shadow: 0 0 0 3px rgba(126, 80, 73, 0.18);
  outline: 3px solid transparent;
  outline-offset: 0;
}

.field input[aria-invalid="true"],
.field textarea[aria-invalid="true"] {
  border-color: var(--c-error);
}

.field__error {
  display: block;
  margin-top: var(--sp-2);
  color: var(--c-error);
  font-size: var(--fs-sm);
  font-weight: 500;
}

.form__consent {
  display: flex;
  align-items: flex-start;
  gap: var(--sp-3);
  margin-top: var(--sp-5);
}

.form__consent input {
  flex: none;
  width: 20px;
  height: 20px;
  min-height: 0;
  margin-top: 0.3em;
  accent-color: var(--c-rose);
}

.form__consent label {
  margin-bottom: 0;
  font-size: var(--fs-sm);
  font-weight: 400;
  line-height: 1.6;
}

.form .btn {
  margin-top: var(--sp-6);
}

.form__hp {
  position: absolute;
  left: -9999px;
  width: 1px;
  height: 1px;
  overflow: hidden;
}

.form__status {
  margin-top: var(--sp-4);
  font-size: var(--fs-sm);
  font-weight: 500;
}

.form__status[data-state="error"] {
  color: var(--c-error);
}

.form__status[data-state="success"] {
  color: var(--c-success);
}

/* --------------------------------------------------------------------------
   19. Contact details block
   -------------------------------------------------------------------------- */

.contact-list {
  padding: 0;
  margin: 0;
  list-style: none;
}

.contact-list li {
  display: flex;
  gap: var(--sp-4);
  padding-block: var(--sp-5);
  margin-top: 0;
  border-bottom: 1px solid var(--c-hairline);
}

.contact-list svg {
  flex: none;
  width: 22px;
  height: 22px;
  margin-top: 0.2em;
  fill: none;
  stroke: var(--c-rose);
  stroke-width: 1.5;
}

/* Brand glyphs are drawn as solid shapes, so they need the fill and stroke
   swapped round rather than the line-art treatment the others use. */
.contact-list svg.icon--solid {
  fill: var(--c-rose);
  stroke: none;
}

.contact-list__label {
  display: block;
  margin-bottom: var(--sp-1);
  color: var(--c-muted);
  font-size: var(--fs-xs);
  letter-spacing: var(--ls-caps);
  text-transform: uppercase;
}

.contact-list__value {
  font-family: var(--ff-display);
  font-size: var(--fs-lg);
}

.contact-list__value a {
  color: var(--c-ink);
  text-decoration: none;
}

.contact-list__value a:hover {
  color: var(--c-rose);
  text-decoration: underline;
}

.contact-list__note {
  margin-top: var(--sp-2);
  color: var(--c-muted);
  font-size: var(--fs-sm);
}

/* --------------------------------------------------------------------------
   20. Footer
   -------------------------------------------------------------------------- */

.site-footer {
  padding-block: var(--sp-9) var(--sp-6);
  background-color: var(--c-espresso);
  color: var(--c-on-dark-muted);
  font-size: var(--fs-sm);
}

.site-footer__grid {
  display: grid;
  gap: var(--sp-7);
}

/* Between 40em and desktop the logo takes a row of its own and the three
   link blocks sit in three columns beneath it. A two column grid put the
   logo level with the Explore heading, so the mark had no space of its own
   and the footer read as two unrelated halves. */
@media (min-width: 40em) and (max-width: 63.99em) {
  .site-footer__grid {
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: var(--sp-8) var(--sp-6);
  }

  .site-footer__grid > :first-child {
    grid-column: 1 / -1;
  }
}

@media (min-width: 64em) {
  .site-footer__grid {
    grid-template-columns: 1.5fr 1fr 1fr 1.3fr;
    gap: var(--sp-8);
  }
}

.site-footer__tagline {
  max-width: 30ch;
  margin-bottom: var(--sp-5);
}

.site-footer address {
  font-style: normal;
  line-height: 1.7;
}

/* Clear separation from the address so the phone number does not read as a
   fifth line of it, which is how it looks when the column stacks on a phone.
   Phone and email keep the inherited 12px between them so they group as a
   pair. */
.site-footer__contact {
  margin-top: var(--sp-7);
}

.site-footer__contact a {
  color: var(--c-on-dark);
  overflow-wrap: break-word;
}

/* The extra .site-footer is deliberate. The generic .site-footer li + li
   rule further down this section carries the same specificity, so without it
   the later rule wins on source order and drops Terms onto its own line. */
.site-footer__legal {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--sp-2) var(--sp-6);
}

.site-footer .site-footer__legal li + li {
  margin-top: 0;
}

.site-footer h2 {
  margin-bottom: var(--sp-4);
  color: var(--c-on-dark);
  font-family: var(--ff-body);
  font-size: var(--fs-xs);
  font-weight: 500;
  letter-spacing: var(--ls-caps-wide);
  text-transform: uppercase;
}

.site-footer__logo img {
  width: auto;
  height: 48px;
  margin-bottom: var(--sp-6);
}

/* No margin reset here. The shorthand carries (0,1,1) specificity, which
   beats the (0,1,0) of .site-footer__contact and .social and silently kills
   their margin-top. The reset at the top of the file already zeroes margins. */
.site-footer ul {
  padding: 0;
  list-style: none;
}

.site-footer li + li {
  margin-top: var(--sp-3);
}

.site-footer a:not(.btn) {
  color: var(--c-on-dark-muted);
  text-decoration: none;
}

.site-footer a:not(.btn):hover {
  color: var(--c-rose-light);
  text-decoration: underline;
}

.social {
  display: flex;
  gap: var(--sp-3);
  margin-top: var(--sp-6);
  padding: 0;
  list-style: none;
}

.social li + li {
  margin-top: 0;
}

.social a {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 44px;
  height: 44px;
  border: 1px solid rgba(243, 241, 236, 0.28);
  border-radius: 50%;
  transition: background-color var(--dur) var(--ease),
    border-color var(--dur) var(--ease);
}

.social a:hover {
  background-color: var(--c-rose);
  border-color: var(--c-rose);
}

.social svg {
  width: 18px;
  height: 18px;
  fill: currentcolor;
}

.site-footer__bottom {
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-3) var(--sp-5);
  align-items: center;
  justify-content: space-between;
  margin-top: var(--sp-8);
  padding-top: var(--sp-5);
  border-top: 1px solid rgba(243, 241, 236, 0.16);
  font-size: var(--fs-xs);
}

/* The copyright and both legal links stay on one line from 40em up. The
   three items need about 461px and the container clears that at roughly
   507px, so 40em leaves headroom. Below it they wrap, which is correct. */
.site-footer__bottom > p,
.site-footer__legal a {
  white-space: nowrap;
}

@media (min-width: 40em) {
  .site-footer__bottom,
  .site-footer__legal {
    flex-wrap: nowrap;
  }
}

/* --------------------------------------------------------------------------
   21. Sticky mobile call bar
   -------------------------------------------------------------------------- */

.callbar {
  position: fixed;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 95;
  display: grid;
  grid-template-columns: 1fr 1fr;
  border-top: 1px solid rgba(243, 241, 236, 0.18);
  transform: translateY(0);
  transition: transform 300ms var(--ease);
}

/* Tucked away while the hero is on screen. The hero has its own Book button
   directly above it, so the bar is duplication there, and it was covering
   62px of the most important screen on the site. JavaScript releases it once
   the hero scrolls away. */
.callbar.is-tucked {
  transform: translateY(100%);
}

/* No safe-area inset here, deliberately. env(safe-area-inset-bottom) reads
   0 while the browser toolbar is on screen and jumps to about 34px the
   moment it auto-hides on scroll. On the container that produced a
   transparent strip with the page showing through it; on the links it made
   the bar grow taller mid-scroll. The bar sits inside browser chrome rather
   than fullscreen, so there is no home indicator to clear. */
.callbar a {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--sp-2);
  min-height: var(--callbar-h);
  padding: var(--sp-3);
  font-size: var(--fs-xs);
  font-weight: 500;
  letter-spacing: var(--ls-caps);
  text-decoration: none;
  text-transform: uppercase;
}

.callbar__call {
  background-color: var(--c-ink);
  color: var(--c-bone);
}

.callbar__call:hover {
  background-color: #000000;
  color: var(--c-bone);
}

.callbar__book {
  background-color: var(--c-rose);
  color: var(--c-bone);
}

.callbar__book:hover {
  background-color: var(--c-rose-deep);
  color: var(--c-bone);
}

.callbar svg {
  width: 16px;
  height: 16px;
  fill: none;
  stroke: currentcolor;
  stroke-width: 1.75;
}

body {
  padding-bottom: var(--callbar-h);
}

@media (min-width: 64em) {
  .callbar {
    display: none;
  }

  body {
    padding-bottom: 0;
  }
}

/* --------------------------------------------------------------------------
   22. Motion
   -------------------------------------------------------------------------- */

.reveal {
  opacity: 0;
  transform: translateY(18px);
  transition: opacity var(--dur-slow) var(--ease),
    transform var(--dur-slow) var(--ease);
}

.reveal.is-visible {
  opacity: 1;
  transform: none;
}

.reveal--delay-1 { transition-delay: 120ms; }
.reveal--delay-2 { transition-delay: 240ms; }

@media (prefers-reduced-motion: reduce) {
  html {
    scroll-behavior: auto;
  }

  *,
  *::before,
  *::after {
    animation-duration: 0.01ms !important;
    animation-delay: 0ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    transition-delay: 0ms !important;
    scroll-behavior: auto !important;
  }

  .reveal {
    opacity: 1;
    transform: none;
  }

  .site-nav,
  .site-nav__list li,
  .site-nav__foot {
    transform: none;
  }

  .gallery-item:hover img,
  .btn:hover {
    transform: none;
  }
}

/* --------------------------------------------------------------------------
   23. Print
   -------------------------------------------------------------------------- */

@media print {
  .site-header,
  .site-nav,
  .callbar,
  .btn,
  .gallery-filter {
    display: none !important;
  }

  body,
  .page {
    padding: 0;
    background: #ffffff;
    color: #000000;
  }
}
