.treatment-group {
  padding-bottom: 2.4rem;
  margin-top: 0rem;
}

.treatment-header a {
  text-decoration: none;
}

/* The frozen h2 size predates the theme's fluid scale (it is that scale's
   phone h2); an h3/h4 heading takes the theme's own size for its level. */
.treatment-header h2 {
  font-size: 2.98598rem;
}

/* The gap between the heading and the description's rule belongs to the
   heading whatever its level (1.14.1) - it used to be h2-only, so a group
   set to h3 sat on the line. */
.treatment-header :is(h2, h3, h4) {
  padding-bottom: 1.2rem;
}

/* A showcase panel's title is the theme's tracked-caps label, spaced by the
   showcase's own rules; it never had this padding (its panels are h3), so
   keep it out rather than move every panel 12px. */
.bs-showcase .treatment-header :is(h3, h4) {
  padding-bottom: 0;
}

/* The group heading a step darker than the theme's heading mauve: the
   palette's ink let up 10% towards the surface, so it sits between the
   page title and the row names. Scoped here on purpose - the page title
   and the rest of the site keep the theme's colour. A chosen headingColor
   (a has-*-color preset) still wins. */
.treatment-header :is(h2, h3, h4) {
  color: var(--bs-heading);
}

/* Horizontal insets (1.13.1). The rows' text starts 1.7rem in from the card
   edge (its 1px border + the row's 1.6rem padding); the description's text
   sits on that same line, and the heading half a rem in - display type
   needs less inset than body text to read as aligned, so it stays
   deliberately proud of the text below. Properties so a theme can retune. */
.treatment-header {
  --bs-heading-inset: 0.5rem;
  --bs-description-inset: calc(1.6rem + 1px); /* the rows' padding + the card border */
}

.treatment-header :is(h2, h3, h4) {
  padding-inline: var(--bs-heading-inset);
}

.treatment-header .treatments-group-description {
  padding-inline: var(--bs-description-inset);
}

.treatment-header .treatments-group-description {
  border-top: 1px solid var(--bs-band-soft);
  padding-top: 0.7rem;
  padding-bottom: 1rem;
  min-height: 4rem;
}

.treatment-header .treatments-group-description *:first-child {
  margin-top: 0;
  margin-bottom: 0.8rem;
}

.treatment-header .treatments-group-description *:last-child {
  margin-bottom: 0rem;
}

.treatment-header .treatments-group-description *:only-child {
  margin-top: 0.8rem;
  margin-bottom: 2rem;
}

.treatments {
  container-type: inline-size;
}

table.responsive-table {
  max-width: calc(100vw - 5rem);
  width: 100%;
  overflow-x: auto;
  display: block;
  margin: 0 auto;
  border-spacing: 0;
  border-collapse: collapse;
}

table.responsive-table .heading {
  font-weight: bold;
}

table.responsive-table thead {
  display: block;
  float: left;
}

table.responsive-table thead > tr th:nth-child(even) {
  border-radius: 1rem 0rem 0rem 1rem;
}

table.responsive-table thead > tr th:nth-child(even) {
  background-color: #f0eded;
}

table.responsive-table thead > tr th:nth-child(even):hover {
  background-color: #edebeb;
}

table.responsive-table thead tr {
  display: block;
}

table.responsive-table tbody {
  display: block;
  width: auto;
  position: relative;
  overflow-x: auto;
  white-space: nowrap;
}

table.responsive-table tbody > tr {
  margin-right: -0.5rem;
}

table.responsive-table tbody > tr td {
  padding: 1.5rem;
}

table.responsive-table tbody > tr td:nth-child(even) {
  background-color: #f4f3f3;
}

table.responsive-table tbody > tr td:nth-child(even):hover {
  background-color: #edebeb;
}

table.responsive-table tbody tr {
  display: inline-block;
  vertical-align: top;
}

table.responsive-table th {
  padding: 1.5rem;
  margin: 0;
  vertical-align: top;
  text-align: left;
  display: block;
  text-align: right;
}

table.responsive-table td {
  margin: 0;
  vertical-align: top;
  display: block;
  text-align: left;
  border-left: 1px solid #f2f0f0;
}

table.responsive-table tr {
  border-bottom: none;
}

table.responsive-table tr:nth-last-child(1) td:nth-child(even) {
  border-radius: 0 10px 10px 0;
}

table.responsive-table .seperator {
  background-color: #f0eded;
  height: 0.2rem !important;
}

/* ==========================================================================
   Display-variant extension (handoff spec) - STREAMLINED per client:
   compact row layout for every row, the theme's own typography and green
   booking pill (no new text styling), no gradient header. Only functional
   UI (tier toggle, chips, add-on panel, badges) keeps accent colours.
   ========================================================================== */
.wp-block-bodysoul-treatments {
  /* The block rides the site-wide semantic palette layer, so the dev
     palette switcher restyles these rows too. */
  /* Palette Kit first, then the theme token, then a literal: the block must
     render identically where palette-kit is not installed. */
  --bs-teal: var(--pal-action, var(--bodysoul-action-book, #1E7A6B));
  /* 2026-09-02: the whole family rides Palette Kit first now, not just the
     base teal — hover/active from the palette's derived modifiers, tint
     from today-highlight (mapped to the same wash), border from line
     (Spa Deep maps line to this exact tint-border colour). Theme token
     second, literal last, as before. */
  --bs-teal-dark: var(--pal-action-hover, var(--bodysoul-action-book-hover, #16685B));
  --bs-teal-deep: var(--pal-action-active, var(--bodysoul-action-book-hover, #14584C));
  --bs-teal-tint: var(--pal-today-highlight, var(--bodysoul-tint-book, #E9F3F0));
  --bs-teal-border: var(--pal-line, var(--bodysoul-tint-book-border, #CFE5DF));
  /* The surface the rows sit on. It has to be OPAQUE and owned by the block:
     the row inks below are fixed dark, so if the card lets a coloured Group or
     Row background through, every even row renders near-black text on whatever
     that colour is (measured 1.5:1 on a dark teal group - a contrast failure,
     not a cosmetic one). Set this on a container to re-skin the card; the dark
     scheme at the end of this file does exactly that. */
  --bs-surface: var(--pal-surface, var(--bodysoul-surface-page, #FFFFFF));
  --bs-row-alt: var(--pal-row-wash, var(--bodysoul-row-wash, #F5EFF0));
  /* treatment-ink / treatment-hairline are component roles this plugin
     registers (includes/palette.php): the row ink is near-black and the
     hairline warm, while a palette's core ink/line are usually neither —
     so these get their own mapper knobs instead of claiming core roles
     that would move them wrongly. Unmapped (the default), the literals
     stand and nothing changes. */
  --bs-hairline: var(--pal-treatment-hairline, #F0E7E8);
  --bs-ink: var(--pal-treatment-ink, #1A1A1A);
  --bs-meta: #8f8f8f;
  --bs-muted: #AAAAAA;
  --bs-faint: #CCCCCC;
  /* The cell styles' three literals (see "Cell styles"): a readable grey a
     step above meta, the count band, and a divider a step darker than the
     hairline. */
  --bs-dim: #555555;
  --bs-band: #4F4A49;
  --bs-rule: #E3DADB;
  /* The flush style's band and divider ride the palette's surface in its
     hover and active states - the neutral, barely-warm greys the palette
     derives from the surface - so they desaturate with it. The band is
     that hover grey let down 40% towards the surface (the full grey read
     as heavy; the literal is the same mix for a browser without
     color-mix, and the @supports block below is what applies the live
     one). Any lighter and it vanishes against the odd rows' wash. */
  --bs-band-soft: #E8E4E5;
  --bs-divider: var(--pal-surface-active, #C3C0C1);
  --bs-heading: #7C6E6B;
  /* Georgia is the theme's existing serif (headings, .money prices) -
     no new font families. */
  --bs-serif: Georgia, "Times New Roman", Times, serif;
}

@supports (color: color-mix(in oklab, red 50%, blue)) {
  .wp-block-bodysoul-treatments {
    --bs-band-soft: color-mix(in oklab, var(--pal-surface-hover, #DCD8D9) 60%, var(--bs-surface));
    --bs-heading: color-mix(in oklab, var(--pal-ink, #6E5F5B) 90%, var(--bs-surface));
  }
}

/* Tier toggle - plain pill that sits in the standard heading area */
.bs-tier-toggle {
  display: inline-flex;
  padding: 3px;
  border-radius: 100px;
  background: rgba(0, 0, 0, 0.08);
  vertical-align: middle;
  margin: 0.4rem 0;
}

.bs-tier-toggle__btn {
  border: 0;
  background: transparent;
  color: inherit;
  padding: 0.4rem 1.4rem;
  border-radius: 100px;
  cursor: pointer;
}

.bs-tier-toggle__btn.is-active {
  background: var(--bs-teal);
  color: var(--bodysoul-btn-ink, #fff);
}

.bs-savings-note {
  color: var(--bs-muted);
  margin: 0.8rem 0 0;
}

/* Active special shared by every priced row (specialMessaging auto/group).
   Its own element, so a theme can skin it apart from the savings note. */
.bs-special-line {
  color: var(--bs-teal-dark);
  font-weight: 600;
  margin: 0.8rem 0 0;
}

/* Row container + compact rows: layout only, text inherits the theme */
.bs-rows {
  background: var(--bs-surface);
  border: 1px solid rgba(0, 0, 0, 0.07);
  border-radius: 12px;
  overflow: hidden;
}

.bs-row {
  border-bottom: 1px solid rgba(0, 0, 0, 0.06);
}

.bs-row:nth-child(odd) {
  background: var(--bs-row-alt);
}

.bs-row:last-child {
  border-bottom: 0;
}

.bs-row__main {
  position: relative; /* the edit circle's containing block */
  display: flex;
  align-items: center;
  gap: 1.2rem;
  min-height: 5.8rem;
  padding: 0.7rem 1.6rem;
  box-sizing: border-box;
}

/* Row quick-edit circle (includes/quick-edit.php) - editors only. Out of the
   flow, parked in the row head's 1.6rem left padding and vertically centred on
   the head (not the row, so a packs row's track is not what it centres on),
   so the row measures the same with it as without. Sized to that gutter: it
   clears the name's first letter by a hair and grows on hover, where the
   overlap no longer matters. */
.bs-row__edit {
  position: absolute;
  z-index: 3;
  top: 50%;
  left: 0.1rem;
  display: grid;
  place-items: center;
  width: 1.4rem;
  height: 1.4rem;
  box-sizing: border-box;
  border-radius: 50%;
  border: 1px solid var(--bs-teal);
  background: var(--bs-surface);
  color: var(--bs-teal);
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.18);
  opacity: 0.8;
  text-decoration: none;
  transform: translateY(-50%);
  transition: opacity 150ms ease, transform 150ms ease;
  pointer-events: auto; /* stays clickable inside an editor wrapper that disables pointer events */
}

.bs-row__edit:hover,
.bs-row__edit:focus-visible {
  opacity: 1;
  transform: translateY(-50%) scale(1.4);
  background: var(--bs-teal);
  color: var(--bodysoul-btn-ink, #fff);
}

.bs-row__edit:focus-visible {
  outline: 2px solid var(--bs-teal);
  outline-offset: 2px;
}

.bs-row__edit svg {
  display: block;
}

.bs-row__text {
  flex: 1;
  min-width: 0;
}

.bs-row__name {
  font-weight: 700;
  font-size: 1.7rem;
  line-height: 1.35;
  color: var(--bs-ink);
  display: flex;
  align-items: center;
  gap: 0.6rem;
}

.bs-row__infobtn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 1.8rem;
  height: 1.8rem;
  border-radius: 50%;
  border: 1px solid var(--bs-faint);
  background: transparent;
  color: var(--bs-muted);
  font-size: 1.3rem;
  font-weight: 700;
  font-style: italic;
  line-height: 1;
  cursor: pointer;
  flex: none;
  /* The em box centres; the glyph does not - an "i" has no descender, so
     a centred em box leaves it high in the circle, and the italic leans
     it right. The top and right padding are those two shares, which put
     the glyph on the circle's centre. */
  padding: 0.1rem 0.2rem 0 0;
}

.bs-row__infobtn[aria-expanded="true"] {
  background: var(--bs-teal);
  border-color: var(--bs-teal);
  color: var(--bodysoul-btn-ink, #fff);
}

.bs-row__meta {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 0.7rem;
  margin-top: 0.3rem;
  font-size: 1.4rem;
  color: var(--bs-meta);
}

.bs-row__dot {
  color: var(--bs-faint);
}

/* No flex gap: the markup's "&nbsp;mins" is its own flex item, so a gap
   stacked a second space onto the one it already carries. The clock keeps
   its own margin, and sits a step lighter than the time it labels. */
.bs-row__duration {
  display: inline-flex;
  align-items: center;
}

.bs-row__duration > svg {
  margin-right: 0.35rem;
  color: var(--bs-muted);
}

.bs-row__duration.is-modified {
  color: var(--bs-teal-dark);
  font-weight: 600;
}

.bs-row__duration.is-modified > svg {
  color: inherit;
}

.bs-row__pricecol {
  flex: none;
  min-width: 6.4rem;
  text-align: right;
}

.bs-row__price {
  font-family: var(--bs-serif);
  font-size: 1.8rem;
  font-weight: 600;
  line-height: 1;
  color: var(--bs-ink);
}

/* Pre-special price (specials meta, active window): struck-out original
   ahead of the discounted price the row context carries. */
.bs-row__was {
  margin-right: 0.4rem;
  font-size: 1.2rem;
  color: var(--bs-faint);
  text-decoration: line-through;
  text-decoration-thickness: 1px;
}

/* Row tag for an active special (specialMessaging rows, or auto when the
   rows' specials differ). Static text, rendered server-side. */
.bs-tag {
  display: inline-flex;
  align-items: center;
  padding: 0.1rem 0.7rem;
  border-radius: 100px;
  font-size: 1.15rem;
  font-weight: 600;
  line-height: 1.6;
  white-space: nowrap;
}

.bs-tag--special {
  background: var(--bs-teal-tint);
  border: 1px solid var(--bs-teal-border);
  color: var(--bs-teal-dark);
}

.bs-row__breakdown {
  display: block;
  margin-top: 0.3rem;
  color: var(--bs-faint);
  font-size: 1.1rem;
}

.bs-row__breakdown:empty {
  display: none;
}

.bs-book {
  flex: none;
  /* Containing block for the visually-hidden spans below. Without it they are
     positioned against a distant ancestor and escape any scroll container the
     button sits in - see the note on .bs-book__for. */
  position: relative;
  display: inline-flex;
  align-items: center;
  gap: 0.6rem;
  /* Same metrics as the theme's button mixin (create-button-var): each row's
     pill is a first-class booking CTA per client direction, and the 19px
     bold text is WCAG-large - required for the bright 3:1 palettes. */
  padding: 0.6rem 1.4rem;
  border-radius: 100px;
  background: var(--bodysoul-btn-book-bg, var(--bs-teal));
  color: var(--bodysoul-btn-ink, #fcfcfc);
  font-size: 1.9rem;
  font-weight: bold;
  /* line-height 1 keeps the row at the ~58px density target even when the
     live button mode adds its 3px ring */
  line-height: 1;
  text-decoration: none;
  white-space: nowrap;
}

.bs-book:hover,
.bs-book:focus-visible {
  background: var(--bodysoul-btn-book-bg-hover, var(--bs-teal-dark));
  color: var(--bodysoul-btn-ink, #fff);
}

/* Row Book button states (bookButtonStyle: auto | pill | compact | icon).
   Every mode renders BOTH labels and hides what it does not want, because
   `auto` switches state on width and CSS cannot restore a label the server
   never printed. `pill` is the base state, so it needs no modifier. */
.bs-book__short {
  display: none;
}

.bs-book--compact .bs-book__long,
.bs-book--icon .bs-book__short {
  display: none;
}

.bs-book--compact .bs-book__short {
  display: inline;
}

/* Screen-reader-only, and deliberately NOT display:none - that would drop the
   treatment name from the accessible name, which is the only reason it is
   here. In icon states the label rides the same rule so the button keeps a
   name with no visible text at all.

   The `position: relative` on .bs-book above is what CONTAINS these: absolutely
   positioned children of a static button resolve their containing block to
   whatever distant ancestor happens to be positioned - a split-section wrapper,
   in the showcase - which puts them outside the rail's overflow clipping. That
   stretched the document to 2235px on a 1280px window before it was found. */
.bs-book__for,
.bs-book--icon .bs-book__label {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

/* Icon-only row booking button: a compact circle for dense lists.
   The glyph is the sprite's bstr-icon-book symbol (includes/icons.php). */
.bs-book--icon {
  width: 3.6rem;
  height: 3.6rem;
  padding: 0;
  justify-content: center;
  border-radius: 50%;
}

.bs-book--icon svg {
  width: 1.7rem;
  height: 1.7rem;
}

/* Auto: the button trades words for space as the BLOCK narrows - container
   width, not viewport, because a panel in a two-up showcase is narrow on a
   desktop screen and a phone-width media query would never fire for it.
   Both thresholds are the ones this stylesheet already uses for the row
   grid (40rem / 55rem), a hair under so they cannot both match at the edge;
   at 320-430px the row list measures 32.6-39.8rem, so every phone lands in
   the icon band and the 140px pill stops eating 43% of the row. */
@container (max-width: 54.99rem) {
  .bs-book--auto .bs-book__long {
    display: none;
  }
  .bs-book--auto .bs-book__short {
    display: inline;
  }
}

@container (max-width: 39.99rem) {
  .bs-book--auto {
    width: 3.6rem;
    height: 3.6rem;
    padding: 0;
    justify-content: center;
    border-radius: 50%;
  }
  .bs-book--auto svg {
    width: 1.7rem;
    height: 1.7rem;
  }
  .bs-book--auto .bs-book__label {
    position: absolute;
    width: 1px;
    height: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
    border: 0;
  }
}

/* Category-level "Book Any …" (spec 4, level 1): the largest of the three
   booking CTAs, in the block header. */
.bs-book--category {
  padding: 1.3rem 2.6rem;
  font-size: 1.6rem;
  box-shadow: 0 3px 12px rgba(0, 0, 0, 0.18);
  margin: 0.4rem 0 0.4rem 1.2rem;
  vertical-align: middle;
}

@media (prefers-reduced-motion: no-preference) {
  .bs-book {
    transition: background 150ms ease, transform 150ms ease;
  }
  .bs-book:hover {
    transform: scale(1.02);
  }
}

/* Sliding panels (info / add-ons). Padding lives on the nested div so the
   0fr collapse really is 0px tall. */
.bs-panel {
  display: grid;
  grid-template-rows: 0fr;
  visibility: hidden;
}

@media (prefers-reduced-motion: no-preference) {
  .bs-panel {
    transition: grid-template-rows 240ms ease, visibility 240ms;
  }
}

.bs-panel.is-open {
  grid-template-rows: 1fr;
  visibility: visible;
}

.bs-panel__inner {
  overflow: hidden;
  min-height: 0;
}

/* The description: a step smaller than the page text, on the band grey,
   so an open row reads as a note under its heading rather than more page. */
.bs-row__info {
  padding: 1.2rem 1.6rem 1.3rem;
  font-size: 1.3rem;
  line-height: 1.5;
  color: var(--bs-dim);
  background: var(--bs-band-soft);
}

.bs-row__info p {
  margin: 0 0 0.8em;
}

.bs-row__info p:last-child {
  margin-bottom: 0;
}

.bs-row__learn {
  color: var(--bs-teal-dark);
  text-decoration: none;
  font-weight: 500;
}

/* Footer link out to the full category page (seeAllUrl). Structure only -
   the theme skins it through .bs-seeall. */
.bs-seeall {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  margin-top: 1.2rem;
  color: var(--bs-teal-dark);
  text-decoration: none;
  font-weight: 600;
}

.bs-seeall:hover,
.bs-seeall:focus-visible {
  text-decoration: underline;
}

@media (prefers-reduced-motion: no-preference) {
  .bs-seeall__arrow {
    transition: transform 150ms ease;
  }
  .bs-seeall:hover .bs-seeall__arrow {
    transform: translateX(3px);
  }
}

/* Add-on chips (inline, <=2 add-ons) */
.bs-chip {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  padding: 0.25rem 0.9rem;
  border-radius: 100px;
  border: 1px solid var(--bs-faint);
  background: transparent;
  color: inherit;
  font-size: 0.8em;
  line-height: 1.5;
  cursor: pointer;
  white-space: nowrap;
}

@media (prefers-reduced-motion: no-preference) {
  .bs-chip {
    transition: background 140ms ease, border-color 140ms ease, color 140ms ease;
  }
}

.bs-chip.is-active {
  background: var(--bs-teal-tint);
  border-color: var(--bs-teal);
  color: var(--bs-teal-deep);
}

.bs-chip__mark {
  font-weight: 700;
}

.bs-chip__price {
  color: var(--bs-muted);
}

.bs-chip.is-active .bs-chip__price {
  color: var(--bs-teal-deep);
}

/* Add-on panel (3+ add-ons) */
.bs-chip--trigger .bs-chip__badge {
  display: none;
  min-width: 1.6rem;
  height: 1.6rem;
  border-radius: 100px;
  background: var(--bs-teal);
  color: #fff;
  font-weight: 700;
  line-height: 1.6rem;
  text-align: center;
  padding: 0 0.3rem;
}

.bs-chip--trigger.has-active .bs-chip__badge {
  display: inline-block;
}

.bs-chip--trigger.is-open {
  border-color: var(--bs-teal);
  color: var(--bs-teal-deep);
}

.bs-addons {
  padding: 0.4rem 1.6rem 1.2rem;
  display: grid;
  gap: 0.6rem;
}

.bs-addons__item {
  display: flex;
  align-items: center;
  gap: 1rem;
  width: 100%;
  text-align: left;
  padding: 0.8rem 1.2rem;
  border-radius: 12px;
  border: 1px solid var(--bs-hairline);
  background: var(--bs-surface);
  color: inherit;
  cursor: pointer;
}

@media (prefers-reduced-motion: no-preference) {
  .bs-addons__item {
    transition: border-color 140ms ease, background 140ms ease;
  }
}

.bs-addons__item.is-active {
  background: var(--bs-teal-tint);
  border-color: var(--bs-teal-border);
}

.bs-addons__emoji {
  flex: none;
}

.bs-addons__text {
  flex: 1;
  min-width: 0;
}

.bs-addons__label {
  display: block;
  font-weight: 600;
}

.bs-addons__desc {
  display: block;
  font-size: 0.85em;
}

.bs-addons__cost {
  flex: none;
  text-align: right;
  font-weight: 600;
}

.bs-addons__mins {
  display: block;
  font-size: 0.85em;
  font-weight: 400;
  color: var(--bs-muted);
}

.bs-addons__mark {
  flex: none;
  width: 2rem;
  height: 2rem;
  border-radius: 50%;
  border: 1px solid var(--bs-faint);
  color: var(--bs-muted);
  font-weight: 700;
  line-height: 1.9rem;
  text-align: center;
}

.bs-addons__item.is-active .bs-addons__mark {
  background: var(--bs-teal);
  border-color: var(--bs-teal);
  color: #fff;
}

.bs-addons__summary {
  font-size: 0.85em;
  color: var(--bs-muted);
}

.bs-addons__summary:empty {
  display: none;
}

.bs-addons__total {
  display: none;
  padding: 0.7rem 1.2rem;
  border-radius: 10px;
  background: var(--bs-teal-tint);
  border: 1px solid var(--bs-teal-border);
  color: var(--bs-teal-deep);
  font-weight: 600;
}

.bs-addons__total.is-visible {
  display: block;
}

/* Session-pack scroll track + book strip (sessions variant, spec 3.4).
   Edge fades take their colour from the row they sit on, so they blend on
   both the white and the --bs-row-alt washed rows. */
.bs-row {
  --bs-fade-bg: var(--bs-surface);
}

.bs-row:nth-child(odd) {
  --bs-fade-bg: var(--bs-row-alt);
}

.bs-track-wrap {
  position: relative;
  border-top: 1px solid var(--bs-hairline);
}

.bs-track {
  position: relative; /* cells' offsetParent, for the auto-scroll maths */
  display: flex;
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  scrollbar-width: none;
  -webkit-overflow-scrolling: touch;
}

.bs-track::-webkit-scrollbar {
  display: none;
}

.bs-track-wrap::before,
.bs-track-wrap::after {
  content: "";
  position: absolute;
  top: 0;
  bottom: 0;
  z-index: 2;
  pointer-events: none;
  opacity: 0;
}

.bs-track-wrap::before {
  left: 0;
  width: 2.8rem;
  background: linear-gradient(to right, var(--bs-fade-bg), transparent);
}

.bs-track-wrap::after {
  right: 0;
  width: 3.6rem;
  background: linear-gradient(to left, var(--bs-fade-bg), transparent);
}

.bs-track-wrap.has-fade-l::before,
.bs-track-wrap.has-fade-r::after {
  opacity: 1;
}

.bs-track__hint {
  position: absolute;
  right: 0.6rem;
  top: 50%;
  transform: translateY(-50%);
  z-index: 3;
  pointer-events: none;
  font-size: 1.2rem;
  font-weight: 700;
  color: var(--bs-faint);
  opacity: 0;
}

.bs-track-wrap.has-fade-r .bs-track__hint {
  opacity: 1;
}

/* A top-aligned column whose was/per lines keep their box when empty: a
   <button> centres its content, so a 1x cell (no /ea) or a cell the special
   did not lower used to sit its price a line off its neighbours'. */
.bs-cell {
  position: relative;
  display: flex;
  flex-direction: column;
  justify-content: flex-start;
  flex: 0 0 8.8rem;
  scroll-snap-align: start;
  padding: 1.1rem 0.6rem 1.3rem;
  border: 0;
  border-right: 1px solid var(--bs-hairline);
  background: transparent;
  color: inherit;
  text-align: center;
  cursor: pointer;
}

.bs-cell:last-child {
  border-right: 0;
}

/* A duration cell (multi-time row): the same cell, nothing to select. */
.bs-cell--time {
  cursor: default;
}

.bs-cell::before {
  content: "";
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  height: 2.5px;
  border-radius: 0 0 3px 3px;
  background: var(--bs-teal);
  opacity: 0;
}

.bs-cell.is-selected {
  background: var(--bs-teal-tint);
}

.bs-cell.is-selected::before {
  opacity: 1;
}

.bs-cell.is-dimmed {
  opacity: 0.3;
}

.bs-cell[disabled] {
  cursor: default;
  color: var(--bs-muted);
}

.bs-cell__label {
  display: block;
  font-size: 1.05rem;
  font-weight: 700;
  letter-spacing: 0.07em;
  text-transform: uppercase;
  color: var(--bs-faint);
  margin-bottom: 0.6rem;
}

.bs-cell.is-selected .bs-cell__label {
  color: var(--bs-teal);
}

/* A pack's (or duration's) pre-special total, above the serif price.
   Printed only on rows whose special lowered one; empty, but still a line
   tall, for a cell (or tier) it did not. */
.bs-cell__was {
  display: block;
  font-size: 1.05rem;
  line-height: 1.4;
  min-height: 1.4em;
  color: var(--bs-faint);
  text-decoration-thickness: 1px;
  margin-bottom: 0.2rem;
}

.bs-cell__price {
  display: block;
  font-family: var(--bs-serif);
  font-size: 2rem;
  font-weight: 600;
  line-height: 1;
  color: var(--bs-ink);
}

.bs-cell__per {
  display: block;
  font-size: 1.05rem;
  line-height: 1.4;
  min-height: 1.4em;
  color: var(--bs-faint);
  margin-top: 0.3rem;
}

/* ---- Cell styles (cellStyle, 1.7.0) ------------------------------------
   The pack/duration cell's look, chosen per block, page or site. The rules
   above ARE `plain` - render.php prints no modifier for it, so a site that
   never chose renders byte for byte. The three variations share one
   correction (the count and the /ea line in ink with air around the /ea;
   the struck original stays faint, it is indicative) and differ in
   structure. Each keeps the 1.6.2 invariant the audit measures on every
   one: the price line level across a row, a row's cells one height. */
.bs-cells--weighted .bs-cell,
.bs-cells--banded .bs-cell,
.bs-cells--joined .bs-cell,
.bs-cells--flush .bs-cell,
.bs-cells--linked .bs-cell {
  flex-basis: 9.6rem;
  border-right-color: var(--bs-rule);
}

.bs-cells--weighted .bs-cell__label,
.bs-cells--banded .bs-cell__label,
.bs-cells--joined .bs-cell__label,
.bs-cells--flush .bs-cell__label,
.bs-cells--linked .bs-cell__label {
  font-size: 1.15rem;
  color: var(--bs-ink);
}

.bs-cells--weighted .bs-cell[disabled] .bs-cell__label,
.bs-cells--banded .bs-cell[disabled] .bs-cell__label,
.bs-cells--joined .bs-cell[disabled] .bs-cell__label,
.bs-cells--flush .bs-cell[disabled] .bs-cell__label,
.bs-cells--linked .bs-cell[disabled] .bs-cell__label {
  color: var(--bs-muted);
}

.bs-cells--weighted .bs-cell__per,
.bs-cells--banded .bs-cell__per,
.bs-cells--joined .bs-cell__per,
.bs-cells--flush .bs-cell__per,
.bs-cells--linked .bs-cell__per {
  font-size: 1.15rem;
  font-weight: 600;
  color: var(--bs-dim);
}

/* Weighted: the stack as it was, with air. */
.bs-cells--weighted .bs-cell {
  padding: 1.3rem 0.8rem 1.5rem;
}

.bs-cells--weighted .bs-cell__label {
  margin-bottom: 0.8rem;
}

.bs-cells--weighted .bs-cell__per {
  margin-top: 0.7rem;
}

/* Banded: a card per cell - the count in a dark band (teal once selected,
   which is what carries the selection here, so the top bar is off), the
   struck original and the price on the card, a rule above the /ea. Joined
   (below) is the same cell; the rules it shares name both. */
.bs-cells--banded .bs-track {
  gap: 0.6rem;
  padding: 0.9rem 0.6rem 1.1rem;
}

.bs-cells--banded .bs-cell {
  padding: 0;
  border: 1px solid var(--bs-rule);
  border-radius: 8px;
  overflow: hidden;
  background: var(--bs-surface);
}

.bs-cells--banded .bs-cell::before,
.bs-cells--joined .bs-cell::before,
.bs-cells--flush .bs-cell::before {
  display: none;
}

.bs-cells--banded .bs-cell.is-selected,
.bs-cells--joined .bs-cell.is-selected,
.bs-cells--flush .bs-cell.is-selected {
  background: var(--bs-teal-tint);
  border-color: var(--bs-teal-border);
}

.bs-cells--banded .bs-cell__label,
.bs-cells--joined .bs-cell__label,
.bs-cells--flush .bs-cell__label {
  margin: 0 0 0.9rem;
  padding: 0.55rem 0.4rem;
  background: var(--bs-band);
  color: #fff;
}

.bs-cells--banded .bs-cell.is-selected .bs-cell__label,
.bs-cells--joined .bs-cell.is-selected .bs-cell__label,
.bs-cells--flush .bs-cell.is-selected .bs-cell__label {
  background: var(--bs-teal);
  color: #fff;
}

.bs-cells--banded .bs-cell[disabled] .bs-cell__label,
.bs-cells--joined .bs-cell[disabled] .bs-cell__label,
.bs-cells--flush .bs-cell[disabled] .bs-cell__label {
  background: var(--bs-muted);
  color: #fff;
}

.bs-cells--banded .bs-cell__was,
.bs-cells--banded .bs-cell__price,
.bs-cells--joined .bs-cell__was,
.bs-cells--flush .bs-cell__was,
.bs-cells--joined .bs-cell__price,
.bs-cells--flush .bs-cell__price {
  padding: 0 0.6rem;
}

.bs-cells--banded .bs-cell__price,
.bs-cells--joined .bs-cell__price,
.bs-cells--flush .bs-cell__price {
  padding-bottom: 1rem;
}

.bs-cells--banded .bs-cell__per,
.bs-cells--joined .bs-cell__per,
.bs-cells--flush .bs-cell__per {
  margin-top: auto; /* the rule sits at the card's foot in every cell */
  padding: 0.6rem 0.4rem 0.8rem;
  border-top: 1px solid var(--bs-rule);
}

.bs-cells--banded .bs-cell__per:empty,
.bs-cells--joined .bs-cell__per:empty,
.bs-cells--flush .bs-cell__per:empty {
  border-top-color: transparent; /* the 1x cell: the box stays, the rule goes */
}

/* Joined: banded without the gaps - the cells share one card and the band
   runs across them. The card's edge is the outer cells' borders (the track
   stays full width: a scroll container's fit-content is its cells' TEXT
   width in WebKit, not their flex basis) and the divider between cells is
   an inset shadow, which the band paints over where a border would cut a
   light line through it. */
.bs-cells--joined .bs-track {
  padding: 0.9rem 0.6rem 1.1rem;
}

.bs-cells--joined .bs-cell {
  padding: 0;
  border: 1px solid var(--bs-rule);
  border-left-width: 0;
  border-right-width: 0;
  box-shadow: inset -1px 0 0 var(--bs-rule);
  background: var(--bs-surface);
}

.bs-cells--joined .bs-cell:first-child {
  border-left-width: 1px;
  border-radius: 8px 0 0 8px;
  overflow: hidden; /* clips the band to the corner */
}

.bs-cells--joined .bs-cell:last-child {
  border-right-width: 1px;
  border-radius: 0 8px 8px 0;
  overflow: hidden;
  box-shadow: none;
}

.bs-cells--joined .bs-cell__label {
  box-shadow: inset -1px 0 0 rgba(255, 255, 255, 0.18);
}

.bs-cells--joined .bs-cell:last-child .bs-cell__label {
  box-shadow: none;
}

/* Flush: the band, the divider and the rule with no card - the cells sit in
   the row as plain's do. The band is the palette's neutral (surface in its
   hover state - the teal tint read as too saturated) with the row ink on
   it, and runs the row's FULL width: it is painted on the track wrap behind
   the cells at the label's fixed height, so the two agree to the pixel;
   every cell keeps its right divider, so the strip reads as a table whose
   header spans the row. */
.bs-cells--flush .bs-track-wrap {
  background: linear-gradient(var(--bs-band-soft), var(--bs-band-soft)) 0 0 / 100% 2.8rem no-repeat;
}

.bs-cells--flush .bs-cell {
  padding: 0;
  border: 0;
  box-shadow: inset -1px 0 0 var(--bs-divider);
}

.bs-cells--flush .bs-cell__label {
  height: 2.8rem;
  line-height: 2.8rem;
  padding: 0 0.4rem;
  background: var(--bs-band-soft);
  color: var(--bs-ink);
  box-shadow: inset -1px 0 0 var(--bs-divider);
}

.bs-cells--flush .bs-cell[disabled] .bs-cell__label {
  background: var(--bs-band-soft);
  color: var(--bs-muted);
}

.bs-cells--flush .bs-cell__per {
  border-top-color: var(--bs-divider);
}

/* Linked: the count and the per-session figure read as one line under the
   price - "6× at $108/ea", the maths the total came from. The "at" is
   generated on a non-empty /ea only, so the 1x cell reads "1×". A duration
   cell has no /ea and keeps its label on top. */
.bs-cells--linked .bs-cell {
  display: grid;
  grid-template-columns: auto auto;
  justify-content: center;
  align-content: start;
  align-items: baseline;
  column-gap: 0.35em;
  padding: 1.3rem 0.8rem 1.5rem;
}

.bs-cells--linked .bs-cell__was,
.bs-cells--linked .bs-cell__price {
  grid-column: 1 / -1;
}

.bs-cells--linked .bs-cell__label,
.bs-cells--linked .bs-cell__per {
  grid-row: 3;
  line-height: 1.4;
  margin: 0.8rem 0 0;
}

.bs-cells--linked .bs-cell__per:not(:empty)::before {
  content: "at ";
  font-weight: 400;
}

.bs-cells--linked .bs-cell--time {
  display: flex;
  justify-content: flex-start; /* the grid's centring would re-centre the column */
  align-items: stretch;
}

.bs-cells--linked .bs-cell--time .bs-cell__label {
  margin: 0 0 0.8rem;
}

/* A duration cell's label reads as the row's own duration does - clock,
   number, "mins", lower case, regular weight - under every cell style, so
   it sits after them all. The pack count keeps its small caps. */
.bs-cell--time .bs-cell__label {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 0.3rem;
  font-size: 1.2rem;
  font-weight: 400;
  letter-spacing: 0;
  text-transform: none;
}

.bs-cell--time .bs-cell__label > svg {
  flex: none;
  opacity: 0.7; /* a step lighter than its label whatever the style paints it */
}

.bs-strip {
  display: flex;
  align-items: center;
  gap: 1rem;
  padding: 1rem 1.6rem 1.3rem;
  border-top: 1px solid var(--bs-hairline);
}

.bs-strip__text {
  flex: 1;
  min-width: 0;
}

.bs-strip__label {
  display: block;
  font-size: 1.2rem;
  font-weight: 600;
  color: var(--bs-teal-dark);
}

.bs-strip__meta {
  display: block;
  font-size: 1.25rem;
  color: var(--bs-meta);
  margin-top: 0.1rem;
}

@media (prefers-reduced-motion: no-preference) {
  .bs-cell {
    transition: background 150ms ease, opacity 150ms ease;
  }
  .bs-cell__label {
    transition: color 150ms ease;
  }
  .bs-track-wrap::before,
  .bs-track-wrap::after,
  .bs-track__hint {
    transition: opacity 150ms ease;
  }
}

/* Dark mode: surfaces follow the theme's dark tokens */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .wp-block-bodysoul-treatments {
    --bs-surface: var(--pal-surface-dark, var(--bodysoul-surface-raised, #272221));
    --bs-teal: var(--pal-action-dark, var(--pal-action, var(--bodysoul-action-book, #1E7A6B)));
    --bs-ink: #e8e0dc;
    --bs-meta: #a89f9b;
    --bs-row-alt: #2c2726;
    --bs-hairline: #3a3433;
    --bs-teal-tint: #1d2b29;
    --bs-teal-border: #2f4a47;
    --bs-muted: #9b918d;
    --bs-faint: #6f6663;
    --bs-dim: #c9c0bc;
    --bs-band: #4a4342;
    --bs-rule: #46403f;
    --bs-band-soft: #3a3433;
    --bs-divider: #4a4342;
    --bs-heading: var(--pal-ink-dark, #cbbdbb);
  }
  :root:not([data-theme="light"]) .bs-rows,
  :root:not([data-theme="light"]) .bs-row,
  :root:not([data-theme="light"]) .bs-addons__item {
    background: var(--bs-surface);
    border-color: rgba(255, 255, 255, 0.07);
  }
  :root:not([data-theme="light"]) .bs-row:nth-child(odd) {
    background: var(--bs-row-alt);
  }
  :root:not([data-theme="light"]) .bs-row {
    --bs-fade-bg: var(--bs-surface);
  }
  :root:not([data-theme="light"]) .bs-row:nth-child(odd) {
    --bs-fade-bg: var(--bs-row-alt);
  }
}
:root[data-theme="dark"] .wp-block-bodysoul-treatments {
  --bs-surface: var(--pal-surface-dark, var(--bodysoul-surface-raised, #272221));
  --bs-teal: var(--pal-action-dark, var(--pal-action, var(--bodysoul-action-book, #1E7A6B)));
  --bs-ink: #e8e0dc;
  --bs-meta: #a89f9b;
  --bs-row-alt: #2c2726;
  --bs-hairline: #3a3433;
  --bs-teal-tint: #1d2b29;
  --bs-teal-border: #2f4a47;
  --bs-muted: #9b918d;
  --bs-faint: #6f6663;
  --bs-dim: #c9c0bc;
  --bs-band: #4a4342;
  --bs-rule: #46403f;
  --bs-band-soft: #3a3433;
  --bs-divider: #4a4342;
  --bs-heading: var(--pal-ink-dark, #cbbdbb);
}
:root[data-theme="dark"] .bs-rows,
:root[data-theme="dark"] .bs-row,
:root[data-theme="dark"] .bs-addons__item {
  background: var(--bs-surface);
  border-color: rgba(255, 255, 255, 0.07);
}
:root[data-theme="dark"] .bs-row:nth-child(odd) {
  background: var(--bs-row-alt);
}
:root[data-theme="dark"] .bs-row {
  --bs-fade-bg: var(--bs-surface);
}
:root[data-theme="dark"] .bs-row:nth-child(odd) {
  --bs-fade-bg: var(--bs-row-alt);
}

/* No-container-query fallback (Safari <16, Chrome <105): mirror the two
   @container blocks above (the auto Book button's) as viewport queries, else
   those browsers show the full pill at every width. The container is the
   content column, not the window, so each threshold carries ~8rem of slack
   for theme chrome: 40rem/55rem of container are 48rem/64rem of window,
   read as max-widths stopping a hair short of each. */
@supports not (container-type: inline-size) {
  @media (max-width: 63.99rem) {
    .bs-book--auto .bs-book__long {
      display: none;
    }
    .bs-book--auto .bs-book__short {
      display: inline;
    }
  }
  @media (max-width: 47.99rem) {
    .bs-book--auto {
      width: 3.6rem;
      height: 3.6rem;
      padding: 0;
      justify-content: center;
      border-radius: 50%;
    }
    .bs-book--auto svg {
      width: 1.7rem;
      height: 1.7rem;
    }
    .bs-book--auto .bs-book__label {
      position: absolute;
      width: 1px;
      height: 1px;
      padding: 0;
      margin: -1px;
      overflow: hidden;
      clip-path: inset(50%);
      white-space: nowrap;
      border: 0;
    }
  }
}
