/* Booking page: the printed style menu (services, prices, timings), the shaping
   explainer and the booking request form. Colour, type and spacing come from
   tokens.css only, the shell (header, footer, buttons, fields) from layout.css. */

/* ---------- page head ---------- */
.menu-head {
  /* the header is position: fixed, so the first block clears it by hand */
  padding-top: calc(var(--header-h) + clamp(44px, 7vw, 96px));
  padding-bottom: clamp(26px, 4vw, 44px);
}
.menu-head__title {
  font-family: var(--font-sans);
  font-weight: 200;
  font-size: var(--fs-h1);
  text-transform: uppercase;
  letter-spacing: 0.2em;
  line-height: 1.15;
  text-align: center;
  /* absorbs the trailing letter space so the line optically centres */
  margin-right: -0.2em;
}

/* ---------- the menu ---------- */
.menu-cols {
  display: grid;
  /* matches .menu-item so THE SERVICES sits over the text column, THB over the
     price rail, and the photo column stays empty in the header */
  grid-template-columns: clamp(160px, 23vw, 300px) minmax(0, 1fr) auto;
  column-gap: clamp(14px, 2.6vw, 34px);
  align-items: end;
  padding-top: clamp(22px, 3vw, 34px);
  padding-bottom: clamp(12px, 1.6vw, 18px);
  font-size: var(--fs-eyebrow);
  text-transform: uppercase;
  letter-spacing: var(--ls-wide);
  color: var(--ink-muted);
  line-height: 1.5;
}
.menu-cols--group {
  margin-top: clamp(26px, 4vw, 52px);
  border-top: 1px solid var(--line);
}
/* The label starts on the page's left edge, over the photo column, but the cell
   now runs across the copy column too so the rates sentence can sit beside it on
   the same line instead of in a column of its own. */
.menu-cols__left { grid-column: 1 / 3; }
/* the low season line, in the header's middle column, over the copy. Sentence
   case against the two uppercase labels either side of it: it is a sentence to
   read, not a column heading. */
/* The rates run on from THE SERVICES after a middle dot, sentence case against
   the uppercase label: one heading that happens to carry a sentence, not a
   second column. The dot is CSS so it is there in both languages. */
.menu-cols__season {
  text-transform: none;
  letter-spacing: normal;
  font-size: var(--fs-small);
  line-height: 1.5;
  /* no colour of its own: it inherits --ink-muted from .menu-cols, the same tone
     as THE SERVICES and THB, so the row reads as one heading */
}
.menu-cols__season::before {
  content: "\00a0\00b7\00a0";
  color: var(--ink-muted);
}
.menu-cols__right { grid-column: 3; text-align: right; white-space: nowrap; }

/* On a phone the header drops to two columns. This block has to sit AFTER the
   three rules above: same specificity, so source order is what decides, and
   above them the desktop grid-column simply won at every width. Rows are set
   explicitly too — left to auto placement the sentence lands back on the labels'
   row and prints straight over THE SERVICES. */
@media (max-width: 759px) {
  .menu-cols { grid-template-columns: minmax(0, 1fr) auto; align-items: start; }
  .menu-cols__left  { grid-column: 1; }
  .menu-cols__right { grid-column: 2; }
}

.menu-list--last { border-bottom: 1px solid var(--line); }

/* One grid for the whole service: the name, tagline, description and note stack
   down the left column, and the price rail sits in the right column spanning all
   of them, the way the printed menu sheet sets it.
   This is not cosmetic. While the price, duration and BOOK NOW button shared a
   ROW with the title, that column was the tallest thing in the row, so the
   description could not begin until the button had ended: a 73px hole under the
   tagline that no margin could close. .menu-item__row is display: contents so
   its children join this grid instead of forming that row. */
.menu-item {
  border-top: 1px solid var(--line);
  padding-block: clamp(24px, 3.2vw, 38px);
  display: grid;
  /* photo | text | price rail */
  grid-template-columns: clamp(160px, 23vw, 300px) minmax(0, 1fr) auto;
  column-gap: clamp(14px, 2.6vw, 34px);
  align-items: start;
}
.menu-item__row { display: contents; }
.menu-item__head { grid-column: 2; }
.menu-item__desc,
.menu-item__note { grid-column: 2; }

/* ---- the before and after ----
   Square: a brow pair reads across, not down, and a square is the one crop that
   never makes the photo taller than the copy beside it, so the rows stay even
   however long a description runs. Spans every text row of its own item. */
.menu-item__photo {
  grid-column: 1;
  grid-row: 1 / span 9;
  margin: 0;
  align-self: start;
}
.menu-item__photo img {
  display: block;
  width: 100%;
  /* height:auto is doing real work — the width/height attributes on the img
     would otherwise pin it to 640px tall and the row would blow open */
  height: auto;
  aspect-ratio: 1 / 1;
  max-width: 100%;
  object-fit: cover;
  background: var(--bg-alt);
}
.menu-item__title {
  font-family: var(--font-sans);
  font-weight: 400;
  font-size: clamp(1rem, 1.9vw, 1.28rem);
  text-transform: uppercase;
  letter-spacing: var(--ls-mid);
  line-height: 1.3;
}
.menu-item__includes {
  margin-top: 8px;
  font-size: var(--fs-eyebrow);
  text-transform: uppercase;
  letter-spacing: var(--ls-mid);
  color: var(--ink-muted);
  line-height: 1.5;
}
.menu-item__price {
  grid-column: 3;
  grid-row: 1 / span 9; /* however many text rows the service has */
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: 7px;   /* one more line in the rail now the standard rate sits above */
  text-align: right;
  white-space: nowrap;
}
/* ---- the low season rate ----
   The standard price sits above the one being charged: small, grey, one hairline
   through it. No percentage, no badge, no colour and never the word save — the
   rail is a price list, not a sale rack. The dates live once above the list, in
   .menu-cols__season, instead of being repeated on every row. */
.menu-item__was {
  font-size: var(--fs-small);
  color: var(--ink-muted);
  text-decoration: line-through;
  text-decoration-thickness: 1px;
  font-variant-numeric: tabular-nums;
  line-height: 1.3;
}
.menu-item__amount {
  font-size: clamp(1rem, 1.9vw, 1.28rem);
  font-weight: 400;
  letter-spacing: 0.04em;
  font-variant-numeric: tabular-nums;
  line-height: 1.3;
}
.menu-item__time {
  font-size: var(--fs-eyebrow);
  text-transform: uppercase;
  letter-spacing: var(--ls-mid);
  color: var(--ink-muted);
  line-height: 1.5;
}
.menu-item__desc {
  margin-top: 22px;
  max-width: 52ch;
  color: var(--ink-soft);
}
.menu-item__note {
  margin-top: 14px;
  max-width: 52ch;
  font-size: var(--fs-small);
  line-height: 1.7;
  color: var(--ink-muted);
}

/* ---------- choose your finish ----------
   Set from the printed menu sheet. The block sits on one filled panel, the three
   method names are small tracked labels rather than headings the size of a
   service name, and the closing line is tied to the block by a hairline instead
   of floating below it. The rule that used to sit over each column is gone: the
   panel already groups them, and three rules on a filled surface is one device
   too many. */
.finish-panel {
  background: var(--bg-alt);
  padding: clamp(28px, 3.4vw, 40px) clamp(22px, 2.8vw, 32px);
}
.finish-intro { margin-top: 12px; max-width: 48ch; }
.finish-grid {
  margin-top: 28px;
  display: grid;
  gap: 26px 24px;
  grid-template-columns: 1fr;
}
.finish-col { }
.finish-col__title {
  font-family: var(--font-sans);
  font-weight: 400;
  font-size: 0.78rem;
  text-transform: uppercase;
  letter-spacing: 0.22em;
}
.finish-col__desc { margin-top: 7px; color: var(--ink-soft); font-size: var(--fs-small); line-height: 1.55; }
.finish-foot {
  margin-top: 28px;
  padding-top: 22px;
  border-top: 1px solid var(--line-strong);
  color: var(--ink);
  font-size: var(--fs-small);
  line-height: 1.7;
}

/* ---------- BOOK NOW, the link that sits next to every price ---------- */
.btn--book {
  min-height: 44px;
  padding: 0 16px;
  font-size: var(--fs-eyebrow);
  letter-spacing: var(--ls-mid);
  margin-top: 2px;
}

/* ================================================================
   reserve.html, the reservation page
   ================================================================ */

.reserve {
  /* The header is position: fixed, so the first block clears it by hand. Every
     number from here down to the calendar is set tight on purpose: service,
     calendar and times have to land inside one screen, with nothing to scroll
     before the client can pick a day. */
  padding-top: calc(var(--header-h) + clamp(12px, 1.4vw, 20px));
  padding-bottom: clamp(40px, 5vw, 72px);
}
.reserve .bk { margin-top: 0; }
/* the page title, a step smaller here than on the other pages */
.reserve .section-title { font-size: clamp(1.6rem, 2.7vw, 2rem); }
/* The intro lives at the top of the left column, not across the page. On a wide
   screen the calendar is much taller than a five line service list, and without
   the intro the left column ended in a long empty drop. */
.reserve-head { max-width: 60ch; margin-bottom: clamp(14px, 1.6vw, 18px); }
.book-intro { margin-top: 14px; }
.book-policy {
  display: inline-block;
  margin-top: 6px;
  font-size: var(--fs-small);
  /* padding keeps the tap target at 44px, the underline still hugs the text */
  padding-block: 11px;
  text-decoration: underline;
  text-decoration-thickness: 1px;
  text-underline-offset: 5px;
  text-decoration-color: var(--line-strong);
  transition: text-decoration-color var(--dur) var(--ease), color var(--dur) var(--ease);
}
.book-policy:hover { color: var(--accent); text-decoration-color: var(--accent); }

/* ---------- panel scaffolding ----------
   Two custom properties keep the layout from jumping. --bk-cell fixes the height of
   one calendar day, so six week rows are always the same height whatever month is on
   screen, and --bk-slot-rows says how many rows the eleven time slots take at this
   width. The placeholders below reuse both numbers, so swapping a placeholder for the
   real calendar or the real slot grid moves nothing on the page. */
.bk {
  margin-top: clamp(22px, 3vw, 34px);
  --bk-cell: 48px;
  --bk-slot-rows: 4;
}
@media (min-width: 420px) { .bk { --bk-cell: 52px; --bk-slot-rows: 3; } }
@media (min-width: 620px) { .bk { --bk-slot-rows: 2; } }
@media (min-width: 900px) { .bk { --bk-cell: 44px; } }

.bk-cols {
  display: grid;
  grid-template-columns: 1fr;
  gap: clamp(26px, 3.4vw, 40px);
  /* CHANGE SERVICE and PICK A DAY are both small tracked labels, so without this
     they stack into what reads as one three line label under the black bar. */
  margin-top: clamp(16px, 1.8vw, 20px);
}
.bk-col { min-width: 0; }
.bk-col + .bk-col {
  border-top: 1px solid var(--line);
  padding-top: clamp(26px, 3.4vw, 40px);
}
@media (min-width: 900px) {
  /* .bk-cols used to hold the service list on the left and the calendar with the
     times beneath it on the right. It now holds only the two halves of the date
     choice: calendar left, times right. The service sits full width above it.
     Stretch, not start: both boxes have to finish on the same line. */
  .bk-cols {
    grid-template-columns: minmax(0, 1.6fr) minmax(0, 1fr);
    gap: clamp(28px, 3.4vw, 44px);
    align-items: stretch;
  }
  .bk-col { display: flex; flex-direction: column; }
  .bk-col + .bk-col { border-top: 0; padding-top: 0; }
  .bk-col .bk-step { display: flex; flex-direction: column; flex: 1; }
  /* the calendar grows to meet the taller rail beside it. margin-top is zeroed
     because the label above already sets the gap, and 22px on top of it pushed
     the calendar 22px below the rail. */
  .bk-col--left .bk-cal { flex: 1; margin-top: 0; display: flex; flex-direction: column; }
  .bk-col--left .bk-cal__grid { flex: 1; }
}

/* ---- the policy strip, above everything ----
   Was a bare link under the page intro, which meant it was read after the times
   or not at all. The sentence beside it is the page's own intro line. */
.bk-policy {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: clamp(18px, 2.6vw, 32px);
  flex-wrap: wrap;
  background: var(--bg-alt);
  border: 1px solid var(--line);
  padding: clamp(14px, 1.6vw, 18px) clamp(16px, 2vw, 22px);
  margin-bottom: clamp(14px, 1.6vw, 18px);
}
/* 105ch plus the link came to more than the strip is wide, so the link was
   dropping to a second row. Capped narrower and allowed to shrink, the sentence
   wraps inside its own column and the link stays beside it. */
.bk-policy p { margin: 0; color: var(--ink-soft); max-width: 70ch; flex: 1 1 auto; min-width: 0; }
.bk-policy .book-policy { flex: 0 0 auto; margin: 0; padding-block: 7px; }

/* ---- the time rail ----
   A box, so it balances the calendar's box beside it. It stretches to the
   calendar's height, so the content is centred to keep the gap above and below equal. */
.bk-rail {
  border: 1px solid var(--line);
  padding: clamp(16px, 2vw, 22px);
  flex: 1;
  display: flex;
  flex-direction: column;
  justify-content: center;
}
.bk-rail .bk-slots { margin-top: 0; margin-bottom: 0; }
/* Desktop only: one column, full width. Four small squares in a row left most of
   the box empty and read as an afterthought beside the calendar. On a phone the
   rail is not beside anything, and four stacked rows would cost a screen. */
@media (min-width: 900px) {
  .bk-rail .bk-slots { grid-template-columns: 1fr; gap: 10px; }
  .bk-rail .bk-slot { min-height: 50px; }
}

.bk-next {
  margin-top: auto;
  width: 100%;
  min-height: 54px;
  background: var(--ink);
  color: var(--on-dark);
  border: 1px solid var(--ink);
  font-family: var(--font-sans);
  font-size: var(--fs-eyebrow);
  font-weight: 400;
  letter-spacing: var(--ls-wide);
  text-transform: uppercase;
}
.bk-next[disabled] {
  background: transparent;
  color: var(--ink-muted);
  border-color: var(--line-strong);
  cursor: not-allowed;
}

.bk-step[hidden] { display: none; }
.bk-step + .bk-step {
  margin-top: clamp(26px, 3.4vw, 40px);
  padding-top: clamp(26px, 3.4vw, 40px);
  border-top: 1px solid var(--line);
}
.bk-step--details {
  margin-top: clamp(30px, 4vw, 52px);
  padding-top: clamp(30px, 4vw, 52px);
  border-top: 1px solid var(--line);
}
@keyframes bkStepIn {
  from { opacity: 0; transform: translateY(14px); }
  to { opacity: 1; transform: none; }
}
.bk-step.is-in,
.bk-cal.is-in,
.bk-slots.is-in,
.bk-details.is-in { animation: bkStepIn 0.5s var(--ease) both; }
@media (prefers-reduced-motion: reduce) {
  .bk-step.is-in,
  .bk-cal.is-in,
  .bk-slots.is-in,
  .bk-details.is-in { animation: none; }
}

.bk-step__label {
  font-size: var(--fs-eyebrow);
  text-transform: uppercase;
  letter-spacing: var(--ls-wide);
  color: var(--ink-muted);
}
.bk-step__title {
  margin-top: 6px;
  font-family: var(--font-display);
  font-size: clamp(1.35rem, 2.6vw, 1.9rem);
  font-weight: 300;
}

/* ---- day and time headings ----
   Set as labels, not as the serif step titles: they head a box each, and the
   two have to read as a pair rather than as two more page headings. */
.bk-step__title--rail {
  font-family: var(--font-sans);
  font-size: var(--fs-eyebrow);
  font-weight: 400;
  letter-spacing: var(--ls-wide);
  text-transform: uppercase;
  color: var(--ink-muted);
  margin-bottom: 10px;
}

/* ---------- placeholders that hold the space open ---------- */
.bk-hint {
  margin-top: clamp(16px, 2.2vw, 22px);
  display: flex;
  align-items: center;
  justify-content: center;
  /* six week rows plus the month bar and the weekday row, the exact height of .bk-cal */
  min-height: calc(var(--bk-cell) * 6 + 83px);
  padding: 20px 24px;
  /* hairline only, a filled slab this size reads far too heavy on a wide screen */
  border: 1px solid var(--line);
  background: transparent;
  color: var(--ink-muted);
  font-size: var(--fs-small);
  line-height: 1.7;
  text-align: center;
}
.bk-hint[hidden] { display: none; }
.bk-hint--slots {
  /* one slot row is 46px tall (border-box) with a 2px gap between rows */
  min-height: calc(var(--bk-slot-rows) * 46px + (var(--bk-slot-rows) - 1) * 2px);
}
.bk-hint--line {
  display: block;
  min-height: 0;
  margin-top: 14px;
  padding: 0;
  border: 0;
  background: none;
  text-align: left;
  max-width: 60ch;
}

.bk-legend {
  margin-top: 14px;
  font-size: var(--fs-small);
  line-height: 1.7;
  color: var(--ink-muted);
}
.bk-legend[hidden] { display: none; }
.bk-note {
  margin-top: 14px;
  max-width: 56ch;
  font-size: var(--fs-small);
  line-height: 1.7;
  color: var(--ink-muted);
}
.bk-noscript {
  margin-top: 24px;
  padding: 18px 20px;
  border: 1px solid var(--line);
  background: var(--bg-alt);
  font-size: var(--fs-small);
  line-height: 1.7;
  color: var(--ink-soft);
}
/* English originals for everything the script draws, never shown */
.bk-strings { display: none; }

/* ---------- step 1: the services ---------- */
.bk-services {
  margin-top: clamp(16px, 2.2vw, 22px);
  border-top: 1px solid var(--line);
}
.bk-service {
  width: 100%;
  display: grid;
  /* photo | name and copy | price. The list carries the same photo and the same
     description as the collapsed card, so a client switching services sees each
     one the way they will see the one they keep, not a bare price line. */
  grid-template-columns: clamp(88px, 14vw, 124px) minmax(0, 1fr) auto;
  grid-template-areas:
    "photo name price"
    "photo meta meta"
    "photo desc desc";
  align-items: start;
  gap: 2px clamp(12px, 2vw, 24px);
  min-height: 62px;
  padding: 15px 14px;
  text-align: left;
  border: 0;
  border-bottom: 1px solid var(--line);
  background: transparent;
  color: var(--ink);
  transition: background var(--dur) var(--ease), color var(--dur) var(--ease);
}
.bk-service__name {
  grid-area: name;
  font-size: var(--fs-small);
  text-transform: uppercase;
  letter-spacing: var(--ls-mid);
  line-height: 1.4;
}
.bk-service__price {
  grid-area: price;
  font-size: var(--fs-small);
  font-variant-numeric: tabular-nums;
  letter-spacing: 0.04em;
  white-space: nowrap;
  text-align: right;
}
.bk-service__meta {
  grid-area: meta;
  font-size: var(--fs-eyebrow);
  text-transform: uppercase;
  letter-spacing: var(--ls-mid);
  color: var(--ink-muted);
  transition: color var(--dur) var(--ease);
}
.bk-service:hover { background: var(--bg-alt); }
.bk-service[aria-pressed="true"] { background: var(--ink); color: var(--on-dark); }
.bk-service[aria-pressed="true"]:hover { background: var(--ink); }
.bk-service[aria-pressed="true"] .bk-service__meta { color: var(--accent-soft); }

/* ---- step one, collapsed ----
   Set by js/booking.js when the page opens with ?service=, i.e. the client came
   from a BOOK NOW on the menu and has already decided. The unchosen rows come
   out, the heading stops telling them to choose, and a quiet link puts the whole
   list back if they did want to change after all. */
.bk-step.is-preset .bk-step__title { display: none; }
.bk-step.is-preset .bk-service[aria-pressed="false"] { display: none; }

/* The chosen service as a card: bordered panel, name, one meta line, a short
   description, Change in the top right. Filled black it shouted over the
   calendar, which is the thing the client actually has to act on. */
.bk-service-card { position: relative; }
.bk-step.is-preset .bk-service-card {
  margin-top: clamp(14px, 1.8vw, 20px);
  border: 1px solid var(--line);
  padding: clamp(16px, 1.8vw, 19px);
}
.bk-step.is-preset .bk-services { margin-top: 0; border-top: 0; }
.bk-step.is-preset .bk-service,
.bk-step.is-preset .bk-service:hover,
.bk-step.is-preset .bk-service[aria-pressed="true"] {
  min-height: 0;
  padding: 0;
  padding-right: 96px;            /* clear of Change */
  border-bottom: 0;
  background: transparent;
  color: var(--ink);
  cursor: default;
  align-items: start;
  grid-template-columns: clamp(88px, 14vw, 124px) auto auto minmax(0, 1fr);
  grid-template-areas:
    "photo name  name  name"
    "photo meta  price ."
    "photo desc  desc  desc";
  /* No column gap: the gutter belongs between the photo and the text only, and a
     grid gap would also open up between "105 MIN ·" and the price. */
  gap: 0;
}
.bk-step.is-preset .bk-service__photo { margin-right: clamp(14px, 1.8vw, 22px); }

/* Every row carries it, chosen or not: the work is the reason to pick one
   service over another, so it has to be visible while the choice is open. */
.bk-service__photo {
  grid-area: photo;
  display: block;
  align-self: start;
}
.bk-service__photo img {
  display: block;
  width: 100%;
  height: auto;                   /* the width/height attributes would pin it otherwise */
  aspect-ratio: 1 / 1;
  object-fit: cover;
  background: var(--bg-alt);
}
.bk-step.is-preset .bk-service__name {
  grid-area: name;
  font-size: clamp(0.95rem, 1.5vw, 1.02rem);
}
.bk-step.is-preset .bk-service__meta {
  grid-area: meta;
  margin-top: 7px;
  color: var(--ink-muted);
}
.bk-step.is-preset .bk-service__meta::after { content: "\00a0\00b7\00a0"; }
.bk-step.is-preset .bk-service__price {
  grid-area: price;
  margin-top: 7px;
  text-align: left;
  font-size: var(--fs-eyebrow);
  text-transform: uppercase;
  letter-spacing: var(--ls-mid);
  color: var(--ink-muted);
}
.bk-service__desc {
  grid-area: desc;
  display: block;
  margin-top: 11px;
  max-width: 82ch;
  font-size: 0.9rem;
  line-height: 1.6;
  letter-spacing: normal;
  text-transform: none;
  color: var(--ink-soft);
}
/* In the open list the chosen row is filled black, so its copy has to lift. Only
   there: collapsed, the same row is the card, on white, where this light tone
   washed the description out almost to nothing. */
.bk-step:not(.is-preset) .bk-service[aria-pressed="true"] .bk-service__desc { color: var(--accent-soft); }

.bk-service-change {
  display: none;
  position: absolute;
  /* pulled up and out by the padding so the 44px tap target does not push the
     label off the card's top right corner */
  top: calc(clamp(16px, 1.8vw, 19px) - 12px);
  right: calc(clamp(16px, 1.8vw, 19px) - 8px);
  margin: 0;
  padding: 12px 8px;
  min-height: 0;
  font-size: var(--fs-eyebrow);
  text-transform: uppercase;
  letter-spacing: var(--ls-mid);
  color: var(--ink-muted);
  border: 0;
  background: transparent;
}
.bk-step.is-preset .bk-service-change { display: inline-block; }
.bk-service-change:hover, .bk-service-change:focus-visible { color: var(--ink); }

/* The short "what is included" line and the card footer only show on a phone. */
.bk-service__inc { display: none; }
.bk-card-policy { display: none; }

/* ---- the collapsed card on a phone (mock-up C, 2026-09-16) ----
   Photo beside the name, what is included, time and price, a small Change link
   under them, and the policy link in a grey footer strip. The long description
   and the grey policy strip above the page are dropped: the card is enough. */
@media (max-width: 759px) {
  body:has(.bk-step.is-preset) .bk-policy { display: none; }
  .bk-step.is-preset .bk-service-card { display: flex; flex-direction: column; padding: 16px 16px 0; }
  .bk-step.is-preset .bk-services { order: 1; }
  .bk-step.is-preset .bk-service,
  .bk-step.is-preset .bk-service:hover,
  .bk-step.is-preset .bk-service[aria-pressed="true"] {
    padding-right: 0;
    grid-template-columns: 76px auto auto minmax(0, 1fr);
    grid-template-areas:
      "photo name  name  name"
      "photo inc   inc   inc"
      "photo meta  price .";
  }
  .bk-step.is-preset .bk-service__photo { margin-right: 14px; }
  .bk-step.is-preset .bk-service__desc { display: none; }
  .bk-step.is-preset .bk-service__inc {
    display: block;
    grid-area: inc;
    margin-top: 6px;
    font-size: var(--fs-eyebrow);
    text-transform: uppercase;
    letter-spacing: var(--ls-mid);
    line-height: 1.6;
    color: var(--ink-soft);
  }
  .bk-step.is-preset .bk-service-change {
    order: 2;
    position: static;
    align-self: flex-start;
    margin: 8px 0 14px 76px;          /* lines up with the text beside the photo */
    padding: 4px 0 2px;
    color: var(--ink);
    border-bottom: 1px solid var(--line-strong);
  }
  .bk-step.is-preset .bk-card-policy {
    order: 3;
    display: flex;
    justify-content: space-between;
    align-items: center;
    gap: 12px;
    margin: 0 -16px;
    padding: 12px 16px;
    background: var(--bg-alt);
    font-size: var(--fs-small);
    color: var(--ink-muted);
  }
  .bk-card-policy a {
    flex: none;
    font-size: var(--fs-eyebrow);
    text-transform: uppercase;
    letter-spacing: var(--ls-mid);
    color: var(--ink);
    border-bottom: 1px solid var(--line-strong);
    padding: 6px 0 2px;
  }
  :root[lang="th"] .bk-step.is-preset .bk-service__inc,
  :root[lang="th"] .bk-card-policy a { text-transform: none; letter-spacing: 0.02em; }
}

/* ---------- step 2: the calendar, fills its column ---------- */
.bk-cal {
  margin-top: clamp(16px, 2.2vw, 22px);
  border: 1px solid var(--line);
  background: var(--bg);
}
.bk-cal[hidden] { display: none; }
.bk-cal__head {
  display: grid;
  grid-template-columns: 44px minmax(0, 1fr) 44px;
  align-items: center;
  border-bottom: 1px solid var(--line);
}
.bk-cal__nav {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 44px;
  min-height: 40px;
  color: var(--ink);
  transition: color var(--dur) var(--ease), background var(--dur) var(--ease);
}
.bk-cal__nav svg { width: 16px; height: 16px; fill: none; stroke: currentColor; stroke-width: 1.4; }
.bk-cal__nav:hover { background: var(--bg-alt); }
.bk-cal__nav:disabled { color: var(--ink-muted); opacity: 0.35; cursor: default; }
.bk-cal__nav:disabled:hover { background: transparent; }
.bk-cal__month {
  text-align: center;
  font-size: var(--fs-small);
  text-transform: uppercase;
  letter-spacing: var(--ls-mid);
  line-height: 1.4;
}
.bk-cal__dow,
.bk-cal__grid { display: grid; grid-template-columns: repeat(7, minmax(0, 1fr)); }
.bk-cal__dow {
  padding-block: 7px;
  border-bottom: 1px solid var(--line);
}
.bk-cal__dowcell {
  text-align: center;
  font-size: var(--fs-eyebrow);
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--ink-muted);
  line-height: 1.4;
}
.bk-day {
  display: flex;
  align-items: center;
  justify-content: center;
  /* fixed height, so six rows are always the same block whatever the month */
  height: var(--bk-cell);
  font-size: var(--fs-small);
  font-variant-numeric: tabular-nums;
  color: var(--ink);
  background: transparent;
  border: 0;
  transition: background var(--dur) var(--ease), color var(--dur) var(--ease);
}
.bk-day--blank { pointer-events: none; }
.bk-day:hover { background: var(--bg-alt); }
.bk-day:disabled { color: var(--ink-muted); opacity: 0.3; cursor: default; background: transparent; }
.bk-day.is-today { box-shadow: inset 0 0 0 1px var(--line-strong); }
.bk-day[aria-pressed="true"] { background: var(--ink); color: var(--on-dark); box-shadow: none; }

/* ---------- step 3: the time slots, under the calendar in the same column ----------
   Fixed column counts, not auto-fill: auto-fill combined with a max-width reports a
   large min-content size and blows the column open on a phone. */
.bk-slots {
  margin-top: clamp(16px, 2.2vw, 22px);
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 2px;
}
.bk-slots[hidden] { display: none; }
.bk-slot {
  min-height: 46px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-size: var(--fs-small);
  font-variant-numeric: tabular-nums;
  letter-spacing: 0.04em;
  color: var(--ink);
  background: transparent;
  border: 1px solid var(--line);
  transition: background var(--dur) var(--ease), color var(--dur) var(--ease), border-color var(--dur) var(--ease);
}
.bk-slot:hover { background: var(--bg-alt); border-color: var(--line-strong); }
.bk-slot:disabled { color: var(--ink-muted); opacity: 0.35; cursor: default; background: transparent; border-color: var(--line); }
.bk-slot[aria-pressed="true"] { background: var(--ink); color: var(--on-dark); border-color: var(--ink); }

/* ---------- step 4: summary beside the form, under both columns ---------- */
.bk-details {
  display: grid;
  grid-template-columns: 1fr;
  grid-template-areas: "sum" "form" "pay";
  gap: clamp(20px, 2.6vw, 30px);
  margin-top: clamp(16px, 2.2vw, 22px);
}
.bk-summary { grid-area: sum; }
.bk-form { grid-area: form; }
.bk-paywrap { grid-area: pay; }
.bk-details[hidden] { display: none; }
/* Bordered and white, like the service card and the calendar. Filled grey it
   merged with the form fields beside it and the whole step read as one slab. */
.bk-summary {
  border: 1px solid var(--line);
  background: var(--bg);
  padding: clamp(16px, 1.8vw, 22px);
}
.bk-summary__title {
  font-size: var(--fs-eyebrow);
  text-transform: uppercase;
  letter-spacing: var(--ls-wide);
  color: var(--ink-muted);
}
.bk-summary__row {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  grid-template-areas: "label change" "value change";
  align-items: center;
  column-gap: 14px;
  margin-top: 12px;
  padding-top: 12px;
  border-top: 1px solid var(--line);
}
.bk-summary__label {
  grid-area: label;
  font-size: var(--fs-eyebrow);
  text-transform: uppercase;
  letter-spacing: var(--ls-mid);
  color: var(--ink-muted);
  line-height: 1.5;
}
.bk-summary__value {
  grid-area: value;
  font-size: var(--fs-small);
  line-height: 1.5;
  color: var(--ink);
}
.bk-change {
  grid-area: change;
  align-self: center;
  min-height: 44px;
  padding-inline: 4px;
  font-size: var(--fs-eyebrow);
  text-transform: uppercase;
  letter-spacing: var(--ls-mid);
  color: var(--ink-muted);
  text-decoration: none;
  transition: color var(--dur) var(--ease), text-decoration-color var(--dur) var(--ease);
}
.bk-change:hover { color: var(--ink); }

/* ---- the deposit block ----
   Tinted, inside the white summary, so the two numbers the client has to act on
   are the one thing in this step that is not a form field. */
.bk-pay {
  background: var(--ink);
  border: 1px solid var(--ink);
  color: var(--on-dark);
  padding: clamp(15px, 1.7vw, 19px);
}
.bk-pay__line {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 12px;
}
.bk-pay__line + .bk-pay__line {
  margin-top: 11px;
  padding-top: 11px;
  border-top: 1px solid rgba(246, 246, 248, 0.22);
}
.bk-pay__label {
  font-size: var(--fs-eyebrow);
  text-transform: uppercase;
  letter-spacing: var(--ls-mid);
  color: rgba(246, 246, 248, 0.62);
  line-height: 1.4;
}
.bk-pay__amount {
  font-size: clamp(1.15rem, 2vw, 1.4rem);
  font-variant-numeric: tabular-nums;
  letter-spacing: 0.02em;
  white-space: nowrap;
  line-height: 1.2;
}
.bk-pay__value {
  font-size: var(--fs-small);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
.bk-pay__note {
  margin: 6px 0 0;
  font-size: var(--fs-eyebrow);
  text-transform: uppercase;
  letter-spacing: var(--ls-mid);
  color: rgba(246, 246, 248, 0.62);
  line-height: 1.5;
}

/* the light button inside the dark block: the money and the act are one object */
.bk-cta {
  display: block;
  width: 100%;
  margin-top: 16px;
  min-height: 56px;
  padding: 18px 20px;
  background: var(--on-dark);
  color: var(--ink);
  border: 1px solid var(--on-dark);
  font-family: var(--font-sans);
  font-weight: 400;
  font-size: var(--fs-eyebrow);
  letter-spacing: var(--ls-wide);
  text-transform: uppercase;
  text-align: center;
  transition: background var(--dur) var(--ease), color var(--dur) var(--ease);
}
.bk-cta:hover { background: var(--bg-alt); }
.bk-cta[disabled] { opacity: 0.55; cursor: default; }

.bk-summary__hold {
  margin: 14px 0 0;
  font-size: var(--fs-small);
  line-height: 1.65;
  color: var(--ink-soft);
}

/* ---- mobile number: dial code welded to the number ---- */
.bk-tel { display: grid; grid-template-columns: 1fr; }
/* stacked on a narrow phone: pull the number up so the seam is one hairline */
.bk-tel .input { margin-top: -1px; }
@media (min-width: 420px) {
  .bk-tel { grid-template-columns: 168px minmax(0, 1fr); }
  .bk-tel .input { margin-top: 0; }
}
.bk-tel__code {
  -webkit-appearance: none;
  appearance: none;
  min-height: 52px;
  padding: 14px 30px 14px 14px;
  font-family: inherit;
  font-size: 1rem;              /* 16px keeps iOS from zooming */
  font-weight: 300;
  color: var(--ink);
  background-color: var(--bg-alt);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  /* a chevron drawn in CSS, so no icon font and no image request */
  background-image:
    linear-gradient(45deg, transparent 50%, var(--ink-muted) 50%),
    linear-gradient(135deg, var(--ink-muted) 50%, transparent 50%);
  background-position: calc(100% - 16px) calc(50% - 2px), calc(100% - 11px) calc(50% - 2px);
  background-size: 5px 5px, 5px 5px;
  background-repeat: no-repeat;
}
.bk-tel__code:focus { border-color: var(--accent); outline: none; }
@media (min-width: 420px) {
  /* one control, not two: the seam between them is a single hairline */
  .bk-tel__code { border-right: 0; border-radius: var(--radius) 0 0 var(--radius); }
  .bk-tel .input { border-radius: 0 var(--radius) var(--radius) 0; }
}

.bk-form .btn { margin-top: 10px; width: 100%; }
.bk-form .input,
.bk-form .textarea { min-height: 52px; background: var(--bg); }
.bk-form .textarea { min-height: 108px; }
.bk-form .field { margin-bottom: 14px; }

/* ---------- breakpoints ---------- */
@media (max-width: 759px) {
  /* Phone layout, chosen 2026-09-16 (mock-up D2): the before and after runs full
     width as a wide crop around the brows and eyes, then the name, what is
     included, the price line and BOOK NOW are centred under it. The description
     and note stay left aligned, since centred paragraphs are hard to read. */
  .menu-item { display: block; text-align: center; }
  .menu-item__photo {
    aspect-ratio: 16 / 9;
    overflow: hidden;
    background: var(--bg-alt);
    margin-bottom: 20px;
  }
  .menu-item__photo img {
    height: 100%;
    aspect-ratio: auto;
    object-position: 50% 38%;
  }
  .menu-item__row { display: block; }
  .menu-item__price {
    flex-direction: row;
    flex-wrap: wrap;
    justify-content: center;
    align-items: baseline;
    column-gap: 8px;
    row-gap: 0;
    margin-top: 12px;
  }
  .menu-item__amount::after { content: " THB"; }
  :root[lang="th"] .menu-item__amount::after { content: " บาท"; }
  .menu-item__time::before { content: "· "; }
  /* an empty full-width item pushes BOOK NOW onto its own centred line */
  .menu-item__price::after { content: ""; flex-basis: 100%; order: 3; }
  .menu-item__price .btn--book { order: 4; margin-top: 14px; padding: 0 26px; }
  .menu-item__desc,
  .menu-item__note { text-align: left; max-width: none; }
  .menu-item__desc { margin-top: 20px; }
}
@media (max-width: 420px) {
  /* the menu row gets tight once BOOK NOW shares it with the price */
  .btn--book { padding: 0 12px; }
  .bk-service { padding-inline: 10px; }
}
@media (max-width: 520px) {
  /* wide tracking eats the line on a 360px screen, so the header row tightens */
  .menu-cols { letter-spacing: var(--ls-mid); }
}
@media (min-width: 420px) { .bk-slots { grid-template-columns: repeat(4, minmax(0, 1fr)); } }
@media (min-width: 520px) { .bk-form .btn { width: auto; min-width: 260px; } }
@media (min-width: 620px) { .bk-slots { grid-template-columns: repeat(6, minmax(0, 1fr)); } }
@media (min-width: 860px) { .finish-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
@media (min-width: 900px) {
  /* Same 1.6 / 1 split as the calendar and the time rail above, so the page has
     one pair of column edges from top to bottom rather than two. The form spans
     both rows on the left; the summary and the deposit stack in the rail. */
  .bk-details {
    grid-template-columns: minmax(0, 1.6fr) minmax(0, 1fr);
    grid-template-areas:
      "form sum"
      "form pay";
    grid-template-rows: auto 1fr;
    column-gap: clamp(24px, 3vw, 40px);
    row-gap: clamp(14px, 1.6vw, 18px);
    align-items: start;
  }
}

/* ---------- Thai ----------
   Thai has no capitals and composed glyphs break under wide tracking,
   so every uppercase label on these two pages falls back to plain text. */
:root[lang="th"] .menu-head__title,
:root[lang="th"] .menu-cols,
:root[lang="th"] .menu-item__title,
:root[lang="th"] .menu-item__includes,
:root[lang="th"] .menu-item__time,
:root[lang="th"] .finish-col__title,
:root[lang="th"] .bk-step__label,
:root[lang="th"] .bk-service__name,
:root[lang="th"] .bk-service__meta,
:root[lang="th"] .bk-cal__month,
:root[lang="th"] .bk-cal__dowcell,
:root[lang="th"] .bk-summary__title,
:root[lang="th"] .bk-summary__label,
:root[lang="th"] .bk-pay__label,
:root[lang="th"] .bk-pay__note {
  text-transform: none;
  letter-spacing: var(--ls-mid);
}
:root[lang="th"] .menu-head__title { margin-right: 0; }
:root[lang="th"] .menu-item__note,
:root[lang="th"] .finish-col__desc,
:root[lang="th"] .finish-foot,
:root[lang="th"] .bk-hint,
:root[lang="th"] .bk-legend,
:root[lang="th"] .bk-note,
:root[lang="th"] .bk-noscript,
:root[lang="th"] .bk-summary__value { line-height: var(--lh-body); }
