/* ==========================================================================
   The Wax Bar — styles.css
   Single-page marketing site. Mobile-first, no build step, no preprocessor.

   Sections
     1.  Design tokens
     2.  Base / reset
     3.  Layout & rhythm
     4.  Typography
     5.  Damask flourish
     6.  Hero
     7.  Call-to-action button
     8.  About
     9.  Price list — tabs
     10. Price list — rows
     11. Combo & Save
     12. Bookings / footer
     13. Wider screens
     14. Reduced motion
     15. Print
   ========================================================================== */


/* --------------------------------------------------------------------------
   1. Design tokens

   Contrast ratios, all computed against the backgrounds actually used:

     --ink       on --cream   13.73:1   AAA
     --ink       on --white   15.34:1   AAA
     --ink-soft  on --cream    6.92:1   AA
     --ink-soft  on --white    7.73:1   AAA
     --muted     on --cream    5.10:1   AA
     --muted     on --white    5.70:1   AA
     --gold-text on --cream    4.81:1   AA   <- the binding constraint
     --gold-text on --white    5.37:1   AA
     --cream     on --ink     13.73:1   AAA  (the CTA, reversed out)

   --cream was warmed from #FAF7F2 to #F7F2E6 on 19 Sep 2026: the page read as
   plain white on a phone. Red-blue spread went 8 -> 17 and the hue moved from
   37 deg to 42 deg, close to --marigold's 48 deg, so the ground reads as the
   flyer's paper stock rather than as neutral beige.

   DO NOT darken the ground further without also darkening --gold-text. It is
   what fails first: 5.02 on the old cream, 4.81 here, and only 4.44 (below AA)
   by #F1E9D6. --gold-text #7E5B0E would buy room down to about #F3ECDC.

   --marigold is 1.50:1 on cream and fails WCAG badly. It is used ONLY as a
   decorative fill: the flourishes, the active tab underline, the Combo rule
   and the favicon. It must never carry text or a meaning-bearing icon.
   -------------------------------------------------------------------------- */
:root {
  --cream:      #F7F2E6;  /* page background — warmed 19 Sep 2026, see above */
  --white:      #FFFFFF;  /* Combo panel — now sits 1.124x the ground's luminance */
  --ink:        #2B2419;  /* headings + body — warm near-black */
  --ink-soft:   #5C5145;  /* secondary copy, category labels */
  --muted:      #6E655D;  /* fine print, cancellation policy */
  --marigold:   #F4C200;  /* DECORATIVE ONLY — see note above */
  --gold-text:  #8A6410;  /* the only gold permitted for text */
  --rule:       #E5DED4;  /* hairline rules, dotted price leaders */

  /* 4px spacing scale */
  --s-1:  4px;
  --s-2:  8px;
  --s-3:  12px;
  --s-4:  16px;
  --s-6:  24px;
  --s-8:  32px;
  --s-12: 48px;
  --s-16: 64px;
  --s-24: 96px;

  --measure: 680px;
  --gutter:  20px;

  --font-display: 'Cormorant Garamond', Georgia, 'Times New Roman', serif;
  --font-body:    'Inter', 'Inter Fallback', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
}

/* --------------------------------------------------------------------------
   1a. Metric-matched fallback for Inter

   Inter sets ~7% wider than the system sans faces it falls back to (measured
   18 Sep 2026: Segoe UI 108.1%, Roboto 107.9%, Arial/Helvetica 106.5%,
   Tahoma 106.9%). Before this face existed, the About paragraph wrapped to one
   fewer line in the fallback and then gained a line (+27px) the moment the
   Google Fonts swap landed, shoving the price list and footer down — the
   page's only layout shift, and enough to put CLS at ~0.098.

   Scaling the fallback to 107% holds the line count steady across the swap.
   Browsers without size-adjust (Safari < 17) simply get the unscaled local
   font, i.e. the previous behaviour — so this can only help.
   Display font needs no equivalent: nothing set in Cormorant re-wraps, as the
   wordmark, section titles and prices are all short single lines.
   -------------------------------------------------------------------------- */
@font-face {
  font-family: 'Inter Fallback';
  src: local('Segoe UI'), local('Roboto'), local('Helvetica Neue'), local('Arial');
  size-adjust: 107%;
  font-weight: 400 600;   /* 600 added 19 Sep 2026 for the category labels */
  font-style: normal;
}


/* --------------------------------------------------------------------------
   2. Base / reset
   -------------------------------------------------------------------------- */
*,
*::before,
*::after { box-sizing: border-box; }

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

body {
  margin: 0;
  background: var(--cream);
  color: var(--ink);
  font-family: var(--font-body);
  font-size: clamp(1rem, 0.97rem + 0.15vw, 1.0625rem);  /* 16 → 17px */
  line-height: 1.7;
  -webkit-font-smoothing: antialiased;
}

p { margin: 0 0 var(--s-4); }

svg { display: block; }


/* --------------------------------------------------------------------------
   3. Layout & rhythm
   Single column throughout, centred, with a minimum gutter on small screens.
   -------------------------------------------------------------------------- */
.hero,
.section {
  max-width: var(--measure);
  margin-inline: auto;
  padding-inline: var(--gutter);
}

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

#about { border-top: 1px solid var(--rule); }


/* --------------------------------------------------------------------------
   4. Typography
   -------------------------------------------------------------------------- */
.section__title {
  margin: 0 0 var(--s-6);
  font-family: var(--font-display);
  font-weight: 500;
  font-size: clamp(1.5rem, 1.3rem + 1vw, 1.875rem);
  line-height: 1.2;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  text-align: center;
  padding-left: 0.06em;  /* cancels the trailing letter-space, see .wordmark */
}

/* Category labels carry weight 600 in full --ink (14.35:1) rather than the
   earlier 500 in --ink-soft, so the groupings read at a glance while scrolling
   the list on a phone. */
.cat {
  margin: var(--s-8) 0 var(--s-2);
  font-family: var(--font-body);
  font-weight: 600;
  font-size: 0.875rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--ink);
  padding-bottom: var(--s-2);
  border-bottom: 1px solid var(--rule);
}

.cat:first-of-type { margin-top: 0; }


/* --------------------------------------------------------------------------
   5. Damask flourish
   Hand-authored inline SVG. Decorative only, aria-hidden in the markup.
   -------------------------------------------------------------------------- */
.flourish {
  width: clamp(90px, 28vw, 120px);
  height: auto;
  margin: 0 auto;
  color: var(--marigold);
}

.flourish--mirrored { transform: scaleY(-1); }


/* --------------------------------------------------------------------------
   6. Hero
   -------------------------------------------------------------------------- */
.hero {
  padding-block: var(--s-16) var(--s-12);
  text-align: center;
}

.wordmark {
  margin: var(--s-4) 0;
  font-family: var(--font-display);
  font-weight: 500;
  font-size: clamp(1.875rem, 1.1rem + 3.9vw, 3.25rem);
  line-height: 1.15;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--ink);

  /* letter-spacing appends a trailing space to the final character, which
     pushes centred text visually left by half that amount. A left padding
     equal to the letter-spacing restores true optical centring. */
  padding-left: 0.2em;
}

.hero__descriptor {
  /* The old var(--s-8) bottom margin was spacing for the hero call button,
     removed 18 Sep 2026 — the only CTA now lives in the Bookings footer. */
  margin: var(--s-6) auto var(--s-4);
  max-width: 34ch;
  color: var(--ink-soft);
}

.hero__note {
  margin: 0;
  font-size: 0.875rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--muted);
  text-wrap: balance;    /* keeps "ONLY" off a line of its own on a phone */
}


/* --------------------------------------------------------------------------
   7. Call-to-action button
   Solid ink on cream (14.35:1 reversed). Hover swaps to the inverse, which
   uses the same two tokens and so holds the same ratio. Minimum 48px tall,
   full width within the gutters on mobile.
   -------------------------------------------------------------------------- */
.cta {
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 48px;
  padding: var(--s-3) var(--s-6);
  border: 1px solid var(--ink);
  border-radius: 4px;            /* just enough to take the hard edge off */
  background: var(--ink);
  color: var(--cream);
  font-family: var(--font-body);
  font-size: 1.0625rem;
  font-weight: 500;
  letter-spacing: 0.01em;
  text-align: center;
  text-decoration: none;
}

.cta:hover {
  background: var(--cream);
  color: var(--ink);
}

.cta:focus-visible {
  outline: 2px solid var(--ink);
  outline-offset: 3px;
}


/* --------------------------------------------------------------------------
   8. About
   -------------------------------------------------------------------------- */
#about p {
  color: var(--ink-soft);
  text-align: center;
}

/* This centred paragraph is the element that used to drive the page's CLS: it
   re-wrapped when the Google Fonts swap landed. Addressed by the metric-matched
   'Inter Fallback' face in section 1a — do not remove that face without
   re-measuring CLS here. text-wrap: pretty was tested and made no difference. */

#about p:last-child { margin-bottom: 0; }


/* --------------------------------------------------------------------------
   9. Price list — tabs

   No-JS contract: the markup ships with both panels visible and the tablist
   carrying the `hidden` attribute. tabs.js removes `hidden`, adds .js-tabs
   and only then starts hiding panels. Every hiding rule below is scoped to
   .js-tabs, so a JS failure leaves the full price list readable.
   -------------------------------------------------------------------------- */
.tabs {
  display: flex;
  justify-content: center;
  gap: var(--s-6);
  margin-bottom: var(--s-8);
  border-bottom: 1px solid var(--rule);
}

/* `display: flex` above outranks the browser's own [hidden] rule, so the
   tablist has to be told to stay down. Without this, a JS failure leaves two
   dead buttons on the page. */
.tabs[hidden] { display: none; }

.tab {
  appearance: none;
  min-height: 44px;              /* tap target */
  padding: 0 var(--s-4);
  margin-bottom: -1px;
  border: 0;
  border-bottom: 3px solid transparent;
  background: none;
  font-family: var(--font-body);
  font-size: 1rem;
  font-weight: 400;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ink-soft);
  cursor: pointer;
}

/* Active state is carried by weight AND colour as well as the marigold
   underline, so it never depends on colour alone. */
.tab[aria-selected="true"] {
  color: var(--ink);
  font-weight: 500;
  border-bottom-color: var(--marigold);
}

.tab:focus-visible {
  outline: 2px solid var(--ink);
  outline-offset: 2px;
}

.panel:focus-visible {
  outline: 2px solid var(--ink);
  outline-offset: 4px;
}

/* Once the tabs are live the panel heading duplicates the tab label. Keep it
   in the DOM for assistive tech, take it out of the visual flow. */
.js-tabs .panel__title {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

/* Without .js-tabs the two panels stack, each under its own heading. */
.panel__title {
  margin: var(--s-12) 0 var(--s-6);
  font-family: var(--font-display);
  font-weight: 500;
  font-size: 1.5rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  text-align: center;
}

.panel:first-of-type .panel__title { margin-top: 0; }


/* --------------------------------------------------------------------------
   10. Price list — rows
   Service name left in the body sans, price right in the display serif,
   joined by a dotted leader.
   -------------------------------------------------------------------------- */
.rows {
  margin: 0 0 var(--s-8);
  padding: 0;
  list-style: none;
}

.row {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 0 var(--s-2);
  padding: var(--s-2) 0;
}

.row__name { flex: 0 1 auto; }

.row__leader {
  flex: 1 1 var(--s-8);
  min-width: var(--s-6);
  border-bottom: 1px dotted var(--rule);
  /* An empty baseline-aligned box puts its bottom border exactly on the text
     baseline; a hair of lift keeps the dots clear of descenders. */
  transform: translateY(-0.1em);
}

.row__price {
  flex: 0 0 auto;
  font-family: var(--font-display);
  font-size: 1.375rem;
  font-weight: 600;
  white-space: nowrap;
}

/* The "from" qualifier — smaller, in the body sans, so the figure still leads. */
.row__qual {
  font-family: var(--font-body);
  font-size: 0.75rem;
  font-weight: 400;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--ink-soft);
}

/* Male Full Body carries no figure — this is prose, not a price. */
.row__price--text {
  font-family: var(--font-body);
  font-size: 0.875rem;
  font-weight: 400;
  color: var(--ink-soft);
  white-space: normal;
  text-align: right;
}

.finenote {
  margin: 0;
  font-size: 0.8125rem;
  line-height: 1.6;
  color: var(--muted);
}

/* In the women's panel the note sits above the Combo block rather than at the
   end of the panel, so it reads as a footnote to the service rows and not to
   the offer. */
.finenote--women { margin-bottom: var(--s-6); }


/* --------------------------------------------------------------------------
   11. Combo & Save
   Lifted off the cream on a white panel with a marigold rule, so it reads as
   an offer. No new colours: the badge is --gold-text on --white at 5.37:1.
   -------------------------------------------------------------------------- */
.combo {
  margin-top: var(--s-8);
  padding: var(--s-6) var(--s-6) var(--s-4);
  background: var(--white);
  border-top: 2px solid var(--marigold);
}

.cat--combo {
  margin-top: 0;
  font-family: var(--font-display);
  font-size: 1.25rem;
  font-weight: 600;
  letter-spacing: 0.08em;
  color: var(--ink);
  text-align: center;
  border-bottom-color: var(--rule);
}

.rows--combo { margin-bottom: 0; }

.badge {
  flex: 0 0 100%;
  margin-top: var(--s-1);
  font-size: 0.6875rem;
  font-weight: 500;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--gold-text);
}


/* --------------------------------------------------------------------------
   12. Bookings / footer
   -------------------------------------------------------------------------- */
#bookings {
  border-top: 1px solid var(--rule);
  text-align: center;
  padding-bottom: var(--s-16);
}

/* Leanne does not answer unknown numbers, so the CTA is an sms: link and this
   line tells people what to put in the message. One line on desktop; balanced
   across two or three on a phone rather than leaving a word stranded. */
.cta-note {
  margin: var(--s-3) auto 0;
  max-width: 52ch;
  font-size: 0.8125rem;
  line-height: 1.6;
  color: var(--muted);
  text-wrap: balance;
}

.addr {
  margin: var(--s-8) 0 var(--s-2);
  font-style: normal;
  color: var(--ink-soft);
}

.note {
  margin: 0 0 var(--s-6);
  font-size: 0.875rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--muted);
  text-wrap: balance;
}

/* No max-width: the 40ch measure that used to sit here forced this single
   sentence onto two lines even on desktop. It now takes the full content
   width and stays on one line wherever that width allows. */
.policy {
  margin: 0 auto var(--s-8);
  /* 12.5px rather than the 13px used elsewhere for fine print: at 13px the
     sentence measures 334px against the 335px available on a 375px phone, so
     it would wrap on a one-pixel margin. This buys ~14px of headroom and
     holds one line on every viewport from 375px up. */
  font-size: 0.78125rem;
  line-height: 1.6;
  color: var(--muted);
  text-wrap: balance;     /* below 375px it must wrap; split it evenly */
}

.copyright {
  margin: 0;
  padding-top: var(--s-6);
  border-top: 1px solid var(--rule);
  font-size: 0.8125rem;
  color: var(--muted);
}

/* Studio credit. The only outbound link on the site — kept quiet so it does
   not compete with the booking CTA. --ink-soft is 7.23:1 on cream.
   rel="noopener" without "noreferrer" on purpose: the referrer is what lets
   Swipe Digital see traffic arriving from client sites. */
.credit {
  margin: var(--s-2) 0 0;
  font-size: 0.8125rem;
  color: var(--muted);
}

.credit a {
  color: var(--ink-soft);
  text-decoration: underline;
  text-underline-offset: 2px;
}

.credit a:hover { color: var(--ink); }

.credit a:focus-visible {
  outline: 2px solid var(--ink);
  outline-offset: 2px;
}


/* --------------------------------------------------------------------------
   13. Wider screens
   One breakpoint. The CTA stops being full-bleed and the rhythm opens up.
   -------------------------------------------------------------------------- */
@media (min-width: 40em) {
  .hero { padding-block: var(--s-24) var(--s-16); }

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

  .cta {
    display: inline-flex;
    min-width: 20rem;
  }

  .row { padding: var(--s-3) 0; }
}


/* --------------------------------------------------------------------------
   14. Reduced motion
   There is barely any motion on the page; this makes sure the tab switch and
   the CTA hover are instant for anyone who has asked for that.
   -------------------------------------------------------------------------- */
@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
}


/* --------------------------------------------------------------------------
   15. Print
   Both panels, both headings, no CTA, no flourishes, black type.
   -------------------------------------------------------------------------- */
@media print {
  :root {
    --ink: #000;
    --ink-soft: #000;
    --muted: #000;
    --cream: #fff;
    --white: #fff;
  }

  body { font-size: 11pt; }

  .cta,
  .flourish,
  .tabs { display: none !important; }

  /* Undo the JS panel hiding so the printed sheet carries the full list. */
  .js-tabs .panel[hidden] { display: block !important; }

  .js-tabs .panel__title {
    position: static;
    width: auto;
    height: auto;
    margin: 24pt 0 12pt;
    clip-path: none;
  }

  .combo { border-top: 1pt solid #000; }

  .badge { color: #000; }

  .section { padding-block: 12pt; }

  .panel { break-inside: auto; }

  .row { break-inside: avoid; }
}
