/* ============================================================================
   HAIR BY CHRISSY — editorial luxury minimal
   Built to CLAUDE.md. Palette resampled from her Instagram profile mark, as
   that file instructs: token ROLES are the spec's, the VALUES are hers.

     spec            resampled from the logo
     --espresso      #2E1A12  ->  #33261c
     --espresso-70   #4A3226  ->  #6b5646
     --clay          #C98A7E  ->  #a98744   (her accent is gold, not rose)
     --cream         #FAF7F4  ->  #f7f2ea

   Rules held: one accent only, never on body copy and never on a button.
   Backgrounds alternate paper/cream, no dark sections (the footer legal bar is
   the single espresso band the spec allows). No gradients as fills, no shadows
   on UI — the photography carries the depth.
   ========================================================================= */

:root {
  --espresso:     #33261c;
  --espresso-70:  #6b5646;
  --clay:         #a98744;   /* accent: numerals, connector lines, markers */
  --clay-deep:    #856a36;   /* the same accent where it must clear 4.5:1 */
  --cream:        #f7f2ea;
  --paper:        #ffffff;
  --taupe:        #b99a7b;   /* her logo ground — imagery tint only */
  --hairline:     rgba(51, 38, 28, 0.22);
  --hairline-soft:rgba(51, 38, 28, 0.10);

  --ok:      #3a5f31;
  --warn:    #735214;
  --danger:  #913b32;

  --wordmark: 'Cormorant Garamond', 'Times New Roman', Times, serif;
  --sans: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif;
  /* The display face is the serif. Inter sets the interface and the body and
     nothing else — a premium beauty page cannot lead on the same grotesque
     every SaaS dashboard leads on. */
  --display-face: var(--wordmark);

  /* ------------------------------------------------------ type scale
     One scale, ratio 1.25 (major third) from a 16px base, and nothing off
     it. Before this there were seventeen sizes on the client site and
     sixteen more on the dashboard, rem and px mixed, with 0.8125 / 0.85 /
     0.875 all in play and none of them meaning anything different.

     The floor is 12.8px rather than a step lower: below that is unreadable
     on a phone, and nine in ten of her clients are on one. Anything that
     used to be 10px or 11px comes up to it.

     Fluid sizes clamp between two steps of this same scale, so even at an
     arbitrary viewport the ends land on the scale. */
  --t-xs:   0.8rem;      /* 12.8px — uppercase labels, pills, legal      */
  --t-sm:   1rem;        /* 16px   — body, inputs (the iOS-zoom floor)   */
  --t-md:   1.25rem;     /* 20px   — lede                                */
  --t-lg:   1.5625rem;   /* 25px   — card and step headings              */
  --t-xl:   1.953rem;    /* 31px   — sub-heads                           */
  --t-2xl:  2.441rem;    /* 39px   — section headings                    */
  --t-3xl:  3.815rem;    /* 61px   — page headings                       */
  --t-4xl:  5.96rem;     /* 95px   — the hero, and nothing else          */

  /* Line height is a property of the role, not of each rule. */
  --lh-display: 1.04;
  --lh-snug:    1.24;
  --lh-body:    1.65;

  /* Tracking. Large serif needs negative; small uppercase needs a lot. */
  --ls-display: -0.015em;
  --ls-heading: -0.005em;
  --ls-body:    0em;
  --ls-label:   0.14em;   /* small uppercase                       */
  --ls-caps:    0.08em;   /* uppercase at body size and above      */

  --shell: 1440px;
  --gutter: clamp(20px, 5vw, 72px);
  --header-h: 72px;

  /* ---------------------------------------------------- vertical rhythm
     Whitespace is the primary device, so it gets a scale of its own rather
     than a number typed into each style attribute. There were fifteen
     different hand-written margins in index.html alone — 10, 16, 18, 24, 28,
     32, 40, 48 and four separate hand-rolled clamps — which is not a rhythm,
     it is an absence of one.

     Steps are on an 8px grid. Everything vertical uses one of them. */
  --s-1: 0.5rem;    /*  8px */
  --s-2: 1rem;      /* 16px */
  --s-3: 1.5rem;    /* 24px */
  --s-4: 2rem;      /* 32px */
  --s-5: 3rem;      /* 48px */
  --s-6: 4.5rem;    /* 72px */

  /* Fluid steps, for the gaps that must open up on a large screen and close
     to something sane on a phone. */
  --band: clamp(112px, 20vh, 208px);          /* between sections          */
  --band-tight: clamp(72px, 12vh, 128px);     /* inside utility pages      */
  --stack: clamp(2.5rem, 6vh, 4.5rem);        /* section head to content   */
  --stack-lg: clamp(4rem, 9vh, 7rem);         /* between blocks in a band  */
}

:root, :root[data-theme='light'], :root[data-theme='dark'] { color-scheme: light; }

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

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
  -webkit-tap-highlight-color: rgba(169, 135, 68, 0.14);
}

body {
  margin: 0;
  background: var(--paper);
  color: var(--espresso-70);
  font-family: var(--sans);
  font-weight: 400;
  font-size: var(--t-sm);
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
  overflow-x: hidden;
}

img { max-width: 100%; display: block; }
[hidden] { display: none !important; }

button, a, label, summary, [role='tab'] { touch-action: manipulation; }

/* Focus is visible because the design is minimal, not despite it. */
:focus-visible {
  outline: 2px solid var(--clay-deep);
  outline-offset: 3px;
}

/* Sticky header must never sit over a heading it scrolled to. */
[id] { scroll-margin-top: calc(var(--header-h) + 24px); }

/* --------------------------------------------------------------- type */

h1, h2, h3, h4 { margin: 0; color: var(--espresso); font-weight: 500; }

/* Role 1 — wordmark. Logo only. */
.wordmark {
  font-family: var(--wordmark);
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: var(--ls-caps);
  color: var(--espresso);
  line-height: 1;
}

/* Role 2 — display headings, set in the serif at its lightest weight.
   Uppercase Inter read as a software product, not as her studio. */
.display, .display-sm {
  font-family: var(--display-face);
  font-weight: 300;
  text-transform: uppercase;
  color: var(--espresso);
  line-height: var(--lh-display);
  letter-spacing: var(--ls-display);
  /* Serif caps at this size sit better with the ascenders trimmed. */
  text-wrap: balance;
}
.display    { font-size: clamp(var(--t-2xl), 11vw, var(--t-4xl)); }
.display-sm { font-size: clamp(var(--t-xl), 6vw, var(--t-2xl)); letter-spacing: var(--ls-heading); }

/* Role 3 — body. Measure capped so lines stay readable. */
p {
  margin: 0 0 1.1em;
  max-width: 42ch;
  font-size: var(--t-sm);
  line-height: var(--lh-body);
  letter-spacing: var(--ls-body);
}
p:last-child { margin-bottom: 0; }
.lede {
  font-size: var(--t-md);
  line-height: 1.5;
  letter-spacing: var(--ls-heading);
  color: var(--espresso-70);
  max-width: 38ch;
}

/* Role 4 — the label. Small, uppercase, heavily tracked; the only thing on
   the page allowed below body size. */
.label {
  display: inline-flex;
  align-items: center;
  gap: 0.7em;
  font-family: var(--sans);
  font-size: var(--t-xs);
  font-weight: 500;
  letter-spacing: var(--ls-label);
  line-height: 1.3;
  text-transform: uppercase;
  color: var(--espresso);
}
.label::before {
  content: '';
  width: 5px; height: 5px;
  border-radius: 50%;
  background: var(--clay);
  flex: none;
}
.label-plain::before { display: none; }

.muted { color: var(--espresso-70); }
.small { font-size: var(--t-xs); line-height: 1.5; }

a { color: inherit; text-decoration: none; }

/* Oversized numerals as layout anchors — thin, clay, never decoration.
   In the serif now, with the rest of the display role. */
.numeral {
  font-family: var(--display-face);
  font-weight: 300;
  font-size: clamp(var(--t-3xl), 11vw, var(--t-4xl));
  line-height: 0.82;
  color: var(--clay);
  letter-spacing: var(--ls-display);
}

/* ------------------------------------------------------------- layout */

.shell { max-width: var(--shell); margin: 0 auto; padding-left: max(var(--gutter), env(safe-area-inset-left)); padding-right: max(var(--gutter), env(safe-area-inset-right)); }

.band { padding: var(--band) 0; background: var(--paper); }
.band-cream { background: var(--cream); }
.band-tight { padding: var(--band-tight) 0; }

.rule { height: 1px; background: var(--hairline-soft); border: 0; margin: 0; }

/* Asymmetric split — visual one side, offset text the other. Alternates. */
.split {
  display: grid;
  grid-template-columns: 1.05fr 0.95fr;
  gap: var(--stack-lg) clamp(32px, 6vw, 96px);
  align-items: center;
}
.split-flip > .split-visual { order: 2; }
.split-text { max-width: 46ch; }
.split-text .label { margin-bottom: var(--s-3); }
.split-text .display-sm { margin-bottom: var(--s-3); }

.section-head { margin-bottom: var(--stack); }
.section-head .label { margin-bottom: var(--s-3); }
.section-head .display { margin-bottom: var(--s-3); }

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

/* ------------------------------------------------------------ buttons */
/* Never clay. Espresso or outline only. */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: 48px;
  padding: 14px 30px;
  border: 1px solid var(--espresso);
  border-radius: 0;
  background: var(--espresso);
  color: var(--paper);
  font-family: var(--sans);
  font-size: var(--t-xs);
  font-weight: 500;
  letter-spacing: var(--ls-label);
  text-transform: uppercase;
  cursor: pointer;
  transition: background 200ms ease, color 200ms ease;
}
.btn-outline { background: transparent; color: var(--espresso); }
.btn-light { background: var(--paper); color: var(--espresso); border-color: var(--paper); }
.btn-sm { min-height: 44px; padding: 10px 20px; font-size: var(--t-xs); }
.btn[disabled], .btn[aria-disabled='true'] { opacity: 0.35; pointer-events: none; }

/* ------------------------------------------------------------ the CTA
   One action on this site: book a slot. It wears the same words and the same
   treatment everywhere it appears, so a client who has scrolled past it four
   times recognises it on the fifth rather than reading it again.

   The clay rule under it is the accent doing what the accent is for —
   marking the one thing that matters, never decorating a button face. */
.btn-cta { position: relative; }
.btn-cta::after {
  content: '';
  position: absolute; left: 0; right: 0; bottom: -1px;
  height: 2px; background: var(--clay);
  transform: scaleX(0); transform-origin: left;
  transition: transform 240ms ease;
}

.cta-repeat {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--s-3) var(--s-4);
  margin-top: var(--stack-lg);
  padding-top: clamp(28px, 4vh, 44px);
  border-top: 1px solid var(--hairline-soft);
}
.cta-note {
  font-size: var(--t-xs);
  letter-spacing: var(--ls-caps);
  color: var(--espresso-70);
  max-width: 32ch;
}

/* In the header it sits at nav weight but keeps the button's shape, so the
   one action is always on screen without shouting over the wordmark. */
.nav-cta { padding: 8px 18px; min-height: 40px; }

/* The hero's second link is a link, not a button. Two buttons side by side
   are two calls to action, and the brief allows one. */
.hero-secondary {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  font-size: var(--t-xs);
  letter-spacing: var(--ls-label);
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.86);
  border-bottom: 1px solid rgba(255, 255, 255, 0.4);
  transition: color 200ms ease, border-color 200ms ease;
}

.link-underline {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  font-size: var(--t-xs);
  letter-spacing: var(--ls-label);
  text-transform: uppercase;
  color: var(--espresso);
  border-bottom: 1px solid var(--hairline);
  padding-bottom: 2px;
}

@media (hover: hover) and (pointer: fine) {
  .btn:hover { background: var(--espresso-70); border-color: var(--espresso-70); color: var(--paper); }
  .btn-outline:hover { background: var(--espresso); color: var(--paper); }
  .btn-light:hover { background: var(--cream); border-color: var(--cream); }
  .link-underline:hover { border-bottom-color: var(--espresso); }
}

/* ------------------------------------------------------------- header */

.site-header {
  position: sticky;
  top: 0;
  z-index: 80;
  background: var(--paper);
  border-bottom: 1px solid var(--hairline-soft);
}
/**
 * The wordmark is centred against the PAGE, not against a grid column.
 *
 * A three-column grid only centres the middle column while the outer two stay
 * equal — and they do not: at 1024px the five nav links outgrew their share and
 * shoved the wordmark 41px right. Absolute centring is immune to whatever the
 * nav happens to weigh.
 */
.site-header .shell {
  height: var(--header-h);
  position: relative;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
}
.nav-left, .nav-right { display: flex; align-items: center; gap: clamp(16px, 2.4vw, 32px); }
/* The gap belongs on the nav itself, or the links run into one another. */
.site-header nav { display: flex; align-items: center; gap: clamp(14px, 2vw, 28px); }
.nav-right { justify-content: flex-end; }
/* Nav links, but not the CTA — it is a button that happens to live in the
   nav, and this rule out-specifies .btn. Left unexcluded it painted
   espresso-70 text onto the button's espresso ground: 2.12:1, caught by the
   contrast audit. The same specificity trap hid the nav links behind the
   wordmark once already. */
.site-header nav a:not(.btn),
.site-header .nav-right a:not(.btn) {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  font-size: var(--t-xs);
  letter-spacing: var(--ls-label);
  text-transform: uppercase;
  color: var(--espresso-70);
}
.site-header .brand {
  position: absolute;
  left: 50%;
  transform: translateX(-50%);
  display: inline-flex;
  align-items: center;
  gap: 12px;
  font-size: clamp(var(--t-sm), 1.6vw, var(--t-md));
  white-space: nowrap;
  /* Never allowed to run into the nav on either side. */
  max-width: calc(100% - 200px);
  overflow: hidden;
}
.brand-mark {
  width: 40px; height: 40px;
  border-radius: 50%;
  flex: none;
  /* A hairline ring keeps the circular mark from floating on the white ground. */
  box-shadow: 0 0 0 1px var(--hairline-soft);
}
/* Drawn, not typed. The menu control was the character U+2630, which is a
   glyph from whatever font happens to be installed — it rendered at a
   different weight and baseline on every platform and had nothing to do with
   the hairlines everywhere else on the page. Two rules and a pseudo-element
   give the same mark in the same stroke as the rest of the design. */
.nav-toggle {
  position: relative;
  display: none;
  width: 44px; height: 44px;
  align-items: center; justify-content: center;
  background: none; border: 0; cursor: pointer; padding: 0;
  color: var(--espresso);
}
.nav-toggle .bars,
.nav-toggle .bars::before,
.nav-toggle .bars::after {
  display: block;
  width: 22px; height: 1px;
  background: currentColor;
  transition: transform 240ms ease, opacity 240ms ease;
}
.nav-toggle .bars::before,
.nav-toggle .bars::after { content: ''; position: absolute; left: 50%; margin-left: -11px; }
.nav-toggle .bars::before { transform: translateY(-7px); }
.nav-toggle .bars::after  { transform: translateY(7px); }

/* Open: the outer strokes cross and the middle one goes. */
.nav-toggle[aria-expanded='true'] .bars { background: transparent; }
.nav-toggle[aria-expanded='true'] .bars::before { transform: rotate(45deg); }
.nav-toggle[aria-expanded='true'] .bars::after  { transform: rotate(-45deg); }

@media (hover: hover) and (pointer: fine) {
  .site-header nav a:not(.btn):hover,
  .site-header .nav-right a:not(.btn):hover { color: var(--espresso); }
}

/* --------------------------------------------------------------- hero */

.hero {
  position: relative;
  min-height: calc(100vh - var(--header-h));
  min-height: calc(100dvh - var(--header-h));
  display: flex;
  align-items: flex-end;
  /* Padding measured against the window, not a fixed floor. At 320px of
     viewport height the old values spent 120px — 37% of the screen — on
     nothing. */
  padding: clamp(28px, 8vh, 128px) 0 clamp(24px, 7vh, 104px);
  /* The imagery band's own ground. Cream here would leave the white hero type
     unreadable in the moment before a photograph loads, or if one is missing —
     "use a scrim, not hope" applies to the fallback as well as the photo. */
  background: #2a1f16;
  overflow: hidden;
}
.hero-media { position: absolute; inset: 0; z-index: 0; }
.hero-media img, .hero-media video { width: 100%; height: 100%; object-fit: cover; object-position: center 28%; }
/* The video is a vertical reel; on a wide screen it crops to the subject
   rather than letterboxing. */
@media (min-width: 861px) { .hero-media video { object-position: center 22%; } }
/* A scrim, not hope — the spec's words. */
.hero-media::after {
  content: '';
  position: absolute; inset: 0;
  /* Weighted to the band the type actually occupies. Measured against the
     lightest pixel of the photograph behind each element, not eyeballed —
     see tools/scrim-audit.js. */
  background: linear-gradient(
    to top,
    rgba(35, 25, 17, 0.90) 0%,
    rgba(35, 25, 17, 0.78) 30%,
    rgba(35, 25, 17, 0.68) 55%,
    rgba(35, 25, 17, 0.52) 78%,
    rgba(35, 25, 17, 0.38) 100%
  );
}
.hero .shell { position: relative; z-index: 1; width: 100%; }

/*
 * The hero has to fit in one window, because the CTA inside it is the only
 * thing this page is for.
 *
 * The heading was sized from viewport WIDTH alone — clamp(…, 11vw, …) — and a
 * landscape tablet has width to spare and very little height. So the type
 * grew to its 95px cap and stayed there while the window got shorter, and the
 * whole stack stayed ~680px tall: on anything under about 700px of viewport
 * height the "Book your slot" button started below the fold. Sizing on the
 * tighter of the two axes is the fix; tools/hero-audit.js holds it.
 */
.hero .display { font-size: clamp(var(--t-2xl), min(10vw, 11.5vh), var(--t-4xl)); }
.hero .lede { font-size: clamp(var(--t-sm), 2.4vh, var(--t-md)); }

/*
 * A phone held sideways: ~850px of width and ~320px of height. Stacking
 * label, heading, lede and button down that is hopeless — the button ends up
 * 350px below the fold — and the usual answers (shrink everything, or hide
 * the lede) either make it unreadable or throw away the copy.
 *
 * So use the axis that has room. The heading takes a tall left column and the
 * lede and the CTA sit beside it, which is the same editorial split used
 * further down the page and reads deliberately rather than squeezed.
 */
@media (orientation: landscape) and (max-height: 560px) {
  .hero .shell {
    display: grid;
    grid-template-columns: 1.15fr 0.85fr;
    column-gap: clamp(24px, 4vw, 64px);
    align-items: end;
  }
  .hero .label   { grid-area: 1 / 1 / 2 / 2; }
  .hero .display { grid-area: 2 / 1 / 4 / 2; margin: var(--s-1) 0 0; }
  .hero .lede    { grid-area: 2 / 2 / 3 / 3; margin-bottom: var(--s-2); max-width: 34ch; }
  .hero-actions  { grid-area: 3 / 2 / 4 / 3; }
  .hero .display { font-size: clamp(var(--t-xl), 11.5vh, var(--t-3xl)); }
  /* At 330px of window the padding is the difference between fitting and
     not, so it comes off the scale here and is measured instead. */
  .hero { padding: clamp(20px, 5vh, 48px) 0 clamp(18px, 5vh, 48px); }
  /* The right column is not wide enough to hold the button and the secondary
     link on one line, so the link wrapped under it and off the bottom of the
     screen. It goes here: it points at the price list, and "Services" is in
     the menu two centimetres above it. The one action stays. */
  .hero-secondary { display: none; }
}
.hero .label, .hero .display, .hero .lede { color: var(--paper); }
.hero .label::before { background: var(--paper); }
.hero .display { margin: 18px 0 22px; }
.hero .lede { color: rgba(255, 255, 255, 0.92); margin-bottom: var(--s-4); }
.hero-actions { display: flex; flex-wrap: wrap; align-items: center; gap: var(--s-2) var(--s-4); }

/* The frame before a photograph loads into it.
   This used to fake one — two radial gradients over her logo's taupe, doing
   an impression of a soft-lit portrait. A pretend photograph is worse than an
   honest empty frame: it reads as a stock image, and every real photograph
   that replaced one looked like a downgrade for the first half second. Now it
   is a flat tint with a hairline, which is plainly a frame waiting to be
   filled. */
.media-placeholder {
  background-color: var(--cream);
  box-shadow: inset 0 0 0 1px var(--hairline-soft);
}

/* ------------------------------------------------------- service grid */

.grid-services {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: var(--s-5) clamp(16px, 2vw, 28px);
}
.card {
  position: relative;
  display: flex;
  flex-direction: column;
  background: none;
  border: 0;
  padding: 0;
  text-align: left;
  font: inherit;
  color: inherit;
  cursor: pointer;
}
.card-media {
  position: relative;
  display: block;
  aspect-ratio: 4 / 5;
  overflow: hidden;
  /* Sizing only — no background-color. .media-placeholder is declared earlier
     in the file, so a colour here would win and blank its texture out. These
     two properties are what make an inline background-image actually fill the
     box; without them it renders at natural size from the top-left corner. */
  background-size: cover;
  background-position: center 32%;
  background-repeat: no-repeat;
}
/* The media fills the frame; the SELECT bar is not media and must not be
   stretched to the frame's height along with it. */
.card-media > :not(.card-select) { width: 100%; height: 100%; }
/* Hover reveals a full-width SELECT bar over the image bottom. */
.card-select {
  position: absolute;
  left: 0; right: 0; bottom: 0;
  padding: 14px;
  background: var(--espresso);
  color: var(--paper);
  font-size: var(--t-xs);
  letter-spacing: var(--ls-label);
  text-transform: uppercase;
  text-align: center;
  transform: translateY(100%);
  transition: transform 220ms ease;
}
.card-body { padding-top: var(--s-2); display: flex; justify-content: space-between; gap: 12px; align-items: baseline; }
.card-name { font-size: var(--t-xs); letter-spacing: var(--ls-caps); text-transform: uppercase; color: var(--espresso); }
.card-price { font-size: var(--t-sm); color: var(--espresso-70); white-space: nowrap; }
.card[aria-pressed='true'] .card-select { transform: translateY(0); }
.card[aria-pressed='true'] .card-name { border-bottom: 1px solid var(--clay); }

@media (hover: hover) and (pointer: fine) {
  .card:hover .card-select { transform: translateY(0); }
}
.card:focus-visible .card-select { transform: translateY(0); }

/* ------------------------------------------------------------ process */

.process { display: grid; grid-template-columns: repeat(3, 1fr); gap: var(--stack) clamp(24px, 4vw, 64px); }
.step .numeral { display: block; margin-bottom: var(--s-3); }
.step h3 { font-size: var(--t-sm); letter-spacing: var(--ls-label); text-transform: uppercase; margin-bottom: var(--s-2); }
/* Connector line in clay, as a marker — not decoration. */
.step { position: relative; padding-top: 26px; border-top: 1px solid var(--hairline-soft); }
.step::before { content: ''; position: absolute; top: -1px; left: 0; width: 42px; height: 1px; background: var(--clay); }

/* ----------------------------------------------------------- benefits */
/* Two by two, so four short reasons read as a set rather than a list. The
   numerals are deliberately absent — they are already doing work twice on
   this page, and a fourth run would make them wallpaper. */

/* ------------------------------------------------- maintenance essentials */
/*
 * Replaces the poster she sent. A framed card, because that content was a
 * framed card on her graphic and it reads as a reference panel beside the
 * prose — not as more prose. Hairline and paper on the cream band, so it lifts
 * without needing a shadow, which the system does not use.
 */
.care {
  border: 1px solid var(--hairline);
  background: var(--paper);
  padding: clamp(24px, 3.5vw, 40px);
}
.care-intro {
  color: var(--espresso-70);
  margin-bottom: var(--s-4);
  padding-bottom: var(--s-4);
  border-bottom: 1px solid var(--hairline-soft);
}
.care-list { list-style: none; margin: 0; padding: 0; }
.care-item {
  display: grid;
  grid-template-columns: 28px minmax(0, 1fr);
  gap: var(--s-3);
  align-items: start;
}
.care-item + .care-item {
  margin-top: var(--s-4);
  padding-top: var(--s-4);
  border-top: 1px solid var(--hairline-soft);
}
/* The one place clay appears here — as a marker, never on the copy. */
.care-mark { color: var(--clay); flex: none; margin-top: 2px; }
.care-item h3 {
  font-size: var(--t-xs);
  letter-spacing: var(--ls-label);
  text-transform: uppercase;
  margin-bottom: var(--s-1);
}
.care-item p { color: var(--espresso-70); font-size: var(--t-sm); }

.benefits { display: grid; grid-template-columns: repeat(2, 1fr); gap: var(--stack) clamp(32px, 5vw, 96px); }
.benefit { position: relative; padding-top: 26px; border-top: 1px solid var(--hairline-soft); }
.benefit::before { content: ''; position: absolute; top: -1px; left: 0; width: 42px; height: 1px; background: var(--clay); }
.benefit h3 { font-size: var(--t-sm); letter-spacing: var(--ls-label); text-transform: uppercase; margin-bottom: var(--s-2); }
.benefit p { color: var(--espresso-70); max-width: 44ch; }

/* ------------------------------------------------------------ reviews */

.reviews { display: grid; grid-template-columns: repeat(3, 1fr); gap: var(--stack) clamp(24px, 4vw, 56px); }
.review p { font-size: var(--t-md); color: var(--espresso); }
.review footer { margin-top: var(--s-3); font-size: var(--t-xs); letter-spacing: var(--ls-caps); text-transform: uppercase; color: var(--espresso-70); }
.review .mark { color: var(--clay); font-size: var(--t-lg); line-height: 1; display: block; margin-bottom: var(--s-2); }

/* ---------------------------------------------------------------- FAQ */

.faq details { border-bottom: 1px solid var(--hairline-soft); }
.faq summary {
  list-style: none; cursor: pointer;
  min-height: 64px;
  display: flex; align-items: center; justify-content: space-between; gap: 24px;
  font-size: var(--t-sm); letter-spacing: var(--ls-caps); text-transform: uppercase; color: var(--espresso);
}
.faq summary::-webkit-details-marker { display: none; }
.faq summary::after { content: '+'; color: var(--clay); font-size: var(--t-md); font-weight: 300; }
.faq details[open] summary::after { content: '–'; }
.faq .answer { padding: 0 0 28px; }

/* ------------------------------------------------------------- forms */

.field { margin-bottom: var(--s-3); }
.field label { display: block; margin-bottom: var(--s-1); font-size: var(--t-xs); letter-spacing: var(--ls-label); text-transform: uppercase; color: var(--espresso); }
.input, .textarea, .select {
  width: 100%;
  min-height: 52px;
  padding: 14px 16px;
  background: var(--paper);
  border: 1px solid var(--hairline);
  border-radius: 0;
  color: var(--espresso);
  font-family: var(--sans);
  font-size: var(--t-sm);
}
.band-cream .input, .band-cream .textarea, .band-cream .select { background: var(--paper); }
.textarea { min-height: 104px; resize: vertical; }
.input:focus, .textarea:focus, .select:focus { outline: none; border-color: var(--espresso); }
.field .hint { margin-top: var(--s-1); font-size: var(--t-xs); color: var(--espresso-70); }

.notice {
  border: 1px solid var(--hairline);
  border-left: 2px solid var(--clay);
  background: var(--paper);
  padding: 18px 20px;
  font-size: var(--t-sm);
  color: var(--espresso-70);
}
.notice p { max-width: none; }
.notice-error { border-left-color: var(--danger); }
.notice-ok { border-left-color: var(--ok); }
.notice-warn { border-left-color: var(--warn); }

.empty {
  padding: 40px 24px;
  border: 1px dashed var(--hairline);
  text-align: center;
  color: var(--espresso-70);
  font-size: var(--t-xs);
  letter-spacing: var(--ls-caps);
}

/* --------------------------------------------------- booking page bits */

/* What you just picked, confirmed back to you before you commit to a day. */
.svc-preview {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: var(--s-1) var(--s-3);
  margin-top: var(--s-3);
  padding-top: var(--s-3);
  border-top: 1px solid var(--hairline-soft);
}
.svc-preview-name {
  font-size: var(--t-xs);
  letter-spacing: var(--ls-label);
  text-transform: uppercase;
  color: var(--espresso);
}
.svc-preview-meta { font-size: var(--t-xs); color: var(--espresso-70); }

/* The photo picker. The native control is hidden and the label is the target,
   because a file input cannot be styled and its default reads as a form from
   1998 sitting in the middle of an otherwise considered page. */
.filedrop {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--s-1);
  padding: var(--s-4);
  border: 1px dashed var(--hairline);
  cursor: pointer;
  transition: border-color 200ms ease, background 200ms ease;
}
.filedrop input[type='file'] { position: absolute; width: 1px; height: 1px; opacity: 0; pointer-events: none; }
.filedrop-mark { width: 22px; height: 1px; background: var(--clay); }
.filedrop-text {
  font-size: var(--t-xs);
  letter-spacing: var(--ls-label);
  text-transform: uppercase;
  color: var(--espresso);
}
.filedrop-hint { font-size: var(--t-xs); color: var(--espresso-70); }
.filedrop:focus-within { outline: 2px solid var(--clay-deep); outline-offset: 3px; }

.thumbs { display: flex; flex-wrap: wrap; gap: var(--s-2); margin-top: var(--s-2); }
.thumbs:empty { margin-top: 0; }
.thumb { position: relative; margin: 0; width: 84px; height: 84px; }
.thumb img { width: 100%; height: 100%; object-fit: cover; }
/*
 * The button is 44x44 and invisible; the small chip inside it is what you see.
 * Removing a photo you picked by mistake is a one-handed, thumb-on-glass tap,
 * so the target has to be a thumb's width even though a 44px mark would sit
 * heavily on an 84px thumbnail.
 */
.thumb-x {
  position: absolute; top: -16px; right: -16px;
  width: 44px; height: 44px;
  display: grid; place-items: center;
  border: 0; padding: 0; background: none;
  color: var(--espresso);
  cursor: pointer;
}
.thumb-x span {
  display: grid; place-items: center;
  width: 30px; height: 30px;
  border: 1px solid var(--hairline);
  background: var(--paper);
  font-size: var(--t-sm);
  line-height: 1;
  transition: background var(--ease-dur) var(--ease), border-color var(--ease-dur) var(--ease);
}

/* -------------------------------------------------------------- motion */
/*
 * Two jobs only: bring a section in as it is reached, and answer a pointer.
 *
 * Everything runs 200-300ms on a plain ease. Nothing overshoots, nothing
 * springs back, nothing loops — an infinite animation on a page about hair is
 * a thing that moves in the corner of the eye while somebody is trying to
 * read a price list. (There was one: a 26s drifting blob that no page had
 * referenced since the rebuild. Deleted rather than kept running.)
 *
 * The reveal used to take 600ms, which is long enough to notice as an effect
 * rather than register as the page settling.
 */

.reveal { opacity: 0; transform: translateY(14px); }
.reveal.in {
  opacity: 1;
  transform: none;
  transition: opacity 280ms ease-out, transform 280ms ease-out;
}

/* ---- hover, on devices that actually have a pointer.
   Guarded, because on a touch screen :hover sticks after a tap and leaves an
   element looking permanently pressed. */

@media (hover: hover) and (pointer: fine) {
  /* The one action. Fills from the accent rule upward. */
  .btn:hover { background: var(--espresso-70); border-color: var(--espresso-70); }
  .btn-outline:hover { background: var(--espresso); color: var(--paper); border-color: var(--espresso); }
  .btn-light:hover { background: var(--cream); border-color: var(--cream); color: var(--espresso); }
  .btn-cta:hover::after { transform: scaleX(1); }

  .hero-secondary:hover { color: var(--paper); border-bottom-color: var(--paper); }

  /* Links underline from the left rather than blinking a colour. */
  .link-underline { position: relative; }
  .link-underline::after {
    content: '';
    position: absolute; left: 0; right: 0; bottom: -1px;
    height: 1px; background: var(--clay);
    transform: scaleX(0); transform-origin: left;
    transition: transform 220ms ease;
  }
  .link-underline:hover::after { transform: scaleX(1); }

  /* A service card lifts its image very slightly and brings the SELECT bar
     up. One millimetre, not a jump. */
  .card:hover .card-media { transform: scale(1.02); }
  .card .card-media { transition: transform 300ms ease; }

  /* Portfolio figures and before/after halves answer the same way. */
  #folioGrid figure:hover .card-media,
  .ba-side:hover .card-media { transform: scale(1.02); }

  /* Rows that are clickable say so with the accent, not with a fill. */
  .faq summary:hover { color: var(--clay-deep); }
  .slot:not([disabled]):hover { border-color: var(--espresso); }

  .site-footer a:hover { color: var(--espresso); }
  .filedrop:hover { border-color: var(--clay); background: var(--cream); }
  .thumb-x:hover span { border-color: var(--danger); color: var(--danger); }
}

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  .reveal { transform: none; }
  .reveal.in { transition: opacity 200ms linear; transform: none; }
  * { transition-duration: 0.01ms !important; animation-duration: 0.01ms !important; animation-iteration-count: 1 !important; }
}

/* Utility-page header links are tap targets like any other. They measured
   17px tall — the height of the text and nothing else. */
.topnav .wordmark,
.topnav .navlinks a { display: inline-flex; align-items: center; min-height: 44px; }

/* -------------------------------------------------------------- footer */

.site-footer { background: var(--cream); padding: var(--band-tight) 0 0; }
.footer-top { display: grid; grid-template-columns: 1fr auto; gap: clamp(32px, 6vw, 80px); align-items: start; }
.footer-lockup { display: flex; align-items: flex-end; gap: var(--s-3); }
.footer-lockup .rotated {
  writing-mode: vertical-rl;
  transform: rotate(180deg);
  font-family: var(--wordmark);
  text-transform: uppercase;
  letter-spacing: var(--ls-label);
  font-size: var(--t-xs);
  color: var(--espresso-70);
}
.footer-lockup .giant {
  font-family: var(--display-face);
  font-weight: 300;
  font-size: clamp(var(--t-3xl), 13vw, var(--t-4xl));
  line-height: var(--lh-display);
  text-transform: uppercase;
  color: var(--espresso);
  letter-spacing: var(--ls-display);
}
.footer-aside { display: grid; gap: var(--s-3); justify-items: start; min-width: min(320px, 100%); }
.newsletter { display: flex; gap: 0; width: 100%; }
.newsletter .input { border-right: 0; }
.newsletter .btn { white-space: nowrap; }
.footer-links {
  margin-top: var(--stack);
  padding: 24px 0;
  border-top: 1px solid var(--hairline-soft);
  display: flex; flex-wrap: wrap; gap: clamp(16px, 3vw, 40px);
}
.footer-links a {
  display: inline-flex; align-items: center; min-height: 44px;
  font-size: var(--t-xs); letter-spacing: var(--ls-label); text-transform: uppercase; color: var(--espresso-70);
}
@media (hover: hover) and (pointer: fine) { .footer-links a:hover { color: var(--espresso); } }

/* The one espresso band the spec allows, and it closes the page. */
.legal-bar { background: var(--espresso); color: rgba(253, 247, 239, 0.86); }
.legal-bar .shell {
  padding-top: 18px;
  padding-bottom: calc(18px + env(safe-area-inset-bottom));
  display: flex; flex-wrap: wrap; gap: 12px 32px; justify-content: space-between;
  font-size: var(--t-xs); letter-spacing: var(--ls-caps);
}
.legal-bar a { color: var(--paper); }


/* ---------------------------------------------------- accessibility utils
   A 1px clip rather than left:-9999px: the offscreen technique pushes a real
   box outside the viewport, which is indistinguishable from a layout overflow
   bug and trips the mobile audit. */
.visually-hidden {
  position: absolute;
  width: 1px; height: 1px;
  margin: -1px; padding: 0;
  overflow: hidden;
  clip: rect(0 0 0 0);
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}
.skip-link {
  position: absolute;
  width: 1px; height: 1px;
  margin: -1px; padding: 0;
  overflow: hidden;
  clip-path: inset(50%);
}
.skip-link:focus {
  position: fixed;
  top: 12px; left: 12px;
  width: auto; height: auto;
  margin: 0; padding: 14px 24px;
  clip-path: none;
  overflow: visible;
  z-index: 999;
}

/* Every link a thumb has to find clears 44px, and narrow labels get enough
   width not to be a lottery. */
.site-header .brand { min-height: 44px; display: inline-flex; align-items: center; }
.footer-links a { padding: 0 4px; min-width: 44px; justify-content: center; }
.footer-aside ul a,
.legal-bar a {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
}
.footer-aside ul li { display: flex; align-items: center; min-height: 32px; }

@media (pointer: coarse), (max-width: 900px) {
  .footer-aside ul li { min-height: 44px; }
  .legal-bar .shell { gap: 4px 32px; }
}

/* --------------------------------------------------------- responsive */

@media (max-width: 1100px) {
  .grid-services { grid-template-columns: repeat(2, 1fr); }
  .process { grid-template-columns: 1fr; gap: var(--s-6); }
  .benefits { grid-template-columns: 1fr; gap: var(--s-6); }
  .reviews { grid-template-columns: 1fr; }
  .split { grid-template-columns: 1fr; }
  .split-flip > .split-visual { order: 0; }
  /*
   * ...except the maintenance card. When that column held a poster, showing it
   * first was right — a photograph introduces the section. It holds five
   * paragraphs of detail now, and detail before its own heading reads as a
   * list that fell out of the section above it.
   */
  #maintenance .split-flip > .split-visual { order: 2; }
}

@media (max-width: 1100px) {
  .site-header { position: sticky; }
  /* The outer columns must stay equal or the middle column is not the page
     centre — hiding .nav-right entirely collapsed the right column and pushed
     the wordmark off centre on every phone. */
  .site-header nav { display: none; }
  .site-header nav.open {
    display: flex;
    position: absolute; top: var(--header-h); left: 0; right: 0;
    flex-direction: column; align-items: stretch; gap: 0;
    background: var(--paper);
    border-bottom: 1px solid var(--hairline);
    padding: 8px max(var(--gutter), env(safe-area-inset-left)) max(20px, env(safe-area-inset-bottom));
    max-height: calc(100dvh - var(--header-h));
    overflow-y: auto;
    overscroll-behavior: contain;
  }
  .site-header nav.open a { min-height: 52px; border-bottom: 1px solid var(--hairline-soft); }
  .nav-toggle { display: inline-flex; }
  /* Keep the box, drop the links: the column still balances the hamburger. */
  /* Kept as an empty 44px box so the flex row stays symmetrical. */
  .nav-right { display: block; min-width: 44px; }
  /* Must match .site-header .nav-right a from the base rules, or that wins on
     specificity and the links stay visible over the wordmark. */
  /* Everything in the right-hand column goes, the CTA included. It is a
     130px button and the wordmark is centred against the page, so keeping it
     would sit on top of the wordmark — the exact failure the header audit
     exists to catch. Nothing is lost: the hero CTA is directly below the fold
     line, and "Book your slot" is the first item in the menu the hamburger
     opens.

     BOTH selectors are needed and both must carry the :not()/.btn weight of
     the base rule above. The base rule became `a:not(.btn)` so the CTA could
     keep the button's own colour; that raised its specificity above a plain
     `.nav-right a`, and this hide silently stopped applying — putting the
     Instagram link back on top of the wordmark at every width under 640px.
     The comment that used to live here warned about precisely this and I
     broke it anyway. The header audit caught it. */
  .site-header .nav-right a:not(.btn) { display: none; }
  .site-header .brand { max-width: calc(100% - 110px); }
  .brand-mark { width: 34px; height: 34px; }
  .footer-top { grid-template-columns: 1fr; }
  .footer-aside { min-width: 0; width: 100%; }
}

@media (max-width: 380px) {
  .site-header .brand { gap: 8px; font-size: var(--t-xs); }
  .brand-mark { width: 30px; height: 30px; }
}

@media (max-width: 640px) {
  .filedrop { width: 100%; }
  .thumb { width: 72px; height: 72px; }

  /* Below this the wordmark is wide enough, and the button close enough to
     it, that the two collide — measured, not guessed. Above it there is a
     clear 150px between them and the one action stays on screen. */
  .site-header .nav-right a.btn { display: none; }

  /* Two columns, not one.
     One card per row put seven 4:5 images at full bleed down a 375px screen —
     3,654px for the price list, and the same seven cards appear again inside
     the booking step, so a client scrolled past 7,300px of photographs to read
     six prices. A price list is something you scan; at one-per-screen you
     cannot compare two of them without scrolling between. Two up brings the
     grid to roughly 900px and puts four services in view at once. */
  .grid-services { grid-template-columns: repeat(2, 1fr); gap: var(--s-4) var(--s-2); }
  .card-media { aspect-ratio: 1 / 1; }
  .card-body { flex-direction: column; align-items: flex-start; gap: 2px; }
  .card-price { white-space: normal; }
  .btn { width: 100%; }
  .hero-actions .btn { width: auto; flex: 1 1 220px; }
  /* Touch: the SELECT bar cannot rely on hover, so it is always visible. */
  /* Touch has no hover, so the bar is always shown — but it stays pinned to
     the bottom of the image. position:static put it back in flow, where it
     sat on top of the photograph as a block of espresso across the top. */
  .card-select { transform: translateY(0); padding: 12px 8px; }
  .newsletter { flex-direction: column; }
  .newsletter .input { border-right: 1px solid var(--hairline); }
}

@media print {
  .site-header, .site-footer, .legal-bar, .hero, .btn { display: none !important; }
  body { background: #fff; color: #241a12; }
}

/* ==================================================== BOOKING =============
   The live calendar, kept in the same editorial register: hairlines, no fills,
   the accent used only as a marker.
   ======================================================================== */

.booking-grid { display: grid; grid-template-columns: 1fr 340px; gap: clamp(32px, 5vw, 80px); align-items: start; }

.steps { display: flex; flex-wrap: wrap; gap: clamp(16px, 3vw, 40px); border-bottom: 1px solid var(--hairline-soft); margin-bottom: clamp(28px, 5vh, 56px); }
.step-tab {
  position: relative;
  min-height: 48px;
  padding: 12px 0;
  background: none; border: 0; cursor: pointer;
  font-family: var(--sans); font-size: var(--t-xs); letter-spacing: var(--ls-label); text-transform: uppercase;
  color: var(--espresso-70);
}
.step-tab[aria-selected='true'] { color: var(--espresso); }
.step-tab[aria-selected='true']::after { content: ''; position: absolute; left: 0; right: 0; bottom: -1px; height: 1px; background: var(--clay); }
.step-tab[disabled] { opacity: 0.35; cursor: not-allowed; }

.cal-head { display: flex; align-items: center; justify-content: space-between; gap: var(--s-2); margin-bottom: var(--s-3); }
.cal-month { font-size: var(--t-sm); letter-spacing: var(--ls-label); text-transform: uppercase; color: var(--espresso); }
.cal-nav {
  width: 48px; height: 48px;
  display: inline-flex; align-items: center; justify-content: center;
  border: 1px solid var(--hairline); background: none; cursor: pointer;
  color: var(--espresso); font-size: var(--t-sm);
}
.cal-nav[disabled] { opacity: 0.3; cursor: not-allowed; }

.cal-grid { display: grid; grid-template-columns: repeat(7, 1fr); border-top: 1px solid var(--hairline-soft); border-left: 1px solid var(--hairline-soft); }
.cal-dow { padding: 10px 0; text-align: center; font-size: var(--t-xs); letter-spacing: var(--ls-label); color: var(--espresso-70); border-right: 1px solid var(--hairline-soft); border-bottom: 1px solid var(--hairline-soft); }
.cal-cell {
  min-height: 76px;
  padding: 10px;
  background: var(--paper);
  border: 0;
  border-right: 1px solid var(--hairline-soft);
  border-bottom: 1px solid var(--hairline-soft);
  font-family: var(--sans);
  display: flex; flex-direction: column; align-items: flex-start; gap: 4px;
  cursor: pointer; text-align: left;
}
.band-cream .cal-cell, .band-cream .cal-dow { background: var(--cream); }
.cal-cell .n { font-size: var(--t-sm); color: var(--espresso); }
.cal-cell .free { font-size: var(--t-xs); letter-spacing: var(--ls-caps); color: var(--clay-deep); }
.cal-cell .none { font-size: var(--t-xs); letter-spacing: var(--ls-caps); color: var(--espresso-70); }
.cal-cell[aria-pressed='true'] { background: var(--espresso); }
.cal-cell[aria-pressed='true'] .n,
.cal-cell[aria-pressed='true'] .free { color: var(--paper); }
.cal-cell[disabled] { cursor: not-allowed; opacity: 0.4; }
.cal-blank { background: transparent; cursor: default; }
.band-cream .cal-blank { background: transparent; }
.cal-cell.is-today .n { border-bottom: 1px solid var(--clay); }

@media (hover: hover) and (pointer: fine) {
  .cal-cell:not([disabled]):not([aria-pressed='true']):hover { background: var(--cream); }
  .band-cream .cal-cell:not([disabled]):not([aria-pressed='true']):hover { background: var(--paper); }
  .cal-nav:hover:not([disabled]) { border-color: var(--espresso); }
}

.cal-legend { display: flex; flex-wrap: wrap; gap: var(--s-3); margin-top: var(--s-3); font-size: var(--t-xs); color: var(--espresso-70); }
.cal-legend span { display: inline-flex; align-items: center; gap: 8px; }
.swatch { width: 8px; height: 8px; display: inline-block; }
.swatch-free { background: var(--clay); }
.swatch-none { background: var(--hairline); }
.swatch-sel { background: var(--espresso); }

.slots { display: grid; grid-template-columns: repeat(auto-fill, minmax(104px, 1fr)); gap: 10px; }
.slot {
  min-height: 56px;
  border: 1px solid var(--hairline);
  background: var(--paper);
  color: var(--espresso);
  font-family: var(--sans); font-size: var(--t-sm);
  cursor: pointer;
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 2px;
}
.slot small { font-size: var(--t-xs); color: var(--espresso-70); letter-spacing: var(--ls-caps); }
.slot[aria-pressed='true'] { background: var(--espresso); color: var(--paper); border-color: var(--espresso); }
.slot[aria-pressed='true'] small { color: rgba(255,255,255,0.8); }
@media (hover: hover) and (pointer: fine) {
  .slot:not([aria-pressed='true']):hover { border-color: var(--espresso); }
}

.live-dot { display: inline-flex; align-items: center; gap: 8px; font-size: var(--t-xs); letter-spacing: var(--ls-label); text-transform: uppercase; color: var(--espresso-70); }
.live-dot::before { content: ''; width: 6px; height: 6px; border-radius: 50%; background: var(--ok); }
.live-dot[data-state='offline']::before { background: var(--warn); }
.live-dot[data-state='static']::before { background: var(--hairline); }

.pay-options { display: grid; grid-template-columns: 1fr 1fr; gap: 14px; }
.pay-option { position: relative; display: block; padding: 20px; border: 1px solid var(--hairline); cursor: pointer; background: var(--paper); }
.pay-option input { position: absolute; opacity: 0; pointer-events: none; }
.pay-option:has(input:checked) { border-color: var(--espresso); }
.pay-option:has(input:focus-visible) { outline: 2px solid var(--clay-deep); outline-offset: 2px; }
.pay-option .t { display: block; font-size: var(--t-xs); letter-spacing: var(--ls-label); text-transform: uppercase; color: var(--espresso); }
.pay-option .s { display: block; margin-top: var(--s-1); font-size: var(--t-sm); color: var(--espresso-70); }

.summary { border: 1px solid var(--hairline); padding: 28px; position: sticky; top: calc(var(--header-h) + 24px); background: var(--paper); }
.summary h3 { font-size: var(--t-xs); letter-spacing: var(--ls-label); text-transform: uppercase; margin-bottom: 20px; }
.summary dl { margin: 0; display: grid; grid-template-columns: 1fr auto; gap: 10px 16px; }
.summary dt { font-size: var(--t-xs); letter-spacing: var(--ls-caps); text-transform: uppercase; color: var(--espresso-70); }
.summary dd { margin: 0; font-size: var(--t-sm); color: var(--espresso); text-align: right; }
.summary .total { margin-top: 20px; padding-top: 20px; border-top: 1px solid var(--hairline-soft); }
.summary .total dd { font-size: var(--t-lg); }

/* Running total pinned on phones. */
.mobile-summary { display: none; }
@media (max-width: 1100px) {
  .booking-grid { grid-template-columns: 1fr; }
  .summary { position: static; display: none; }
  body[data-step='4'] .summary { display: block; }
  .mobile-summary {
    position: fixed; left: 0; right: 0; bottom: 0; z-index: 90;
    background: var(--paper);
    border-top: 1px solid var(--hairline);
    padding: 12px max(16px, env(safe-area-inset-left)) calc(12px + env(safe-area-inset-bottom)) max(16px, env(safe-area-inset-right));
    display: flex; align-items: center; justify-content: space-between; gap: 16px;
    transform: translateY(110%);
    transition: transform 200ms ease-out;
  }
  .mobile-summary[data-shown='true'] { transform: translateY(0); }
  .mobile-summary .what { font-size: var(--t-xs); letter-spacing: var(--ls-caps); text-transform: uppercase; color: var(--espresso); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .mobile-summary .when { font-size: var(--t-xs); color: var(--espresso-70); margin-top: 2px; }
  .mobile-summary .amount { font-size: var(--t-md); color: var(--espresso); white-space: nowrap; }
  .mobile-summary .amount small { display: block; font-size: var(--t-xs); color: var(--espresso-70); letter-spacing: var(--ls-caps); text-align: right; }
  body[data-summary='true'] #book { padding-bottom: 104px; }
}

@media (max-width: 640px) {
  .cal-grid { margin-left: calc(max(var(--gutter), env(safe-area-inset-left)) * -1); margin-right: calc(max(var(--gutter), env(safe-area-inset-right)) * -1); border-left: 0; }
  .cal-cell { min-height: 62px; padding: 8px; }
  .pay-options { grid-template-columns: 1fr; }
  .slots { grid-template-columns: repeat(auto-fill, minmax(92px, 1fr)); }
}

/* ------------------------------------------------- before / after + reels */

.ba-set { display: grid; gap: clamp(40px, 6vh, 72px); }
.ba { margin: 0; }
.ba-pair { display: grid; grid-template-columns: 1fr 1fr; gap: clamp(10px, 1.6vw, 20px); }
.ba-side { position: relative; }
.ba .card-media {
  aspect-ratio: 4 / 5;
  background-size: cover;
  background-position: center 32%;
  background-color: var(--cream);
}
.ba-tag {
  position: absolute; left: 12px; bottom: 12px;
  padding: 6px 12px;
  background: var(--espresso);
  color: var(--paper);
  font-size: var(--t-xs); letter-spacing: var(--ls-label); text-transform: uppercase;
}
.ba figcaption {
  margin-top: 16px;
  font-size: var(--t-sm);
  color: var(--espresso-70);
  max-width: 48ch;
}

.reel-grid { display: grid; grid-template-columns: repeat(2, 1fr); gap: clamp(20px, 3vw, 40px); max-width: 720px; }
.reel { margin: 0; }
.reel video {
  width: 100%;
  aspect-ratio: 9 / 16;
  object-fit: cover;
  background: var(--cream);
  display: block;
}
.reel figcaption {
  margin-top: 14px;
  font-size: var(--t-xs);
  color: var(--espresso-70);
}

@media (max-width: 860px) {
  #folioGrid { grid-template-columns: repeat(2, 1fr) !important; }
}

@media (max-width: 640px) {
  #folioGrid { grid-template-columns: 1fr !important; }
  .reel-grid { grid-template-columns: 1fr; max-width: 420px; }
}
