/* ── BOOKING WIZARD ── */
.wizard {
  position: relative;
  max-width: 780px;
  margin: 0 auto;
  padding: 0 1.25rem 5rem;
}
/* Soft blurred color blobs behind the glass cards — gives the frosted-glass
   effect something to actually show through, since the page itself is a
   flat color. Contained to this stacking context via position:relative
   above + z-index here, so they can't bleed behind the nav/footer.

   Both blobs sit fully INSIDE the wizard's box horizontally (left/right: 0
   rather than the -40px/-60px they used to use). That matters: hanging them
   over the edge added 60px of horizontal scroll to every page width, and the
   `overflow-x: clip` added to stop it then sliced the 60px blur off square,
   leaving a hard vertical seam down the full height of the page at the
   wizard's right edge. Keeping them inside means neither the scrollbar nor
   the clip is needed, and the blur stays soft all the way out. */
.wizard::before,
.wizard::after {
  content: '';
  position: absolute;
  z-index: 0;
  border-radius: 50%;
  filter: blur(60px);
  pointer-events: none;
}
.wizard::before {
  width: 260px; height: 260px;
  background: var(--blush);
  opacity: 0.65;
  top: -20px; left: 0;
}
.wizard::after {
  width: 280px; height: 280px;
  background: var(--gold);
  opacity: 0.35;
  top: 420px; right: 0;
}
.wizard-steps, .wizard-panel { position: relative; z-index: 1; }

.wizard-steps {
  display: flex;
  justify-content: center;
  gap: 0.4rem;
  margin-bottom: 1.5rem;
  flex-wrap: wrap;
}
.wizard-step-dot {
  display: flex;
  align-items: center;
  gap: 0.4rem;
  font-size: 0.62rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--greige);
  padding: 0.4rem 0.7rem;
  border-radius: 50px;
  border: 1px solid var(--warmgrey);
}
.wizard-step-dot.active {
  color: #fff;
  background: var(--taupe);
  border-color: var(--taupe);
}
.wizard-step-dot.done {
  color: var(--taupe);
  border-color: var(--taupe);
}

/* .wizard-panel is a <section>, which picks up the generic mobile
   "clear the fixed nav" section padding-top (5.5rem) meant for standalone
   page sections - but these are nested step-panels well below the page
   header already, so that padding just reads as a huge dead gap.

   background:none matters as much as the padding: the same generic rule
   sets background:var(--cream), and because the panel is inset by the
   wizard's 20px side padding that opaque block cut a hard vertical seam
   straight through the soft blurred blobs behind it - visible as a crisp
   edge down both sides of the step content. Transparent lets the blobs
   run behind the panel the way they were meant to. */
.wizard-panel { display: none; padding: 0; background: none; }
.wizard-panel.active { display: block; animation: wizardFadeIn 0.35s ease; }
@keyframes wizardFadeIn {
  from { opacity: 0; transform: translateY(8px); }
  to { opacity: 1; transform: translateY(0); }
}

.wizard-panel-title {
  font-family: var(--font-display);
  font-size: 1.6rem;
  font-weight: 300;
  color: var(--espresso);
  text-align: center;
  margin-bottom: 1.75rem;
}
.wizard-panel-title em { font-style: italic; color: var(--taupe); }

/* Service / staff option cards */
.option-grid {
  display: grid;
  grid-template-columns: 1fr;
  gap: 0.85rem;
  align-items: stretch;
}
@media (min-width: 820px) {
  .option-grid { grid-template-columns: 1fr 1fr; }
}
.option-card {
  display: flex;
  align-items: center;
  gap: 0.9rem;
  padding: 0.95rem 1rem;
  border: 1px solid rgba(255,255,255,0.5);
  border-radius: 16px;
  background: rgba(255,255,255,0.38);
  backdrop-filter: blur(16px);
  -webkit-backdrop-filter: blur(16px);
  box-shadow: 0 8px 26px rgba(44,36,32,0.06);
  cursor: pointer;
  text-align: left;
  font-family: var(--font-body);
  transition: all 0.2s ease;
}
.option-card:hover { border-color: var(--taupe); transform: translateY(-2px); }
.option-card.external .option-card-check { color: var(--taupe); opacity: 0.85; }
.option-card.external.selected { border-color: var(--taupe); }
.option-card.selected {
  border-color: var(--taupe);
  background: rgba(255,255,255,0.58);
  box-shadow: 0 10px 28px rgba(181,168,154,0.3);
}
.option-card-img {
  width: 52px;
  height: 52px;
  border-radius: 50%;
  overflow: hidden;
  flex-shrink: 0;
  background: var(--warmgrey);
}
.option-card-img img { width: 100%; height: 100%; object-fit: cover; display: block; }
.option-card-img-empty {
  width: 100%; height: 100%;
  display: flex; align-items: center; justify-content: center;
  background: linear-gradient(140deg, var(--linen), var(--warmgrey));
  color: var(--greige);
  font-size: 0.85rem;
}
.option-card-body { flex: 1; min-width: 0; }
.option-card-title {
  display: block;
  font-size: 0.95rem;
  font-weight: 500;
  color: var(--espresso);
  line-height: 1.35;
}
/* Duration and price on their own line, separated by a dot that's drawn
   rather than typed - so it disappears cleanly when the price wraps below
   the duration on a narrow card. */
.option-card-meta {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 0.15rem 0.5rem;
  margin-top: 0.3rem;
}
/* The add-on prompt goes on its own line under the price, so it reads as an
   instruction rather than a third statistic in the same row. */
.option-card-meta > .option-card-addcount { flex-basis: 100%; }
.option-card-dur { font-size: 0.72rem; color: var(--greige); }
.option-card-price {
  font-size: 0.78rem;
  font-weight: 600;
  color: var(--taupe);
  position: relative;
  padding-left: 0.65rem;
}
.option-card-price::before {
  content: '';
  position: absolute; left: 0; top: 50%;
  width: 3px; height: 3px; border-radius: 50%;
  background: var(--warmgrey);
  transform: translateY(-50%);
}
.option-card-meta > .option-card-dur:only-child { font-size: 0.74rem; }
.option-card-check {
  width: 20px; height: 20px; border-radius: 50%;
  border: 1px solid var(--warmgrey); flex-shrink: 0;
  display: flex; align-items: center; justify-content: center;
  color: transparent; font-size: 0.6rem;
}
.option-card.selected .option-card-check {
  background: var(--taupe); border-color: var(--taupe); color: #fff;
}

/* Services with an add-on/combo option are wrapped in .option-card-wrap so
   the toggle can sit inside the same visual card, below the clickable
   selection button - the wrap now owns the card's border/background, and
   the nested .option-card becomes a plain unstyled clickable region. */
.option-card-wrap {
  display: flex;
  flex-direction: column;
  height: 100%;
  border: 1px solid rgba(255,255,255,0.5);
  border-radius: 16px;
  background: rgba(255,255,255,0.38);
  backdrop-filter: blur(16px);
  -webkit-backdrop-filter: blur(16px);
  box-shadow: 0 8px 26px rgba(44,36,32,0.06);
  overflow: hidden;
  transition: all 0.2s ease;
}
.option-card-wrap:hover { border-color: var(--taupe); }
.option-card-wrap.selected {
  border-color: var(--taupe);
  background: rgba(255,255,255,0.58);
  box-shadow: 0 10px 28px rgba(181,168,154,0.3);
}
.option-card-wrap .option-card {
  border: none;
  background: none;
  box-shadow: none;
  width: 100%;
}
.option-card-wrap .option-card:hover { transform: none; }

.option-card-addon {
  display: flex;
  align-items: center;
  gap: 0.65rem;
  padding: 0.8rem 1rem;
  border-top: 1px dashed var(--warmgrey);
  cursor: pointer;
}
.option-card-addon input {
  appearance: none;
  -webkit-appearance: none;
  width: 18px;
  height: 18px;
  border-radius: 50%;
  border: 1px solid var(--warmgrey);
  background: var(--cream);
  flex-shrink: 0;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  transition: all 0.2s ease;
}
.option-card-addon input:checked {
  background: var(--taupe);
  border-color: var(--taupe);
}
.option-card-addon input:checked::after {
  content: '\f00c';
  font-family: 'Font Awesome 6 Free';
  font-weight: 900;
  font-size: 0.55rem;
  color: #fff;
}
.option-card-addon-body {
  display: flex;
  flex: 1;
  justify-content: space-between;
  align-items: center;
  gap: 0.5rem;
  font-size: 0.76rem;
  color: var(--espresso);
}
.option-card-addon-price { color: var(--taupe); font-weight: 600; white-space: nowrap; }

.option-card-combos {
  margin-top: auto;
  padding: 0.8rem 1rem;
  border-top: 1px dashed var(--warmgrey);
}
.option-card-combos-label {
  display: block;
  font-size: 0.66rem;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: var(--greige);
  margin-bottom: 0.5rem;
}
/* A responsive grid rather than free-flowing flex: chips end up the same
   width, so the strip reads as a set of options instead of a ragged line
   that re-flows differently on every card. The minimum is set by the longest
   label a chip carries - "Extensions (100-150g)" over "Price on
   consultation" - because anything narrower breaks those across lines. */
.combo-chip-row {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(152px, 1fr));
  gap: 0.45rem;
}
.combo-chip {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  justify-content: center;
  gap: 0.15rem;
  min-height: 46px;
  padding: 0.5rem 0.7rem;
  border-radius: 12px;
  border: 1px solid var(--warmgrey);
  background: rgba(255,255,255,0.5);
  cursor: pointer;
  font-family: var(--font-body);
  transition: all 0.2s ease;
}
.combo-chip:hover { border-color: var(--taupe); }
.combo-chip-name {
  font-size: 0.74rem;
  font-weight: 500;
  color: var(--espresso);
  line-height: 1.25;
}
.combo-chip-price { font-size: 0.64rem; color: var(--greige); line-height: 1.25; }
/* Long names shouldn't push a chip wider than its column. */
.combo-chip-name, .combo-chip-price { max-width: 100%; overflow-wrap: anywhere; }
.combo-chip.active {
  border-color: var(--taupe);
  background: var(--taupe);
}
.combo-chip.active .combo-chip-name { color: #fff; }
.combo-chip.active .combo-chip-price { color: rgba(255,255,255,0.85); }

.extensions-notice {
  grid-column: 1 / -1;
  display: flex;
  align-items: flex-start;
  gap: 0.65rem;
  padding: 0.9rem 1.1rem;
  margin-top: -0.4rem;
  border-radius: 14px;
  background: rgba(201, 169, 110, 0.08);
  border: 1px solid rgba(201, 169, 110, 0.35);
  font-size: 0.78rem;
  color: var(--espresso);
  line-height: 1.5;
}
.extensions-notice i { color: var(--gold, #C9A96E); margin-top: 0.15rem; flex-shrink: 0; }
.extensions-notice-link {
  display: inline-block;
  margin-top: 0.4rem;
  background: none;
  border: none;
  padding: 0;
  color: var(--taupe);
  font-weight: 600;
  text-decoration: underline;
  cursor: pointer;
  font-size: 0.78rem;
}

.category-group { margin-bottom: 1.75rem; }
.category-group-title {
  font-size: 0.7rem;
  letter-spacing: 0.15em;
  text-transform: uppercase;
  color: var(--greige);
  margin-bottom: 0.75rem;
}

/* Service search + category filter dropdown */
.service-filter-bar {
  display: flex;
  gap: 0.6rem;
  margin-bottom: 1.75rem;
}
.service-search-wrap {
  flex: 1;
  min-width: 0;
  display: flex;
  align-items: center;
  gap: 0.6rem;
  padding: 0.7rem 1rem;
  border-radius: 50px;
  border: 1px solid rgba(255,255,255,0.6);
  background: rgba(255,255,255,0.35);
  backdrop-filter: blur(12px);
  -webkit-backdrop-filter: blur(12px);
  color: var(--greige);
  font-size: 0.8rem;
}
.service-search-wrap input {
  flex: 1;
  min-width: 0;
  border: none;
  background: none;
  font-family: var(--font-body);
  font-size: 0.82rem;
  color: var(--espresso);
  outline: none;
}
/* Custom category dropdown — a real styled button + menu, since a native
   <select>'s open popup is rendered by the OS and can't be themed. */
.custom-select {
  position: relative;
  flex-shrink: 0;
  max-width: 45%;
}
.custom-select-trigger {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.6rem;
  width: 100%;
  padding: 0.7rem 1rem;
  border-radius: 50px;
  border: 1px solid rgba(255,255,255,0.6);
  background: rgba(255,255,255,0.35);
  backdrop-filter: blur(12px);
  -webkit-backdrop-filter: blur(12px);
  color: var(--espresso);
  font-family: var(--font-body);
  font-size: 0.72rem;
  cursor: pointer;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.custom-select-trigger i { font-size: 0.6rem; color: var(--taupe); flex-shrink: 0; transition: transform 0.2s ease; }
.custom-select.open .custom-select-trigger i { transform: rotate(180deg); }
.custom-select-menu {
  display: none;
  position: absolute;
  top: calc(100% + 0.5rem);
  right: 0;
  min-width: 220px;
  max-width: 80vw;
  background: var(--cream);
  backdrop-filter: blur(20px);
  -webkit-backdrop-filter: blur(20px);
  border: 1px solid var(--warmgrey);
  border-radius: 14px;
  box-shadow: 0 14px 36px rgba(44,36,32,0.16);
  padding: 0.4rem;
  z-index: 20;
}
.custom-select.open .custom-select-menu { display: block; }
.custom-select-option {
  display: block;
  width: 100%;
  text-align: left;
  padding: 0.6rem 0.75rem;
  border-radius: 8px;
  border: none;
  background: none;
  color: var(--espresso);
  font-family: var(--font-body);
  font-size: 0.78rem;
  cursor: pointer;
  transition: background 0.15s ease;
}
.custom-select-option:hover { background: var(--blush); }
.custom-select-option.active { background: var(--taupe); color: #fff; }
/* ── SEARCH AND CATEGORY, SIDE BY SIDE AT EVERY WIDTH ──
   flex-basis:100% on the search used to push the dropdown onto its own line
   below 480px, which cost a whole row of a phone screen to a control that
   fits perfectly well beside it. They share the row now: the search takes
   what is left, the dropdown keeps enough width to stay readable, and its
   label truncates rather than wrapping the button to two lines. */
@media (max-width: 480px) {
  .service-filter-bar { flex-wrap: nowrap; gap: 0.45rem; }
  .service-search-wrap { flex: 1 1 auto; min-width: 0; padding: 0.62rem 0.8rem; }
  .service-search-wrap input { font-size: 0.78rem; }
  .custom-select { flex: 0 0 auto; width: 42%; max-width: 10.5rem; }
  .custom-select-trigger { padding: 0.62rem 0.75rem; gap: 0.35rem; }
  .custom-select-current {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    min-width: 0;
  }
  .custom-select-menu { left: auto; right: 0; min-width: 13rem; }
}

/* Date + time */
.calendar-widget {
  background: rgba(255,255,255,0.4);
  backdrop-filter: blur(16px);
  -webkit-backdrop-filter: blur(16px);
  border: 1px solid rgba(255,255,255,0.55);
  border-radius: 16px;
  box-shadow: 0 8px 26px rgba(44,36,32,0.06);
  padding: 0.8rem 0.8rem 0.9rem;
  margin-bottom: 1.25rem;
}
.calendar-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 0.5rem;
}
.calendar-month-label {
  font-family: var(--font-display);
  font-size: 0.92rem;
  color: var(--espresso);
}
.calendar-nav-btn {
  width: 24px; height: 24px;
  border-radius: 50%;
  border: 1px solid var(--warmgrey);
  background: var(--cream);
  color: var(--taupe);
  cursor: pointer;
  font-size: 0.62rem;
  transition: all 0.2s ease;
}
.calendar-nav-btn:hover:not(:disabled) { background: var(--taupe); color: #fff; border-color: var(--taupe); }
.calendar-nav-btn:disabled { opacity: 0.3; cursor: not-allowed; }
.calendar-weekdays {
  display: grid;
  grid-template-columns: repeat(7, 1fr);
  gap: 0.15rem;
  margin-bottom: 0.15rem;
}
.calendar-weekdays span {
  text-align: center;
  font-size: 0.55rem;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--greige);
}
.calendar-grid {
  display: grid;
  grid-template-columns: repeat(7, 1fr);
  gap: 0.15rem;
}
.calendar-day {
  height: 32px;
  display: flex;
  align-items: center;
  justify-content: center;
  border: none;
  border-radius: 8px;
  background: transparent;
  color: var(--espresso);
  font-family: var(--font-body);
  font-size: 0.74rem;
  cursor: pointer;
  transition: all 0.2s ease;
}
.calendar-day:hover:not(:disabled) { background: var(--blush); }
.calendar-day:disabled { color: var(--warmgrey); cursor: not-allowed; }
.calendar-day.selected { background: var(--taupe); color: #fff; }
.calendar-day-blank { cursor: default; }

/* A day the salon works but has sold out. Deliberately distinct from a plain
   disabled day (a Sunday, or a date out of range): those are simply not
   working days and get no mark, while this one is worth telling the client
   about so they stop tapping it. The number stays legible - struck through
   rather than faded away - because "the 14th is gone" is the information. */
/* .calendar-day:disabled sets --warmgrey and out-specifies a plain class, so
   this needs the extra .calendar-day to win. Without it the date washes out
   to near-invisible and the client can see that SOME day is full but not
   which one - which is the whole point of marking it. */
/* A sold-out day has to read as unavailable at a glance, and has to look
   different from BOTH an open day and a past one. A past day is just pale
   text; an open day is dark text on nothing. So this gets its own tinted
   cell plus a strike through the number - three states, three appearances.
   The date stays legible on purpose: "the 14th is gone" is the information. */
.calendar-day.calendar-day-full,
.calendar-day.calendar-day-full:disabled {
  position: relative;
  color: var(--greige);
  background: rgba(181, 168, 154, 0.13);
  font-weight: 500;
}
.calendar-day-full::after {
  content: '';
  position: absolute;
  left: 50%;
  top: 50%;
  width: 18px;
  height: 2px;
  border-radius: 1px;
  background: var(--taupe);
  transform: translate(-50%, -50%);
}
/* Hover still does nothing (the button is disabled) but the cursor and the
   tooltip both say why. */
.calendar-day-full:disabled { cursor: not-allowed; }

.slot-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(80px, 1fr));
  gap: 0.6rem;
}
.slot-btn {
  padding: 0.6rem 0.4rem;
  border: 1px solid rgba(255,255,255,0.55);
  border-radius: 10px;
  background: rgba(255,255,255,0.38);
  backdrop-filter: blur(12px);
  -webkit-backdrop-filter: blur(12px);
  color: var(--espresso);
  font-family: var(--font-body);
  font-size: 0.8rem;
  cursor: pointer;
  transition: all 0.2s ease;
}
.slot-btn:hover { border-color: var(--taupe); }
.slot-btn.selected { background: var(--taupe); border-color: var(--taupe); color: #fff; }
.slot-empty {
  grid-column: 1 / -1;
  text-align: center;
  color: var(--greige);
  font-size: 0.85rem;
  padding: 1.5rem 0;
}

/* Contact form */
.form-row { margin-bottom: 1.1rem; }
.form-row label {
  display: block;
  font-size: 0.68rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--greige);
  margin-bottom: 0.4rem;
}
.form-row input,
.form-row textarea {
  width: 100%;
  padding: 0.8rem 1rem;
  border: 1px solid rgba(255,255,255,0.55);
  border-radius: 12px;
  background: rgba(255,255,255,0.4);
  backdrop-filter: blur(14px);
  -webkit-backdrop-filter: blur(14px);
  box-shadow: 0 6px 20px rgba(44,36,32,0.05);
  color: var(--espresso);
  font-family: var(--font-body);
  font-size: 0.88rem;
  transition: border-color 0.2s ease;
}
.form-row input:focus,
.form-row textarea:focus { outline: none; border-color: var(--taupe); }
.form-row textarea { resize: vertical; min-height: 80px; }

/* Summary */
.summary-card {
  background: rgba(255,255,255,0.4);
  backdrop-filter: blur(16px);
  -webkit-backdrop-filter: blur(16px);
  border: 1px solid rgba(255,255,255,0.55);
  box-shadow: 0 8px 26px rgba(44,36,32,0.06);
  border-radius: 16px;
  padding: 1.5rem;
  margin-bottom: 1.5rem;
}
.summary-row {
  display: flex;
  justify-content: space-between;
  gap: 1rem;
  padding: 0.55rem 0;
  border-bottom: 1px dashed var(--warmgrey);
  font-size: 0.85rem;
}
.summary-row:last-child { border-bottom: none; }
.summary-row span:first-child { color: var(--greige); }
.summary-row span:last-child { color: var(--espresso); font-weight: 500; text-align: right; }

/* Service price + every selected add-on, added up. Set apart from the rows
   above it because it's the one number the client is actually agreeing to. */
.summary-row-total {
  margin-top: 0.35rem;
  padding-top: 0.7rem;
  border-top: 1px solid var(--warmgrey);
  border-bottom: none;
  font-size: 0.92rem;
}
.summary-row-total span:first-child { color: var(--espresso); font-weight: 500; }
.summary-row-total span:last-child { color: var(--espresso); font-weight: 700; }

/* Nav buttons */
.wizard-nav {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 1rem;
  margin-top: 2rem;
}
/* Empty on every other step; on the extensions gate it explains why Next
   is disabled and, tapped, scrolls back up to the fields she needs - so a
   button that can no longer even fire a click event still tells her
   something when she reaches for it. */
.wizard-nav-hint {
  font-size: 0.78rem;
  color: var(--taupe);
  font-weight: 600;
  cursor: pointer;
  text-decoration: underline;
  text-underline-offset: 3px;
}
.wizard-nav-hint:empty { display: none; }
.wizard-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.5rem;
  padding: 0.8rem 1.8rem;
  border-radius: 50px;
  font-family: var(--font-body);
  font-size: 0.8rem;
  font-weight: 500;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  text-decoration: none;
  cursor: pointer;
  border: none;
  transition: all 0.2s ease;
}
.wizard-btn-back {
  background: transparent;
  border: 1px solid var(--warmgrey);
  color: var(--greige);
}
.wizard-btn-back:hover { border-color: var(--taupe); color: var(--espresso); }
.wizard-btn-next {
  background: var(--taupe);
  color: #fff;
  margin-left: auto;
}
.wizard-btn-next:hover { background: var(--espresso); }
.wizard-btn-next:disabled { opacity: 0.5; cursor: not-allowed; }

.wizard-error {
  background: rgba(192,57,43,0.08);
  border: 1px solid rgba(192,57,43,0.3);
  color: #c0392b;
  border-radius: 10px;
  padding: 0.85rem 1rem;
  font-size: 0.82rem;
  margin-bottom: 1.25rem;
  display: none;
}
.wizard-error.visible { display: block; }

.wizard-unavailable {
  text-align: center;
  padding: 3rem 1.5rem;
  background: var(--linen);
  border-radius: 20px;
}
.wizard-unavailable i { font-size: 2rem; color: var(--taupe); margin-bottom: 1rem; }
.wizard-unavailable p { color: var(--greige); font-size: 0.9rem; line-height: 1.7; max-width: 420px; margin: 0 auto 1.5rem; }

/* Success screen */
.wizard-success {
  text-align: center;
  padding: 2rem 1rem;
}
.wizard-success-icon {
  width: 72px; height: 72px; border-radius: 50%;
  background: var(--taupe); color: #fff;
  display: flex; align-items: center; justify-content: center;
  font-size: 1.8rem; margin: 0 auto 1.5rem;
}
.wizard-success-ref {
  font-family: var(--font-display);
  font-size: 1.5rem;
  color: var(--espresso);
  letter-spacing: 0.1em;
  margin: 0.5rem 0 1.5rem;
}
.wizard-success-actions {
  display: flex;
  gap: 1rem;
  justify-content: center;
  flex-wrap: wrap;
  margin-top: 1.5rem;
}

/* ── PHONE ── */
/* Below 480px the cards are the whole screen, so the photo disc shrinks and
   the type steps down a touch to keep long service names on two lines
   rather than four. */
@media (max-width: 479px) {
  .option-card { gap: 0.75rem; padding: 0.85rem 0.9rem; }
  .option-card-img { width: 44px; height: 44px; }
  .option-card-title { font-size: 0.9rem; }
  .option-card-combos { padding: 0.7rem 0.9rem; }
  /* Two per row on a phone: three would put every label back on two lines. */
  .combo-chip-row { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .wizard { padding-left: 0.9rem; padding-right: 0.9rem; }
  .wizard-panel-title { font-size: 1.35rem; margin-bottom: 1.35rem; }
}

/* ── STICKY CONFIRM BAR ── */
.wizard-sticky {
  position: fixed;
  left: 50%;
  bottom: 0;
  transform: translateX(-50%);
  z-index: 40;
  width: min(760px, calc(100% - 1.6rem));
  margin-bottom: calc(0.8rem + env(safe-area-inset-bottom, 0px));
  display: flex;
  align-items: center;
  gap: 1rem;
  padding: 0.7rem 0.75rem 0.7rem 1.1rem;
  border-radius: 16px;
  border: 1px solid rgba(255,255,255,0.6);
  background: rgba(253,250,245,0.92);
  backdrop-filter: blur(18px);
  -webkit-backdrop-filter: blur(18px);
  box-shadow: 0 12px 34px rgba(44,36,32,0.14);
  animation: stickyRise 0.22s ease;
}
.wizard-sticky[hidden] { display: none; }
@keyframes stickyRise {
  from { opacity: 0; transform: translate(-50%, 12px); }
  to { opacity: 1; transform: translate(-50%, 0); }
}
.wizard-sticky-info { flex: 1; min-width: 0; }
.wizard-sticky-name {
  display: block;
  font-size: 0.85rem;
  font-weight: 500;
  color: var(--espresso);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.wizard-sticky-meta {
  display: block;
  margin-top: 0.15rem;
  font-size: 0.72rem;
  color: var(--greige);
}
/* .wizard-btn sets a display value, which beats the [hidden] attribute's
   default display:none - so whichever of the two buttons is meant to be
   hidden was still painting a stub. */
.wizard-sticky-btn[hidden] { display: none; }
.wizard-sticky-btn {
  flex-shrink: 0;
  margin-left: 0;
  padding: 0.7rem 1.4rem;
  font-size: 0.78rem;
}
@media (max-width: 479px) {
  .wizard-sticky { gap: 0.7rem; padding: 0.6rem 0.6rem 0.6rem 0.9rem; }
  .wizard-sticky-btn { padding: 0.65rem 1.05rem; font-size: 0.74rem; }
  .wizard-sticky-name { font-size: 0.8rem; }
}

/* #back-top is fixed bottom-left at z-index 9500 — the same corner the bar
   occupies. Raise it above the bar while the bar is up, rather than hiding a
   control the client may still want on a long list. The selector is scoped to
   the body class so it only applies while the bar is actually showing. */
body.has-sticky-bar #back-top.visible {
  transform: translateY(-4.6rem);
}


/* ── DEAD-END HELP ──
   Shown under the calendar when the chosen stylist has nothing on the day
   picked: who else is free, or when that stylist is next open. Spans the
   slot grid, which is otherwise a row of time buttons. */
.slot-alt {
  grid-column: 1 / -1;
  margin-top: 0.35rem;
  padding: 0.9rem 1rem;
  border-radius: 14px;
  border: 1px solid var(--warmgrey);
  background: rgba(255,255,255,0.5);
  text-align: center;
}
.slot-alt-lead {
  font-size: 0.8rem;
  color: var(--espresso);
  margin-bottom: 0.7rem;
}
.slot-alt-row {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 0.5rem;
}
.slot-alt-btn {
  padding: 0.55rem 1.1rem;
  border-radius: 50px;
  border: 1px solid var(--taupe);
  background: var(--taupe);
  color: #fff;
  font-family: var(--font-body);
  font-size: 0.76rem;
  cursor: pointer;
  transition: background 0.2s ease;
}
.slot-alt-btn:hover { background: var(--espresso); border-color: var(--espresso); }
.slot-alt-link {
  display: inline-block;
  margin-top: 0.7rem;
  background: none;
  border: none;
  padding: 0;
  color: var(--taupe);
  font-family: var(--font-body);
  font-size: 0.74rem;
  text-decoration: underline;
  text-underline-offset: 3px;
  cursor: pointer;
}
.slot-alt-link:hover { color: var(--espresso); }


/* ── WIDE SCREENS ──
   The wizard was pinned to 780px at every size, which on a 1900px monitor
   left the service list as a narrow ribbon down the middle with acres of
   empty page either side. Widen the shell on large screens and let the card
   grid use it - but only the steps that are actually a grid. A contact form
   or a summary read worse the wider they get, so those stay narrow and
   centred inside the wider shell. */
@media (min-width: 1100px) {
  .wizard { max-width: 1080px; }
  /* Blobs are positioned against the wizard box, so they grow with it. */
  .wizard::before { width: 320px; height: 320px; }
  .wizard::after { width: 340px; height: 340px; }
}
@media (min-width: 1240px) {
  .wizard { max-width: 1180px; }
  .option-grid { grid-template-columns: repeat(3, 1fr); }
}

/* Steps whose content is prose, fields or a single card don't benefit from
   the extra width - measure matters more than fill. */
@media (min-width: 1100px) {
  /* The calendar is capped much tighter further down (a month reads as a
     block, not as seven distant columns), so it is deliberately not listed
     here — this 760px would win on specificity and stretch it back out. */
  .wizard-panel[data-panel="3"] > .slot-grid { max-width: 760px; margin-left: auto; margin-right: auto; }
  .wizard-panel[data-panel="4"] .form-row,
  .wizard-panel[data-panel="5"] .summary-card { max-width: 620px; margin-left: auto; margin-right: auto; }
  .wizard-panel[data-panel="2"] .wizard-nav,
  .wizard-panel[data-panel="3"] .wizard-nav,
  .wizard-panel[data-panel="4"] .wizard-nav,
  .wizard-panel[data-panel="5"] .wizard-nav { max-width: 760px; margin-left: auto; margin-right: auto; }
  /* The salon has two or three stylists, never twenty — a grid as wide as the
     service list leaves them stranded beside an empty column. */
  .wizard-panel[data-panel="2"] > .option-grid {
    max-width: 760px;
    margin-left: auto;
    margin-right: auto;
    grid-template-columns: repeat(2, 1fr);
  }
  .wizard-success, .wizard-unavailable { max-width: 620px; margin-left: auto; margin-right: auto; }
  /* The confirm bar mirrors step 1's Next button, so it should track the
     shell it belongs to rather than staying at its phone width. */
  .wizard-sticky { width: min(1080px, calc(100% - 1.6rem)); }
}
@media (min-width: 1240px) {
  .wizard-sticky { width: min(1180px, calc(100% - 1.6rem)); }
}



/* Shown above the stylist list when an add-on has narrowed it — otherwise a
   single card appears with no hint as to why the others went. */
.staff-narrowed {
  grid-column: 1 / -1;
  margin: 0 0 0.2rem;
  font-size: 0.78rem;
  color: var(--greige);
  text-align: center;
}


/* ── PHONE / SMALL TABLET ──
   Between 480 and 820px the service list is still one column, so each card is
   nearly the full screen and its chips have room for two per row rather than
   the three or four the auto-fit grid would otherwise squeeze in. */
@media (min-width: 480px) and (max-width: 819px) {
  .combo-chip-row { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}





/* ── PHONE: COLLAPSE THE ADD-ONS UNTIL A SERVICE IS CHOSEN ──
   Every card was carrying its full chip strip, so twenty-two services meant
   twenty-two blocks a few hundred pixels tall and a very long scroll to find
   anything. The chips only matter once a service is actually picked, so on a
   phone they stay folded away until then and open on the selected card. The
   list becomes scannable rows; the detail arrives when it's relevant. */
@media (max-width: 819px) {
  .option-card-wrap:not(.selected) .option-card-combos { display: none; }

  /* With the chips gone the card is a row, so it can be tighter. */
  .option-card { padding: 0.75rem 0.85rem; gap: 0.7rem; }
  .option-card-img { width: 40px; height: 40px; }
  .option-card-title { font-size: 0.88rem; }
  .option-card-meta { margin-top: 0.2rem; }
  .option-grid { gap: 0.6rem; }
  .category-group { margin-bottom: 1.35rem; }

  /* A quiet marker that a chosen card has more inside it. */
  .option-card-wrap.selected .option-card-combos { padding-top: 0.75rem; }
}

/* Below 480 the same, a shade tighter again. */
@media (max-width: 479px) {
  .option-card { padding: 0.7rem 0.75rem; gap: 0.6rem; }
  .option-card-img { width: 38px; height: 38px; }
  .option-card-title { font-size: 0.85rem; }
  .option-card-dur { font-size: 0.68rem; }
  .option-card-price { font-size: 0.74rem; }
  .wizard-sticky { padding: 0.55rem 0.55rem 0.55rem 0.85rem; }
  .wizard-sticky-name { font-size: 0.78rem; }
  .wizard-sticky-meta { font-size: 0.68rem; }
}

/* Tells a folded card it has options without opening them. Hidden once the
   card is selected, because the chips themselves are then on screen. */
.option-card-addcount {
  display: inline-block;
  margin-top: 0.3rem;
  font-size: 0.68rem;
  font-weight: 500;
  color: var(--taupe);
  text-decoration: underline;
  text-decoration-color: var(--warmgrey);
  text-underline-offset: 3px;
}
.option-card-wrap.selected .option-card-addcount { display: none; }
@media (min-width: 820px) { .option-card-addcount { display: none; } }

/* ── CANCELLATION POLICY TICK-BOX ──
   Deliberately not styled as fine print. She has to read it for it to mean
   anything, so it sits at full body size next to the Confirm button. */
.terms-check {
  display: flex;
  gap: 0.7rem;
  align-items: flex-start;
  margin: 1.2rem 0 0.4rem;
  padding: 0.9rem 1rem;
  border: 1px solid var(--warmgrey, #e9e3db);
  border-radius: 10px;
  background: var(--linen, #fdfaf5);
  font-size: 0.88rem;
  line-height: 1.55;
  cursor: pointer;
  transition: border-color 0.25s ease, background 0.25s ease;
}
.terms-check input {
  flex: none;
  width: 1.1rem;
  height: 1.1rem;
  margin-top: 0.15rem;
  accent-color: var(--gold, #C9A96E);
  cursor: pointer;
}
.terms-check:hover { border-color: var(--taupe, #B5A89A); }
.terms-check:focus-within { outline: 2px solid var(--gold, #C9A96E); outline-offset: 2px; }
.terms-check-missing {
  border-color: #C25E4B;
  background: rgba(194, 94, 75, 0.06);
  animation: terms-nudge 0.35s ease;
}
@keyframes terms-nudge {
  0%, 100% { transform: translateX(0); }
  25% { transform: translateX(-4px); }
  75% { transform: translateX(4px); }
}
@media (prefers-reduced-motion: reduce) {
  .terms-check-missing { animation: none; }
}

/* The earliest bookable day, when the chosen one is reserved for colour work.
   This is the answer to the client's question, not a footnote, so it is a real
   button rather than a link buried under the alternatives. */
.slot-alt-primary {
  display: block;
  width: 100%;
  margin: 0.9rem 0 0.2rem;
  padding: 0.85rem 1rem;
  font: inherit;
  font-size: 0.92rem;
  text-align: center;
  color: var(--espresso, #3f3632);
  background: var(--linen, #fdfaf5);
  border: 1px solid var(--gold, #C9A96E);
  border-radius: 10px;
  cursor: pointer;
  transition: background 0.2s ease, transform 0.15s ease;
}
.slot-alt-primary strong { font-weight: 600; }
.slot-alt-primary:hover { background: var(--blush, #ebe2d6); }
.slot-alt-primary:active { transform: translateY(1px); }
.slot-alt-primary:focus-visible { outline: 2px solid var(--gold, #C9A96E); outline-offset: 2px; }
@media (prefers-reduced-motion: reduce) {
  .slot-alt-primary { transition: none; }
}

/* ── CATEGORY TABS ──
   Replaced the circular photo beside each heading. TO GO BACK TO CIRCLES:
   restore .category-group-head / .category-group-img (git history has them),
   put the head wrapper back in booking.js, and delete this block.

   A scrolling row rather than a dropdown, so every category is visible without
   a tap - a client who never thought to look for bridal work can see the salon
   does it. */
.category-tabs {
  display: flex;
  gap: 0.4rem;
  overflow-x: auto;
  padding: 0.2rem 0.1rem 0.6rem;
  margin-bottom: 1.4rem;
  scrollbar-width: none;
  -webkit-overflow-scrolling: touch;
  scroll-snap-type: x proximity;
}
.category-tabs::-webkit-scrollbar { display: none; }
.category-tab {
  flex: none;
  scroll-snap-align: start;
  font: inherit;
  font-size: 0.82rem;
  letter-spacing: 0.02em;
  white-space: nowrap;
  padding: 0.5rem 0.95rem;
  border-radius: 999px;
  border: 1px solid var(--warmgrey);
  background: rgba(255, 255, 255, 0.45);
  color: var(--greige);
  cursor: pointer;
  transition: background 0.2s ease, color 0.2s ease, border-color 0.2s ease;
}
.category-tab:hover { color: var(--espresso); border-color: var(--taupe); }
.category-tab.active {
  background: var(--espresso);
  border-color: var(--espresso);
  color: var(--linen);
}
.category-tab:focus-visible { outline: 2px solid var(--gold); outline-offset: 2px; }
@media (prefers-reduced-motion: reduce) {
  .category-tab { transition: none; }
}
@media (max-width: 560px) {
  .category-tab { font-size: 0.78rem; padding: 0.45rem 0.8rem; }
}

/* Cards are text only. */
.option-card { align-items: center; }
.option-card-body { flex: 1; min-width: 0; }
.option-card-check { align-self: center; }

/* The category's photo inside its tab. Small and circular so the row still
   reads as tabs rather than a gallery. */
.category-tab {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  padding-left: 0.45rem;
}
.category-tab-img {
  width: 26px;
  height: 26px;
  border-radius: 50%;
  overflow: hidden;
  flex: none;
  background: var(--warmgrey);
}
.category-tab-img img { width: 100%; height: 100%; object-fit: cover; display: block; }
/* "All categories" has no photo, so it keeps even padding. */
.category-tab[data-value="all"] { padding-left: 0.95rem; }
@media (max-width: 560px) {
  .category-tab-img { width: 22px; height: 22px; }
}

/* ── "NOT CONFIRMED YET" NOTICE ──
   Used in three places unrelated to the step-1 extensions panel above: the
   booking summary before she confirms, the success screen once she has, and
   the "please call us" gate for a client the salon has flagged. All three
   are one line, no search fields, and genuinely worth a client noticing -
   so they keep the warmer terracotta the step-1 panel moved away from,
   rather than being redesigned along with it. */
.notice-pending {
  display: flex;
  align-items: flex-start;
  gap: 0.65rem;
  margin-top: 0.7rem;
  padding: 0.9rem 1rem;
  border-radius: 10px;
  border: 1px solid rgba(166, 74, 58, 0.25);
  border-left: 2px solid #a64a3a;
  background: rgba(166, 74, 58, 0.06);
  color: #7d3a2e;
  font-size: 0.8rem;
  line-height: 1.5;
  text-align: left;
}
.notice-pending[hidden] { display: none; }
.notice-pending i { color: #a64a3a; margin-top: 0.15rem; flex-shrink: 0; }
.notice-pending strong { color: #8c3b2c; font-weight: 600; }
.notice-pending p { margin: 0.35rem 0 0; }
.notice-pending a { color: #8c3b2c; font-weight: 600; }

/* ── ONE PANEL FOR EVERYTHING ABOUT EXTENSIONS ──
   What used to be three bordered boxes - a gold quality note, a red warning,
   and a search panel nested inside a white box inside the red one - is one
   card in one colour family. Nothing here is an error: every extensions
   booking works this way, so it is fine print, not an alarm. A hairline rule
   inside the card separates "what the hair is" from "what happens next"
   instead of a second border and a second background.

   The taupe/gold family the rest of the wizard already uses, not a new red -
   this card and the calendar three taps later should look like the same
   product. */
.extensions-panel {
  margin: 0.7rem 0 0.2rem;
  padding: 1.1rem 1.2rem;
  border: 1px solid rgba(201, 169, 110, 0.3);
  border-radius: 14px;
  background: linear-gradient(180deg, rgba(201, 169, 110, 0.09), rgba(201, 169, 110, 0.04));
  font-size: 0.83rem;
  line-height: 1.6;
  color: var(--espresso, #3f3632);
}
.extensions-panel-quality { margin: 0; }
.extensions-panel-request {
  margin-top: 0.9rem;
  padding-top: 0.9rem;
  border-top: 1px solid rgba(201, 169, 110, 0.28);
}
.extensions-panel-lead { margin: 0; }
/* The one thing worth a client's attention sits in the site's own editorial
   voice - the same italic taupe the page titles already use for emphasis -
   rather than bold red text playing the part of a system warning. */
.extensions-panel-lead em {
  font-style: italic;
  font-family: var(--font-display);
  font-size: 1.05em;
  color: var(--taupe);
  font-weight: 600;
}
.extensions-panel-link {
  display: inline-block;
  margin-top: 0.7rem;
  background: none;
  border: none;
  padding: 0;
  color: var(--taupe);
  font-family: var(--font-body);
  font-size: 0.76rem;
  font-weight: 600;
  letter-spacing: 0.02em;
  text-decoration: underline;
  text-underline-offset: 3px;
  cursor: pointer;
}
.extensions-panel-link:hover { color: var(--espresso); }

/* ── THE LOOKUP, FLUSH IN THE SAME CARD ──
   No inner box: the fields sit directly on the panel so there is one
   background and one border for the whole thing, not a card inside a card. */
.ext-lookup { margin-top: 0.75rem; }
.ext-lookup-intro { margin: 0 0 0.6rem; font-size: 0.79rem; color: var(--espresso); }
/* The deposit terms. Money she does not get back is the one line here she
   must not skim past, so it carries a rule and a heavier weight - but it
   stays in the panel's own gold rather than becoming a red warning box.
   Nothing is going wrong; this is simply a term of the sale, and dressing
   it as an alarm would misrepresent it in both directions. */
.ext-lookup-deposit {
  margin: 0 0 0.7rem;
  padding-left: 0.7rem;
  border-left: 2px solid rgba(201, 169, 110, 0.55);
  font-size: 0.79rem;
  font-weight: 600;
  color: var(--espresso);
}
.ext-lookup-fields {
  display: flex;
  flex-wrap: wrap;
  gap: 0.55rem;
}
/* Frosted like every other input in this wizard (see .form-row on the
   details step), so this reads as part of the same form rather than a
   plain-HTML widget dropped into a styled page. */
.ext-lookup-fields input {
  flex: 1 1 9rem;
  min-width: 0;
  padding: 0.7rem 0.9rem;
  border: 1px solid rgba(255,255,255,0.6);
  border-radius: 12px;
  background: rgba(255,255,255,0.45);
  backdrop-filter: blur(14px);
  -webkit-backdrop-filter: blur(14px);
  box-shadow: 0 4px 14px rgba(44,36,32,0.04);
  font-family: var(--font-body);
  font-size: 0.85rem;
  color: var(--espresso);
}
.ext-lookup-fields input::placeholder { color: var(--greige); }
.ext-lookup-fields input:focus-visible { outline: none; border-color: var(--taupe); }
/* The site's own pill button, at the size this card calls for - full width
   below the fields on a phone, sitting beside them once there's room, rather
   than a flat rectangle in a different shape language from every other
   button on the page. */
.ext-lookup-fields .wizard-btn {
  flex: 1 1 100%;
  margin-left: 0;
  padding: 0.7rem 1.4rem;
}
@media (min-width: 460px) {
  .ext-lookup-fields .wizard-btn { flex: 0 0 auto; }
}
.ext-lookup-fields .wizard-btn:disabled { opacity: 0.55; cursor: default; }
.ext-lookup-result { margin: 0.6rem 0 0; font-size: 0.8rem; font-weight: 500; }
/* Colour carries the answer, but never alone - the message says it in words
   too, for anyone who cannot tell the two apart. */
.ext-lookup-result.ok  { color: #3B7355; }
.ext-lookup-result.bad { color: #A8503C; }

/* ── CATEGORY HEADING PHOTO ──
   Circular, beside the group heading. The same image appears smaller inside
   that category's tab above, so the tab and the section it jumps to read as
   the same thing. */
.category-group-head {
  display: flex;
  align-items: center;
  gap: 0.85rem;
  margin-bottom: 0.9rem;
}
.category-group-img {
  width: 64px;
  height: 64px;
  border-radius: 50%;
  overflow: hidden;
  flex-shrink: 0;
  background: var(--warmgrey);
  box-shadow: 0 6px 18px rgba(44, 36, 32, 0.10);
}
.category-group-img img { width: 100%; height: 100%; object-fit: cover; display: block; }
.category-group-head .category-group-title { margin-bottom: 0; }
@media (max-width: 560px) {
  .category-group-img { width: 52px; height: 52px; }
  .category-group-head { gap: 0.7rem; }
}

/* ── THE CANCELLATION TICK-BOX ──
   Warm red rather than the page's beige, because this is the one thing on the
   step that carries a consequence - at beige it read as decoration and people
   skimmed past it. Round to match the tick on the service and stylist cards,
   so "chosen" looks the same everywhere on the site. */
.terms-check {
  border-color: rgba(194, 94, 75, 0.35);
  background: rgba(194, 94, 75, 0.05);
  color: var(--espresso, #3f3632);
}
.terms-check:hover { border-color: rgba(194, 94, 75, 0.6); }
.terms-check input[type="checkbox"] {
  appearance: none;
  -webkit-appearance: none;
  width: 1.25rem;
  height: 1.25rem;
  margin-top: 0.1rem;
  border: 1.5px solid rgba(194, 94, 75, 0.55);
  border-radius: 50%;
  background: #fff;
  display: grid;
  place-content: center;
  transition: background 0.18s ease, border-color 0.18s ease;
}
.terms-check input[type="checkbox"]::after {
  content: '';
  width: 0.62rem;
  height: 0.34rem;
  border-left: 2px solid #fff;
  border-bottom: 2px solid #fff;
  transform: rotate(-45deg) translate(1px, -1px);
  opacity: 0;
  transition: opacity 0.15s ease;
}
.terms-check input[type="checkbox"]:checked {
  background: #C25E4B;
  border-color: #C25E4B;
}
.terms-check input[type="checkbox"]:checked::after { opacity: 1; }
.terms-check input[type="checkbox"]:focus-visible {
  outline: 2px solid #C25E4B;
  outline-offset: 2px;
}
.terms-check-missing {
  border-color: #C25E4B;
  background: rgba(194, 94, 75, 0.12);
}
@media (prefers-reduced-motion: reduce) {
  .terms-check input[type="checkbox"],
  .terms-check input[type="checkbox"]::after { transition: none; }
}

/* ── ADD-ONS OPEN ONLY ON THE CARD YOU TAP ──
   This used to apply on phones alone. It belongs at every width: with the
   chips always open, one card in a row carries five of them and its
   neighbours carry two, so the row stretches to the tallest and the short
   cards sit in a pool of empty space. Folded away, the list is a set of even
   rows you can scan; the add-ons arrive on the card you actually chose, which
   is the only moment they mean anything. */
/* ── WHEN THE ADD-ONS ARE VISIBLE ──
   On a wide screen they are always open. There is room for them, and a client
   comparing three colour services wants to see that two of them take grey
   coverage without tapping each one to find out. Cards no longer stretch to
   match their row (see the grid note below), so an open card sitting beside a
   shorter one costs nothing.

   On a phone they stay folded until the card is tapped. There the list is a
   single column, and five chips on every card turns a scannable list into a
   long scroll where nothing can be compared at all. */
@media (max-width: 819px) {
  .option-card-wrap:not(.selected) .option-card-combos { display: none; }
}
.option-card-wrap.selected .option-card-combos { padding-top: 0.75rem; }

/* ── TABS ON A WIDE SCREEN, DROPDOWN ON A PHONE ──
   A scrolling tab row only works when most of it is visible. On a phone it
   shows two and a half categories and hides the rest off the right edge, which
   is worse than a dropdown that lists them all. Same photos either way. */
#categoryDropdown { display: none; }
@media (max-width: 819px) {
  .category-tabs { display: none; }
  #categoryDropdown { display: block; }
}
.custom-select-option {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  text-align: left;
}
.custom-select-option .category-tab-img { width: 30px; height: 30px; }
.custom-select-trigger .custom-select-current { text-align: left; }

/* ── THE CALENDAR, TIGHTENED ──
   It was stretching to the full width of the step, so seven narrow columns sat
   far apart with 32px-tall cells between them. A month reads as a block, not a
   grid of distant numbers, so the widget is capped and centred and the cells
   are square. */
.calendar-widget,
.wizard-panel[data-panel="3"] > .calendar-widget {
  max-width: 22rem;
  margin-left: auto;
  margin-right: auto;
  padding: 1rem 1rem 1.1rem;
  border-radius: 18px;
}
.calendar-header { margin-bottom: 0.85rem; }
.calendar-month-label { font-size: 1.08rem; letter-spacing: 0.01em; }
.calendar-nav-btn { width: 28px; height: 28px; font-size: 0.7rem; }
.calendar-weekdays { gap: 0.25rem; margin-bottom: 0.35rem; }
.calendar-weekdays span { font-size: 0.58rem; letter-spacing: 0.08em; }
.calendar-grid { gap: 0.25rem; }
.calendar-day {
  /* Square, so the month keeps its shape at any width. */
  height: auto;
  aspect-ratio: 1;
  border-radius: 10px;
  font-size: 0.82rem;
  font-variant-numeric: tabular-nums;
}
.calendar-day.selected {
  /* A filled circle, the way a date is marked on paper. */
  border-radius: 50%;
  box-shadow: 0 4px 12px rgba(181, 168, 154, 0.45);
}
.calendar-day:hover:not(:disabled) { border-radius: 50%; }

/* The slot buttons underneath belong to the calendar above them, so they get
   the same width and centring rather than running the full step. */
#slotGrid {
  max-width: 22rem;
  margin-left: auto;
  margin-right: auto;
}

@media (max-width: 560px) {
  .calendar-widget,
  .wizard-panel[data-panel="3"] > .calendar-widget { max-width: 20rem; padding: 0.85rem; }
  .calendar-day { font-size: 0.78rem; }
  #slotGrid { max-width: 20rem; }
}

/* ── THE CALENDAR, TIGHTENED ──
   It was stretching to the full width of the step, so seven narrow columns sat
   far apart with 32px-tall cells between them. A month reads as a block, not a
   grid of distant numbers, so the widget is capped and centred and the cells
   are square. */
.calendar-widget,
.wizard-panel[data-panel="3"] > .calendar-widget {
  max-width: 22rem;
  margin-left: auto;
  margin-right: auto;
  padding: 1rem 1rem 1.1rem;
  border-radius: 18px;
}
.calendar-header { margin-bottom: 0.85rem; }
.calendar-month-label { font-size: 1.08rem; letter-spacing: 0.01em; }
.calendar-nav-btn { width: 28px; height: 28px; font-size: 0.7rem; }
.calendar-weekdays { gap: 0.25rem; margin-bottom: 0.35rem; }
.calendar-weekdays span { font-size: 0.58rem; letter-spacing: 0.08em; }
.calendar-grid { gap: 0.25rem; }
.calendar-day {
  /* Square, so the month keeps its shape at any width. */
  height: auto;
  aspect-ratio: 1;
  border-radius: 10px;
  font-size: 0.82rem;
  font-variant-numeric: tabular-nums;
}
.calendar-day.selected {
  /* A filled circle, the way a date is marked on paper. */
  border-radius: 50%;
  box-shadow: 0 4px 12px rgba(181, 168, 154, 0.45);
}
.calendar-day:hover:not(:disabled) { border-radius: 50%; }

/* The slot buttons underneath belong to the calendar above them, so they get
   the same width and centring rather than running the full step. */
#slotGrid {
  max-width: 22rem;
  margin-left: auto;
  margin-right: auto;
}

@media (max-width: 560px) {
  .calendar-widget,
  .wizard-panel[data-panel="3"] > .calendar-widget { max-width: 20rem; padding: 0.85rem; }
  .calendar-day { font-size: 0.78rem; }
  #slotGrid { max-width: 20rem; }
}


/* ── WHY THE SERVICE GRID KEPT BREAKING ──
   Two separate bugs, both of them the grid's doing.

   1. Grid items stretch to the height of their row by default. So one card
      with five add-ons open made its two neighbours just as tall, and they sat
      in a pool of empty space. align-items:start ends each card where its own
      content ends.

   2. The notices - the extensions confirmation warning and the hair-quality
      note - are inserted straight after the card they belong to, which makes
      them GRID ITEMS. They were being dealt into whatever cell came next, so a
      warning about Half Head Foil appeared beside Full Head Foil. Spanning the
      full row puts each one on its own line directly under its card, which is
      where it was always meant to be. */
.option-grid { align-items: start; }
/* height:100% earlier in this file stretches the wrap to the grid AREA, which
   is still the row height even once the grid stops stretching its items. Both
   have to go for a card to end where its content ends. */
.option-card-wrap { height: auto; }
/* The notices live inside the card they belong to now, so they no longer need
   to span the row - and must not, or they would stretch the card. Kept as a
   selector so an older cached page still lays them out sensibly. */
.option-grid > .extensions-panel,
.option-grid > .notice-external {
  grid-column: 1 / -1;
  margin-top: 0;
}
/* Inside a card: flush to its edges, sitting under the add-ons rather than
   floating in a gap of its own. */
.option-card-wrap > .extensions-panel,
.option-card-wrap > .notice-external {
  margin: 0;
  border-radius: 0;
  border-right: none;
  border-bottom: none;
  border-left: none;
  border-top: 1px solid rgba(201, 169, 110, 0.3);
  font-size: 0.8rem;
}

/* ── WAITING LIST ──
   Offered where a client has just been told there is nothing. Quiet by
   default: a closed button, not a form, because most people who hit a dead end
   simply pick another date and a form in their way would be noise. */
.waitlist-offer { margin-top: 1.1rem; }
.waitlist-open {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  font: inherit;
  font-size: 0.85rem;
  padding: 0.6rem 1.1rem;
  border-radius: 999px;
  border: 1px solid var(--warmgrey, #e9e3db);
  background: rgba(255,255,255,0.55);
  color: var(--espresso, #3f3632);
  cursor: pointer;
  transition: border-color 0.2s ease, background 0.2s ease;
}
.waitlist-open:hover { border-color: var(--taupe, #B5A89A); background: rgba(255,255,255,0.8); }
.waitlist-open i { color: var(--gold, #C9A96E); }

.waitlist-form {
  margin-top: 0.9rem;
  padding: 1.1rem 1.15rem 1.2rem;
  border: 1px solid var(--warmgrey, #e9e3db);
  border-radius: 14px;
  background: var(--linen, #fdfaf5);
  text-align: left;
}
.waitlist-form[hidden] { display: none; }
.waitlist-lead { font-size: 0.88rem; margin-bottom: 0.8rem; color: var(--espresso, #3f3632); }

/* The honest warning. Prominent on purpose: a client who thinks the list is a
   booking and turns up to nothing is worse off than one who never joined. */
.waitlist-nudge {
  background: rgba(201, 169, 110, 0.09);
  border: 1px solid rgba(201, 169, 110, 0.3);
  border-radius: 10px;
  padding: 0.8rem 0.95rem;
  font-size: 0.8rem;
  line-height: 1.6;
  color: var(--espresso, #3f3632);
  margin-bottom: 1rem;
}
.waitlist-nudge strong { display: block; margin-bottom: 0.25rem; }

.waitlist-fields {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(9.5rem, 1fr));
  gap: 0.6rem 0.8rem;
  margin-bottom: 0.9rem;
}
.waitlist-fields label {
  display: flex;
  flex-direction: column;
  gap: 0.25rem;
  font-size: 0.72rem;
  letter-spacing: 0.04em;
  color: var(--greige, #9f948e);
}
.waitlist-fields input {
  font: inherit;
  font-size: 0.88rem;
  padding: 0.5rem 0.6rem;
  border: 1px solid var(--warmgrey, #e9e3db);
  border-radius: 8px;
  background: #fff;
  color: var(--espresso, #3f3632);
}
.waitlist-fields input:focus-visible { outline: 2px solid var(--gold, #C9A96E); outline-offset: 1px; }

.waitlist-check {
  display: flex;
  gap: 0.6rem;
  align-items: flex-start;
  font-size: 0.8rem;
  line-height: 1.5;
  margin-bottom: 0.6rem;
  cursor: pointer;
  color: var(--espresso, #3f3632);
}
.waitlist-check input { margin-top: 0.15rem; accent-color: var(--gold, #C9A96E); flex: none; }

.waitlist-submit {
  font: inherit;
  font-size: 0.82rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  padding: 0.7rem 1.4rem;
  border: none;
  border-radius: 999px;
  background: var(--espresso, #3f3632);
  color: var(--linen, #fdfaf5);
  cursor: pointer;
  margin-top: 0.3rem;
}
.waitlist-submit:hover { background: var(--gold, #C9A96E); }
.waitlist-status { font-size: 0.8rem; margin-top: 0.6rem; color: var(--greige, #9f948e); }
.waitlist-status.bad { color: #C25E4B; }
.waitlist-done { font-size: 0.9rem; color: #059669; display: flex; gap: 0.5rem; align-items: flex-start; }

/* Consent, asked plainly and never pre-ticked. */
.form-check{
  display:flex; align-items:flex-start; gap:.55rem;
  margin:.2rem 0 .9rem; font-size:.86rem; line-height:1.45;
  color:var(--greige,#9f948e); cursor:pointer;
}
.form-check input{width:auto; margin:.2rem 0 0; accent-color:var(--taupe,#9a8577); flex:none}

