/* ==========================================================================
   JioMassage — theme layer on top of Pico CSS v2.1.1
   --------------------------------------------------------------------------
   Header  : built from reference  teamskeet.com   (Notion > "Header")
   Footer  : built from reference  xhamster.com    (Notion > "Footer")
   Palette : Deep Aubergine + Rose Gold (chosen by client)

   Rule for this file: Pico owns the reset, typography rhythm and form
   controls. This file only re-maps Pico's custom properties to the brand
   and adds the two structural blocks Pico has no opinion about — the
   masthead and the sitemap footer.
   ========================================================================== */


/* --------------------------------------------------------------------------
   1. Fonts — self-hosted, no third-party request on the critical path
   -------------------------------------------------------------------------- */

@font-face {
  font-family: 'Anton';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url('../fonts/anton-latin.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6,
                 U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F,
                 U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
  font-family: 'Anton';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url('../fonts/anton-latin-ext.woff2') format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7,
                 U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF,
                 U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0,
                 U+2113, U+2C60-2C7F, U+A720-A7FF;
}


/* --------------------------------------------------------------------------
   2. Brand tokens
   -------------------------------------------------------------------------- */

:root {
  /* Palette. Every colour in this stylesheet resolves through these tokens,
     so a whole theme is swapped by redefining this block and nothing else.
     The named themes live in includes/config.php ($PALETTES). */

  --jm-ink:        #1A0B1F;   /* deep aubergine — masthead ground       */
  --jm-ink-soft:   #241031;   /* raised surface on dark                 */
  --jm-ink-line:   #2E1636;   /* hairline on dark                       */
  --jm-ink-line-2: #43254E;   /* control border on dark                 */
  --jm-on-ink:     #FFFFFF;   /* text sitting on the masthead           */

  --jm-accent:     #E0A899;   /* rose gold — primary action             */
  --jm-accent-lit: #EFC3B6;   /* rose gold hover                        */
  --jm-accent-dim: #C98D7C;   /* rose gold on light backgrounds         */
  --jm-on-accent:  #1A0B1F;   /* text sitting on an accent fill         */
  --jm-ring:  rgba(224, 168, 153, .32);  /* focus glow, derived from accent */

  --jm-nav:        #9B8AA0;   /* muted mauve — nav rest state           */
  --jm-nav-dim:    #7A6C80;   /* micro-tagline                          */

  --jm-paper:      #F6F2F4;   /* warm off-white — footer ground         */
  --jm-heading:    #1A0B1F;   /* headings and strong text on light      */
  --jm-body:       #2B2230;   /* body copy                              */
  --jm-muted:      #6B5F6E;   /* footer links, secondary copy           */
  --jm-line:       #E2D9DF;   /* hairline on light                      */
  --jm-chip:       #E7E0E4;   /* footer CTA button surface              */
  --jm-chip-lit:   #DCD2D8;   /* footer CTA button hover                */

  /* -- Surfaces on the light half of the site -----------------------------
     Added 2026-09-06 for the background pass the client agreed on
     2026-09-04: "a soft tinted page + white cards, brand colours unchanged".
     Until then the page was WHITE and the cards were --jm-paper — the same
     two colours, the wrong way round, which is why the cards never read as
     cards.

     Derived from the palette with color-mix() rather than added to each
     theme's `vars`, so switching theme still means editing one block in
     config.php and the eight existing palettes did not have to be touched. */

  --jm-ground:  var(--jm-paper);                                  /* page ground   */
  --jm-card:    #FFFFFF;                                          /* card surface  */
  --jm-card-2:  color-mix(in srgb, var(--jm-paper) 60%, #FFFFFF); /* inset panel   */
  --jm-shadow:  color-mix(in srgb, var(--jm-heading) 8%,  transparent);
  --jm-shadow-2:color-mix(in srgb, var(--jm-heading) 15%, transparent);

  /* Accent, but safe to set as TEXT on whatever ground is current.
     --jm-accent is a light gold: ~1.9:1 on white, which is unreadable, and
     the colour pass turns three formerly-dark sections light underneath a
     lot of rules that set `color: var(--jm-accent)`. Those rules now read
     this instead. On the dark half it IS --jm-accent, so nothing moves;
     .jm-lit re-points it to --jm-accent-dim, which is ~5.2:1 on white.
     A FILL stays --jm-accent — gold behind --jm-on-accent is fine either
     way round, and it is what keeps the brand visible on a light panel. */
  --jm-accent-ink: var(--jm-accent);

  /* Form errors on book.php. Deliberately NOT part of a palette: an error is
     the one thing on the site that must not take the brand's colour, and a
     theme that tinted it towards its own accent would bury it. Defined once
     here, so palette_css() leaves it alone on every theme.
     --jm-warn sits on a dark panel, --jm-warn-dim on paper. */
  --jm-warn:       #F08A80;
  --jm-warn-dim:   #B03A32;

  /* WhatsApp and Telegram, in their own colours. Deliberately NOT part of a
     palette, for the same reason as the error colours above: a channel's
     recognisability IS its colour, and a theme that tinted the WhatsApp
     button gold would make it stop reading as WhatsApp. These two are the
     only brand colours on the site that are not JioMassage's own. */
  --jm-whatsapp:   #25D366;
  --jm-telegram:   #229ED9;

  /* -- Corner radii --------------------------------------------------------
     Added 2026-09-06. The client supplied their own sister site,
     mumbai.neverendservice.com, as the design reference for the whole site
     and it is built on pills and soft cards, where this site was squared and
     editorial. Four tokens rather than literals so the whole language can be
     tightened or loosened from one place — and so going back is one edit. */
  --jm-r-sm:  10px;   /* inputs, small chips                                */
  --jm-r:     16px;   /* cards                                              */
  --jm-r-lg:  22px;   /* large panels                                       */
  --jm-pill:  100px;  /* every button, and every badge                      */

  /* Not a colour: which way the browser should paint the UI it renders
     itself (the native <select> option list, above all). Overridden per
     theme by palette_css() — sand-clay's masthead is light. */
  --jm-scheme:     dark;

  --jm-header-h:   76px;
  --jm-gutter:     clamp(16px, 3vw, 40px);
  --jm-wide:       1560px;
  --jm-tile-gap:   clamp(8px, 1vw, 14px);   /* gap between hero mosaic tiles */

  /* ref 05's display heading is a serif; the rest of the site is the system
     sans, and Anton is reserved for the wordmark and the areas heading. */
  --jm-serif: Georgia, 'Iowan Old Style', 'Times New Roman', Times, serif;

  --jm-sans: system-ui, -apple-system, 'Segoe UI', Roboto, 'Helvetica Neue',
             Arial, 'Noto Sans', sans-serif;
  --jm-display: 'Anton', 'Arial Narrow', Impact, var(--jm-sans);
}


/* --------------------------------------------------------------------------
   3. Pico re-map — brand the library instead of overriding it
   -------------------------------------------------------------------------- */

:root {
  --pico-font-family-sans-serif: var(--jm-sans);
  --pico-font-family:            var(--jm-sans);
  --pico-border-radius:          var(--jm-r-sm);
  --pico-typography-spacing-vertical: 1.15rem;

  --pico-background-color:  #FFFFFF;
  --pico-color:             var(--jm-body);
  --pico-muted-color:       var(--jm-muted);
  --pico-muted-border-color: var(--jm-line);

  --pico-h1-color: var(--jm-heading);
  --pico-h2-color: var(--jm-heading);
  --pico-h3-color: var(--jm-heading);
  --pico-h4-color: var(--jm-heading);
  --pico-h5-color: var(--jm-heading);
  --pico-h6-color: var(--jm-heading);

  --pico-primary:                 var(--jm-accent-dim);
  --pico-primary-background:      var(--jm-accent);
  --pico-primary-border:          var(--jm-accent);
  --pico-primary-inverse:         var(--jm-on-accent);
  --pico-primary-hover:           var(--jm-heading);
  --pico-primary-hover-background: var(--jm-accent-lit);
  --pico-primary-hover-border:    var(--jm-accent-lit);
  --pico-primary-focus:           var(--jm-ring);
  --pico-primary-underline:       var(--jm-accent-dim);

  --pico-contrast:            var(--jm-heading);
  --pico-contrast-background: var(--jm-heading);
  --pico-contrast-border:     var(--jm-heading);
  --pico-contrast-inverse:    #FFFFFF;
}

/* The soft tint the client asked for. Cards on top of it are --jm-card. */
body {
  background: var(--jm-ground);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

/* --------------------------------------------------------------------------
   3b. .jm-lit — the light-panel switch
   --------------------------------------------------------------------------
   Put this class on a section that was built against a DARK reference and the
   whole ink family re-points to light equivalents, so every rule inside it
   renders light without being rewritten. Take the class off and the section is
   dark again — which is the point: three near-black panels were converted on
   2026-09-06 and the client can have any of them back in one word.

   It carries --jm-scheme too, so the native <select> popup inside section 8
   flips to a light popup at the same time as the control it belongs to. That
   is the whole of the dropdown handling in §5 of CLAUDE.md, undone by getting
   rid of the dark control.

   NOT re-pointed here: --jm-accent. It is a fill as often as it is text, and
   one token cannot be both on a light ground. Text reads --jm-accent-ink.
   -------------------------------------------------------------------------- */

.jm-lit {
  --jm-ink:        var(--jm-ground);
  --jm-ink-soft:   var(--jm-card);
  --jm-ink-line:   var(--jm-line);
  --jm-ink-line-2: color-mix(in srgb, var(--jm-heading) 15%, transparent);
  --jm-on-ink:     var(--jm-heading);
  --jm-nav:        var(--jm-muted);
  /* was muted 80% + paper (#868177, 3.5–3.9:1 — Lighthouse, 2026-10-09) */
  --jm-nav-dim:    var(--jm-muted);
  --jm-accent-ink: var(--jm-accent-dim);
  --jm-scheme:     light;
}

/* Wider than Pico's .container, used by the masthead and the footer so both
   line up on the same optical gutter. */
.jm-shell {
  width: 100%;
  max-width: var(--jm-wide);
  margin-inline: auto;
  padding-inline: var(--jm-gutter);
}

.jm-skip {
  position: absolute;
  left: -9999px;
  top: 0;
  z-index: 1000;
  background: var(--jm-accent);
  color: var(--jm-on-accent);
  padding: 12px 20px;
  font-weight: 700;
  border-radius: 0 0 5px 0;
  text-decoration: none;
}
.jm-skip:focus { left: 0; }

.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}


/* ==========================================================================
   4. MASTHEAD                                     ref: teamskeet.com
   ========================================================================== */

.site-header {
  position: sticky;
  top: 0;
  z-index: 900;
  background: var(--jm-ink);
  border-bottom: 1px solid var(--jm-ink-line);
}

.site-header__inner {
  display: flex;
  align-items: center;
  gap: clamp(20px, 3vw, 46px);
  min-height: var(--jm-header-h);
}

/* --- wordmark ------------------------------------------------------------ */

.brand {
  flex: 0 0 auto;
  display: block;
  line-height: 1;
  text-decoration: none;
  color: inherit;
}
.brand:hover { text-decoration: none; }

.brand__mark {
  display: block;
  font-family: var(--jm-display);
  font-weight: 400;
  font-size: clamp(25px, 2.5vw, 37px);
  letter-spacing: .006em;
  text-transform: uppercase;
  color: var(--jm-on-ink);
}
.brand__mark em {
  font-style: normal;
  color: var(--jm-accent);
}

.brand__sub {
  display: block;
  margin-top: 5px;
  font-size: 9px;
  font-weight: 700;
  letter-spacing: .17em;
  text-transform: uppercase;
  color: var(--jm-nav-dim);
}
.brand__sub b { font-weight: 700; color: var(--jm-accent); }

/* --- primary navigation --------------------------------------------------- */

.main-nav ul {
  display: flex;
  align-items: center;
  gap: clamp(18px, 2.1vw, 34px);
  margin: 0;
  padding: 0;
  list-style: none;
}
/* Pico ships opinionated <nav> styling that outranks a plain `.main-nav ul`:
     nav ul:first-of-type  -> margin-left: -0.5rem      (0,1,2)
     nav ul:last-of-type   -> margin-right: -0.5rem     (0,1,2)
     nav li                -> display: inline-block     (0,0,2)
     ul li                 -> list-style: square        (0,0,2)
   Each has to be beaten on specificity, not just source order, so these
   selectors carry the `nav` type as well as the class.

   Margin only: `:last-of-type` here scores (0,1,3), so adding padding to it
   would outrank the mobile panel's own gutter rule and flatten it. */
nav.main-nav ul,
nav.main-nav ul:first-of-type,
nav.main-nav ul:last-of-type { margin: 0; }

nav.main-nav li {
  display: block;
  margin: 0;
  padding: 0;
  list-style: none;
}

.main-nav a {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding-block: 8px;
  font-size: 13px;
  font-weight: 600;
  letter-spacing: .11em;
  text-transform: uppercase;
  color: var(--jm-nav);
  text-decoration: none;
  white-space: nowrap;
  transition: color .18s ease;
}
.main-nav a:hover,
.main-nav a:focus-visible,
.main-nav a[aria-current="page"] { color: var(--jm-on-ink); }

.nav-badge {
  display: inline-block;
  padding: 3px 7px 2px;
  border-radius: 3px;
  background: var(--jm-accent);
  color: var(--jm-on-accent);
  font-size: 9.5px;
  font-weight: 800;
  letter-spacing: .09em;
  line-height: 1.35;
}

/* --- right-hand actions --------------------------------------------------- */

.header-actions {
  margin-left: auto;
  flex: 0 0 auto;
  display: flex;
  align-items: center;
  gap: 10px;
}

.icon-btn {
  width: 42px;
  height: 42px;
  flex: 0 0 42px;
  padding: 0;
  margin: 0;
  display: grid;
  place-items: center;
  border: 1px solid var(--jm-ink-line-2);
  border-radius: 50%;
  background: transparent;
  color: var(--jm-nav);
  cursor: pointer;
  box-shadow: none;
  transition: color .18s ease, border-color .18s ease;
}
.icon-btn:hover,
.icon-btn:focus-visible {
  background: transparent;
  border-color: var(--jm-accent);
  color: var(--jm-accent);
}
.icon-btn svg { width: 17px; height: 17px; display: block; }

.btn-outline,
.btn-solid {
  width: auto;
  height: 42px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding-inline: 22px;
  border: 1px solid transparent;
  border-radius: 5px;
  font-size: 13px;
  font-weight: 800;
  letter-spacing: .09em;
  text-transform: uppercase;
  text-decoration: none;
  white-space: nowrap;
  transition: background-color .18s ease, border-color .18s ease, color .18s ease;
}
.btn-outline { background: transparent; border-color: var(--jm-ink-line-2); color: var(--jm-on-ink); }
.btn-outline:hover, .btn-outline:focus-visible { border-color: var(--jm-on-ink); color: var(--jm-on-ink); text-decoration: none; }

/* `.btn-outline` above is a MASTHEAD button: its label is `--jm-on-ink`, which
   is white on every dark-masthead theme, and its border is `--jm-ink-line-2`,
   a dark grey. Dropped onto a light page — profile.php's "See the full team"
   was the first — that is white text and a near-invisible border on paper: the
   button is there, focusable and clickable, and reads as an empty box.
   `.page .btn-outline` (0,2,0) beats `.btn-outline` (0,1,0), so every outline
   button inside a light `.page` section is restated once, here.
   `.btn-solid` needs no equivalent: an accent fill works on either ground. */
.page .btn-outline {
  border-color: var(--jm-line);
  color: var(--jm-heading);
}
.page .btn-outline:hover,
.page .btn-outline:focus-visible {
  border-color: var(--jm-accent-dim);
  color: var(--jm-accent-dim);
}

.btn-solid { background: var(--jm-accent); color: var(--jm-on-accent); }
.btn-solid:hover, .btn-solid:focus-visible { background: var(--jm-accent-lit); color: var(--jm-on-accent); text-decoration: none; }

/* --- search drawer + burger (CSS only, no JavaScript) --------------------- */

/* The checkboxes stay in the tab order — space toggles them — but are pulled
   out of sight; the focus ring is painted on their matching <label>. */
.hdr-switch {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  opacity: 0;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
}

#hdr-search:focus-visible ~ .site-header__inner label[for="hdr-search"],
#hdr-nav:focus-visible    ~ .site-header__inner label[for="hdr-nav"] {
  outline: 2px solid var(--jm-accent);
  outline-offset: 2px;
}

.burger {
  display: none;
  width: 42px;
  height: 42px;
  flex: 0 0 42px;
  place-items: center;
  border: 1px solid var(--jm-ink-line-2);
  border-radius: 50%;
  color: var(--jm-nav);
  cursor: pointer;
}
.burger:hover { border-color: var(--jm-accent); color: var(--jm-accent); }
.burger span {
  position: relative;
  display: block;
  width: 16px;
  height: 1.5px;
  background: currentColor;
}
.burger span::before,
.burger span::after {
  content: '';
  position: absolute;
  left: 0;
  width: 16px;
  height: 1.5px;
  background: currentColor;
}
.burger span::before { top: -5px; }
.burger span::after  { top:  5px; }

/* max-height rather than the 0fr/1fr grid trick: `overflow:hidden` on a grid
   item zeroes its automatic minimum size, so the 1fr track resolves to 0 and
   the drawer never opens. The drawer's content height is fixed and known, so
   a max-height ceiling is both predictable and safe. */
.search-drawer {
  overflow: hidden;
  max-height: 0;
  background: var(--jm-ink-soft);
  border-bottom: 1px solid transparent;
  transition: max-height .25s ease, border-color .25s ease;
}

#hdr-search:checked ~ .search-drawer {
  max-height: 140px;
  border-bottom-color: var(--jm-ink-line);
}

.search-drawer form {
  display: flex;
  gap: 10px;
  align-items: center;
  padding-block: 18px;
  margin: 0;
}
.search-drawer input[type="search"] {
  flex: 1 1 auto;
  height: 46px;
  margin: 0;
  background: var(--jm-ink);
  border: 1px solid var(--jm-ink-line-2);
  border-radius: 5px;
  color: var(--jm-on-ink);
  font-size: 15px;
  box-shadow: none;
}
.search-drawer input[type="search"]::placeholder { color: var(--jm-nav-dim); }
.search-drawer input[type="search"]:focus {
  border-color: var(--jm-accent);
  box-shadow: 0 0 0 3px var(--jm-ring);
}
.search-drawer button { flex: 0 0 auto; }


/* --- masthead: tablet + mobile -------------------------------------------- */

@media (max-width: 1180px) {
  .burger { display: grid; }

  /* Below this width the search lives inside the menu panel, so the drawer
     and its circular trigger step aside — one panel, never two overlapping. */
  .header-actions .icon-btn,
  .search-drawer { display: none; }

  .site-header__inner { position: relative; }

  /* The panel is absolutely positioned, so it has no in-flow height to
     animate — the 0fr/1fr grid trick collapses to 0 on an abspos box. It
     reveals with visibility/opacity instead, which is independent of
     content height and overlays the page the way a mobile menu should. */
  /* Pico sets `nav{display:flex}` (0,0,1); left as a flex container the list
     would size to its content instead of filling the panel. */
  nav.main-nav {
    display: block;
    position: absolute;
    left: 0;
    right: 0;
    top: 100%;
    background: var(--jm-ink);
    border-bottom: 1px solid transparent;
    visibility: hidden;
    opacity: 0;
    transform: translateY(-8px);
    transition: opacity .2s ease, transform .2s ease,
                border-color .2s ease, visibility .2s;
  }
  nav.main-nav > ul {
    display: block;
    padding-inline: var(--jm-gutter);
  }
  #hdr-nav:checked ~ .site-header__inner .main-nav {
    visibility: visible;
    opacity: 1;
    transform: none;
    border-bottom-color: var(--jm-ink-line);
  }

  .main-nav li + li { border-top: 1px solid var(--jm-ink-line); }
  .main-nav a {
    width: 100%;
    padding-block: 17px;
    font-size: 14px;
  }

  .main-nav .mobile-only { display: block; }
  .main-nav .mobile-only,
  .main-nav .mobile-only + .mobile-only { border-top: 0; }

  /* `.main-nav a` (0,1,1) outranks `.btn-solid` / `.btn-outline` (0,1,0), so
     the button colours have to be restated at this depth or BOOK NOW renders
     muted mauve on rose gold. */
  .main-nav .mobile-only .btn-outline,
  .main-nav .mobile-only .btn-solid {
    justify-content: center;
    padding-block: 0;
    font-size: 13px;
  }
  .main-nav .mobile-only .btn-outline {
    margin-block: 18px 10px;
    color: var(--jm-on-ink);
  }
  .main-nav .mobile-only .btn-solid {
    margin-block: 0 24px;
    color: var(--jm-on-accent);
  }

  .main-nav .nav-search { border-bottom: 1px solid var(--jm-ink-line); }
  .main-nav .nav-search form {
    display: flex;
    gap: 8px;
    align-items: center;
    margin: 0;
    padding-block: 18px;
  }
  .main-nav .nav-search input[type="search"] {
    flex: 1 1 auto;
    height: 44px;
    margin: 0;
    background: var(--jm-ink-soft);
    border: 1px solid var(--jm-ink-line-2);
    border-radius: 5px;
    color: var(--jm-on-ink);
    font-size: 15px;
    box-shadow: none;
  }
  .main-nav .nav-search input[type="search"]::placeholder { color: var(--jm-nav-dim); }
  .main-nav .nav-search input[type="search"]:focus {
    border-color: var(--jm-accent);
    box-shadow: 0 0 0 3px var(--jm-ring);
  }
  .main-nav .nav-search .btn-solid {
    flex: 0 0 auto;
    height: 44px;
    margin: 0;
    padding-inline: 20px;
  }

  .header-actions .btn-outline,
  .header-actions .btn-solid { display: none; }
}

@media (min-width: 1181px) {
  .main-nav .mobile-only { display: none; }
}

/* --- Locations dropdown  (2026-10-07) -------------------------------------
   "Locations" in the top menu, listing every $AREAS page. No script: opens on
   :hover / :focus-within. Written at (0,2,x) so `.main-nav ul` (flex, gap)
   and `.main-nav a` do not leak into it. */
.main-nav .nav-caret {
  width: 6px;
  height: 6px;
  margin-top: -3px;
  border-right: 1.6px solid currentColor;
  border-bottom: 1.6px solid currentColor;
  transform: rotate(45deg);
}
@media (min-width: 1181px) {
  nav.main-nav li.has-drop { position: relative; }
  .main-nav .nav-drop {
    position: absolute;
    top: 100%;
    left: 50%;
    z-index: 60;
    display: grid;
    grid-template-columns: repeat(2, minmax(150px, 1fr));
    gap: 2px 10px;
    width: max-content;
    margin: 0;
    padding: 14px;
    background: var(--jm-ink-soft);
    border: 1px solid var(--jm-ink-line-2);
    border-top: 2px solid var(--jm-accent);
    border-radius: var(--jm-r);
    box-shadow: 0 22px 44px -18px color-mix(in srgb, var(--jm-ink) 85%, transparent);
    visibility: hidden;
    opacity: 0;
    transform: translate(-50%, 6px);
    transition: opacity .16s ease, transform .16s ease, visibility .16s;
  }
  /* a small bridge so the pointer can cross the gap without the menu closing */
  .main-nav .nav-drop::before {
    content: '';
    position: absolute;
    left: 0; right: 0; top: -12px;
    height: 12px;
  }
  .main-nav li.has-drop:hover > .nav-drop,
  .main-nav li.has-drop:focus-within > .nav-drop {
    visibility: visible;
    opacity: 1;
    transform: translate(-50%, 0);
  }
  .main-nav .nav-drop a {
    display: block;
    padding: 8px 12px;
    border-radius: var(--jm-r-sm);
    font-size: 12.5px;
    letter-spacing: .06em;
  }
  .main-nav .nav-drop a:hover,
  .main-nav .nav-drop a:focus-visible {
    background: color-mix(in srgb, var(--jm-accent) 14%, transparent);
    color: var(--jm-on-ink);
  }
  .main-nav .nav-drop .nav-drop__all {
    grid-column: 1 / -1;
    margin-top: 6px;
    padding-top: 6px;
    border-top: 1px solid var(--jm-ink-line);
  }
  .main-nav .nav-drop .nav-drop__all a { color: var(--jm-accent); }
  nav.main-nav .nav-drop li { margin: 0; }
}
/* Five menu items since Locations was added: between the burger (1180) and
   1440 the bar ran out of room at ~1320 and pushed BOOK NOW off the edge.
   Tighter gap and tracking here, rather than hiding more controls. */
@media (min-width: 1181px) and (max-width: 1440px) {
  .main-nav > ul { gap: 16px; }
  .main-nav > ul > li > a { letter-spacing: .05em; font-size: 12.5px; }
}
@media (max-width: 1180px) {
  /* inside the burger panel: a compact two-column list under "Locations" */
  .main-nav .nav-drop {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 0 14px;
    margin: -6px 0 0;
    padding: 0 0 14px 14px;
  }
  .main-nav .nav-drop li + li { border-top: 0; }
  .main-nav .nav-drop a {
    padding-block: 9px;
    font-size: 12.5px;
    letter-spacing: .06em;
    color: var(--jm-nav-dim);
  }
  .main-nav .nav-drop .nav-drop__all { grid-column: 1 / -1; }
  .main-nav .nav-drop .nav-drop__all a { color: var(--jm-accent); }
  .main-nav .nav-caret { display: none; }
  /* fourteen more links make the panel taller than a phone: let it scroll */
  #hdr-nav:checked ~ .site-header__inner .main-nav {
    max-height: calc(100dvh - 76px);
    overflow-y: auto;
  }
}

@media (max-width: 560px) {
  :root { --jm-header-h: 66px; }
  .brand__mark { font-size: 23px; }
  .brand__sub  { font-size: 8px; letter-spacing: .14em; }
  .header-actions { gap: 8px; }
}


/* ==========================================================================
   5. FOOTER                                        ref: xhamster.com
   ========================================================================== */

.site-footer {
  background: var(--jm-paper);
  border-top: 1px solid var(--jm-line);
  margin-top: 0;
}

.footer-grid {
  display: grid;
  /* Column 4 is wider than the other three, as in the reference footer — it
     has to seat the CTA button and the avatar stack on one line. */
  grid-template-columns: 1fr 1fr 1fr 1.4fr;
  gap: 40px clamp(24px, 4vw, 72px);
  padding-block: clamp(44px, 5vw, 62px) clamp(30px, 4vw, 46px);
}

/* 2026-09-12: "site-footer h2 tag need colors". All four column headings were
   --jm-heading, i.e. the same near-black as the body copy under them, so the
   footer read as one undifferentiated block of text.

   >>> THE TOKEN IS --jm-accent-dim, NOT --jm-accent. The footer sits on
       --jm-paper, and --jm-accent (#D9B44A) is about 1.9:1 on it — a heading
       nobody could read. --jm-accent-dim (#8A6D1F) is ~5.2:1 and is the
       site's designated accent-as-TEXT colour on a light ground. This is the
       exact trap the §14–16 rewrite and --jm-accent-ink exist for.       <<< */
.footer-col h2 {
  margin: 0 0 18px;
  font-size: 19px;
  font-weight: 700;
  letter-spacing: -.01em;
  color: var(--jm-accent-dim);
  line-height: 1.25;
}

/* The brand column, two-tone like the masthead: "Jio" takes the heading's own
   near-black so it does not disappear into the gold, "Massage" keeps the
   accent. Nowrap because it is one word and must never break across lines. */
.foot__mark { white-space: nowrap; color: var(--jm-heading); }
.foot__mark em { font-style: normal; color: var(--jm-accent-dim); }

.footer-col ul {
  margin: 0;
  padding: 0;
  list-style: none;
}
.footer-col li { margin: 0; padding: 0; list-style: none; }

/* Scoped to the link lists on purpose: the recruiting CTA in column 4 is an
   anchor too, and a bare `.footer-col a` would outrank `.recruit-cta` on
   specificity and force it back to a block box. */
.footer-col ul a {
  display: inline-block;
  padding-block: 7px;
  font-size: 14px;
  color: var(--jm-muted);
  text-decoration: none;
  transition: color .16s ease;
}
.footer-col ul a:hover,
.footer-col ul a:focus-visible {
  color: var(--jm-heading);
  text-decoration: underline;
  text-underline-offset: 3px;
}

/* the single highlighted recruiting link, as in the reference footer */
.footer-col ul a.is-flagged {
  color: var(--jm-heading);
  font-weight: 700;
}
.footer-col ul a.is-flagged::after {
  content: '';
  display: inline-block;
  width: 9px;
  height: 11px;
  margin-left: 6px;
  vertical-align: -1px;
  background: var(--jm-accent-dim);
  clip-path: polygon(0 0, 100% 0, 100% 62%, 30% 62%, 30% 100%, 0 100%);
}

/* --- column 4: recruiting block ------------------------------------------- */

.footer-col--wide ul.split {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 0 24px;
}
.footer-col--wide ul.split li:last-child { grid-column: 1 / -1; }

.footer-col h3 {
  margin: 30px 0 14px;
  font-size: 17px;
  font-weight: 700;
  color: var(--jm-heading);
  line-height: 1.3;
}

.recruit-row {
  display: flex;
  align-items: center;
  gap: 0;
  flex-wrap: wrap;
}

.recruit-cta {
  width: auto;
  flex: 0 0 auto;          /* never let the flex row squeeze the label onto two lines */
  display: inline-flex;
  align-items: center;
  gap: 12px;
  height: 48px;
  padding-inline: 18px 22px;
  border: 1px solid transparent;
  border-radius: 6px;
  background: var(--jm-chip);
  color: var(--jm-heading);
  font-size: 15px;
  font-weight: 700;
  text-decoration: none;
  white-space: nowrap;
  transition: background-color .18s ease;
}
.recruit-cta:hover,
.recruit-cta:focus-visible { background: var(--jm-chip-lit); color: var(--jm-heading); text-decoration: none; }

.recruit-cta i {
  display: grid;
  place-items: center;
  width: 26px;
  height: 26px;
  flex: 0 0 26px;
  border-radius: 50%;
  background: var(--jm-accent);
  color: var(--jm-on-accent);
}
.recruit-cta i svg { width: 14px; height: 14px; display: block; }

.avatar-stack {
  display: flex;
  align-items: center;
  padding-left: 10px;
}
.avatar-stack img {
  width: 40px;
  height: 40px;
  border-radius: 50%;
  object-fit: cover;
  background: var(--jm-line);
  border: 2px solid var(--jm-paper);
  margin-left: -12px;
}
.avatar-stack img:first-child { margin-left: 0; }

/* --- legal strip ---------------------------------------------------------- */

.footer-legal {
  border-top: 1px solid var(--jm-line);
  padding-block: 26px 34px;
}

.footer-legal .disclaimer {
  margin: 0 0 18px;
  max-width: 90ch;
  font-size: 12.5px;
  line-height: 1.75;
  color: var(--jm-muted);
}
.footer-legal .disclaimer strong { color: var(--jm-heading); font-weight: 700; }

.footer-legal__bar {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 12px 28px;
}

.footer-legal__bar p {
  margin: 0;
  font-size: 13px;
  color: var(--jm-muted);
}

.footer-legal__bar ul {
  display: flex;
  flex-wrap: wrap;
  gap: 10px 22px;
  margin: 0;
  padding: 0;
}
.footer-legal__bar li { margin: 0; padding: 0; list-style: none; }
.footer-legal__bar a {
  font-size: 13px;
  color: var(--jm-muted);
  text-decoration: none;
}
.footer-legal__bar a:hover { color: var(--jm-heading); text-decoration: underline; text-underline-offset: 3px; }

/* --- footer: tablet + mobile ---------------------------------------------- */

@media (max-width: 1024px) {
  .footer-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 38px 40px; }
  .footer-col--wide { grid-column: 1 / -1; }
}

@media (max-width: 560px) {
  .footer-grid { grid-template-columns: 1fr; gap: 32px; }
  .footer-col--wide ul.split { grid-template-columns: 1fr; }
  .recruit-row { gap: 16px 0; }
  .avatar-stack { padding-left: 0; }
  .footer-legal__bar { flex-direction: column; align-items: flex-start; }
}


/* --------------------------------------------------------------------------
   6. Shared homepage furniture
   -------------------------------------------------------------------------- */

/* Inline icons from includes/icons.php. Sized in `em`, drawn in
   `currentColor`, so an icon inherits both size and colour from its holder
   and never needs a token of its own. */
.jm-ico {
  width: 1em;
  height: 1em;
  display: inline-block;
  vertical-align: -.15em;
  flex: 0 0 auto;
}

/* the hairline under the Learn More heading (ref 02) */
.jm-rule {
  height: 1px;
  border: 0;
  margin: 0 0 clamp(26px, 3vw, 40px);
  background: var(--jm-line);
}


/* ==========================================================================
   7. HERO                                          ref: makelovenotporn.tv
   --------------------------------------------------------------------------
   An angled mosaic of photographs drifting endlessly sideways behind a
   dark→gold gradient, with the headline, subhead and a solid square CTA on
   the left and a floating pill in the top-right corner.
   ========================================================================== */

.hero {
  position: relative;
  overflow: hidden;              /* clips the rotated, over-wide mosaic */
  isolation: isolate;            /* keeps the z-index:-1/-2 layers inside */
  background: linear-gradient(103deg,
    var(--jm-ink) 0%,
    var(--jm-ink) 24%,
    var(--jm-ink-soft) 44%,
    color-mix(in srgb, var(--jm-accent-dim) 80%, var(--jm-ink)) 100%);
}

/* --- the drifting mosaic --------------------------------------------------- */

.hero__mosaic {
  position: absolute;
  inset: -18% -8%;
  z-index: -2;
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: var(--jm-tile-gap);
  transform: rotate(-3.4deg) scale(1.06);
}

.hero__row {
  display: flex;
  flex: 0 0 auto;
  width: max-content;
  will-change: transform;
  animation: jm-drift 64s linear infinite;
}
.hero__row--2 { animation-duration: 86s; animation-direction: reverse; }
.hero__row--3 { animation-duration: 74s; }

/* The row holds three identical copies of its tiles (HERO_COPIES in
   config.php), so sliding it one third of its width lands exactly back where
   it started — and the two copies that are not sliding keep the screen
   covered. Two copies and a -50% slide leaves a bare wedge on wide screens,
   which is what the reversed middle row exposes first.

   The trailing gap lives on the tile as `margin-right`, NOT as `gap` on the
   row: with `gap` the row measures (n tiles + n-1 gaps), so a third of it is
   two-thirds of a gap short of one copy — enough to jump on every loop. */
@keyframes jm-drift {
  from { transform: translate3d(0, 0, 0); }
  to   { transform: translate3d(-33.3333%, 0, 0); }
}

.hero__row img {
  display: block;
  width: clamp(150px, 17vw, 232px);
  height: auto;
  aspect-ratio: 4 / 3;
  margin-right: var(--jm-tile-gap);
  border-radius: 4px;
  object-fit: cover;
  background: var(--jm-ink-line);
  box-shadow: 0 10px 26px color-mix(in srgb, var(--jm-ink) 42%, transparent);
}

@media (prefers-reduced-motion: reduce) {
  .hero__row { animation: none; }
}

/* --- the gradient veil that makes the headline legible --------------------- */

.hero__veil {
  position: absolute;
  inset: 0;
  z-index: -1;
  background: linear-gradient(96deg,
    var(--jm-ink) 0%,
    color-mix(in srgb, var(--jm-ink) 92%, transparent) 26%,
    color-mix(in srgb, var(--jm-ink) 60%, transparent) 45%,
    color-mix(in srgb, var(--jm-ink) 14%, transparent) 68%,
    transparent 88%);
}

/* --- content --------------------------------------------------------------- */

.hero__inner {
  position: relative;
  z-index: 1;
  padding-block: clamp(64px, 9vw, 130px);
}

.hero__title {
  margin: 0 0 clamp(14px, 1.7vw, 22px);
  max-width: 16ch;
  font-size: clamp(30px, 4.4vw, 58px);
  font-weight: 800;
  line-height: 1.06;
  letter-spacing: -.022em;
  color: var(--jm-on-ink);
}

/* THE LIT PHRASE IN THE HEADLINE — 2026-09-12: "title need color full design".
   ---------------------------------------------------------------------------
   A gradient that drifts across the words, in five stops.

   >>> EVERY STOP IS THE ACCENT OR THE ACCENT MIXED WITH --jm-on-ink, and that
       is the same decision the verified badge's animated rings took: five
       actual HUES would be five hard-coded values, the end of theme switching,
       and the only place on this site that is not charcoal and gold. Switch
       the theme and this headline re-colours with it. If the client wants a
       genuine rainbow, it is this one gradient — but it costs the eight themes
       and it should be asked for, not assumed.                           <<<

   >>> THE @supports IS LOAD-BEARING, exactly like the one on the services
       cards (§35). `color: transparent` over a clipped background is INVISIBLE
       TEXT anywhere `background-clip: text` is not honoured — which would mean
       the site's own headline silently missing two words. Outside the guard,
       the phrase is a flat accent-lit and perfectly readable.            <<< */
.hero__hi {
  /* <em> means "this phrase takes the stress", which is true — but it should
     not be italic here, so the element's default is turned off. */
  font-style: normal;
  color: var(--jm-accent-lit);
}

@supports ((-webkit-background-clip: text) or (background-clip: text)) {
  .hero__hi {
    /* A GLINT, not a wash. The bright stop is --jm-on-ink itself — pure white
       on every dark-masthead theme — so the sweep is plainly visible rather
       than two shades of gold sliding past each other, and the phrase gets
       BRIGHTER as it passes rather than dimmer. Widening downwards instead,
       through --jm-accent-dim (#8A6D1F on this theme), was tried and rejected:
       a whole word landing on it mid-sweep is close to unreadable on ink. */
    background-image: linear-gradient(100deg,
      var(--jm-accent)                                             0%,
      var(--jm-accent)                                            14%,
      var(--jm-accent-lit)                                        26%,
      var(--jm-on-ink)                                            34%,   /* the glint */
      var(--jm-accent-lit)                                        42%,
      var(--jm-accent)                                            56%,
      color-mix(in srgb, var(--jm-accent-lit) 60%, var(--jm-on-ink)) 74%,
      var(--jm-accent-lit)                                        86%,
      var(--jm-accent)                                           100%);
    /* Wider than the text, so there is somewhere for the sweep to travel. */
    background-size: 280% 100%;
    background-position: 0% 50%;
    -webkit-background-clip: text;
    background-clip: text;
    color: transparent;
    /* Safari paints the fill colour over a clipped background without this. */
    -webkit-text-fill-color: transparent;
    /* The warmth around the letters. drop-shadow follows the alpha of the
       glyphs, unlike text-shadow, which would sit behind transparent text. */
    filter: drop-shadow(0 0 18px color-mix(in srgb, var(--jm-accent) 34%, transparent));
    animation: heroHi 8s ease-in-out infinite;
  }
}

@keyframes heroHi {
  0%, 100% { background-position:   0% 50%; }
  50%      { background-position: 100% 50%; }
}

/* The site's standing rule — the hero marquee and the section-7 bubbles both
   do this. A drifting gradient is decoration and nothing is lost by stopping
   it; the colour stays. */
@media (prefers-reduced-motion: reduce) {
  .hero__hi { animation: none; }
}

.hero__lede {
  margin: 0 0 clamp(24px, 3vw, 38px);
  max-width: 34ch;
  font-size: clamp(16px, 1.5vw, 21px);
  line-height: 1.5;
  color: color-mix(in srgb, var(--jm-on-ink) 84%, transparent);
}
.hero__lede b { font-weight: 700; color: var(--jm-on-ink); }

.hero__cta {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  height: 56px;
  padding-inline: 34px;
  border-radius: 3px;            /* the reference CTA is a hard square block */
  background: var(--jm-accent);
  color: var(--jm-on-accent);
  font-size: 16px;
  font-weight: 800;
  letter-spacing: .015em;
  text-decoration: none;
  transition: background-color .18s ease;
}
.hero__cta:hover,
.hero__cta:focus-visible {
  background: var(--jm-accent-lit);
  color: var(--jm-on-accent);
  text-decoration: none;
}

.hero__pill {
  position: absolute;
  z-index: 2;
  top: clamp(14px, 2vw, 26px);
  right: clamp(14px, 3vw, 40px);
  max-width: min(370px, 60vw);
  padding: 11px 18px;
  border-radius: 4px;
  background: var(--jm-accent);
  color: var(--jm-on-accent);
  font-size: 13px;
  font-weight: 700;
  line-height: 1.35;
  text-decoration: none;
  box-shadow: 0 8px 22px color-mix(in srgb, var(--jm-ink) 45%, transparent);
}
.hero__pill:hover,
.hero__pill:focus-visible {
  background: var(--jm-accent-lit);
  color: var(--jm-on-accent);
  text-decoration: none;
}

/* --- hero: tablet + mobile -------------------------------------------------- */

@media (max-width: 860px) {
  /* Side-to-side gradient leaves nothing readable once the column narrows,
     so the veil turns vertical and the pill drops into the flow. Kept as
     light as the headline allows — at 90% the mosaic disappears entirely
     and the hero reads as a plain dark box. */
  .hero__veil {
    background: linear-gradient(180deg,
      color-mix(in srgb, var(--jm-ink) 58%, transparent) 0%,
      color-mix(in srgb, var(--jm-ink) 78%, transparent) 48%,
      color-mix(in srgb, var(--jm-ink) 94%, transparent) 100%);
  }

  .hero__pill {
    position: static;
    display: block;
    max-width: none;
    margin: clamp(16px, 4vw, 24px) var(--jm-gutter) 0;
    text-align: center;
  }

  .hero__inner { padding-block: clamp(34px, 7vw, 54px) clamp(48px, 10vw, 76px); }
  .hero__title { max-width: none; }
  .hero__lede  { max-width: 42ch; }
}


/* ==========================================================================
   8. ANNOUNCEMENT BAR + LEARN MORE CARDS   ref: makelovenotporn.tv/learn-more
   ========================================================================== */

.learn { padding-block: clamp(46px, 6.5vw, 84px) clamp(46px, 6vw, 78px); }

.ann-bar {
  display: block;
  margin-bottom: clamp(28px, 4vw, 46px);
  padding: 16px 22px;
  border-radius: 6px;
  background: var(--jm-accent);
  color: var(--jm-on-accent);
  font-size: 14px;
  font-weight: 700;
  line-height: 1.4;
  text-align: center;
  text-decoration: none;
  transition: background-color .18s ease;
}
.ann-bar:hover,
.ann-bar:focus-visible {
  background: var(--jm-accent-lit);
  color: var(--jm-on-accent);
  text-decoration: none;
}

.learn__title {
  margin: 0 0 clamp(16px, 2vw, 24px);
  font-size: clamp(26px, 3.6vw, 44px);
  font-weight: 800;
  line-height: 1.1;
  letter-spacing: -.024em;
  color: var(--jm-heading);
}

/* The brand, two-tone — 2026-09-12, the third of the three headings that name
   the business (with `.why__mark` and `.foot__mark`). This section sits on the
   light page ground, so the accent half is --jm-accent-dim: --jm-accent is
   about 1.9:1 there and would be an unreadable heading. Nowrap because
   "JioMassage" is one word and must never break across two lines. */
.learn__mark { white-space: nowrap; }
.learn__mark em { font-style: normal; color: var(--jm-accent-dim); }


/* ==========================================================================
   MOVED — see §56 at the FOOT of this file.
   --------------------------------------------------------------------------
   The profile page's portrait strip was first written here, next to
   `.learn__mark`, and it did not work: it overrides `.ashots` rules that live
   in §43 at around line 6475, and BOTH are (0,1,0), so source order decides
   and this position lost. The first portrait rendered 354x283 — landscape,
   with the head cropped off — while its three neighbours were correctly
   253x316. Found by measuring the boxes, not by looking at the page.
   ========================================================================== */

/* (the rules that were here are now at the foot of the file, as §56) */

.learn-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: clamp(16px, 2vw, 28px);
}

/* Three across instead of two — book.php's "what happens next" is three
   steps, and a 2 + 1 grid reads as a missing fourth card. */
.learn-grid--3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }

.lcard {
  display: block;
  padding: clamp(20px, 2.2vw, 28px) clamp(20px, 2.4vw, 30px) clamp(24px, 2.6vw, 32px);
  border: 1px solid var(--jm-line);
  border-radius: 8px;
  background: var(--jm-card);
  box-shadow: 0 1px 2px var(--jm-shadow);
  color: inherit;
  text-decoration: none;
  transition: border-color .18s ease, box-shadow .18s ease, transform .18s ease;
}
/* Scoped to `a.lcard`: the wide Memberships card is a <div> wrapper whose
   links sit inside it, and it must not react to hovering the whole box. */
a.lcard:hover,
a.lcard:focus-visible {
  border-color: var(--jm-accent-dim);
  box-shadow: 0 10px 26px var(--jm-shadow);
  transform: translateY(-2px);
  text-decoration: none;
}

/* (0,1,1) — clears both Pico's `h3` (0,0,1) and its
   `:is(p,ul,…)~:is(h1,…)` top-margin rule (0,0,2).
   `:is(h2,h3)` rather than `h3`: an area page's intro card is the first thing
   under the banner's h1, so its heading has to be an h2 to keep the document
   outline right. `:is()` takes the specificity of its most specific argument
   and both are bare elements, so this is still (0,1,1) and the note above
   still holds. Without it the heading loses `display:flex` and the icon span,
   which is `display:grid`, becomes a full-width block that centres its own
   icon above the title. */
.lcard :is(h2, h3) {
  display: flex;
  align-items: center;
  gap: 10px;
  margin: 0 0 12px;
  font-size: clamp(18px, 1.7vw, 22px);
  font-weight: 800;
  letter-spacing: -.012em;
  line-height: 1.25;
  color: var(--jm-heading);
}
.lcard :is(h2, h3) a { color: inherit; text-decoration: none; }
.lcard :is(h2, h3) a:hover,
.lcard :is(h2, h3) a:focus-visible {
  color: var(--jm-accent-dim);
  text-decoration: underline;
  text-underline-offset: 3px;
}

.lcard__ico {
  display: grid;
  place-items: center;
  font-size: 22px;
  color: var(--jm-accent-dim);
}

.lcard p {
  margin: 0;
  max-width: 48ch;
  font-size: 15px;
  line-height: 1.6;
  color: var(--jm-muted);
}

.lcard--wide { margin-top: clamp(16px, 2vw, 28px); }

/* A wide card carrying several paragraphs of running copy rather than one
   blurb — the area pages' intro. Three things have to change:
     · `.lcard p` caps the measure at 48ch, which is right for a blurb in a
       quarter-width card and leaves most of a wide card empty here;
     · `.lcard p` also sets margin 0, so consecutive paragraphs run together
       into one undifferentiated slab;
     · a single column of prose across a 1360px card is an unreadable line
       length, so above 900px it runs in two columns. That uses the width
       *and* keeps the measure near 60 characters, which one wide column
       cannot do at any max-width.
   Written at (0,3,1) so it beats `.lcard p` (0,1,1) on specificity rather
   than on source order. */
.lcard.lcard--text .lcard__cols p {
  max-width: none;
  margin: 0 0 1.05em;
}
.lcard.lcard--text .lcard__cols p:last-child { margin-bottom: 0; }

@media (min-width: 900px) {
  .lcard__cols { columns: 2; column-gap: clamp(30px, 4vw, 60px); }

  /* A paragraph broken across the column gap reads as two paragraphs. */
  .lcard__cols p { break-inside: avoid; }

  /* Unless it is the ONLY paragraph — the homepage SEO block is one long
     paragraph, and a lone unbreakable one sits in column 1 and leaves column
     2 empty. That one is meant to flow across both. */
  .lcard__cols > p:only-child { break-inside: auto; }

  /* Bottom margins, not top: a top margin on the paragraph that happens to
     start column two indents that column against column one. */
}

.lcard__tiles {
  display: grid;
  gap: 12px;
  margin-top: 18px;
}

.ltile {
  display: block;
  padding: 16px 18px 18px;
  border-radius: 6px;
  background: var(--jm-chip);
  color: inherit;
  text-decoration: none;
  transition: background-color .18s ease;
}
.ltile:hover,
.ltile:focus-visible { background: var(--jm-chip-lit); text-decoration: none; }
.ltile b {
  display: block;
  margin-bottom: 5px;
  font-size: 16px;
  font-weight: 700;
  color: var(--jm-heading);
}
.ltile span {
  display: block;
  font-size: 14px;
  line-height: 1.55;
  color: var(--jm-muted);
}

/* Three cards need to drop to two before the two-card grid needs to drop to
   one. Both rules are (0,1,0), so this has to come first — the 720px block
   below it is what finally flattens either grid. */
@media (max-width: 980px) {
  .learn-grid--3 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

@media (max-width: 720px) {
  .learn-grid { grid-template-columns: 1fr; }
}


/* ==========================================================================
   9. SERVICES                                      ref: dipseastories.com
   --------------------------------------------------------------------------
   A dark, gold-tinted panel: serif display heading with SEE ALL opposite,
   then three columns of four rows divided by hairlines.
   ========================================================================== */

/* Two stacked radials rather than one: the reference panel is saturated
   corner to corner, and a single gradient from the top-left leaves the
   bottom-right flat black. */
.svc {
  padding-block: clamp(48px, 6.5vw, 88px);
  background:
    radial-gradient(70% 110% at 100% 108%,
      color-mix(in srgb, var(--jm-accent-dim) 34%, transparent) 0%,
      transparent 62%),
    radial-gradient(125% 145% at 12% 0%,
      color-mix(in srgb, var(--jm-accent-dim) 56%, var(--jm-ink)) 0%,
      var(--jm-ink-soft) 48%,
      var(--jm-ink) 100%);
}

.svc__head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 20px;
  margin-bottom: clamp(22px, 3vw, 36px);
}

.svc__title {
  margin: 0;
  font-family: var(--jm-serif);
  font-weight: 400;
  font-size: clamp(28px, 3.6vw, 46px);
  line-height: 1.08;
  letter-spacing: -.012em;
  color: var(--jm-on-ink);
}

.svc__all {
  flex: 0 0 auto;
  font-size: 12px;
  font-weight: 800;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--jm-accent);
  text-decoration: underline;
  text-underline-offset: 4px;
}
.svc__all:hover,
.svc__all:focus-visible { color: var(--jm-accent-lit); }

/* CSS multi-column, not grid: `column-rule` draws the vertical hairlines
   between columns for free, the count is one number to change per
   breakpoint, and the fill order runs down each column exactly as in the
   reference — while the DOM order a screen reader follows stays the
   order of $SERVICES. */
.svc-list {
  margin: 0;
  padding: 0;
  list-style: none;
  columns: 3;
  column-gap: clamp(26px, 3vw, 54px);
  column-rule: 1px solid var(--jm-ink-line-2);
}
/* Pico's `ul li{list-style:square}` is (0,0,2); clearing it has to happen on
   the `li`, not the `ul` — see the masthead notes above. */
.svc-list li {
  margin: 0;
  padding: 0;
  list-style: none;
  break-inside: avoid;
  border-bottom: 1px solid var(--jm-ink-line-2);
}

.svc-row {
  display: flex;
  align-items: center;
  gap: 14px;
  padding-block: 14px;
  color: inherit;
  text-decoration: none;
}
.svc-row:hover,
.svc-row:focus-visible { text-decoration: none; }

.svc-row__thumb {
  flex: 0 0 auto;
  width: 64px;
  height: 48px;
  border-radius: 4px;
  object-fit: cover;
  background: var(--jm-ink-line);
}

.svc-row__body { flex: 1 1 auto; min-width: 0; }
.svc-row__body b {
  display: block;
  margin-bottom: 3px;
  font-size: 15px;
  font-weight: 700;
  color: var(--jm-on-ink);
  transition: color .16s ease;
}
.svc-row__body span {
  display: block;
  font-size: 13px;
  line-height: 1.45;
  color: var(--jm-nav);
}

.svc-row__go {
  flex: 0 0 auto;
  display: grid;
  place-items: center;
  width: 26px;
  height: 26px;
  border-radius: 50%;
  font-size: 13px;
  background: var(--jm-accent);
  color: var(--jm-on-accent);
  transition: background-color .16s ease;
}

.svc-row:hover .svc-row__body b,
.svc-row:focus-visible .svc-row__body b { color: var(--jm-accent); }
.svc-row:hover .svc-row__go,
.svc-row:focus-visible .svc-row__go { background: var(--jm-accent-lit); }

@media (max-width: 1024px) { .svc-list { columns: 2; } }
@media (max-width: 640px)  { .svc-list { columns: 1; column-rule: none; } }


/* ==========================================================================
   10. SERVICE AREAS                          ref: teamskeet.com/verify
   --------------------------------------------------------------------------
   Near-black panel, centred: accent eyebrow, heavy two-tone display
   heading, wide-tracked subline, grid of bordered area tiles.
   ========================================================================== */

.areas {
  padding-block: clamp(50px, 7vw, 92px);
  background: var(--jm-ink);
  text-align: center;
}

.areas__eyebrow {
  margin: 0 0 12px;
  font-size: 12px;
  font-weight: 800;
  letter-spacing: .28em;
  text-transform: uppercase;
  color: var(--jm-accent);
}

.areas__title {
  margin: 0 0 14px;
  font-family: var(--jm-display);
  font-weight: 400;
  font-size: clamp(30px, 5vw, 62px);
  line-height: 1;
  letter-spacing: .006em;
  text-transform: uppercase;
  color: var(--jm-on-ink);
}
.areas__title em { font-style: normal; color: var(--jm-accent); }

.areas__sub {
  margin: 0 auto clamp(28px, 3.6vw, 46px);
  max-width: 64ch;
  font-size: 12.5px;
  font-weight: 600;
  line-height: 1.7;
  letter-spacing: .16em;
  text-transform: uppercase;
  color: var(--jm-nav);
}

.areas-grid {
  display: grid;
  grid-template-columns: repeat(6, minmax(0, 1fr));
  gap: clamp(10px, 1.2vw, 18px);
  margin: 0;
  padding: 0;
  list-style: none;
}
.areas-grid li { margin: 0; padding: 0; list-style: none; }

.area-tile {
  display: grid;
  place-items: center;
  min-height: clamp(72px, 7vw, 94px);
  padding: 14px 10px;
  border: 1px solid var(--jm-ink-line-2);
  border-radius: 8px;
  background: var(--jm-ink-soft);
  color: var(--jm-on-ink);
  text-decoration: none;
  transition: border-color .18s ease, color .18s ease, background-color .18s ease;
}
.area-tile span {
  font-size: clamp(12px, 1.15vw, 14px);
  font-weight: 700;
  line-height: 1.35;
  letter-spacing: .1em;
  text-transform: uppercase;
  text-align: center;
}
.area-tile:hover,
.area-tile:focus-visible {
  border-color: var(--jm-accent);
  background: var(--jm-ink-line);
  color: var(--jm-accent);
  text-decoration: none;
}

@media (max-width: 1100px) { .areas-grid { grid-template-columns: repeat(4, minmax(0, 1fr)); } }
@media (max-width: 720px)  { .areas-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
@media (max-width: 460px)  { .areas-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); } }


/* ==========================================================================
   11. GALLERY                                        ref: frolicme.com/stories
   --------------------------------------------------------------------------
   Portrait cards: overlay label at the top, serif title and credit on the
   photo, caption strip along the bottom, centred copy beneath. Two cards
   start blurred behind a padlock and unblur when clicked — a hidden
   checkbox, the same CSS-only technique the masthead uses.
   ========================================================================== */

.gal {
  padding-block: clamp(50px, 7vw, 90px);
  background: var(--jm-paper);
}

.gal__title {
  margin: 0 0 10px;
  font-size: clamp(26px, 3.4vw, 42px);
  font-weight: 800;
  line-height: 1.12;
  letter-spacing: -.022em;
  text-align: center;
  color: var(--jm-heading);
}

.gal__sub {
  margin: 0 auto clamp(28px, 3.6vw, 46px);
  max-width: 60ch;
  font-size: 15px;
  line-height: 1.6;
  text-align: center;
  color: var(--jm-muted);
}

.gal-grid {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: clamp(20px, 2.4vw, 34px);
}

/* Pico gives `figure` no box of its own, but it does style `figure
   figcaption` (0,0,2) — beaten by `.gcard figcaption` (0,1,1) below. */
.gcard { margin: 0; padding: 0; }

/* Kept in the tab order so the padlock can be opened from the keyboard, but
   pulled out of sight — the focus ring is painted on the <label>, exactly as
   the masthead's `.hdr-switch` does. */
.lock-switch {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  opacity: 0;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
}

.gcard__frame {
  position: relative;
  overflow: hidden;
  aspect-ratio: 56 / 75;
  border-radius: 6px;
  background: var(--jm-chip);
}
.gcard__frame img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  transition: filter .35s ease, transform .35s ease;
}

/* The scale hides the soft edges the blur would otherwise leave inside the
   frame. No `brightness()` here: the overlay already darkens the tile, and
   dimming a dark photo on top of that turns it to flat black. Both rules are
   (0,3,1); the reveal is written one class deeper so it wins on specificity
   rather than on source order. */
.gcard.is-locked .gcard__frame img {
  filter: blur(15px) saturate(.75);
  transform: scale(1.09);
}
.gcard .lock-switch:checked ~ .gcard__frame img {
  filter: none;
  transform: none;
}

/* In the reference the locked card carries nothing but the blur and its
   badge — the title, credit and caption strip only appear once the photo
   does. They fade back in with it. */
.gcard.is-locked .gcard__label,
.gcard.is-locked .gcard__name,
.gcard.is-locked .gcard__no,
.gcard.is-locked .gcard__strip {
  opacity: 0;
  transition: opacity .3s ease;
}
.gcard .lock-switch:checked ~ .gcard__frame .gcard__label,
.gcard .lock-switch:checked ~ .gcard__frame .gcard__name,
.gcard .lock-switch:checked ~ .gcard__frame .gcard__no,
.gcard .lock-switch:checked ~ .gcard__frame .gcard__strip {
  opacity: 1;
}

.gcard__label {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  padding: 10px 12px;
  font-size: 11px;
  font-weight: 800;
  letter-spacing: .14em;
  text-transform: uppercase;
  text-align: center;
  color: var(--jm-on-ink);
  background: linear-gradient(180deg,
    color-mix(in srgb, var(--jm-ink) 62%, transparent), transparent);
  text-shadow: 0 1px 3px color-mix(in srgb, var(--jm-ink) 70%, transparent);
}

.gcard__name {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 66px;
  padding-inline: 14px;
  font-family: var(--jm-serif);
  font-style: italic;
  font-size: clamp(26px, 2.9vw, 38px);
  line-height: 1.05;
  text-align: center;
  color: var(--jm-on-ink);
  text-shadow: 0 2px 12px color-mix(in srgb, var(--jm-ink) 74%, transparent);
}

.gcard__no {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 46px;
  font-size: 12px;
  font-weight: 700;
  text-align: center;
  color: var(--jm-on-ink);
  text-shadow: 0 1px 6px color-mix(in srgb, var(--jm-ink) 76%, transparent);
}

.gcard__strip {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  padding: 8px 10px;
  font-size: 11.5px;
  font-weight: 600;
  line-height: 1.3;
  text-align: center;
  background: var(--jm-chip);
  color: var(--jm-body);
}

/* --- the padlock overlay ---------------------------------------------------- */

.gcard__lock {
  position: absolute;
  inset: 0;
  display: block;
  cursor: pointer;
  background: color-mix(in srgb, var(--jm-ink) 26%, transparent);
  transition: opacity .3s ease, visibility .3s;
}
.gcard .lock-switch:checked ~ .gcard__frame .gcard__lock {
  opacity: 0;
  visibility: hidden;
  pointer-events: none;
}
.gcard .lock-switch:focus-visible ~ .gcard__frame .gcard__lock {
  outline: 3px solid var(--jm-accent);
  outline-offset: -3px;
}

/* Top-left badge, as in the reference. */
.gcard__badge {
  position: absolute;
  top: 14px;
  left: 14px;
  display: grid;
  justify-items: center;
  gap: 5px;
  width: 68px;
  font-size: 26px;                 /* drives the padlock, which is 1em */
  color: var(--jm-on-ink);
  text-shadow: 0 1px 6px color-mix(in srgb, var(--jm-ink) 70%, transparent);
}
.gcard__badge b {
  font-size: 11px;
  font-weight: 800;
  line-height: 1.35;
  letter-spacing: .14em;
  text-transform: uppercase;
  text-align: center;
}

/* The one thing the reference has no equivalent for: it never unlocks, so it
   needs no affordance. Click-to-reveal does. */
.gcard__hint {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  padding: 8px 16px;
  border-radius: 100px;
  background: var(--jm-accent);
  color: var(--jm-on-accent);
  font-size: 11.5px;
  font-weight: 800;
  letter-spacing: .1em;
  text-transform: uppercase;
  white-space: nowrap;
}

/* --- copy under the card ---------------------------------------------------- */

.gcard figcaption {
  padding: 16px 6px 0;
  text-align: center;
}

.gcard__link {
  display: inline-block;
  margin-bottom: 6px;
  font-size: clamp(16px, 1.5vw, 20px);
  font-weight: 700;
  letter-spacing: .01em;
  color: var(--jm-heading);
  text-decoration: none;
}
.gcard__link:hover,
.gcard__link:focus-visible {
  color: var(--jm-accent-dim);
  text-decoration: underline;
  text-underline-offset: 3px;
}

.gcard__meta {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 5px;
  margin: 0 0 8px;
  font-size: 13px;
  color: var(--jm-accent-dim);
}
.gcard__meta .jm-ico { font-size: 14px; }

.gcard__text {
  margin: 0;
  font-size: 14px;
  line-height: 1.6;
  color: var(--jm-muted);
}

@media (max-width: 900px) { .gal-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 560px) { .gal-grid { grid-template-columns: 1fr; } }


/* ==========================================================================
   12. FAQ                                          ref: makelovenotporn.tv
   --------------------------------------------------------------------------
   Plain accordion rows split by hairlines, chevron on the right, no boxes.
   Native <details>/<summary>: it opens without JavaScript, and every answer
   is in the HTML for Google to read.
   ========================================================================== */

.faq {
  padding-block: clamp(48px, 6.5vw, 86px);

  /* Pico paints the summary through three of its own variables, from
     selectors that are hard to outrank cleanly:
       details summary:not([role])                          (0,1,2)
       details[open]>summary:not([role]):not(:focus)        (0,3,2)
     Re-mapping the variables is both shorter and the approach the library
     is designed for. */
  --pico-accordion-close-summary-color:  var(--jm-heading);
  --pico-accordion-open-summary-color:   var(--jm-heading);
  --pico-accordion-active-summary-color: var(--jm-accent-dim);
}

/* --------------------------------------------------------------------------
   REDESIGNED 2026-09-12 — "change design home page ... give me yours best".

   Two columns: copy and the two ways out on the left, the accordion in a white
   card on the right. Three measurable faults, not taste:

     1. The rows ran the full 1480px of the shell for a ~400px question, six
        times, with the chevron marooned at the far right — the same fault
        `.ptable`'s right-aligned last cell had.
     2. This was the ONE block the 2026-09-06 background pass missed: every
        other section got white cards on the tinted ground, the FAQ stayed as
        bare text on the ground, and so read as unfinished.
     3. Every row was shut, so the section showed six lines of link-like text
        and no content.

   REF 03 IS NOT DISCARDED. Its actual contribution — hairline rows, a chevron
   on the right, no box around each individual row — is unchanged below; it is
   simply inside a card now. The markup is still native <details> and still
   carries the FAQPage JSON-LD.
   -------------------------------------------------------------------------- */

.faq__grid {
  display: grid;
  /* The left column is capped rather than fluid: past ~380px the lede's
     measure gets too long to scan, and the accordion is what should grow. */
  grid-template-columns: minmax(0, 360px) minmax(0, 1fr);
  gap: clamp(24px, 3.4vw, 56px);
  align-items: start;
}

/* Sticky, so the heading and the two CTAs stay beside the accordion while a
   long answer is open. `align-items: start` on the grid is what lets this
   work — a stretched grid item cannot stick. */
.faq__aside { position: sticky; top: clamp(88px, 9vw, 108px); }

.faq__eyebrow {
  margin: 0 0 8px;
  font-size: 11px;
  font-weight: 800;
  letter-spacing: .16em;
  text-transform: uppercase;
  /* accent-as-TEXT on the light page ground, so accent-dim — --jm-accent is
     about 1.9:1 here. Same rule as §14–16 and the footer headings. */
  color: var(--jm-accent-dim);
}

.faq__title {
  margin: 0 0 12px;
  font-size: clamp(24px, 2.9vw, 38px);
  font-weight: 800;
  line-height: 1.14;
  letter-spacing: -.022em;
  color: var(--jm-heading);
}

/* Stated, not inherited — Pico sets `color` on `p` explicitly (§5). */
.faq__lede {
  margin: 0 0 18px;
  font-size: 14.5px;
  line-height: 1.65;
  color: var(--jm-muted);
}

.faq__chip {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  margin: 0 0 18px;
  padding: 6px 14px;
  border: 1px solid var(--jm-line);
  border-radius: var(--jm-pill);
  background: var(--jm-chip);
  font-size: 11.5px;
  font-weight: 800;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--jm-heading);
}
.faq__chip .jm-ico { font-size: 14px; color: var(--jm-accent-dim); }

.faq__cta {
  display: inline-flex;
  align-items: center;
  gap: 9px;
  width: fit-content;
}
.faq__cta .jm-ico { font-size: 16px; transition: transform .18s ease; }
.faq__cta:hover .jm-ico { transform: translateX(3px); }

/* --- the "not answered here?" card ---------------------------------------- */

.faq__ask {
  margin-top: clamp(20px, 2.6vw, 30px);
  padding-top: clamp(16px, 2vw, 22px);
  border-top: 1px solid var(--jm-line);
}
.faq__ask-h {
  margin: 0 0 6px;
  font-size: 15px;
  font-weight: 800;
  color: var(--jm-heading);
}
.faq__ask-p {
  margin: 0 0 12px;
  font-size: 13px;
  line-height: 1.6;
  color: var(--jm-muted);
}
.faq__ask-row {
  display: flex;
  flex-wrap: wrap;
  gap: 8px 18px;
  margin: 0;
}
.faq__ask-row a {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  font-size: 13px;
  font-weight: 700;
  color: var(--jm-accent-dim);
  text-decoration: none;
}
.faq__ask-row a:hover,
.faq__ask-row a:focus-visible { text-decoration: underline; }
.faq__ask-row .jm-ico { font-size: 15px; }

/* --- the card the accordion sits in --------------------------------------- */

.faq__panel {
  padding: clamp(6px, 1vw, 12px) clamp(18px, 2.4vw, 30px) clamp(16px, 2vw, 24px);
  border: 1px solid var(--jm-line);
  border-radius: var(--jm-r-lg);
  background: var(--jm-card);
  box-shadow: 0 1px 2px var(--jm-shadow);
}

/* The second way through, under the accordion, for anyone who read to the
   bottom without finding their question. */
.faq__more {
  display: flex;
  gap: 10px;
  align-items: flex-start;
  margin: clamp(16px, 2vw, 22px) 0 0;
  font-size: 13px;
  line-height: 1.6;
  color: var(--jm-muted);
}
.faq__more .jm-ico { flex: 0 0 auto; margin-top: 2px; color: var(--jm-accent-dim); }
.faq__more a { color: var(--jm-accent-dim); font-weight: 700; text-decoration: underline; }

/* No top border now: the card's own edge is the line above the first row, and
   two lines 1px apart read as a mistake. */
.faq-list { border-top: 0; }

@media (max-width: 980px) {
  /* One column, and the aside stops sticking — a sticky block in a single
     column follows you down the page over the content it belongs to. */
  .faq__grid { grid-template-columns: minmax(0, 1fr); }
  .faq__aside { position: static; }
  .faq__lede { max-width: 62ch; }
}

.faq details {
  margin: 0;                       /* Pico: details{margin-bottom:spacing} */
  border-bottom: 1px solid var(--jm-line);
}

.faq summary {
  position: relative;
  padding: 18px 44px 18px 0;
  font-size: clamp(15px, 1.4vw, 17px);
  font-weight: 600;
  line-height: 1.45;               /* Pico pins this to 1rem; long questions clip */
  list-style: none;
}
.faq details[open] summary { margin-bottom: 0; }

/* Pico draws its own chevron as a fixed-colour background image on
   `details summary::after` (0,0,3). Replaced with a box-chevron in
   `currentColor` so it follows the theme — the override carries the `.faq`
   class to outrank it, and the open state carries `[open]` as well. */
.faq details summary::after {
  content: '';
  position: absolute;
  top: 50%;
  right: 4px;
  display: block;
  float: none;
  width: 9px;
  height: 9px;
  margin: 0;
  border-right: 2px solid currentColor;
  border-bottom: 2px solid currentColor;
  background: none;
  transform: translateY(-70%) rotate(45deg);
  transition: transform .22s ease;
}
.faq details[open] summary::after { transform: translateY(-25%) rotate(225deg); }

/* Pico's own focus ring is `:focus-visible:not([role])` (0,3,2) with an 8px
   outline-offset, which collides with the rows above and below. Matched at
   (0,3,2) so source order — style.css loads after pico.min.css — decides. */
.faq details summary:focus-visible:not([role]) {
  outline: 2px solid var(--jm-accent-dim);
  outline-offset: -2px;
}

.faq-a { padding: 0 44px 22px 0; }
.faq-a p {
  margin: 0;
  max-width: 80ch;
  font-size: 15px;
  line-height: 1.7;
  color: var(--jm-muted);
}


/* ==========================================================================
   13. SUB-PAGES
   --------------------------------------------------------------------------
   services.php · therapists.php · pricing.php · about.php

   The Notion board has no screenshot for any of these, so they are built
   out of blocks already approved from the references rather than designed
   from scratch. Almost everything here is reuse:

     .areas.pbanner      the ref 08 panel, shorter, used as the page banner
     .lcard / .ltile     the ref 02 cards, on a <div> instead of an <a>
     .faq                the ref 03 accordion, unchanged
     .areas / .area-tile the homepage areas panel, unchanged
     .btn-solid          the masthead button

   What is genuinely new is only the small furniture the reference cards had
   no equivalent for: the duration line, the "book this if" tick list, the
   avatar row on a therapist card, and the price table.
   ========================================================================== */

/* --- the page banner: ref 08, minus the grid, with less air --------------- */

/* (0,1,0), the same as `.areas`, so source order decides — this file's
   later rule wins and only the padding changes. */
.pbanner { padding-block: clamp(38px, 5vw, 68px); }
.pbanner .areas__sub { margin-bottom: 0; }

/* --- the body of a sub-page ---------------------------------------------- */

.page { padding-block: clamp(42px, 5.5vw, 78px); }
.page--paper { background: var(--jm-paper); }

/* `.page__lede` at (0,1,0) beats Pico's `p` and its
   `:is(p,ul,…)~:is(h1,…,h6)` sibling margin rule.

   Left-aligned, not centred: the heading, the hairline and the card grid
   above and below it all start at the gutter, and a centred column of copy
   between them reads as a mistake. */
.page__lede {
  margin: 0 0 1.15em;
  max-width: 74ch;
  font-size: clamp(16px, 1.5vw, 19px);
  line-height: 1.65;
  color: var(--jm-body);
}
/* Several ledes in a row are one piece of prose, so they sit a paragraph
   apart; only the last one opens up the gap to whatever follows. */
.page__lede:last-of-type { margin-bottom: clamp(30px, 4vw, 52px); }

.page__h2 {
  margin: 0 0 clamp(14px, 1.8vw, 22px);
  font-size: clamp(22px, 2.8vw, 34px);
  font-weight: 800;
  line-height: 1.15;
  letter-spacing: -.02em;
  color: var(--jm-heading);
}

.page__note {
  margin: clamp(18px, 2.2vw, 26px) 0 0;
  max-width: 90ch;
  font-size: 13px;
  line-height: 1.7;
  color: var(--jm-muted);
}

/* --- service cards: a ref 02 card with three additions ------------------- */

/* Anchored from the homepage service rows, and the masthead is sticky —
   without this the card title lands underneath it. */
.lcard[id] { scroll-margin-top: calc(var(--jm-header-h) + 18px); }

/* Both of these are paragraphs inside a card, so they have to be written at
   `.lcard .x` (0,2,0) to outrank `.lcard p` (0,1,1) — which pins margin to 0
   and the colour to muted. */
.lcard .scard__meta,
.lcard .scard__lbl {
  display: flex;
  align-items: center;
  gap: 7px;
  font-size: 12px;
  font-weight: 800;
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--jm-accent-dim);
}
.lcard .scard__meta { margin: 0 0 14px; }
.lcard .scard__lbl  { margin: 20px 0 10px; color: var(--jm-muted); }
.scard__meta .jm-ico { font-size: 15px; }

/* Pico's `ul li{list-style:square}` is (0,0,2), so the reset has to be on
   the `li` — clearing it on the `ul` is inherited and loses. */
.scard__for {
  margin: 16px 0 0;
  padding: 0;
  list-style: none;
}
.scard__for li {
  display: flex;
  align-items: flex-start;
  gap: 9px;
  margin: 0 0 7px;
  padding: 0;
  list-style: none;
  font-size: 14px;
  line-height: 1.5;
  color: var(--jm-body);
}
.scard__for li:last-child { margin-bottom: 0; }
.scard__for .jm-ico {
  margin-top: .2em;
  font-size: 14px;
  color: var(--jm-accent-dim);
}

.scard__cta {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  margin-top: 18px;
  font-size: 13px;
  font-weight: 800;
  letter-spacing: .09em;
  text-transform: uppercase;
  color: var(--jm-accent-dim);
  text-decoration: underline;
  text-underline-offset: 4px;
}
.scard__cta:hover,
.scard__cta:focus-visible { color: var(--jm-heading); }
.scard__cta .jm-ico { font-size: 15px; }

/* --- therapist cards ------------------------------------------------------ */

.tcard__top {
  display: flex;
  align-items: center;
  gap: 14px;
  margin-bottom: 14px;
}
.tcard__top img {
  width: 54px;
  height: 54px;
  flex: 0 0 54px;
  border-radius: 50%;
  object-fit: cover;
  background: var(--jm-chip);
  border: 1px solid var(--jm-line);
}

/* `.tcard__top h3` (0,2,1) clears Pico's `h3` and its sibling-margin rule,
   and overrides `.lcard h3`'s bottom margin without touching the icon
   layout the other cards rely on. */
.tcard__top h3 { margin: 0 0 3px; }

.tcard__role {
  margin: 0;
  font-size: 11.5px;
  font-weight: 800;
  letter-spacing: .13em;
  text-transform: uppercase;
  color: var(--jm-accent-dim);
}

/* --- price table ---------------------------------------------------------- */

/* Twelve treatments against three duration columns will not compress below
   about 620px, so the table scrolls inside its own box rather than pushing
   the page sideways. */
/* >>> WHITE CARD, ROUNDED TOKEN — fixed 2026-09-12. Two leftovers: the radius
       was a hard-coded `8px` that the §24 rounding pass never reached, and the
       fill was `--jm-paper` — which, since `--jm-ground: var(--jm-paper)`, is
       THE EXACT COLOUR OF THE PAGE BEHIND IT. The table had no fill setting it
       apart from the page at all, only its 1px border: the same "two colours
       the wrong way round" fault the 2026-09-06 background pass fixed
       everywhere else and missed here.

       Scope: this changes pricing.php's table. It does NOT change the admin
       desk, which has overridden all four of these properties since it was
       built (`.desk .ptable`, below) — that override is now redundant and
       harmless, and is left alone rather than deleted so the desk keeps
       saying what it wants explicitly.                                  <<< */
.ptable {
  overflow-x: auto;
  border: 1px solid var(--jm-line);
  border-radius: var(--jm-r-lg);
  background: var(--jm-card);
  box-shadow: 0 1px 2px var(--jm-shadow);
}

.ptable table {
  margin: 0;
  min-width: 620px;
  --pico-table-border-color: var(--jm-line);
  --pico-table-row-stripped-background-color: transparent;
}
.ptable caption {
  padding: 16px 18px 0;
  font-size: 12px;
  font-weight: 800;
  letter-spacing: .13em;
  text-transform: uppercase;
  text-align: left;
  color: var(--jm-accent-dim);
}
.ptable th,
.ptable td {
  padding: 14px 18px;
  font-size: 14.5px;
  vertical-align: middle;
}
/* Left to its own devices the browser gives the duration column half the
   table, stranding the price against the far edge. */
.ptable thead th:nth-child(1) { width: 40%; }
.ptable thead th:nth-child(2) { width: 22%; }

.ptable thead th {
  font-size: 11.5px;
  font-weight: 800;
  letter-spacing: .13em;
  text-transform: uppercase;
  color: var(--jm-muted);
  white-space: nowrap;
}
/* Treatment and duration read left; only the money column is right-aligned. */
.ptable th,
.ptable td { text-align: left; }
.ptable thead th:last-child,
.ptable tbody td:last-child { text-align: right; }

/* The treatment name is a row header spanning that treatment's durations. */
.ptable tbody th {
  font-weight: 400;
  vertical-align: top;
  white-space: nowrap;
}
.ptable tbody th a {
  font-weight: 700;
  color: var(--jm-heading);
  text-decoration: none;
}
.ptable tbody th a:hover,
.ptable tbody th a:focus-visible {
  color: var(--jm-accent-dim);
  text-decoration: underline;
  text-underline-offset: 3px;
}
.ptable tbody tr:last-child th,
.ptable tbody tr:last-child td { border-bottom: 0; }

.ptable td { color: var(--jm-body); font-variant-numeric: tabular-nums; }
/* the documented "price not published yet" state, not an error */
.ptable td.is-tbc { color: var(--jm-muted); font-style: italic; }

/* --- closing call-to-action band ----------------------------------------- */

/* >>> REWORKED 2026-09-12 — "this section need attracive design boder and
       sadow and color full text and font". The client pointed at the one on
       profile.php; this class carries FIFTEEN instances across ten files, so
       the work is done here and every closing CTA on the site gets it.

       It also fixes a real leftover: `border-radius: 8px` was hard-coded and
       the §24 rounding pass never reached it, so this was the last square-ish
       card on a site where everything else is 16px.                      <<< */
.cta-band {
  position: relative;                /* for the accent edge below */
  overflow: hidden;                  /* clips the edge to the radius */
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: clamp(18px, 3vw, 40px);
  margin-top: clamp(28px, 3.5vw, 44px);
  /* Extra left padding to clear the accent edge. */
  padding: clamp(22px, 2.6vw, 34px) clamp(22px, 3vw, 38px);
  padding-left: clamp(28px, 3.2vw, 46px);
  border: 1px solid var(--jm-line);
  border-radius: var(--jm-r-lg);
  /* White, not paper: on the tinted page ground since the 2026-09-06
     background pass, a paper-coloured card is invisible against it. */
  background: var(--jm-card);
  box-shadow: 0 2px 16px var(--jm-shadow);
}

/* The accent edge. Absolutely positioned so it is NOT a flex item — a
   ::before on a flex container becomes one otherwise and would sit in the row
   between the copy and the button. */
.cta-band::before {
  content: '';
  position: absolute;
  inset: 0 auto 0 0;
  width: 4px;
  background: linear-gradient(180deg, var(--jm-accent-lit), var(--jm-accent-dim));
}

/* A soft accent wash behind the top-right corner, so the band reads as warm
   rather than as another plain box. Decorative and unclickable. */
.cta-band::after {
  content: '';
  position: absolute;
  top: -40%;
  right: -6%;
  width: 320px;
  height: 320px;
  border-radius: 50%;
  background: radial-gradient(circle,
    color-mix(in srgb, var(--jm-accent) 22%, transparent) 0%,
    transparent 70%);
  pointer-events: none;
}

/* The copy has to sit above both decorations. `position: relative` with no
   offsets is enough — it only needs a stacking context. */
.cta-band > * { position: relative; }

/* `.cta-band h2` (0,1,1) clears Pico's `h2` and the sibling-margin rule.
   THE SERIF is the "unique font": the same display treatment as the services
   panel, the gallery card titles, `.mgr__title` and `.arooms__title`, and
   visibly different from the sans of the copy under it. */
.cta-band h2 {
  margin: 0 0 8px;
  font-family: var(--jm-serif);
  font-size: clamp(21px, 2.2vw, 29px);
  font-weight: 700;
  letter-spacing: -.01em;
  line-height: 1.18;
  color: var(--jm-heading);
}
/* The two-tone half, where a call site marks one up. accent-dim, not accent:
   this card is always on a light ground and --jm-accent is ~1.9:1 there. */
.cta-band h2 em { font-style: italic; color: var(--jm-accent-dim); }

.cta-band p {
  margin: 0;
  max-width: 58ch;
  font-size: 15px;
  line-height: 1.6;
  color: var(--jm-muted);
}
.cta-band .btn-solid { flex: 0 0 auto; height: 48px; }

@media (max-width: 720px) {
  /* The button below the copy rather than squeezed beside it. */
  .cta-band { display: block; }
  .cta-band .btn-solid { margin-top: 18px; }
}

/* --- the About page's contact block -------------------------------------- */

/* A wide card carrying four tiles rather than the homepage's two — two up,
   collapsing to one on a narrow screen. */
.lcard__tiles--2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }

.contact-lines {
  margin: 18px 0 0;
  padding: 0;
  list-style: none;
}
.contact-lines li {
  margin: 0 0 10px;
  padding: 0;
  list-style: none;
  font-size: 15px;
  line-height: 1.5;
}
.contact-lines li:last-child { margin-bottom: 0; }
.contact-lines a {
  font-weight: 700;
  color: var(--jm-heading);
  text-decoration: underline;
  text-underline-offset: 3px;
}
.contact-lines a:hover,
.contact-lines a:focus-visible { color: var(--jm-accent-dim); }
.contact-lines b {
  display: block;
  font-size: 11.5px;
  font-weight: 800;
  letter-spacing: .13em;
  text-transform: uppercase;
  color: var(--jm-muted);
}

/* --- sub-pages: tablet + mobile ------------------------------------------ */

@media (max-width: 720px) {
  .cta-band { flex-direction: column; align-items: flex-start; }
  .cta-band .btn-solid { width: 100%; }
  .lcard__tiles--2 { grid-template-columns: 1fr; }
}


/* ==========================================================================
   14. WHY BOOK WITH US                    ref 09 — board "section 1"
   --------------------------------------------------------------------------
   Dark two-column panel. Left: a phone mockup ringed by floating circular
   icon bubbles. Right: five benefit rows (square icon tile, bold title,
   accent sub-line, description) and a solid CTA.

   The phone and the bubbles are drawn entirely in CSS — no device image, no
   extra requests. The photos inside the screen come from the hero set.
   ========================================================================== */

.why {
  padding-block: clamp(50px, 7vw, 92px);
  background:
    radial-gradient(60% 80% at 18% 30%,
      color-mix(in srgb, var(--jm-accent-dim) 26%, transparent) 0%,
      transparent 64%),
    var(--jm-ink);
}

.why__grid {
  display: grid;
  grid-template-columns: minmax(0, .82fr) minmax(0, 1fr);
  align-items: center;
  gap: clamp(30px, 5vw, 76px);
}

.why__title {
  margin: 0 0 clamp(24px, 3vw, 38px);
  font-size: clamp(26px, 3.4vw, 42px);
  font-weight: 800;
  line-height: 1.1;
  letter-spacing: -.024em;
  color: var(--jm-on-ink);
}

/* THE BRAND NAME, TWO-TONE — 2026-09-12: "Why book with JioMassage ... need
   to colors differntly".

   The same split the masthead, the footer, the entry warning, the desk bar
   and the phone mockup inside this very section already use: `Jio` in the
   heading's own colour, `Massage` in the accent. Painting the whole word one
   colour would have been a seventh way of writing the same name on one site.

   >>> THE ACCENT TOKEN IS --jm-accent-ink, NOT --jm-accent, and that is the
       whole reason this needs its own rule rather than copying `.egate__mark`.
       Section 7 carries `.jm-lit`, so it renders LIGHT — and `--jm-accent`
       (#D9B44A) is about 1.9:1 on white, which is unreadable as text.
       `--jm-accent-ink` resolves to `--jm-accent` on the dark half of the site
       and to `--jm-accent-dim` (~5.2:1) under `.jm-lit`. That split is exactly
       what §14–16 were rewritten for. Take `.jm-lit` off this section and the
       same rule still reads correctly on near-black.                     <<< */
.why__mark {
  /* white-space: nowrap — "Jio" and "Massage" are one word and must never be
     broken across two lines by the wrap that puts the brand at a line end. */
  white-space: nowrap;
}
.why__mark em {
  font-style: normal;              /* <em> is emphasis here, not italics */
  color: var(--jm-accent-ink);
}

/* --- the benefit rows ----------------------------------------------------- */

.why-list {
  margin: 0;
  padding: 0;
  list-style: none;
}
/* Pico's `ul li{list-style:square}` is (0,0,2) — clear it on the `li`. */
.why-list li {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  gap: 4px 18px;
  margin: 0 0 clamp(18px, 2.2vw, 26px);
  padding: 0;
  list-style: none;
}
.why-list li:last-child { margin-bottom: clamp(24px, 3vw, 34px); }

/* The rounded-square icon tile, spanning both text rows. */
.why-list__ico {
  grid-row: 1 / span 3;
  display: grid;
  place-items: center;
  width: 52px;
  height: 52px;
  font-size: 24px;
  border-radius: 11px;
  background: var(--jm-ink-line);
  color: var(--jm-accent-ink);
}

/* (0,1,1) each, clearing Pico's h3/p rules and its
   `:is(p,ul,…)~:is(h1,…,h6)` sibling margin. */
.why-list h3 {
  margin: 0;
  font-size: clamp(17px, 1.6vw, 21px);
  font-weight: 800;
  letter-spacing: -.012em;
  line-height: 1.25;
  color: var(--jm-on-ink);
}
.why-list b {
  display: block;
  font-size: 13.5px;
  font-weight: 800;
  letter-spacing: .04em;
  color: var(--jm-accent-ink);
}
.why-list p {
  margin: 3px 0 0;
  max-width: 52ch;
  font-size: 14.5px;
  line-height: 1.6;
  color: var(--jm-nav);
}

/* --- the phone mockup, drawn in CSS -------------------------------------- */

.why-phone {
  position: relative;
  justify-self: center;
  width: min(300px, 78vw);
  isolation: isolate;
}

.why-phone__body {
  position: relative;
  z-index: 1;
  padding: 12px;
  border: 2px solid var(--jm-ink-line-2);
  border-radius: 40px;
  background: var(--jm-ink-soft);
  box-shadow: 0 30px 70px color-mix(in srgb, var(--jm-ink) 78%, transparent);
}

.why-phone__screen {
  overflow: hidden;
  border-radius: 30px;
  background: var(--jm-ink);
}

/* the notch / speaker pill at the top of the screen */
.why-phone__notch {
  width: 74px;
  height: 5px;
  margin: 9px auto 6px;
  border-radius: 100px;
  background: var(--jm-ink-line-2);
}

.why-phone__bar {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 9px 12px;
}
.why-phone__mark {
  font-family: var(--jm-display);
  font-size: 15px;
  letter-spacing: .01em;
  text-transform: uppercase;
  color: var(--jm-on-ink);
}
.why-phone__mark em { font-style: normal; color: var(--jm-accent-ink); }

.why-phone__find {
  display: flex;
  align-items: center;
  gap: 6px;
  margin: 0 12px 10px;
  padding: 7px 10px;
  border-radius: 6px;
  background: var(--jm-ink-line);
  font-size: 10.5px;
  color: var(--jm-nav-dim);
}
.why-phone__find .jm-ico { font-size: 12px; }

.why-phone__hero {
  display: block;
  width: 100%;
  height: auto;
  aspect-ratio: 16 / 11;
  object-fit: cover;
  background: var(--jm-ink-line);
}
/* The client's clips are 4:3 inside a 16:9 frame; at 16/11 the black
   pillarbox bars would show at both edges. 4:3 crops exactly to the
   picture (a hair of scale hides any encoder edge line). */
.why-phone__hero--vid {
  aspect-ratio: 4 / 3;
  scale: 1.02;
}

.why-phone__cta {
  display: block;
  margin: 10px 12px 8px;
  padding: 9px;
  border-radius: 6px;
  background: var(--jm-accent);
  color: var(--jm-on-accent);
  font-size: 11.5px;
  font-weight: 800;
  letter-spacing: .09em;
  text-transform: uppercase;
  text-align: center;
}
.why-phone__link {
  display: block;
  margin: 0 12px 10px;
  padding: 8px;
  border: 1px solid var(--jm-ink-line-2);
  border-radius: 6px;
  font-size: 10.5px;
  font-weight: 700;
  text-align: center;
  color: var(--jm-nav);
}

.why-phone__tiles {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 6px;
  padding: 0 12px 14px;
}
.why-phone__tiles img {
  display: block;
  width: 100%;
  height: auto;
  aspect-ratio: 4 / 3;
  border-radius: 5px;
  object-fit: cover;
  background: var(--jm-ink-line);
}

/* --- the floating icon bubbles ------------------------------------------- */

/* Six glowing discs scattered around the phone, as in the reference. They
   sit behind the device (z-index 0 against the body's 1) so the phone reads
   as being in front of them. */
.why-bubble {
  position: absolute;
  z-index: 0;
  display: grid;
  place-items: center;
  border-radius: 50%;
  background: radial-gradient(circle at 35% 30%,
    color-mix(in srgb, var(--jm-accent-dim) 52%, transparent) 0%,
    color-mix(in srgb, var(--jm-accent-dim) 16%, transparent) 70%,
    transparent 100%);
  color: color-mix(in srgb, var(--jm-on-ink) 60%, transparent);
}
.why-bubble--1 { width: 78px; height: 78px; font-size: 30px; top:  6%; left: -16%; }
.why-bubble--2 { width: 56px; height: 56px; font-size: 22px; top: 30%; left: -24%; }
.why-bubble--3 { width: 66px; height: 66px; font-size: 26px; top: 66%; left: -19%; }
.why-bubble--4 { width: 60px; height: 60px; font-size: 24px; top: 14%; right:-20%; }
.why-bubble--5 { width: 72px; height: 72px; font-size: 28px; top: 46%; right:-25%; }
.why-bubble--6 { width: 52px; height: 52px; font-size: 20px; top: 76%; right:-16%; }

@media (prefers-reduced-motion: no-preference) {
  .why-bubble { animation: jm-float 7s ease-in-out infinite; }
  .why-bubble--2 { animation-duration: 9s;  animation-delay: -1.5s; }
  .why-bubble--3 { animation-duration: 8s;  animation-delay: -3s;   }
  .why-bubble--4 { animation-duration: 10s; animation-delay: -2s;   }
  .why-bubble--5 { animation-duration: 7.5s;animation-delay: -4s;   }
  .why-bubble--6 { animation-duration: 11s; animation-delay: -1s;   }
}
@keyframes jm-float {
  0%, 100% { transform: translateY(0); }
  50%      { transform: translateY(-12px); }
}

@media (max-width: 900px) {
  .why__grid { grid-template-columns: 1fr; gap: clamp(34px, 7vw, 54px); }
  /* The bubbles hang outside the phone box; once the column is the full
     width of the screen that overflows the page, so they come in. */
  .why-bubble--1, .why-bubble--3 { left: -8%; }
  .why-bubble--2 { left: -12%; }
  .why-bubble--4, .why-bubble--6 { right: -8%; }
  .why-bubble--5 { right: -12%; }
}
@media (max-width: 560px) {
  .why-bubble { display: none; }   /* no room for them beside the phone */
  .why-list__ico { width: 44px; height: 44px; font-size: 21px; }
  .why-list li { gap: 3px 13px; }
}


/* ==========================================================================
   15. MASSAGE SERVICE NEAR YOU             ref 11 — board "section 3"
   --------------------------------------------------------------------------
   A bordered dark panel: serif heading, subline, a two-cell stat box, then
   the primary button + OR + town select, a hairline, and the sort / within /
   clear row.

   Everything is a native <form> control, so the whole panel works with
   scripting off — the reference's GPS button is the submit instead.
   ========================================================================== */

.near {
  padding-block: clamp(44px, 6vw, 78px);
  background: var(--jm-ink-soft);
}

.near__panel {
  max-width: 860px;
  margin-inline: auto;
  padding: clamp(28px, 4vw, 52px) clamp(20px, 3.5vw, 46px);
  border: 1px solid var(--jm-accent-dim);
  border-radius: 10px;
  background: var(--jm-ink);
  text-align: center;
}

.near__title {
  margin: 0 0 10px;
  font-family: var(--jm-serif);
  font-weight: 400;
  font-size: clamp(28px, 4vw, 50px);
  line-height: 1.06;
  letter-spacing: -.014em;
  color: var(--jm-on-ink);
}

.near__sub {
  margin: 0 0 clamp(20px, 2.6vw, 30px);
  font-size: 15px;
  line-height: 1.55;
  color: var(--jm-nav);
}

/* --- the two-cell stat box ----------------------------------------------- */

.near-stats {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  margin: 0 auto clamp(22px, 3vw, 32px);
  max-width: 470px;
  border: 1px solid var(--jm-ink-line-2);
  border-radius: 8px;
  background: var(--jm-ink-soft);
  list-style: none;
  padding: 0;
}
.near-stats li {
  margin: 0;
  padding: 16px 14px;
  list-style: none;
}
/* the vertical hairline splitting the two cells */
.near-stats li + li { border-left: 1px solid var(--jm-ink-line-2); }

.near-stats b {
  display: block;
  font-family: var(--jm-display);
  font-size: clamp(26px, 3vw, 36px);
  font-weight: 400;
  line-height: 1.05;
  color: var(--jm-accent-ink);
}
.near-stats span {
  display: block;
  margin-top: 5px;
  font-size: 10.5px;
  font-weight: 800;
  letter-spacing: .17em;
  text-transform: uppercase;
  color: var(--jm-nav);
}
.near-stats i {
  display: block;
  margin-top: 3px;
  font-size: 9.5px;
  font-style: normal;
  letter-spacing: .13em;
  text-transform: uppercase;
  color: var(--jm-nav-dim);
}

/* --- the primary row: submit + OR + town select -------------------------- */

.near-pick {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 14px;
  flex-wrap: wrap;
  margin: 0;
}

.near-pick__or {
  flex: 0 0 auto;
  font-size: 11px;
  font-weight: 800;
  letter-spacing: .16em;
  text-transform: uppercase;
  color: var(--jm-nav-dim);
}

/* The reference's button is a gold gradient with a glow.
   Written as `button.near-go` (0,1,1), not `.near-go` (0,1,0): Pico's
   `button[type=submit]{width:100%}` is (0,1,1) and would otherwise stretch
   this to the full panel and push OR + the select onto a second line. */
button.near-go {
  flex: 0 0 auto;
  width: auto;
  height: 52px;
  display: inline-flex;
  align-items: center;
  gap: 10px;
  margin: 0;
  padding-inline: 26px;
  border: 1px solid var(--jm-accent-lit);
  border-radius: 6px;
  background: linear-gradient(180deg, var(--jm-accent-lit), var(--jm-accent-dim));
  color: var(--jm-on-accent);
  font-size: 13px;
  font-weight: 800;
  letter-spacing: .13em;
  text-transform: uppercase;
  cursor: pointer;
  box-shadow: 0 0 26px color-mix(in srgb, var(--jm-accent) 34%, transparent);
  transition: filter .18s ease;
}
.near-go:hover,
.near-go:focus-visible {
  filter: brightness(1.1);
  background: linear-gradient(180deg, var(--jm-accent-lit), var(--jm-accent-dim));
  color: var(--jm-on-accent);
}
.near-go .jm-ico { font-size: 15px; }

/* Pico styles selects through its own form variables and paints its own
   chevron; re-mapping them is shorter than outranking `select` (0,0,1) plus
   its `:not([multiple])` background-image. */
.near select,
.near-filters select {
  --pico-form-element-background-color: var(--jm-ink);
  --pico-form-element-border-color:     var(--jm-ink-line-2);
  --pico-form-element-color:            var(--jm-on-ink);
  --pico-form-element-active-border-color: var(--jm-accent);
  --pico-form-element-focus-color:      var(--jm-ring);
  width: auto;
  min-width: 190px;
  height: 52px;
  margin: 0;
  font-size: 14px;
  font-weight: 600;

  /* Pico pads form controls vertically via its own spacing variable. Added
     to a fixed height with `box-sizing:border-box`, that squeezes the text
     box until the option label is clipped mid-glyph. */
  padding-block: 0;
  line-height: normal;

  /* THE DROPDOWN BUG. The closed control is styled through the Pico
     variables above, but the OPTION LIST is drawn by the browser, outside
     this stylesheet. header.php sets data-theme="light", so Pico puts
     `color-scheme: light` on :root and the popup is painted white — while
     the options inherit --jm-on-ink, which on every dark theme is also
     white. White on white: the menu opens and looks empty.
     This flips the popup to match the panel, and fixes its scrollbar and
     hover row at the same time. */
  color-scheme: var(--jm-scheme);
}

/* Belt and braces for the same bug: Safari and some Linux builds ignore
   `color-scheme` for the popup and keep the platform background. Both values
   come from tokens because sand-clay's masthead is light, where --jm-on-ink
   is dark and a hardcoded white would break it the other way. */
.near select option,
.near select optgroup {
  background-color: var(--jm-ink-soft);
  color: var(--jm-on-ink);
}

/* The two group headers — "Bangalore" and "Nearby towns". */
.near select optgroup {
  color: var(--jm-accent-ink);
  font-weight: 700;
}

.near__rule {
  height: 1px;
  border: 0;
  margin: clamp(26px, 3.4vw, 40px) 0 clamp(18px, 2.2vw, 24px);
  background: var(--jm-ink-line-2);
}

/* --- the sort / within / clear row --------------------------------------- */

.near-filters {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 10px 14px;
  flex-wrap: wrap;
}

.near-filters label {
  margin: 0;
  font-size: 10.5px;
  font-weight: 800;
  letter-spacing: .17em;
  text-transform: uppercase;
  color: var(--jm-accent-dim);
}
.near-filters select { min-width: 165px; height: 46px; }

/* CLEAR is a link back to the unfiltered page, not a button that needs JS. */
.near-clear {
  display: inline-flex;
  align-items: center;
  height: 46px;
  padding-inline: 20px;
  border: 1px solid var(--jm-ink-line-2);
  border-radius: 6px;
  font-size: 11.5px;
  font-weight: 800;
  letter-spacing: .13em;
  text-transform: uppercase;
  color: var(--jm-on-ink);
  text-decoration: none;
}
.near-clear:hover,
.near-clear:focus-visible {
  border-color: var(--jm-accent);
  color: var(--jm-accent-ink);
  text-decoration: none;
}

@media (max-width: 620px) {
  .near-pick { flex-direction: column; align-items: stretch; }
  .near-pick__or { text-align: center; }
  .near-go { justify-content: center; }
  .near select,
  .near-filters select { width: 100%; min-width: 0; }
  .near-filters { display: grid; grid-template-columns: auto minmax(0, 1fr); text-align: left; }
  .near-clear { grid-column: 1 / -1; justify-content: center; }
}


/* ==========================================================================
   16. THERAPISTS ON SHIFT                  ref 13 — board "section 5"
   --------------------------------------------------------------------------
   A centred date divider, then a two-column grid of split cards: portrait
   photo down the left, dark info panel on the right carrying the name, a
   VERIFIED pill, an "available in" line, a label/value spec table and three
   action buttons.
   ========================================================================== */

.roster {
  padding-block: clamp(50px, 7vw, 90px);
  background: var(--jm-ink);
}

.roster__head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 20px;
  margin-bottom: 6px;
}
.roster__title {
  margin: 0;
  font-size: clamp(24px, 3.2vw, 38px);
  font-weight: 800;
  line-height: 1.12;
  letter-spacing: -.022em;
  color: var(--jm-on-ink);
}
.roster__all {
  flex: 0 0 auto;
  font-size: 12px;
  font-weight: 800;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--jm-accent-ink);
  text-decoration: underline;
  text-underline-offset: 4px;
}
.roster__all:hover,
.roster__all:focus-visible { color: var(--jm-accent-lit); }
/* accent-lit is a *lighter* gold — a hover that brightens is right on the ink
   and invisible on paper, so on a light panel the hover darkens instead. */
.jm-lit .roster__all:hover,
.jm-lit .roster__all:focus-visible { color: var(--jm-heading); }

.roster__sub {
  margin: 0 0 clamp(22px, 3vw, 32px);
  font-size: 15px;
  line-height: 1.55;
  color: var(--jm-nav);
}

/* --- the date divider ---------------------------------------------------- */

/* The reference centres today's date between two hairlines. Flex with a
   pseudo-element rule either side keeps it centred at any width. */
.roster__date {
  display: flex;
  align-items: center;
  gap: 18px;
  margin: 0 0 clamp(20px, 2.6vw, 30px);
  font-size: 14px;
  font-weight: 700;
  color: var(--jm-on-ink);
}
.roster__date::before,
.roster__date::after {
  content: '';
  flex: 1 1 auto;
  height: 1px;
  background: var(--jm-ink-line-2);
}

/* --- the cards ----------------------------------------------------------- */

.roster-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: clamp(16px, 2vw, 26px);
  margin: 0;
  padding: 0;
  list-style: none;
}
.roster-grid > li { margin: 0; padding: 0; list-style: none; }

/* `figure` is used rather than `article` on purpose: Pico gives `article` a
   background, shadow, padding and margin (0,0,1) that would box the card,
   while `figure` is left alone apart from `figure figcaption` (0,0,2). */
.rcard {
  display: grid;
  grid-template-columns: minmax(0, .78fr) minmax(0, 1fr);
  height: 100%;
  margin: 0;
  padding: 0;
  overflow: hidden;
  border: 1px solid var(--jm-accent-dim);
  border-radius: 8px;
  background: var(--jm-ink-soft);
}

.rcard__photo {
  display: block;
  width: 100%;
  height: 100%;
  min-height: 240px;
  object-fit: cover;
  background: var(--jm-ink-line);
}

/* (0,1,1) — clears Pico's `figure figcaption` (0,0,2). */
.rcard figcaption {
  padding: 14px 16px 16px;
  background: var(--jm-ink-soft);
  text-align: left;
  color: var(--jm-nav);
}

.rcard__name {
  margin: 0 0 8px;
  font-size: clamp(17px, 1.7vw, 21px);
  font-weight: 700;
  letter-spacing: -.01em;
  line-height: 1.2;
  color: var(--jm-accent-ink);
}

.rcard__verified {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  padding: 3px 9px;
  border-radius: 100px;
  background: var(--jm-accent);
  color: var(--jm-on-accent);
  font-size: 9.5px;
  font-weight: 800;
  letter-spacing: .13em;
  text-transform: uppercase;
}
.rcard__verified .jm-ico { font-size: 11px; }

.rcard__where {
  display: flex;
  align-items: center;
  gap: 5px;
  margin: 9px 0 12px;
  font-size: 12.5px;
  color: var(--jm-nav);
}
.rcard__where b { color: var(--jm-on-ink); font-weight: 700; }
.rcard__where .jm-ico { font-size: 13px; color: var(--jm-accent-dim); }

/* --- the spec table ------------------------------------------------------ */

/* A <dl> in a two-column grid: label left, value right, hairline under each
   pair. Pico has no opinion about <dl>, so this needs no defensive rules. */
.rcard__specs {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  gap: 0 12px;
  margin: 0 0 14px;
}
.rcard__specs dt,
.rcard__specs dd {
  margin: 0;
  padding: 7px 0;
  border-bottom: 1px solid var(--jm-ink-line);
  font-size: 11.5px;
  line-height: 1.4;
}
.rcard__specs dt { color: var(--jm-nav-dim); white-space: nowrap; }
.rcard__specs dd { color: var(--jm-on-ink); font-weight: 600; text-align: right; }

/* --- the three action buttons ------------------------------------------- */

.rcard__actions {
  display: flex;
  justify-content: flex-end;
  gap: 7px;
  flex-wrap: wrap;
}

.rcard-act {
  display: grid;
  justify-items: center;
  gap: 3px;
  min-width: 58px;
  padding: 7px 9px;
  border: 1px solid var(--jm-ink-line-2);
  border-radius: 5px;
  font-size: 9.5px;
  font-weight: 800;
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--jm-nav);
  text-decoration: none;
  transition: border-color .16s ease, color .16s ease, background-color .16s ease;
}
.rcard-act .jm-ico { font-size: 15px; }
.rcard-act:hover,
.rcard-act:focus-visible {
  border-color: var(--jm-accent);
  color: var(--jm-accent-ink);
  text-decoration: none;
}

.rcard-act--solid {
  border-color: var(--jm-accent);
  background: var(--jm-accent);
  color: var(--jm-on-accent);
}
.rcard-act--solid:hover,
.rcard-act--solid:focus-visible {
  border-color: var(--jm-accent-lit);
  background: var(--jm-accent-lit);
  color: var(--jm-on-accent);
}

@media (max-width: 1100px) {
  .roster-grid { grid-template-columns: 1fr; }
}
@media (max-width: 560px) {
  /* Photo over panel: at this width the split card leaves the spec table
     about 90px wide and every value wraps to three lines. */
  .rcard { grid-template-columns: 1fr; }
  .rcard__photo { min-height: 0; aspect-ratio: 4 / 3; }
  .roster__head { flex-direction: column; align-items: flex-start; gap: 8px; }
}

/* ==========================================================================
   17. BOOKING FORM                                      ref 02 + ref 11
   --------------------------------------------------------------------------
   book.php. The board has no screenshot for it, so it is assembled rather
   than designed — but with one instruction from the client on top of the
   usual reuse rule (2026-09-04): "need very attractive design and block
   background not needed."

   So the first build's dark ref 11 panel is GONE. The form is a light card on
   the paper ground: ref 02's border, radius and paper fill, carrying ref 11's
   serif heading over an accent hairline. Everything else on the page is
   untouched reuse — ref 08's banner, ref 02's cards and wide card,
   about.php's contact lines.

   Losing the dark panel took a whole class of bug with it. On a light control
   the browser's own popups — the <select> option list, the calendar behind
   <input type="date">, the clock behind <input type="time"> — are already
   correct, so NONE of section 8's `color-scheme` and `option` handling is
   needed here. Do not copy it in.
   ========================================================================== */

.book-page { padding-block: clamp(38px, 5vw, 66px) clamp(30px, 4vw, 52px); }

/* The lede lines up with the card rather than with the page gutter. Left on
   `.page__lede`'s own 74ch measure it starts 400px to the left of the box it
   introduces, and the two read as unrelated. (0,2,0) beats `.page__lede`. */
.book-page .page__lede {
  max-width: 940px;
  margin-inline: auto;
}

/* --- the card ------------------------------------------------------------ */

/* A ref 02 card, given room to breathe and centred on the page: the form is
   the reason this page exists, so it gets the middle of the screen rather
   than the full 1560px gutter-to-gutter measure. */
.bcard {
  max-width: 940px;
  margin-inline: auto;
  padding: clamp(26px, 3.4vw, 52px) clamp(22px, 3vw, 56px) clamp(28px, 3.6vw, 54px);
  border: 1px solid var(--jm-line);
  border-radius: 12px;
  background: var(--jm-paper);
}

.bcard__eyebrow {
  margin: 0 0 10px;
  font-size: 11px;
  font-weight: 800;
  letter-spacing: .19em;
  text-transform: uppercase;
  color: var(--jm-accent-dim);
}

/* Ref 11's serif display heading, in the dark-on-light token. (0,1,1) clears
   Pico's `h2` and its `:is(p,ul,…)~:is(h1,…,h6)` sibling-margin rule. */
.bcard h2.bcard__title {
  margin: 0 0 clamp(16px, 2vw, 22px);
  font-family: var(--jm-serif);
  font-weight: 400;
  font-size: clamp(28px, 4vw, 46px);
  line-height: 1.05;
  letter-spacing: -.015em;
  color: var(--jm-heading);
}

/* A short accent hairline under the title rather than a full rule: it picks
   up the gold without turning the card into a boxed-off section. */
.bcard__rule {
  width: 64px;
  height: 3px;
  margin: 0 0 clamp(16px, 2vw, 22px);
  border: 0;
  border-radius: 2px;
  background: var(--jm-accent);
}

.bcard__sub {
  margin: 0 0 clamp(22px, 2.8vw, 32px);
  max-width: 62ch;
  font-size: 15.5px;
  line-height: 1.6;
  color: var(--jm-muted);
}

/* --- one field ----------------------------------------------------------- */

/* Six fields, three rows of two. */
.bform-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: clamp(16px, 2vw, 24px) clamp(18px, 2.2vw, 28px);
}

/* `.bfield > label`, not `.bfield label`: the consent checkbox's label is a
   sentence, not a micro-label — and it lives outside `.bfield` for the same
   reason. `.bfield__lbl` is the <span> standing in for a label on a radio
   group, which cannot use <label> because it names a group rather than one
   control — the contact block's topic chips (§20) need it. */
.bfield > label,
.bfield__lbl {
  display: block;
  margin: 0 0 8px;
  font-size: 11px;
  font-weight: 800;
  letter-spacing: .15em;
  text-transform: uppercase;
  color: var(--jm-muted);
}

/* Marks a field that matters, not one that is wrong — hence accent, not the
   error colour. */
.breq { color: var(--jm-accent-dim); font-weight: 800; }

/* Pico paints every control through its own variables, so branding them is
   re-mapping rather than overriding. Set on the form, so the selects, the
   inputs and the checkbox all inherit one definition.

   White controls on the paper card, deliberately: it is what separates a
   field you can type in from the card it sits on. */
.bform {
  --pico-form-element-background-color:            #FFFFFF;
  --pico-form-element-active-background-color:     #FFFFFF;
  --pico-form-element-border-color:                var(--jm-line);
  --pico-form-element-active-border-color:         var(--jm-accent-dim);
  --pico-form-element-color:                       var(--jm-body);
  --pico-form-element-placeholder-color:           var(--jm-muted);
  --pico-form-element-focus-color:                 var(--jm-ring);
  --pico-form-element-invalid-border-color:        var(--jm-warn-dim);
  --pico-form-element-invalid-active-border-color: var(--jm-warn-dim);
  --pico-form-element-invalid-focus-color:         var(--jm-warn-dim);

  /* the tick in the consent checkbox once it is checked */
  --pico-primary-background: var(--jm-accent-dim);
  --pico-primary-border:     var(--jm-accent-dim);
}

/* The `:not()`s are not decoration. A rule that sizes text inputs also
   matches a checkbox or a radio, stretching it to the full width of its box
   and shoving its own label off the side of the page. Pico exempts them from
   its own `width:100%` for exactly this reason; anything written alongside it
   has to do the same. It cost an 89px overflow once already. */
.bform .bfield select,
.bform .bfield input:not([type="radio"]):not([type="checkbox"]) {
  width: 100%;
  min-width: 0;
  height: 54px;
  margin: 0;
  border-radius: 7px;
  font-size: 15.5px;
  font-weight: 500;

  /* Pico pads controls vertically through its own spacing variable; added to
     a fixed height with `box-sizing:border-box` that clips the text. The same
     fix section 8 needed. */
  padding-block: 0;
  line-height: normal;
}

.bfield__help {
  margin: 7px 0 0;
  font-size: 12.5px;
  line-height: 1.5;
  color: var(--jm-muted);
}

.bfield__err {
  margin: 7px 0 0;
  font-size: 12.5px;
  font-weight: 600;
  line-height: 1.5;
  color: var(--jm-warn-dim);
}

/* --- the error summary --------------------------------------------------- */

/* With no JavaScript the page cannot move focus to the first bad field, so
   the form reports itself the way a form did before scripting: one box at the
   top, one line per problem, each linking to the control it belongs to. */
.bform-errors {
  margin: 0 0 clamp(22px, 2.8vw, 30px);
  padding: 16px 20px 18px;
  border: 1px solid var(--jm-warn-dim);
  border-radius: 8px;
  background: color-mix(in srgb, var(--jm-warn-dim) 7%, #FFFFFF);
}
.bform-errors p {
  margin: 0 0 9px;
  font-size: 14px;
  font-weight: 700;
  color: var(--jm-warn-dim);
}
.bform-errors ul { margin: 0; padding: 0 0 0 18px; }

/* (0,1,1) clears Pico's `ul li{list-style:square}` (0,0,2). */
.bform-errors li {
  margin: 0 0 5px;
  padding: 0;
  list-style: disc;
  font-size: 13.5px;
  line-height: 1.5;
  color: var(--jm-body);
}
.bform-errors li:last-child { margin-bottom: 0; }
.bform-errors a {
  color: var(--jm-body);
  text-decoration: underline;
  text-underline-offset: 3px;
}
.bform-errors a:hover,
.bform-errors a:focus-visible { color: var(--jm-warn-dim); }

/* --- the consent line ---------------------------------------------------- */

/* Pico ships `label:has([type=checkbox],[type=radio]){width:fit-content}` at
   (0,1,1), which shrink-wraps this label to its own text and beats a plain
   `.bconsent label` on source order alone. (0,2,1) settles it. */
.bform .bconsent label { width: auto; }

.bconsent {
  margin: clamp(22px, 2.8vw, 30px) 0 clamp(22px, 2.8vw, 30px);
  padding-top: clamp(20px, 2.4vw, 26px);
  border-top: 1px solid var(--jm-line);
}
.bconsent label {
  display: flex;
  align-items: flex-start;
  gap: 12px;
  margin: 0;
  font-size: 14.5px;
  line-height: 1.55;
  color: var(--jm-body);
  cursor: pointer;
}
.bconsent input { margin: 2px 0 0; flex: 0 0 auto; }

/* --- submit -------------------------------------------------------------- */

.bform__actions {
  display: flex;
  align-items: center;
  gap: 16px 22px;
  flex-wrap: wrap;
}

/* The masthead's filled accent button, one size up. Written as
   `button.bgo` (0,1,1) because Pico's `button[type=submit]{width:100%}` is
   also (0,1,1) and would otherwise stretch it across the card. */
button.bgo {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  width: auto;
  height: 56px;
  margin: 0;
  padding-inline: 32px;
  border: 1px solid var(--jm-accent);
  border-radius: 7px;
  background: var(--jm-accent);
  color: var(--jm-on-accent);
  font-size: 13.5px;
  font-weight: 800;
  letter-spacing: .13em;
  text-transform: uppercase;
  cursor: pointer;
  transition: background-color .18s ease, border-color .18s ease;
}
.bgo:hover,
.bgo:focus-visible {
  border-color: var(--jm-accent-lit);
  background: var(--jm-accent-lit);
  color: var(--jm-on-accent);
}
.bgo .jm-ico { font-size: 16px; }

.bform__note {
  margin: 0;
  max-width: 40ch;
  font-size: 12.5px;
  line-height: 1.5;
  color: var(--jm-muted);
}
.bform__req {
  margin: 18px 0 0;
  font-size: 12px;
  line-height: 1.5;
  color: var(--jm-muted);
}

/* The honeypot. Off-canvas rather than `display:none`, because a bot that
   reads computed styles skips a hidden field. It is aria-hidden and out of
   the tab order, so nobody using the page can reach it. */
.bpot {
  position: absolute;
  left: -9999px;
  width: 1px;
  height: 1px;
  overflow: hidden;
}

/* --- the confirmation ---------------------------------------------------- */

.bcard--done { max-width: 820px; }

.bcard__ref {
  display: flex;
  align-items: center;
  gap: 8px 18px;
  flex-wrap: wrap;
  margin: 0 0 clamp(24px, 3vw, 32px);
  padding: 16px 22px;
  border: 1px solid var(--jm-accent-dim);
  border-radius: 8px;
  background: var(--jm-chip);
}
.bcard__ref span {
  font-size: 11px;
  font-weight: 800;
  letter-spacing: .17em;
  text-transform: uppercase;
  color: var(--jm-muted);
}
/* (0,1,1) clears Pico's `code` chip, which would box it again. */
.bcard__ref code {
  padding: 0;
  background: none;
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: clamp(19px, 2.4vw, 26px);
  font-weight: 700;
  letter-spacing: .06em;
  color: var(--jm-heading);
}

.bcard__h3 {
  margin: 0 0 12px;
  font-size: 11px;
  font-weight: 800;
  letter-spacing: .18em;
  text-transform: uppercase;
  color: var(--jm-accent-dim);
}

/* Ref 13's spec table on a light ground: label left, value right, hairline
   under each pair. Pico has no opinion about <dl>, so it needs no defence. */
.bsummary {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  gap: 0 16px;
  margin: 0 0 clamp(22px, 2.8vw, 30px);
}
.bsummary dt,
.bsummary dd {
  margin: 0;
  padding: 11px 0;
  border-bottom: 1px solid var(--jm-line);
  font-size: 14px;
  line-height: 1.4;
}
.bsummary dt { color: var(--jm-muted); white-space: nowrap; }
.bsummary dd { color: var(--jm-heading); font-weight: 700; text-align: right; }

.bcard__foot {
  margin: 0;
  font-size: 15px;
  line-height: 1.6;
  color: var(--jm-muted);
}
.bcard__foot + .bcard__foot { margin-top: 12px; }
.bcard__foot a {
  font-weight: 700;
  color: var(--jm-accent-dim);
  text-decoration: underline;
  text-underline-offset: 3px;
}
.bcard__foot a:hover,
.bcard__foot a:focus-visible { color: var(--jm-heading); }

/* The failed-write heading. The one place on the site that must not read as
   brand-coloured good news. */
.bcard h2.bcard__title--bad { color: var(--jm-warn-dim); }

/* --- booking form: tablet + mobile --------------------------------------- */

@media (max-width: 720px) {
  .bform-grid { grid-template-columns: 1fr; }

  /* (0,2,0) beats `button.bgo`'s `width:auto` (0,1,1). */
  .bform__actions .bgo { width: 100%; justify-content: center; }
  .bform__note { max-width: none; }
}


/* ==========================================================================
   18. MODEL PROFILES                    ref 18 — board "model profile"
   --------------------------------------------------------------------------
   Homepage section 7b, directly below "Why book with us", plus profile.php.

   A centred pill, a heavy two-tone heading, a centred lede, three stat chips,
   then twelve cards four across: photo with a badge in each top corner, name
   with a verified tick, three small pills, a hairline, a three-cell stat row
   and a full-width VIEW PROFILE button.

   The button is a plain link to profile.php, which counts the click before it
   renders — no JavaScript is involved in the counting, and the grid orders
   itself by this week is real count. See clicks_bump() in config.php.
   ========================================================================== */

.models {
  padding-block: clamp(50px, 7vw, 92px);
  background: var(--jm-paper);
}

/* --- the head ------------------------------------------------------------ */

.models__pill {
  display: flex;
  align-items: center;
  gap: 9px;
  width: -moz-fit-content;
  width: fit-content;
  margin: 0 auto 18px;
  padding: 8px 18px;
  border: 1px solid var(--jm-line);
  border-radius: 999px;
  background: #FFFFFF;
  font-size: 11px;
  font-weight: 800;
  letter-spacing: .17em;
  text-transform: uppercase;
  color: var(--jm-accent-dim);
}
/* the small live dot the reference puts before the label */
.models__pill span {
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--jm-accent);
}

/* (0,1,1) clears Pico's `h2` and its sibling-margin rule. */
.models h2.models__title {
  margin: 0 auto 16px;
  max-width: 20ch;
  font-size: clamp(30px, 4.6vw, 56px);
  font-weight: 800;
  line-height: 1.06;
  letter-spacing: -.028em;
  text-align: center;
  color: var(--jm-heading);
}
.models__title em {
  font-style: normal;
  color: var(--jm-accent-dim);
}

.models__lede {
  margin: 0 auto clamp(20px, 2.6vw, 28px);
  max-width: 62ch;
  font-size: 15.5px;
  line-height: 1.65;
  text-align: center;
  color: var(--jm-muted);
}

.models-chips {
  display: flex;
  justify-content: center;
  gap: 10px 14px;
  flex-wrap: wrap;
  margin: 0 0 clamp(28px, 3.6vw, 44px);
  padding: 0;
  list-style: none;
}
/* Pico`s `ul li{list-style:square}` is (0,0,2) — clear it on the li. */
.models-chips li {
  display: flex;
  align-items: center;
  gap: 8px;
  margin: 0;
  padding: 9px 16px;
  list-style: none;
  border: 1px solid var(--jm-line);
  border-radius: 999px;
  background: #FFFFFF;
  font-size: 12.5px;
  font-weight: 700;
  color: var(--jm-body);
}
.models-chips .jm-ico { font-size: 14px; color: var(--jm-accent-dim); }

/* --- the grid ------------------------------------------------------------ */

/* Four across, as the client asked and as the reference shows. */
.models-grid {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: clamp(14px, 1.6vw, 22px);
  margin: 0;
  padding: 0;
  list-style: none;
}
.models-grid > li { margin: 0; padding: 0; list-style: none; }

/* `article` would pick up Pico`s own box — its background, shadow, padding and
   margin (0,0,1) — so the card restates all four rather than inheriting a
   second card inside this one. */
.mcard {
  display: flex;
  flex-direction: column;
  height: 100%;
  margin: 0;
  padding: 0;
  overflow: hidden;
  border: 1px solid var(--jm-line);
  border-radius: 14px;
  background: #FFFFFF;
  box-shadow: none;
  transition: border-color .18s ease, transform .18s ease;
}
.mcard:hover { border-color: var(--jm-accent-dim); transform: translateY(-2px); }

/* --- the photo and its two corner badges --------------------------------- */

.mcard__photo {
  position: relative;
  aspect-ratio: 4 / 5;
  background: var(--jm-chip);
}
.mcard__photo img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.mbadge {
  position: absolute;
  top: 10px;
  display: inline-flex;
  align-items: center;
  gap: 5px;
  padding: 5px 10px;
  border-radius: 999px;
  font-size: 10.5px;
  font-weight: 800;
  letter-spacing: .06em;
}
.mbadge .jm-ico { font-size: 11px; }

/* Gold top-left, as in the reference. */
.mbadge--feat {
  left: 10px;
  background: var(--jm-accent);
  color: var(--jm-on-accent);
}
/* The reference`s verified badge is green. Green is not in the palette and a
   hardcoded hex would break theme switching, so it is the ink chip with the
   accent tick — which also stops the two badges fighting each other. */
.mbadge--ver {
  right: 10px;
  background: var(--jm-ink);
  color: var(--jm-on-ink);
}
.mbadge--ver .jm-ico { color: var(--jm-accent); }

/* BASED HERE / TRAVELS HERE — area pages only, 2026-09-12. `.mbadge` pins
   `top: 10px`, so both of these have to release it explicitly; `bottom` alone
   would leave the badge stuck to the top with an ignored bottom offset. */
.mbadge--here,
.mbadge--trav {
  top: auto;
  bottom: 10px;
  left: 10px;
}
/* The local therapist is the one this page is about, so she gets the accent.
   The other seven get the quieter chip — they are true, not the headline. */
.mbadge--here {
  background: var(--jm-accent);
  color: var(--jm-on-accent);
}
.mbadge--trav {
  background: color-mix(in srgb, var(--jm-ink) 82%, transparent);
  color: var(--jm-on-ink);
}
.mbadge--trav .jm-ico { color: var(--jm-accent); }

/* MOST VIEWED THIS WEEK — 2026-09-12, the #1 card on the homepage grid only.
   It takes the top-left slot instead of "Featured": stacking two badges in
   one corner is a pile, and this one is a MEASURED fact where "featured" is
   an editorial choice, so the measured one gets the position.

   Accent fill with dark label, like `.mbadge--feat` — but wider, so the
   longer wording does not wrap, and with a soft ring so it reads as the
   strongest thing on the grid. */
.mbadge--top {
  left: 10px;
  max-width: calc(100% - 20px);
  background: var(--jm-accent);
  color: var(--jm-on-accent);
  box-shadow: 0 2px 10px color-mix(in srgb, var(--jm-ink) 45%, transparent);
}

/* The card itself, so the #1 is findable before you read a badge. A ring
   rather than a different background: the cards are white and a tinted one
   would look like a different component. */
.models-grid .mcard--top {
  box-shadow: 0 0 0 2px var(--jm-accent), 0 10px 28px var(--jm-shadow);
}

/* --- the body ------------------------------------------------------------ */

.mcard__body {
  display: flex;
  flex-direction: column;
  flex: 1 1 auto;
  padding: 14px 16px 16px;
}

/* (0,1,1) clears Pico`s `h3` and its sibling-margin rule. */
.mcard h3.mcard__name {
  display: flex;
  align-items: center;
  gap: 6px;
  margin: 0 0 10px;
  font-size: 18px;
  font-weight: 800;
  letter-spacing: -.01em;
  line-height: 1.2;
  color: var(--jm-heading);
}
.mcard__name .jm-ico { font-size: 15px; color: var(--jm-accent-dim); }

.mpills {
  display: flex;
  gap: 6px;
  flex-wrap: wrap;
  margin: 0;
  padding: 0;
  list-style: none;
}
.mpills li {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  margin: 0;
  padding: 4px 10px;
  list-style: none;
  border: 1px solid var(--jm-line);
  border-radius: 999px;
  background: var(--jm-paper);
  font-size: 11.5px;
  font-weight: 700;
  color: var(--jm-muted);
  white-space: nowrap;
}
.mpills .jm-ico { font-size: 12px; color: var(--jm-accent-dim); }

.mcard__rule {
  height: 1px;
  margin: 14px 0;
  border: 0;
  background: var(--jm-line);
}

/* --- the three-cell stat row --------------------------------------------- */

.mstats {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 8px;
  margin-bottom: 14px;
  text-align: center;
}
.mstats > div + div { border-left: 1px solid var(--jm-line); }
.mstats b {
  display: block;
  font-size: 14px;
  font-weight: 800;
  line-height: 1.2;
  color: var(--jm-accent-dim);
  overflow-wrap: anywhere;
}
.mstats span {
  display: block;
  margin-top: 4px;
  font-size: 9.5px;
  font-weight: 800;
  letter-spacing: .13em;
  text-transform: uppercase;
  color: var(--jm-muted);
}

/* `margin-top:auto` pins the button to the bottom of every card, so a name
   that wraps to two lines cannot push one card`s button out of line with the
   rest of the row. */
.mcard__cta {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  margin-top: auto;
  padding: 12px 14px;
  border: 1px solid var(--jm-line);
  border-radius: 8px;
  background: var(--jm-paper);
  font-size: 11.5px;
  font-weight: 800;
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--jm-accent-dim);
  text-decoration: none;
  transition: background-color .18s ease, color .18s ease, border-color .18s ease;
}
.mcard__cta:hover,
.mcard__cta:focus-visible {
  border-color: var(--jm-accent);
  background: var(--jm-accent);
  color: var(--jm-on-accent);
  text-decoration: none;
}
.mcard__cta .jm-ico { font-size: 14px; }

.models__all {
  margin: clamp(26px, 3.2vw, 38px) 0 0;
  text-align: center;
}
.models__all a {
  display: inline-flex;
  align-items: center;
  gap: 9px;
  padding: 14px 30px;
  border: 1px solid var(--jm-accent-dim);
  border-radius: 999px;
  font-size: 12px;
  font-weight: 800;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--jm-accent-dim);
  text-decoration: none;
}
.models__all a:hover,
.models__all a:focus-visible {
  background: var(--jm-accent);
  border-color: var(--jm-accent);
  color: var(--jm-on-accent);
  text-decoration: none;
}

/* --- profile.php --------------------------------------------------------- */

/* The profile page is one column of reading, not a dashboard. `.jm-shell`'s
   1560px is right for a twelve-card grid and far too wide for a portrait next
   to a five-row spec table — the block ends up stranded against the left with
   400px of nothing beside it. (0,1,0), the same as `.jm-shell`, so source
   order decides and this file's later rule wins. */
.pro-page { max-width: 1240px; }

.pro {
  display: grid;
  grid-template-columns: minmax(0, 420px) minmax(0, 1fr);
  gap: clamp(22px, 3vw, 44px);
  align-items: start;
}

.pro__photo {
  position: relative;
  overflow: hidden;
  border: 1px solid var(--jm-line);
  border-radius: 14px;
  background: var(--jm-chip);
}
.pro__photo img {
  display: block;
  width: 100%;
  height: auto;
  aspect-ratio: 4 / 5;
  object-fit: cover;
}

/* (0,1,1) clears Pico`s `h2` and the sibling-margin rule. */
.pro h2.pro__name {
  display: flex;
  align-items: center;
  gap: 9px;
  margin: 0 0 14px;
  font-size: clamp(28px, 3.4vw, 42px);
  font-weight: 800;
  letter-spacing: -.024em;
  line-height: 1.1;
  color: var(--jm-heading);
}
.pro__name .jm-ico { font-size: 24px; color: var(--jm-accent-dim); }

.pro__stats {
  margin: 20px 0 24px;
  padding: 16px 8px;
  border: 1px solid var(--jm-line);
  border-radius: 10px;
  background: var(--jm-paper);
}
.pro__stats b { font-size: 17px; }

/* Ref 13`s spec table. Pico has no opinion about <dl>, so no defence needed. */
.pro__specs {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  gap: 0 16px;
  margin: 0 0 24px;
}
.pro__specs dt,
.pro__specs dd {
  margin: 0;
  padding: 10px 0;
  border-bottom: 1px solid var(--jm-line);
  font-size: 14px;
  line-height: 1.4;
}
.pro__specs dt { color: var(--jm-muted); white-space: nowrap; }
.pro__specs dd { color: var(--jm-heading); font-weight: 700; text-align: right; }

.pro__actions {
  display: flex;
  gap: 12px;
  flex-wrap: wrap;
  margin-bottom: 22px;
}
.pro__actions .btn-solid,
.pro__actions .btn-outline { height: 50px; }

.pro__note {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  margin: 0;
  max-width: 62ch;
  font-size: 13.5px;
  line-height: 1.6;
  color: var(--jm-muted);
}
.pro__note .jm-ico { margin-top: .15em; font-size: 17px; color: var(--jm-accent-dim); }

/* --- model profiles: tablet + mobile ------------------------------------- */

@media (max-width: 1180px) {
  .models-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}
@media (max-width: 900px) {
  .models-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .pro { grid-template-columns: 1fr; }
  .pro__photo { max-width: 380px; }
}
@media (max-width: 470px) {
  .models-grid { grid-template-columns: 1fr; }
  .mstats b { font-size: 13px; }
}


/* ==========================================================================
   19. HELP CENTRE                          ref 16 — board "faq design"
   --------------------------------------------------------------------------
   faq.php. A masthead card with a search box, then two columns: the numbered
   question list on the left with two contact tiles under it, and the selected
   answer on the right with a highlights panel and a helpful vote.

   Every question is a LINK, not a tab: with no JavaScript the server renders
   the chosen answer, which means every answer has its own URL. The homepage
   keeps its ref 03 accordion — this is the standalone page the footer has
   always linked to.
   ========================================================================== */

.help { padding-block: clamp(32px, 4.4vw, 60px) clamp(40px, 5.5vw, 78px); }

/* --- the masthead card --------------------------------------------------- */

.help-top {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: clamp(16px, 2.4vw, 34px);
  flex-wrap: wrap;
  margin-bottom: clamp(16px, 2vw, 24px);
  padding: clamp(18px, 2.2vw, 26px) clamp(20px, 2.6vw, 32px);
  border: 1px solid var(--jm-line);
  border-radius: 14px;
  background: var(--jm-paper);
}

.help-top__id {
  display: flex;
  align-items: center;
  gap: 16px;
  min-width: 0;
}

.help-top__ico {
  display: grid;
  place-items: center;
  flex: 0 0 auto;
  width: 48px;
  height: 48px;
  border-radius: 12px;
  background: var(--jm-accent);
  color: var(--jm-on-accent);
  font-size: 24px;
}

/* (0,1,1) clears Pico`s `h1` and the sibling-margin rule. */
.help-top__id h1 {
  margin: 0 0 3px;
  font-size: clamp(21px, 2.4vw, 28px);
  font-weight: 800;
  letter-spacing: -.02em;
  line-height: 1.15;
  color: var(--jm-heading);
}
.help-top__id p {
  margin: 0;
  font-size: 13.5px;
  line-height: 1.45;
  color: var(--jm-muted);
}

/* The search field. A GET form, so a search is a URL. */
.help-search {
  position: relative;
  flex: 1 1 300px;
  max-width: 420px;
  margin: 0;
}
.help-search__ico {
  position: absolute;
  top: 50%;
  left: 15px;
  transform: translateY(-50%);
  font-size: 17px;
  color: var(--jm-muted);
  pointer-events: none;
}
/* (0,1,1) beats Pico`s `input` (0,0,1). The left padding clears the icon. */
.help-search input {
  --pico-form-element-background-color: #FFFFFF;
  --pico-form-element-border-color:     var(--jm-line);
  --pico-form-element-color:            var(--jm-body);
  --pico-form-element-placeholder-color: var(--jm-muted);
  --pico-form-element-active-border-color: var(--jm-accent-dim);
  --pico-form-element-focus-color:      var(--jm-ring);
  width: 100%;
  height: 50px;
  margin: 0;
  padding: 0 16px 0 44px;
  border-radius: 999px;
  line-height: normal;
  font-size: 14.5px;
}

/* --- the two columns ----------------------------------------------------- */

.help-cols {
  display: grid;
  grid-template-columns: minmax(0, 340px) minmax(0, 1fr);
  gap: clamp(16px, 2vw, 24px);
  align-items: start;
}

.help-list,
.help-answer {
  padding: clamp(18px, 2.2vw, 26px) clamp(18px, 2.2vw, 28px);
  border: 1px solid var(--jm-line);
  border-radius: 14px;
  background: var(--jm-paper);
}

/* The eyebrow, with the short accent dash the reference puts before it. */
.help-list__lbl,
.help-hi__lbl {
  display: flex;
  align-items: center;
  gap: 10px;
  margin: 0 0 14px;
  padding-bottom: 12px;
  border-bottom: 1px solid var(--jm-line);
  font-size: 10.5px;
  font-weight: 800;
  letter-spacing: .18em;
  text-transform: uppercase;
  color: var(--jm-accent-dim);
}
.help-list__lbl span {
  width: 22px;
  height: 2px;
  border-radius: 2px;
  background: var(--jm-accent);
}
.help-hi__lbl {
  border-bottom: 0;
  padding-bottom: 0;
  margin-bottom: 12px;
}
.help-hi__lbl span {
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--jm-accent);
}

.help-list ul { margin: 0 0 16px; padding: 0; list-style: none; }
/* Pico`s `ul li{list-style:square}` is (0,0,2) — clear it on the li. */
.help-list li { margin: 0; padding: 0; list-style: none; }

.help-q {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr) auto;
  align-items: center;
  gap: 12px;
  padding: 12px 12px;
  border: 1px solid transparent;
  border-radius: 10px;
  color: var(--jm-body);
  text-decoration: none;
  transition: background-color .18s ease, border-color .18s ease;
}
.help-q b {
  display: grid;
  place-items: center;
  width: 28px;
  height: 28px;
  border-radius: 8px;
  background: var(--jm-chip);
  font-size: 11px;
  font-weight: 800;
  color: var(--jm-muted);
}
.help-q span { font-size: 14px; font-weight: 600; line-height: 1.4; }
/* The chevron only appears on the open row, as in the reference. */
.help-q .jm-ico { font-size: 15px; opacity: 0; color: var(--jm-accent-dim); }

.help-q:hover,
.help-q:focus-visible {
  border-color: var(--jm-line);
  background: #FFFFFF;
  text-decoration: none;
}

.help-q.is-open {
  border-color: var(--jm-accent-dim);
  background: #FFFFFF;
}
.help-q.is-open b { background: var(--jm-accent); color: var(--jm-on-accent); }
.help-q.is-open span { color: var(--jm-accent-dim); font-weight: 700; }
.help-q.is-open .jm-ico { opacity: 1; }

/* --- the two contact tiles ----------------------------------------------- */

.help-tile {
  display: flex;
  align-items: flex-start;
  gap: 13px;
  margin-top: 10px;
  padding: 14px 16px;
  border: 1px solid var(--jm-line);
  border-radius: 12px;
  background: #FFFFFF;
  color: inherit;
  text-decoration: none;
  transition: border-color .18s ease;
}
.help-tile:hover,
.help-tile:focus-visible { border-color: var(--jm-accent-dim); text-decoration: none; }
.help-tile__ico {
  display: grid;
  place-items: center;
  flex: 0 0 auto;
  width: 38px;
  height: 38px;
  border-radius: 10px;
  background: var(--jm-chip);
  color: var(--jm-accent-dim);
  font-size: 19px;
}
.help-tile b {
  display: block;
  font-size: 14.5px;
  font-weight: 800;
  color: var(--jm-heading);
}
.help-tile i {
  display: block;
  margin-top: 2px;
  font-style: normal;
  font-size: 12.5px;
  line-height: 1.45;
  color: var(--jm-muted);
}
.help-tile u {
  display: block;
  margin-top: 5px;
  font-size: 12.5px;
  font-weight: 700;
  color: var(--jm-accent-dim);
  text-underline-offset: 3px;
}

/* --- the answer ---------------------------------------------------------- */

.help-crumb {
  margin: 0 0 12px;
  font-size: 10.5px;
  font-weight: 800;
  letter-spacing: .17em;
  text-transform: uppercase;
  color: var(--jm-muted);
}
.help-crumb a { color: var(--jm-muted); text-decoration: none; }
.help-crumb a:hover { color: var(--jm-accent-dim); }
.help-crumb span { margin: 0 7px; }

/* "These questions on the home page", under the list label — 2026-09-12. The
   way back to the homepage accordion, which is the same six questions. Quiet
   on purpose: it is a link home, not a second place to read them. */
.help-list__home { margin: -4px 0 14px; }
.help-list__home a {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  font-size: 12px;
  font-weight: 700;
  color: var(--jm-muted);
  text-decoration: none;
}
.help-list__home .jm-ico {
  font-size: 14px;
  color: var(--jm-accent-dim);
  /* Points back, because the destination is up the tree, not further in. */
  transform: rotate(180deg);
  transition: transform .18s ease;
}
.help-list__home a:hover,
.help-list__home a:focus-visible { color: var(--jm-accent-dim); text-decoration: underline; }
.help-list__home a:hover .jm-ico { transform: rotate(180deg) translateX(3px); }

/* (0,1,1) clears Pico`s `h2` and the sibling-margin rule. */
.help-answer h2.help-answer__q {
  margin: 0 0 16px;
  font-size: clamp(23px, 2.9vw, 34px);
  font-weight: 800;
  letter-spacing: -.024em;
  line-height: 1.18;
  color: var(--jm-heading);
}

/* (0,1,1), so it beats Pico`s `p` and the sibling-margin rule. */
.help-answer p.help-answer__p {
  margin: 0 0 14px;
  max-width: 74ch;
  font-size: 15.5px;
  line-height: 1.7;
  color: var(--jm-body);
}

.help-hi {
  margin: clamp(18px, 2.2vw, 26px) 0 0;
  padding: 16px 18px 18px;
  border: 1px solid var(--jm-line);
  border-radius: 12px;
  background: var(--jm-chip);
}
.help-hi ul {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 10px;
  margin: 0;
  padding: 0;
  list-style: none;
}
.help-hi li {
  margin: 0;
  padding: 12px 14px;
  list-style: none;
  border: 1px solid var(--jm-line);
  border-radius: 9px;
  background: #FFFFFF;
}
.help-hi b {
  display: block;
  font-size: 15px;
  font-weight: 800;
  line-height: 1.2;
  color: var(--jm-accent-dim);
}
.help-hi span {
  display: block;
  margin-top: 4px;
  font-size: 11.5px;
  line-height: 1.35;
  color: var(--jm-muted);
}

.help-answer__rule {
  height: 1px;
  margin: clamp(20px, 2.6vw, 30px) 0 18px;
  border: 0;
  background: var(--jm-line);
}

.help-vote {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 14px;
  flex-wrap: wrap;
}
.help-vote > p {
  margin: 0;
  font-size: 14px;
  font-weight: 600;
  color: var(--jm-muted);
}
.help-vote form { display: flex; gap: 9px; margin: 0; }

/* `button.help-vote__btn` would be (0,1,1) — the same as Pico`s
   `button[type=submit]{width:100%}`. These are name/value submits inside a
   flex row, so the width has to be settled at (0,2,0) instead. */
.help-vote form .help-vote__btn {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  width: auto;
  height: 42px;
  margin: 0;
  padding-inline: 20px;
  border: 1px solid var(--jm-line);
  border-radius: 999px;
  background: #FFFFFF;
  color: var(--jm-body);
  font-size: 12.5px;
  font-weight: 800;
  letter-spacing: .06em;
  cursor: pointer;
}
.help-vote form .help-vote__btn:hover {
  border-color: var(--jm-accent-dim);
  background: #FFFFFF;
  color: var(--jm-accent-dim);
}
.help-vote__btn .jm-ico { font-size: 15px; }
/* The thumb points down for "no" — one icon, flipped, rather than a second. */
.help-vote__btn--no .jm-ico { transform: rotate(180deg); }

.help-vote__thanks {
  display: flex;
  align-items: center;
  gap: 8px;
  margin: 0;
  font-size: 13.5px;
  font-weight: 700;
  color: var(--jm-accent-dim);
}

.help-empty {
  margin: 0 0 10px;
  font-size: 14.5px;
  line-height: 1.6;
  color: var(--jm-muted);
}
.help-empty a { color: var(--jm-accent-dim); font-weight: 700; }

/* --- help centre: tablet + mobile ---------------------------------------- */

@media (max-width: 900px) {
  .help-cols { grid-template-columns: 1fr; }
  .help-hi ul { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (max-width: 560px) {
  .help-top { flex-direction: column; align-items: stretch; }
  .help-search { max-width: none; }
  .help-vote { flex-direction: column; align-items: flex-start; }
  .help-vote form { width: 100%; }
  .help-vote form .help-vote__btn { flex: 1 1 auto; justify-content: center; }
}


/* ==========================================================================
   20. "TELL US WHAT YOU'RE LOOKING FOR"   ref 17 — "contact from book.php"
   --------------------------------------------------------------------------
   The contact block at the foot of book.php. Left: the message form. Right:
   two stacked cards.

   Most of the form furniture is section 17's, reused unchanged — `.bform`,
   `.bform-grid`, `.bfield`, `.bfield__err`, `.bform-errors`, `.bgo` and the
   `.bpot` honeypot all work here as they are, because both forms live on the
   same light card. Only the topic chips and the right column are new.
   ========================================================================== */

.cblock { padding-block: 0 clamp(44px, 6vw, 78px); }

.cblock__grid {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 380px);
  gap: clamp(16px, 2vw, 26px);
  align-items: start;
}

/* --- the message card ---------------------------------------------------- */

.ccard {
  padding: clamp(24px, 3vw, 42px) clamp(22px, 2.8vw, 44px) clamp(26px, 3.2vw, 44px);
  border: 1px solid var(--jm-line);
  border-radius: 14px;
  background: var(--jm-paper);
}

.ccard__head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 14px;
  flex-wrap: wrap;
}

.ccard__eyebrow {
  margin: 0 0 10px;
  font-size: 11px;
  font-weight: 800;
  letter-spacing: .19em;
  text-transform: uppercase;
  color: var(--jm-accent-dim);
}

/* The reference`s "Live reply" chip. Ours says something we can stand behind. */
.ccard__pill {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  margin: 0 0 10px;
  padding: 6px 14px;
  border: 1px solid var(--jm-line);
  border-radius: 999px;
  background: #FFFFFF;
  font-size: 11px;
  font-weight: 800;
  letter-spacing: .1em;
  color: var(--jm-muted);
}
.ccard__pill span {
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--jm-accent);
}

/* (0,1,1) clears Pico`s `h2` and the sibling-margin rule. */
.ccard h2.ccard__title {
  margin: 0 0 12px;
  font-size: clamp(26px, 3.4vw, 42px);
  font-weight: 800;
  letter-spacing: -.026em;
  line-height: 1.08;
  color: var(--jm-heading);
}
.ccard__title em { font-style: normal; color: var(--jm-accent-dim); }
.ccard h2.ccard__title--bad { color: var(--jm-warn-dim); }

.ccard__sub {
  margin: 0 0 clamp(20px, 2.4vw, 28px);
  max-width: 60ch;
  font-size: 15px;
  line-height: 1.6;
  color: var(--jm-muted);
}

/* --- the topic chips ----------------------------------------------------- */

.cfield-topic { margin: clamp(18px, 2.2vw, 24px) 0 0; }

.ctopics {
  display: flex;
  gap: 9px;
  flex-wrap: wrap;
}

/* Pico ships `label:has([type=checkbox],[type=radio]){width:fit-content}` at
   (0,1,1). Here fit-content is exactly what a chip wants, so it is left
   alone — but the rule is why these are chips and the consent line is not. */
.ctopic { margin: 0; cursor: pointer; }

/* The radio itself is taken out of the flow rather than hidden: `display:none`
   would drop it out of the tab order and off the keyboard entirely. */
.ctopic input {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: 0;
  opacity: 0;
}
.ctopic span {
  display: inline-flex;
  align-items: center;
  padding: 10px 18px;
  border: 1px solid var(--jm-line);
  border-radius: 999px;
  background: #FFFFFF;
  font-size: 12px;
  font-weight: 800;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--jm-muted);
  transition: background-color .18s ease, color .18s ease, border-color .18s ease;
}
.ctopic:hover span { border-color: var(--jm-accent-dim); color: var(--jm-accent-dim); }

/* The chosen chip. `:has()` is not load-bearing — a browser without it still
   shows a focus ring and submits the right value; it just looks flatter. */
.ctopic:has(input:checked) span {
  border-color: var(--jm-accent);
  background: var(--jm-accent);
  color: var(--jm-on-accent);
}
.ctopic:has(input:focus-visible) span {
  outline: 3px solid var(--jm-ring);
  outline-offset: 2px;
}

.cfield-msg { margin-top: clamp(18px, 2.2vw, 24px); }
/* (0,2,1), so it clears section 17`s `.bform .bfield textarea` height rule. */
.bform .cfield-msg textarea { min-height: 148px; }

.cform__actions {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px 24px;
  flex-wrap: wrap;
  margin-top: clamp(20px, 2.4vw, 26px);
}
.cform__note {
  display: flex;
  align-items: flex-start;
  gap: 9px;
  margin: 0;
  max-width: 46ch;
  font-size: 12.5px;
  line-height: 1.5;
  color: var(--jm-muted);
}
.cform__note .jm-ico { margin-top: .1em; font-size: 15px; color: var(--jm-accent-dim); }

/* --- the right column ---------------------------------------------------- */

.cside { display: grid; gap: clamp(14px, 1.8vw, 20px); }

.cside__card {
  padding: clamp(18px, 2.2vw, 26px) clamp(18px, 2.2vw, 24px);
  border: 1px solid var(--jm-line);
  border-radius: 14px;
  background: var(--jm-paper);
}
/* (0,1,1) clears Pico's `h2`/`h3` and the sibling-margin rule.

   Both tags are listed on purpose. These cards sit beside the message card,
   not inside it, so they are h2s in the page's outline — but they must not
   look like one. Styling only `h3` here is what let them render at Pico's
   full h2 size the moment the tag changed. */
.cside__card h2,
.cside__card h3 {
  margin: 0 0 4px;
  font-size: 17px;
  font-weight: 800;
  letter-spacing: -.012em;
  line-height: 1.25;
  color: var(--jm-heading);
}
.cside__sub {
  margin: 0 0 14px;
  font-size: 13px;
  line-height: 1.5;
  color: var(--jm-muted);
}

.creach {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr) auto;
  align-items: center;
  gap: 13px;
  margin-top: 10px;
  padding: 13px 15px;
  border: 1px solid var(--jm-line);
  border-radius: 12px;
  background: #FFFFFF;
  color: inherit;
  text-decoration: none;
  transition: border-color .18s ease;
}
.creach:hover,
.creach:focus-visible { border-color: var(--jm-accent-dim); text-decoration: none; }
.creach__ico {
  display: grid;
  place-items: center;
  width: 38px;
  height: 38px;
  border-radius: 10px;
  background: var(--jm-chip);
  color: var(--jm-accent-dim);
  font-size: 19px;
}
.creach b {
  display: block;
  font-size: 14px;
  font-weight: 800;
  color: var(--jm-heading);
}
.creach i {
  display: block;
  margin-top: 2px;
  font-style: normal;
  font-size: 12.5px;
  color: var(--jm-muted);
  overflow-wrap: anywhere;
}
.creach > .jm-ico { font-size: 15px; color: var(--jm-accent-dim); }

/* The reference`s "operating hours" list. Pico has no opinion about <dl>. */
.cfacts {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  gap: 0 14px;
  margin: 0;
}
.cfacts dt,
.cfacts dd {
  margin: 0;
  padding: 10px 0;
  border-bottom: 1px solid var(--jm-line);
  font-size: 13.5px;
  line-height: 1.4;
}
.cfacts dt { color: var(--jm-muted); white-space: nowrap; }
.cfacts dd { color: var(--jm-heading); font-weight: 800; text-align: right; }
.cfacts dt:last-of-type,
.cfacts dd:last-of-type { border-bottom: 0; }

/* --- contact block: tablet + mobile -------------------------------------- */

@media (max-width: 980px) {
  .cblock__grid { grid-template-columns: 1fr; }
}
@media (max-width: 720px) {
  .cform__actions { flex-direction: column-reverse; align-items: stretch; }
  .cform__note { max-width: none; }
}


/* ==========================================================================
   21. PROFILE PAGE BODY                     profile.php, below the card
   --------------------------------------------------------------------------
   The ~300 words the client asked for on every profile, plus a sticky booking
   aside. Two columns on desktop, stacked below 900px.

   Heading order on a profile page is h1 (the ref 08 banner) -> h2 (the name
   on the card, and "About <name>") -> h3 (the spec table, and this aside).
   ========================================================================== */

.pro__h3,
.pro-about__side h3 {
  margin: 0 0 10px;
  font-size: 11px;
  font-weight: 800;
  letter-spacing: .18em;
  text-transform: uppercase;
  color: var(--jm-accent-dim);
}
/* The aside`s heading is a real title, not a micro-label. */
.pro-about__side h3 {
  font-size: 17px;
  letter-spacing: -.012em;
  text-transform: none;
  color: var(--jm-heading);
}

.pro-about { margin-top: clamp(34px, 4.4vw, 60px); }

.pro-about__cols {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 340px);
  gap: clamp(20px, 2.6vw, 40px);
  align-items: start;
}

/* (0,2,1) — clears Pico`s `p` and its `:is(p,ul,...)~:is(h1,...)` rule, and
   holds the measure at something readable for three hundred words. */
.pro-about .pro-about__body p {
  margin: 0 0 1.05em;
  max-width: 72ch;
  font-size: 16px;
  line-height: 1.75;
  color: var(--jm-body);
}
.pro-about .pro-about__body p:last-child { margin-bottom: 0; }

/* The opening paragraph carries the name and the area, so it is given a
   little more weight — the same trick the hero subhead uses. */
.pro-about .pro-about__body p:first-child {
  font-size: 17.5px;
  color: var(--jm-heading);
}

.pro-about__side {
  position: sticky;
  top: calc(var(--jm-header-h) + 18px);
  padding: clamp(18px, 2.2vw, 26px) clamp(18px, 2.2vw, 24px);
  border: 1px solid var(--jm-line);
  border-radius: 14px;
  background: var(--jm-paper);
}
/* (0,2,1), so it beats the body rule above without touching it. */
.pro-about .pro-about__side p {
  margin: 0 0 16px;
  font-size: 14px;
  line-height: 1.6;
  color: var(--jm-muted);
}

.pro-about__list {
  margin: 0 0 18px;
  padding: 0;
  list-style: none;
}
/* Pico`s `ul li{list-style:square}` is (0,0,2) — clear it on the li. */
.pro-about__list li {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  margin: 0 0 9px;
  padding: 0;
  list-style: none;
  font-size: 13.5px;
  line-height: 1.5;
  color: var(--jm-body);
}
.pro-about__list li:last-child { margin-bottom: 0; }
.pro-about__list .jm-ico {
  margin-top: .1em;
  flex: 0 0 auto;
  font-size: 15px;
  color: var(--jm-accent-dim);
}

/* (0,2,0) beats `.btn-solid` (0,1,0) and the `.page .btn-outline` rule. */
.pro-about__side .btn-solid {
  width: 100%;
  height: 48px;
}

@media (max-width: 900px) {
  .pro-about__cols { grid-template-columns: 1fr; }
  .pro-about__side { position: static; }
}


/* ==========================================================================
   22. ENTRY WARNING                        ref 10 — board "section 2"
   --------------------------------------------------------------------------
   The full-screen 18+ dialog. The client asked for "very unique and new
   design" rather than a copy of the reference, which is a plain dark-red
   block with one button — so this is a centred ink card with a gold seal
   breaking its top edge, the two-tone wordmark, three assurance chips and
   two buttons. What is kept from the reference is the STRUCTURE: a warning
   heading, the statement, and a way out.

   No JavaScript anywhere in here. `.jm-gated` on <body> holds the page still
   behind the overlay; the Enter button is a form that PHP answers with a
   cookie and a redirect. See includes/entry-gate.php.
   ========================================================================== */

/* Stops the page behind the dialog scrolling. `position:fixed` on <body>
   would jump the page to the top; `overflow:hidden` just freezes it, and the
   moment the cookie is set the class is gone. */
.jm-gated { overflow: hidden; }

.egate {
  position: fixed;
  inset: 0;
  z-index: 2000;
  display: grid;
  place-items: center;
  padding: clamp(16px, 4vw, 40px);
  overflow-y: auto;

  /* Two layers: a wash of the brand ink, and a soft gold bloom behind the
     card so it does not read as a flat black sheet. */
  background:
    radial-gradient(760px 520px at 50% 34%,
      color-mix(in srgb, var(--jm-accent) 20%, transparent), transparent 70%),
    color-mix(in srgb, var(--jm-ink) 93%, transparent);
  -webkit-backdrop-filter: blur(7px);
  backdrop-filter: blur(7px);
}

.egate__card {
  position: relative;
  width: 100%;
  max-width: 620px;
  margin-block: auto;
  padding: clamp(46px, 6vw, 60px) clamp(22px, 4vw, 52px) clamp(24px, 3.4vw, 36px);
  border: 1px solid var(--jm-accent-dim);
  border-radius: 18px;
  background: var(--jm-ink);
  box-shadow: 0 40px 90px -30px rgba(0, 0, 0, .8);
  text-align: center;
}

/* The seal, sitting half outside the card's top edge. */
.egate__seal {
  position: absolute;
  top: 0;
  left: 50%;
  transform: translate(-50%, -50%);
  display: grid;
  place-items: center;
  width: 68px;
  height: 68px;
  border-radius: 50%;
  border: 2px solid var(--jm-accent);
  background: var(--jm-ink);
  box-shadow: 0 0 0 7px var(--jm-ink), 0 0 34px color-mix(in srgb, var(--jm-accent) 45%, transparent);
  font-family: var(--jm-display);
  font-size: 25px;
  letter-spacing: .02em;
  color: var(--jm-accent);
}

/* The masthead wordmark, restated so the dialog says whose site this is. */
.egate__mark {
  display: block;
  margin-bottom: 20px;
  font-family: var(--jm-display);
  font-size: clamp(21px, 2.6vw, 27px);
  letter-spacing: .015em;
  text-transform: uppercase;
  color: var(--jm-on-ink);
}
.egate__mark em { font-style: normal; color: var(--jm-accent); }

.egate__eyebrow {
  margin: 0 0 12px;
  font-size: 10.5px;
  font-weight: 800;
  letter-spacing: .22em;
  text-transform: uppercase;
  color: var(--jm-accent-dim);
}

/* (0,1,1) clears Pico's `h2` and its sibling-margin rule. */
.egate h2.egate__title {
  margin: 0 0 18px;
  font-family: var(--jm-serif);
  font-weight: 400;
  font-size: clamp(25px, 3.6vw, 38px);
  line-height: 1.12;
  letter-spacing: -.012em;
  color: var(--jm-on-ink);
}
.egate__title em { font-style: normal; color: var(--jm-accent); }

/* (0,1,1) so it beats Pico's `p` and the sibling-margin rule. */
.egate p.egate__p {
  margin: 0 auto 13px;
  max-width: 52ch;
  font-size: 14.5px;
  line-height: 1.65;
  color: var(--jm-nav);
}

.egate__chips {
  display: flex;
  justify-content: center;
  gap: 8px 10px;
  flex-wrap: wrap;
  margin: 22px 0 26px;
  padding: 0;
  list-style: none;
}
/* Pico's `ul li{list-style:square}` is (0,0,2) — clear it on the li. */
.egate__chips li {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  margin: 0;
  padding: 7px 14px;
  list-style: none;
  border: 1px solid var(--jm-ink-line-2);
  border-radius: 999px;
  background: var(--jm-ink-soft);
  font-size: 11.5px;
  font-weight: 700;
  color: var(--jm-on-ink);
  white-space: nowrap;
}
.egate__chips .jm-ico { font-size: 13px; color: var(--jm-accent); }

.egate__actions {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 12px 18px;
  flex-wrap: wrap;
}
.egate__actions form { margin: 0; }

/* `button.egate__go` would be (0,1,1) — the same as Pico's
   `button[type=submit]{width:100%}`, which decides on source order and is a
   coin toss to rely on. (0,2,0) settles it. */
.egate__actions .egate__go {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  width: auto;
  height: 54px;
  margin: 0;
  padding-inline: 30px;
  border: 1px solid var(--jm-accent);
  border-radius: 8px;
  background: linear-gradient(180deg, var(--jm-accent-lit), var(--jm-accent));
  color: var(--jm-on-accent);
  font-size: 13px;
  font-weight: 800;
  letter-spacing: .11em;
  text-transform: uppercase;
  cursor: pointer;
  box-shadow: 0 0 30px color-mix(in srgb, var(--jm-accent) 34%, transparent);
  transition: filter .18s ease;
}
.egate__actions .egate__go:hover,
.egate__actions .egate__go:focus-visible {
  filter: brightness(1.08);
  background: linear-gradient(180deg, var(--jm-accent-lit), var(--jm-accent));
  color: var(--jm-on-accent);
}
.egate__go .jm-ico { font-size: 16px; }

.egate__out {
  display: inline-flex;
  align-items: center;
  height: 54px;
  padding-inline: 24px;
  border: 1px solid var(--jm-ink-line-2);
  border-radius: 8px;
  font-size: 12px;
  font-weight: 800;
  letter-spacing: .11em;
  text-transform: uppercase;
  color: var(--jm-nav);
  text-decoration: none;
}
.egate__out:hover,
.egate__out:focus-visible {
  border-color: var(--jm-nav);
  color: var(--jm-on-ink);
  text-decoration: none;
}

/* (0,1,1), the same trick `.egate__p` needs: at (0,1,0) this ties with
   `.egate__card`'s `text-align:center` and the footnote comes out centred
   under a left-aligned padlock, which reads as a mistake. */
.egate p.egate__foot {
  display: flex;
  align-items: flex-start;
  gap: 8px;
  margin: 24px auto 0;
  padding-top: 18px;
  max-width: 54ch;
  border-top: 1px solid var(--jm-ink-line);
  font-size: 11.5px;
  line-height: 1.55;
  text-align: left;
  color: var(--jm-nav-dim);
}
.egate__foot .jm-ico { margin-top: .1em; flex: 0 0 auto; font-size: 14px; color: var(--jm-accent-dim); }

/* The seal glows gently. Motion only where it is welcome — the dialog is
   perfectly usable without it. */
@media (prefers-reduced-motion: no-preference) {
  .egate__seal { animation: egate-pulse 3.4s ease-in-out infinite; }
}
@keyframes egate-pulse {
  0%, 100% { box-shadow: 0 0 0 7px var(--jm-ink), 0 0 26px color-mix(in srgb, var(--jm-accent) 34%, transparent); }
  50%      { box-shadow: 0 0 0 7px var(--jm-ink), 0 0 46px color-mix(in srgb, var(--jm-accent) 62%, transparent); }
}

/* --- entry warning: mobile ----------------------------------------------- */

@media (max-width: 560px) {
  .egate__actions { flex-direction: column; align-items: stretch; }
  .egate__actions form { width: 100%; }
  .egate__actions .egate__go { width: 100%; justify-content: center; }
  .egate__out { justify-content: center; }
  .egate__chips li { font-size: 11px; padding: 6px 12px; }
}


/* ==========================================================================
   23. BROWSE BY LOCATION                   ref 19 — board "Section6"
   --------------------------------------------------------------------------
   The service-areas block, rebuilt 2026-09-06. It replaces the near-black
   bordered tiles from ref 08 that used to hold this slot; those classes
   (.areas, .areas__*, .area-tile) are STILL LIVE and must not be deleted —
   banner.php renders every sub-page header with them.

   Centred pill, two-tone heading, subline, then four across: a washed band
   carrying a pin disc and a chip, the area name and who covers it, and a
   dashed foot with an availability dot and EXPLORE.

   The whole card is ONE anchor. EXPLORE is a label inside it, not a second
   link — two anchors to one destination is two tab stops and two rows in a
   screen reader's link list for a single place to go.
   ========================================================================== */

.bloc {
  padding-block: clamp(50px, 7vw, 90px);
  background: var(--jm-ground);
}

/* --- the heading group ---------------------------------------------------- */

.bloc__pill {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  width: fit-content;
  margin: 0 auto 16px;
  padding: 7px 16px;
  border: 1px solid color-mix(in srgb, var(--jm-accent-dim) 34%, transparent);
  border-radius: 100px;
  background: color-mix(in srgb, var(--jm-accent) 13%, var(--jm-card));
  font-size: 11px;
  font-weight: 800;
  letter-spacing: .16em;
  text-transform: uppercase;
  color: var(--jm-accent-dim);
}
.bloc__pill span {
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--jm-accent-dim);
}

/* Reference 19's heading is a heavy upright sans, not a condensed display
   face, so this is the weight-800 sans used by the ref 18 heading rather than
   Anton. Anton keeps its two homes — the wordmark, and the sub-page banner
   headings that still use .areas__title. */
.bloc__title {
  margin: 0 0 12px;
  font-size: clamp(28px, 3.8vw, 46px);
  font-weight: 800;
  line-height: 1.08;
  letter-spacing: -.026em;
  text-align: center;
  color: var(--jm-heading);
}
.bloc__title em { font-style: normal; color: var(--jm-accent-dim); }

.bloc__sub {
  margin: 0 auto clamp(26px, 3.6vw, 44px);
  max-width: 62ch;
  font-size: 15.5px;
  line-height: 1.6;
  text-align: center;
  color: var(--jm-muted);
}

/* --- the cards ------------------------------------------------------------ */

.bloc-grid {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: clamp(14px, 1.8vw, 24px);
  margin: 0;
  padding: 0;
  list-style: none;
}
/* Pico's `ul li{list-style:square}` is (0,0,2) — clear it on the `li`. */
.bloc-grid > li { margin: 0; padding: 0; list-style: none; }

/* REBUILT COMPACT on 2026-09-06. The first version followed ref 19 exactly: a
   92px washed banner across the top carrying the pin disc and the count chip,
   then the name, then the foot. The client's verdict was "i don't liked
   design", and the banner was the reason — on a card whose content is two
   short lines it was more than a third of the height and it held nothing but
   a gradient. The pin now sits against the name where it reads as a label,
   the chip sits opposite it, and the card is about half as tall.

   The four accent strengths (.acard--1..4) survive on the pin disc instead of
   the banner, so the "each card is its own" effect from the reference is
   still there without a band of empty colour to carry it. */
.acard {
  display: grid;
  grid-template-rows: 1fr auto;
  height: 100%;
  padding: 16px 18px 0;
  border: 1px solid var(--jm-line);
  background: var(--jm-card);
  box-shadow: 0 1px 2px var(--jm-shadow);
  color: inherit;
  text-decoration: none;
  transition: border-color .18s ease, box-shadow .18s ease, transform .18s ease;
}

.acard__head {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  align-items: start;
  gap: 12px;
  padding-bottom: 14px;
}
.acard__id { display: block; min-width: 0; }
.acard:hover,
.acard:focus-visible {
  border-color: color-mix(in srgb, var(--jm-accent-dim) 55%, transparent);
  box-shadow: 0 14px 34px var(--jm-shadow-2);
  transform: translateY(-3px);
  text-decoration: none;
}

/* --- the pin, the chip, the name ------------------------------------------ */

/* Ref 19 gives each card its own hue — pink, purple, orange, blue. Every
   colour here goes through a token, so four hues would be four hardcoded hex
   values and theme switching would break. Four STRENGTHS of the one accent
   keep the effect on any palette. */
.acard__pin {
  display: grid;
  place-items: center;
  width: 38px;
  height: 38px;
  font-size: 18px;
  border-radius: 50%;
  background: color-mix(in srgb, var(--jm-accent) 22%, var(--jm-card));
  color: var(--jm-accent-dim);
}
.acard--2 .acard__pin { background: color-mix(in srgb, var(--jm-accent) 34%, var(--jm-card)); }
.acard--3 .acard__pin { background: color-mix(in srgb, var(--jm-accent) 48%, var(--jm-card)); }
.acard--4 .acard__pin { background: var(--jm-accent); color: var(--jm-on-accent); }

.acard__name {
  display: block;
  margin-bottom: 3px;
  font-size: 18px;
  font-weight: 700;
  letter-spacing: -.014em;
  line-height: 1.25;
  color: var(--jm-heading);
}

.acard__meta {
  display: block;
  font-size: 12.5px;
  line-height: 1.45;
  color: var(--jm-muted);
}

/* --- the dashed foot ------------------------------------------------------ */

.acard__foot {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  padding: 11px 0 14px;
  border-top: 1px dashed var(--jm-line);
}

.acard__live {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: 11.5px;
  color: var(--jm-muted);
}
.acard__live i {
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--jm-accent-dim);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--jm-accent) 30%, transparent);
}

.acard__go {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  font-size: 11px;
  font-weight: 800;
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--jm-accent-dim);
}
.acard__go .jm-ico { transition: transform .18s ease; }
.acard:hover .acard__go .jm-ico { transform: translateX(3px); }

/* --- "view all locations" ------------------------------------------------- */

.bloc__all { margin: clamp(26px, 3.4vw, 40px) 0 0; text-align: center; }

.bloc__all a {
  display: inline-flex;
  align-items: center;
  gap: 9px;
  padding: 14px 30px;
  border: 1px solid var(--jm-accent-dim);
  border-radius: 100px;
  background: var(--jm-card);
  font-size: 12.5px;
  font-weight: 800;
  letter-spacing: .13em;
  text-transform: uppercase;
  color: var(--jm-accent-dim);
  text-decoration: none;
  transition: background-color .18s ease, color .18s ease;
}
.bloc__all a:hover,
.bloc__all a:focus-visible {
  background: var(--jm-accent);
  border-color: var(--jm-accent);
  color: var(--jm-on-accent);
  text-decoration: none;
}

/* --------------------------------------------------------------------------
   2026-09-12: "below the location tab also will ... button type of color
   button type of animation ... and below a paragraph ... little big [font]
   size user friendly".

   The pill was an outline that filled on hover. It is now a SOLID accent
   button from the start — the outline read as secondary, and this is the way
   through to twelve pages — it lifts, and the arrow travels.
   -------------------------------------------------------------------------- */
.bloc__all a {
  padding: 16px 34px;
  font-size: 13px;
  background: var(--jm-accent);
  border-color: var(--jm-accent);
  color: var(--jm-on-accent);
  box-shadow: 0 8px 22px color-mix(in srgb, var(--jm-accent-dim) 40%, transparent);
  transition: background-color .18s ease, color .18s ease,
              transform .24s cubic-bezier(.2, .7, .3, 1), box-shadow .24s ease;
}
.bloc__all a:hover,
.bloc__all a:focus-visible {
  background: var(--jm-accent-lit);
  border-color: var(--jm-accent-lit);
}
@media (prefers-reduced-motion: no-preference) {
  .bloc__all a:hover,
  .bloc__all a:focus-visible {
    transform: translateY(-3px);
    box-shadow: 0 14px 32px color-mix(in srgb, var(--jm-accent-dim) 52%, transparent);
  }
  /* The trailing arrow travels; the leading pin does not, so the pair reads
     as "here" then "onward" rather than as two things wobbling. */
  .bloc__all a .jm-ico:last-child { transition: transform .24s ease; }
  .bloc__all a:hover .jm-ico:last-child,
  .bloc__all a:focus-visible .jm-ico:last-child { transform: translateX(4px); }
}

/* The paragraph under it. Larger than the site's usual body copy, as asked —
   16px against the 14px most blocks use — and held to a readable measure
   rather than running the full panel width.

   >>> --jm-muted, NOT an --jm-on-ink MIX. The first version of this rule
       assumed `.bloc` was a dark panel and set a 74% white — which rendered
       near-white text on a light ground, barely readable. `.bloc` is
       `background: var(--jm-ground)` and ALL FOUR callers wrap it in a plain
       `<section class="bloc">` with no `.jm-lit`, so there is no dark variant
       to cater for. The sibling `.bloc__sub` in the same block had it right
       all along. Caught by screenshot; the markup and the measurements were
       both fine.                                                        <<< */
.bloc__foot {
  margin: clamp(16px, 2vw, 24px) auto 0;
  max-width: 74ch;
  font-size: 16px;
  line-height: 1.7;
  text-align: center;
  color: var(--jm-muted);
}
/* The three figures in it carry the emphasis, since the sentence is long. */
.bloc__foot b { color: var(--jm-heading); font-weight: 700; }

@media (max-width: 1180px) { .bloc-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
@media (max-width: 860px)  { .bloc-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 520px)  { .bloc-grid { grid-template-columns: 1fr; } }


/* --------------------------------------------------------------------------
   23b. The studio block on an area page
   --------------------------------------------------------------------------
   Reuses ref 04's .gcard whole. The only thing needed is a width — a gallery
   card is one of six in a grid, and on its own it would otherwise stretch to
   the full shell.
   -------------------------------------------------------------------------- */

/* ==========================================================================
   24. THE ROUNDED LANGUAGE          ref 24–29 — mumbai.neverendservice.com
   --------------------------------------------------------------------------
   The client supplied their own sister site as the design reference for the
   whole of JioMassage on 2026-09-06, and asked for the layout with the brand
   colour unchanged. The single biggest difference between the two is SHAPE:
   the reference is built on pills and soft 16px cards, and this site was
   squared and editorial at 4–8px.

   Rather than edit seventy border-radius declarations in place, this block
   restates the shape-carrying ones from the four radius tokens. Every rule
   here is the same selector as the original, so it wins on source order and
   NOTHING ELSE about those rules changes. Deleting this whole block returns
   the site to its previous shapes exactly.

   Colour is untouched throughout — that was the client's instruction.
   ========================================================================== */

/* --- every button is a pill ---------------------------------------------- */

.btn-outline,
.btn-solid,
.hero__cta,
.near-clear,
.rcard-act,
.recruit-cta,
.egate__out,
.help-q { border-radius: var(--jm-pill); }

/* (0,2,0) each — these two are written one class deep in their own sections
   to beat `.main-nav a` and Pico's submit-button rule, so matching them here
   needs the same depth or the pill silently loses. */
.egate__actions .egate__go { border-radius: var(--jm-pill); }
.near .near-go             { border-radius: var(--jm-pill); }
.bform button.bgo          { border-radius: var(--jm-pill); }

/* --- badges and chips ---------------------------------------------------- */

.nav-badge,
.hero__pill,
.rcard__verified { border-radius: var(--jm-pill); }

/* --- cards --------------------------------------------------------------- */

.lcard,
.acard,
.rcard,
.area-tile,
.cta-band,
.ann-bar,
.gcard__frame,
.near-stats,
.bcard__ref,
.help-tile,
.help-hi,
.ccard,
.cside__card,
.creach,
.pro__photo,
.pro-about__side,
.help-list,
.help-answer,
.help-top { border-radius: var(--jm-r); }

/* --- large panels -------------------------------------------------------- */

.near__panel,
.egate__card,
.bcard { border-radius: var(--jm-r-lg); }

/* --- small furniture ----------------------------------------------------- */

.ltile,
.svc-row__thumb,
.hero__row img,
.why-phone__find,
.why-phone__cta,
.why-phone__link,
.why-phone__tiles img,
.why-list__ico,
.pro__stats,
.help-tile__ico,
.creach__ico { border-radius: var(--jm-r-sm); }


/* ==========================================================================
   25. UTILITY BAR · LIGHT MASTHEAD · FLOATING CONTACT RAIL
                                     ref 24 — mumbai.neverendservice.com
   --------------------------------------------------------------------------
   Three things the reference has that this site did not:

     1. a thin dark utility bar above everything, carrying the phone and the
        email — the reference puts social icons on the left, and JioMassage
        has no social accounts, so the left side carries the one line the site
        already says about itself rather than four dead icons;
     2. a WHITE sticky header under it, where this site had a single near-black
        bar;
     3. a floating rail of round chat buttons pinned to the left edge.

   The header goes light the same way sections 7–9 did: `.jm-lit` on the
   element re-points the whole ink family, so every rule in §4 renders light
   without being rewritten. Only the handful below need saying again, and
   they are the ones where "the same rule, lighter" is not the right answer.
   ========================================================================== */

/* --- 1. the utility bar — *** NOT RENDERED *** ---------------------------- */

/* >>> header.php does not emit .util-bar and .site-header does not carry
       `jm-lit`. Both were built on 2026-09-06 and reverted the same day, on
       the client's instruction *"don't edit before header … don't delate
       design"*. The rules are kept so putting them back is two edits in
       header.php rather than a rebuild. Do not delete as dead code.    <<<

   Outside .site-header on purpose: inside it, `.jm-lit` would have re-pointed
   --jm-ink and the bar would come out white like everything else. */
.util-bar {
  background: var(--jm-ink);
  color: var(--jm-nav);
  font-size: 12px;
}
.util-bar__inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  min-height: 38px;
  padding-block: 7px;
}
.util-bar__note { margin: 0; }
.util-bar__links {
  display: flex;
  align-items: center;
  gap: 18px;
  margin: 0;
  padding: 0;
  list-style: none;
}
/* Pico's `ul li{list-style:square}` is (0,0,2) — clear it on the `li`. */
.util-bar__links li { margin: 0; padding: 0; list-style: none; }
.util-bar__links a {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  color: var(--jm-nav);
  text-decoration: none;
  white-space: nowrap;
}
.util-bar__links a:hover,
.util-bar__links a:focus-visible { color: var(--jm-accent); text-decoration: none; }
.util-bar__links .jm-ico { font-size: 14px; color: var(--jm-accent); }

@media (max-width: 860px) {
  /* The note is the first thing to go: the phone and the email are the point
     of the bar, and at this width they need the whole row. */
  .util-bar__note { display: none; }
  .util-bar__inner { justify-content: center; }
}
@media (max-width: 520px) {
  .util-bar__links { gap: 14px; font-size: 11.5px; }
}

/* --- 2. the light masthead ------------------------------------------------ */

/* `.jm-lit` maps --jm-ink to --jm-ground, which is right for a section band
   and wrong for the header: the reference's header is white, sitting on the
   tinted page rather than blending into it. */
.site-header.jm-lit {
  background: var(--jm-card);
  border-bottom: 1px solid var(--jm-line);
}

/* The reference's header lifts off the page as you scroll. There is no
   scroll listener here and there is not going to be one, so it carries a
   permanent hairline shadow instead — the same read, no JavaScript. */
.site-header.jm-lit { box-shadow: 0 2px 14px var(--jm-shadow); }

/* The search drawer is the header's own surface and has to be white for the
   same reason the header is, not the page tint. */
.site-header.jm-lit .search-drawer > div { background: var(--jm-card); }

/* The mobile panel likewise — but ONLY once it IS a panel. `nav.main-nav`
   carries no background above 1180px, where the nav is a plain row of links
   inside the header; painting it there draws a white box with a drop shadow
   around the middle of the masthead. */
@media (max-width: 1180px) {
  .site-header.jm-lit nav.main-nav {
    background: var(--jm-card);
    box-shadow: 0 18px 34px var(--jm-shadow-2);
  }
}

/* --- 3. the floating contact rail ----------------------------------------- */

/* THREE POSITIONS, and the reason is collision, not taste.

   The reference pins this rail to the left edge at every desktop width — it
   can, because its content column is narrow and the margin beside it is
   empty. `.jm-shell` is 1560px wide with a 40px gutter, so on a 1440px screen
   the copy starts 40px in and a 52px button at left:20px lands ON TOP of the
   hero's tick list and its BOOK NOW button. Verified by screenshot; it is not
   subtle.

   So the left rail only appears once there is genuinely room for it beside a
   full-width shell (1560 + two 70px lanes). Between that and mobile it sits
   in the bottom-right corner, which is where a chat launcher lives on most of
   the web anyway, and on mobile it becomes a bar along the bottom. */
.contact-rail {
  position: fixed;
  right: clamp(12px, 1.4vw, 22px);
  bottom: clamp(12px, 1.6vw, 26px);
  z-index: 800;
  display: grid;
  gap: 12px;
  margin: 0;
  padding: 0;
  list-style: none;
}

@media (min-width: 1700px) {
  .contact-rail {
    right: auto;
    left: clamp(16px, 1.6vw, 26px);
    bottom: auto;
    top: 50%;
    transform: translateY(-50%);
  }
}
.contact-rail li { margin: 0; padding: 0; list-style: none; }

.contact-rail a {
  display: grid;
  place-items: center;
  width: 52px;
  height: 52px;
  font-size: 23px;
  border-radius: 50%;
  color: #FFFFFF;
  text-decoration: none;
  box-shadow: 0 6px 20px var(--jm-shadow-2);
  transition: transform .18s ease, box-shadow .18s ease;
}
.contact-rail a:hover,
.contact-rail a:focus-visible {
  transform: scale(1.08);
  box-shadow: 0 10px 28px var(--jm-shadow-2);
  text-decoration: none;
}

/* The two channel colours are the brands' own — see the note beside them in
   §2. The phone button is ours, so it takes the accent and the accent's own
   label colour rather than white. */
.contact-rail__whatsapp { background: var(--jm-whatsapp); }
.contact-rail__telegram { background: var(--jm-telegram); }
.contact-rail__phone    { background: var(--jm-ink); color: var(--jm-accent); }

/* While $SITE['whatsapp'] / ['telegram'] are empty the button falls back to
   contact.php — see rail_href(). It is dimmed so the state is visible on the
   page rather than only in config. */
.contact-rail a[data-pending] { opacity: .55; }

@media (max-width: 860px) {
  /* Along the bottom instead of down the side: at this width a left rail sits
     on top of the content, and a thumb reaches the bottom of the screen more
     easily than its left edge. */
  .contact-rail {
    left: 0;
    right: 0;
    top: auto;
    bottom: 0;
    transform: none;
    grid-auto-flow: column;
    border-radius: 0;
    justify-content: center;
    gap: 14px;
    padding: 9px 0 calc(9px + env(safe-area-inset-bottom, 0px));
    background: color-mix(in srgb, var(--jm-card) 92%, transparent);
    -webkit-backdrop-filter: blur(8px);
    backdrop-filter: blur(8px);
    border-top: 1px solid var(--jm-line);
  }
  .contact-rail a { width: 46px; height: 46px; font-size: 20px; }

  /* The bar covers the last of the page, so the footer gets room under it. */
  .site-footer { padding-bottom: 72px; }
}

/* The rail is fixed over everything; the entry warning is a modal and has to
   be over it in turn. */
.jm-gated .contact-rail { display: none; }


/* ==========================================================================
   25b. THE TWO-COLUMN HERO — *** NOT RENDERED ***
                                       ref 24 — mumbai.neverendservice.com
   --------------------------------------------------------------------------
   >>> NOTHING ON THE SITE USES THIS BLOCK TODAY. index.php renders the ref 01
       marquee hero (§7) instead. Do not delete it and do not "clean it up" as
       dead code — it is kept on purpose, and the reason is below.        <<<

   Built 2026-09-06 to replace the ref 01 hero, on the client's instruction to
   take the design of their sister site. Reverted the same day on their next
   instruction: *"top slide tv running design before used don't delate
   design"* — the drifting photo rows are the part they wanted kept.

   It is left here complete so that going back is one markup swap in index.php
   rather than a rebuild, and $HERO still carries the copy it needs
   ('eyebrow', 'title_hi', 'sub', 'ticks', 'cta2_*', 'note', 'chips', 'strip',
   'cards'). `.btn-ghost` below IS used elsewhere, so that rule is live.

   Two columns on a soft accent wash: copy left, proof and photographs right.
   ========================================================================== */

.nhero {
  padding-block: clamp(34px, 5vw, 76px) clamp(44px, 6vw, 90px);
  background:
    radial-gradient(72% 90% at 12% 8%,
      color-mix(in srgb, var(--jm-accent) 26%, transparent) 0%, transparent 62%),
    radial-gradient(60% 80% at 96% 46%,
      color-mix(in srgb, var(--jm-accent) 17%, transparent) 0%, transparent 60%),
    var(--jm-card);
}

.nhero__grid {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1.02fr);
  align-items: center;
  gap: clamp(30px, 4.5vw, 70px);
}

/* --- left column ---------------------------------------------------------- */

.nhero__eyebrow {
  margin: 0 0 14px;
  font-size: 11.5px;
  font-weight: 800;
  letter-spacing: .19em;
  text-transform: uppercase;
  color: var(--jm-accent-dim);
}

/* (0,1,0) and set explicitly: Pico's h1 rule is (0,0,1) and its
   `:is(p,ul,…)~:is(h1,…,h6)` sibling margin is (0,0,2) — the eyebrow above is
   a <p>, so without this the heading picks up a large top margin. */
.nhero__title {
  margin: 0 0 8px;
  font-size: clamp(38px, 5.6vw, 76px);
  font-weight: 800;
  line-height: 1.02;
  letter-spacing: -.032em;
  color: var(--jm-heading);
}
.nhero__title em { font-style: normal; color: var(--jm-accent-dim); }

.nhero__sub {
  margin: 0 0 18px;
  font-family: var(--jm-serif);
  font-style: italic;
  font-size: clamp(21px, 2.4vw, 34px);
  line-height: 1.15;
  color: var(--jm-muted);
}

.nhero__lede {
  margin: 0 0 22px;
  max-width: 46ch;
  font-size: clamp(15px, 1.15vw, 17.5px);
  line-height: 1.6;
  color: var(--jm-body);
}
.nhero__lede b { color: var(--jm-heading); }

.nhero__ticks { margin: 0 0 clamp(22px, 2.6vw, 30px); padding: 0; list-style: none; }
/* Pico's `ul li{list-style:square}` is (0,0,2) — clear it on the `li`. */
.nhero__ticks li {
  display: flex;
  align-items: baseline;
  gap: 10px;
  margin: 0 0 9px;
  padding: 0;
  list-style: none;
  font-size: 15px;
  line-height: 1.45;
  color: var(--jm-muted);
}
.nhero__ticks b { color: var(--jm-heading); font-weight: 700; }
.nhero__ticks .jm-ico {
  flex: 0 0 auto;
  font-size: 14px;
  color: var(--jm-accent-dim);
  transform: translateY(1px);
}

.nhero__actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 12px;
  margin-bottom: 14px;
}
.nhero__actions .btn-solid { padding: 15px 30px; font-size: 13.5px; gap: 9px; }

/* The reference's second action is a white pill with a dark label. It is not
   `.btn-outline`: that one is a MASTHEAD button whose label is --jm-on-ink,
   and CLAUDE.md §5 records what happens when it is reused on a light page. */
.btn-ghost {
  display: inline-flex;
  align-items: center;
  gap: 9px;
  padding: 15px 30px;
  border: 1px solid var(--jm-line);
  border-radius: var(--jm-pill);
  background: var(--jm-card);
  box-shadow: 0 2px 10px var(--jm-shadow);
  font-size: 13.5px;
  font-weight: 800;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--jm-heading);
  text-decoration: none;
  transition: border-color .18s ease, box-shadow .18s ease;
}
.btn-ghost:hover,
.btn-ghost:focus-visible {
  border-color: var(--jm-accent-dim);
  box-shadow: 0 8px 22px var(--jm-shadow-2);
  color: var(--jm-heading);
  text-decoration: none;
}

.nhero__note {
  margin: 0;
  font-style: italic;
  font-size: 13.5px;
  color: var(--jm-muted);
}

/* --- right column --------------------------------------------------------- */

.nhero__side { display: grid; gap: 14px; }

.nhero__chips {
  display: flex;
  flex-wrap: wrap;
  gap: 9px;
  margin: 0;
  padding: 0;
  list-style: none;
}
.nhero__chips li {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  margin: 0;
  padding: 9px 16px;
  list-style: none;
  border: 1px solid var(--jm-line);
  border-radius: var(--jm-pill);
  background: var(--jm-card);
  box-shadow: 0 2px 8px var(--jm-shadow);
  font-size: 12.5px;
  font-weight: 700;
  color: var(--jm-heading);
}
.nhero__chips .jm-ico { font-size: 14px; color: var(--jm-accent-dim); }

/* The dotted feature strip. Each item carries its own leading dot as a
   pseudo-element rather than a separator character, so the row wraps cleanly
   at any width instead of stranding a lone bullet at the start of line two. */
.nhero__strip {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 6px 20px;
  margin: 0;
  padding: 11px 18px;
  border: 1px dashed color-mix(in srgb, var(--jm-accent-dim) 42%, transparent);
  border-radius: var(--jm-pill);
  list-style: none;
}
/* Pico's `ul li{list-style:square}` is (0,0,2) — clear it on the `li`. */
.nhero__strip li {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  margin: 0;
  padding: 0;
  list-style: none;
  font-size: 11.5px;
  font-weight: 800;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--jm-accent-dim);
}
.nhero__strip li::before {
  content: '';
  width: 5px;
  height: 5px;
  border-radius: 50%;
  background: currentColor;
}

.nhero__cards {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: clamp(10px, 1.2vw, 16px);
  margin: 0;
  padding: 0;
  list-style: none;
}
.nhero__cards li { margin: 0; padding: 0; list-style: none; }

/* `figure`, not `article`: Pico gives `article` a background, shadow, padding
   and margin at (0,0,1) that would box every card. */
.nhero__cards figure {
  position: relative;
  margin: 0;
  overflow: hidden;
  border-radius: var(--jm-r);
  box-shadow: 0 10px 30px var(--jm-shadow-2);
}
.nhero__cards img {
  display: block;
  width: 100%;
  height: 100%;
  aspect-ratio: 3 / 4;
  object-fit: cover;
  background: var(--jm-card-2);
}

/* (0,1,1) — clears Pico's `figure figcaption` (0,0,2), which centres it and
   gives it a margin. */
.nhero__cards figcaption {
  position: absolute;
  top: 10px;
  left: 10px;
  padding: 6px 12px;
  border-radius: var(--jm-pill);
  background: color-mix(in srgb, var(--jm-card) 92%, transparent);
  -webkit-backdrop-filter: blur(6px);
  backdrop-filter: blur(6px);
  font-size: 10.5px;
  font-weight: 800;
  letter-spacing: .08em;
  text-transform: uppercase;
  text-align: left;
  color: var(--jm-heading);
}

/* --- hero: tablet + mobile ------------------------------------------------ */

@media (max-width: 980px) {
  .nhero__grid { grid-template-columns: 1fr; gap: clamp(30px, 6vw, 46px); }
  .nhero__lede { max-width: none; }
}
@media (max-width: 620px) {
  /* Three portrait cards side by side at this width are 90px wide and read as
     stripes. Two, with the third dropped, keeps them legible. */
  .nhero__cards { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .nhero__cards li:last-child { display: none; }
  .nhero__actions .btn-solid,
  .nhero__actions .btn-ghost { flex: 1 1 100%; justify-content: center; }
}


/* ==========================================================================
   26. THE THREE CONVERTED PANELS — sections 7, 8 and 9 on .jm-lit
   --------------------------------------------------------------------------
   The client asked on 2026-09-04 for a soft tinted page with white cards, and
   named these three near-black panels as the ones that had to go: Why book
   with us, Massage service near you, and Therapists on shift. Services (3)
   and Service areas (4) were NOT named and, confirmed on 2026-09-06, stay
   dark — the page keeps a dark band near the top and the hero above it.

   Almost all of the conversion is done by .jm-lit re-pointing the ink family,
   so the rules in §14–16 render light without being touched. What is left
   here is the handful of places where "the same rule, lighter" is not the
   right answer:

     · .near is inside-out on a light ground. Its section is --jm-ink-soft and
       its panel is --jm-ink, which on the dark half means "raised panel on a
       darker ground" and on the light half would mean "tinted panel on white"
       — the opposite of a white card on a tinted page.
     · A tile or an inset box that was a lighter dark grey becomes an almost
       invisible light grey, so both take a wash of the accent instead.
     · The gold gradient button ends on --jm-accent-dim, which is only 2.6:1
       behind --jm-on-accent. On the light panel it ends on --jm-accent.
   -------------------------------------------------------------------------- */

/* --- section 7: why book with us ----------------------------------------- */

/* The rounded-square icon tile was --jm-ink-line, a lift out of a near-black
   ground. The same lift out of paper is a grey nobody can see. */
.why.jm-lit .why-list__ico {
  background: color-mix(in srgb, var(--jm-accent) 18%, var(--jm-card));
}

/* The phone goes light with everything else, which needs no rules at all —
   every part of it is already drawn from the ink family. Only the drop shadow
   has to change: it was --jm-ink at 78%, and a near-black shadow token that
   now resolves to the page tint casts no shadow. */
.why.jm-lit .why-phone__body {
  background: var(--jm-card);
  box-shadow: 0 26px 60px var(--jm-shadow-2);
}
.why.jm-lit .why-phone__screen { background: var(--jm-card-2); }

/* --- section 8: massage service near you --------------------------------- */

/* Turn the panel the right way up: tinted ground, white card. */
.near.jm-lit { background: var(--jm-ground); }
.near.jm-lit .near__panel {
  background: var(--jm-card);
  box-shadow: 0 14px 40px var(--jm-shadow);
}

/* The two-cell stat box sat on a raised dark surface; on a white card it needs
   to sit *down* into it instead. */
.near.jm-lit .near-stats { background: var(--jm-card-2); }

/* The controls, likewise — a white select on a white card is not a control. */
.near.jm-lit select {
  --pico-form-element-background-color: var(--jm-card-2);
}

/* THE CONTRAST TRAP flagged in the CLAUDE.md TODO. The gradient runs
   accent-lit -> accent-dim, and --jm-on-accent (near-black) over
   --jm-accent-dim (#8A6D1F) is about 2.6:1 — a button whose label you cannot
   read. Ending on --jm-accent instead puts the label at about 9:1, and the
   glow becomes an ordinary drop shadow because a bloom only reads on ink.
   `button.near-go` (0,1,1) is deliberate: Pico's `button[type=submit]`
   width rule is (0,1,1) too, and a plain `.near-go` loses to it. */
.near.jm-lit button.near-go {
  border-color: var(--jm-accent);
  background: linear-gradient(180deg, var(--jm-accent-lit), var(--jm-accent));
  color: var(--jm-on-accent);
  box-shadow: 0 6px 18px var(--jm-shadow-2);
}
.near.jm-lit .near-go:hover,
.near.jm-lit .near-go:focus-visible {
  background: linear-gradient(180deg, var(--jm-accent-lit), var(--jm-accent));
}

/* --- section 9: therapists on shift -------------------------------------- */

/* The split cards become white cards on the tinted ground. Their border was
   --jm-accent-dim, which is a dark gold: right on ink, heavy on paper. */
.roster.jm-lit .rcard {
  border-color: var(--jm-line);
  box-shadow: 0 1px 2px var(--jm-shadow);
}
.roster.jm-lit .rcard__photo { background: var(--jm-card-2); }


/* ==========================================================================
   28. SERVICES MASTHEAD            ref 33 — nes /services, TOP OF PAGE ONLY
   --------------------------------------------------------------------------
   The client sent .../services on 2026-09-06 with "use design", then "top
   only". So this is the top block of that page and nothing else: services.php
   drops banner.php and renders this instead, EVERY OTHER PAGE STILL USES THE
   REF 08 BANNER, and the treatment cards below it are untouched.

   Two columns on a soft accent wash: breadcrumb, pill, two-line heading with
   an italic accent line, lede, two pill buttons, hairline, three stats — and
   on the right a three-photo collage with two pills floating over it.

   The collage is aria-hidden and carries no links: every treatment in it is a
   card in the menu directly below, and a decorative duplicate of a link is
   two tab stops for one destination.
   ========================================================================== */

.stop {
  padding-block: clamp(26px, 3.4vw, 52px) clamp(40px, 5.5vw, 84px);
  background:
    radial-gradient(70% 90% at 10% 6%,
      color-mix(in srgb, var(--jm-accent) 24%, transparent) 0%, transparent 62%),
    radial-gradient(58% 76% at 98% 40%,
      color-mix(in srgb, var(--jm-accent) 15%, transparent) 0%, transparent 60%),
    var(--jm-card);
}

.stop__grid {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, .96fr);
  align-items: center;
  gap: clamp(30px, 4.5vw, 70px);
}

/* --- left column ---------------------------------------------------------- */

.stop__crumb {
  display: flex;
  align-items: center;
  /* Pico's `nav` rule is `display:flex; justify-content:space-between` — one
     declaration, (0,0,1). Setting `display` here does NOT cancel the rest of
     it, so without this line the two crumbs are pushed to opposite ends of a
     700px column with the slash marooned in the middle. Setting `display`
     and forgetting `justify-content` is the trap; any future flex row built
     on a <nav> hits it. */
  justify-content: flex-start;
  gap: 9px;
  margin-bottom: clamp(18px, 2.4vw, 30px);
  font-size: 13px;
  color: var(--jm-muted);
}
/* Pico also ships `nav a` styling; this is a breadcrumb, not the primary nav,
   so it only needs the link colours. */
.stop__crumb a { color: var(--jm-muted); text-decoration: none; }
.stop__crumb a:hover,
.stop__crumb a:focus-visible { color: var(--jm-accent-dim); text-decoration: underline; }
.stop__crumb b { color: var(--jm-heading); font-weight: 700; }

.stop__pill {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  margin: 0 0 16px;
  padding: 7px 16px;
  border: 1px solid color-mix(in srgb, var(--jm-accent-dim) 34%, transparent);
  border-radius: var(--jm-pill);
  background: color-mix(in srgb, var(--jm-accent) 13%, var(--jm-card));
  font-size: 11.5px;
  font-weight: 800;
  letter-spacing: .15em;
  text-transform: uppercase;
  color: var(--jm-accent-dim);
}
.stop__pill span {
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--jm-accent-dim);
}

/* (0,1,0), stated explicitly: Pico's h1 is (0,0,1) and its
   `:is(p,ul,…)~:is(h1,…,h6)` sibling margin is (0,0,2) — the pill above is a
   <p>, so without this the heading takes a large top margin. */
.stop__title {
  margin: 0 0 16px;
  font-size: clamp(34px, 4.8vw, 64px);
  font-weight: 800;
  line-height: 1.04;
  letter-spacing: -.03em;
  color: var(--jm-heading);
}
/* The reference's second line is an italic in the accent, on its own line. */
.stop__title em {
  display: block;
  font-family: var(--jm-serif);
  font-style: italic;
  font-weight: 400;
  letter-spacing: -.018em;
  color: var(--jm-accent-dim);
}

.stop__lede {
  margin: 0 0 clamp(20px, 2.6vw, 30px);
  max-width: 52ch;
  font-size: clamp(15px, 1.1vw, 17px);
  line-height: 1.62;
  color: var(--jm-body);
}

.stop__actions {
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
}
.stop__actions .btn-solid { padding: 15px 30px; font-size: 13.5px; gap: 9px; }

.stop__rule {
  height: 1px;
  border: 0;
  margin: clamp(24px, 3vw, 36px) 0 clamp(18px, 2.2vw, 26px);
  background: var(--jm-line);
}

.stop__stats {
  display: flex;
  flex-wrap: wrap;
  gap: 14px clamp(26px, 4vw, 56px);
  margin: 0;
  padding: 0;
  list-style: none;
}
/* Pico's `ul li{list-style:square}` is (0,0,2) — clear it on the `li`. */
.stop__stats li { margin: 0; padding: 0; list-style: none; }
.stop__stats b {
  display: block;
  font-size: clamp(24px, 2.6vw, 34px);
  font-weight: 800;
  line-height: 1.05;
  letter-spacing: -.02em;
  color: var(--jm-heading);
}
.stop__stats span {
  display: block;
  margin-top: 4px;
  font-size: 12px;
  color: var(--jm-muted);
}

/* --- right column: the collage -------------------------------------------- */

.stop__art { position: relative; }

.stop__shots {
  display: grid;
  grid-template-columns: 1.06fr 1fr;
  gap: clamp(10px, 1.2vw, 16px);
  margin: 0;
  padding: 0;
  list-style: none;
}
.stop__shots li { margin: 0; padding: 0; list-style: none; }
/* The first shot is the tall one down the left, as in the reference. */
.stop__shots li:first-child { grid-row: span 2; }

/* `figure`, not `article`: Pico gives `article` a background, shadow, padding
   and margin at (0,0,1) that would box every shot. */
.stop__shots figure {
  position: relative;
  height: 100%;
  margin: 0;
  overflow: hidden;
  border-radius: var(--jm-r);
  box-shadow: 0 12px 34px var(--jm-shadow-2);
}
.stop__shots img {
  display: block;
  width: 100%;
  height: 100%;
  min-height: 132px;
  object-fit: cover;
  background: var(--jm-card-2);
}

/* (0,1,1) — clears Pico's `figure figcaption` (0,0,2). The gradient is what
   keeps white text legible over an unknown photograph. */
.stop__shots figcaption {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  padding: 26px 14px 12px;
  background: linear-gradient(180deg, transparent,
    color-mix(in srgb, var(--jm-ink) 82%, transparent));
  text-align: left;
}
.stop__shots figcaption b {
  display: block;
  font-size: 15px;
  font-weight: 700;
  line-height: 1.2;
  color: #FFFFFF;
}
.stop__shots figcaption span {
  display: block;
  margin-top: 2px;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: .06em;
  text-transform: uppercase;
  color: var(--jm-accent);
}

/* --- the two floating pills ----------------------------------------------- */

.stop__float {
  position: absolute;
  z-index: 2;
  display: flex;
  align-items: center;
  gap: 10px;
  margin: 0;
  padding: 9px 15px 9px 9px;
  border-radius: var(--jm-pill);
  background: var(--jm-card);
  box-shadow: 0 10px 28px var(--jm-shadow-2);
  white-space: nowrap;
}
.stop__float__ico {
  display: grid;
  place-items: center;
  width: 32px;
  height: 32px;
  font-size: 16px;
  border-radius: 50%;
  background: color-mix(in srgb, var(--jm-accent) 24%, var(--jm-card));
  color: var(--jm-accent-dim);
}
.stop__float b {
  display: block;
  font-size: 12.5px;
  font-weight: 700;
  line-height: 1.2;
  color: var(--jm-heading);
}
.stop__float i {
  display: block;
  font-style: normal;
  font-size: 11px;
  color: var(--jm-muted);
}

.stop__float--1 { top: -14px; right: -10px; }
.stop__float--2 { bottom: -14px; left: -18px; }

/* The bottom-left pill lands exactly where the tall shot's caption sits, and
   the two overlapped. The reference has the same diagonal composition but its
   caption is higher up the photo, so the caption moves rather than the pill. */
.stop__shots li:first-child figcaption { padding-bottom: 58px; }

/* --- services masthead: tablet + mobile ----------------------------------- */

@media (max-width: 980px) {
  .stop__grid { grid-template-columns: 1fr; gap: clamp(30px, 6vw, 48px); }
  .stop__lede { max-width: none; }
  /* The pills hang outside the collage; once it is the full width of the
     screen that overflows the page, so they come in. */
  .stop__float--1 { right: 0; }
  .stop__float--2 { left: 0; }
}
@media (max-width: 560px) {
  /* Two shots side by side at this width are ~130px each. One tall shot with
     one beside it reads; three do not. */
  .stop__shots li:last-child { display: none; }
  .stop__shots li:first-child { grid-row: auto; }
  .stop__float { display: none; }
  .stop__actions .btn-solid,
  .stop__actions .btn-ghost { flex: 1 1 100%; justify-content: center; }
}


/* ==========================================================================
   45. TOWNS NEARBY — /bangalore/
   --------------------------------------------------------------------------
   Twelve town links under the twelve area cards. Added 2026-09-07; until then
   the towns were <option> elements and no crawler had ever seen them.

   >>> THE WEIGHT IS THE POINT. The areas above are PAGES — white cards, a
       photograph's worth of padding, a dashed foot. These are booking
       shortcuts, so they are a row of small tinted tiles: same family, half
       the presence. If they ever look as important as the area cards, the
       page is telling the visitor something untrue about which matters.
   ========================================================================== */

.towns {
  padding-block: clamp(10px, 1.6vw, 20px) clamp(44px, 6vw, 82px);
}

.towns__eyebrow {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  width: fit-content;
  margin: 0 auto 14px;
  padding: 7px 16px;
  border: 1px solid color-mix(in srgb, var(--jm-accent-dim) 30%, transparent);
  border-radius: var(--jm-pill);
  background: color-mix(in srgb, var(--jm-accent) 11%, var(--jm-card));
  font-size: 11px;
  font-weight: 800;
  letter-spacing: .16em;
  text-transform: uppercase;
  color: var(--jm-accent-dim);
}
.towns__eyebrow span {
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--jm-accent-dim);
}

/* (0,1,0) — the eyebrow above is a <p>, so Pico's
   `:is(p,ul,…)~:is(h1,…,h6)` (0,0,2) would add a large top margin.
   Deliberately a step smaller than `.bloc__title` on the same page: the
   areas are the heading of record here. */
.towns__title {
  margin: 0 0 10px;
  font-size: clamp(22px, 2.8vw, 34px);
  font-weight: 800;
  line-height: 1.1;
  letter-spacing: -.024em;
  text-align: center;
  color: var(--jm-heading);
}
.towns__title em { font-style: normal; color: var(--jm-accent-dim); }

.towns__lede {
  margin: 0 auto clamp(22px, 2.8vw, 32px);
  max-width: 58ch;
  font-size: 15px;
  line-height: 1.6;
  text-align: center;
  color: var(--jm-muted);
}

.towns-grid {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 10px;
  margin: 0;
  padding: 0;
  list-style: none;
}
/* Pico's `ul li{list-style:square}` is (0,0,2) — clear it on the `li`. */
.towns-grid > li { margin: 0; padding: 0; list-style: none; }

.town {
  display: flex;
  align-items: center;
  gap: 11px;
  padding: 12px 14px;
  border: 1px solid var(--jm-line);
  border-radius: var(--jm-pill);
  background: var(--jm-card);
  color: inherit;
  text-decoration: none;
  transition: border-color .18s ease, box-shadow .18s ease, transform .18s ease;
}
.town:hover,
.town:focus-visible {
  border-color: color-mix(in srgb, var(--jm-accent-dim) 55%, transparent);
  box-shadow: 0 8px 22px var(--jm-shadow);
  transform: translateY(-2px);
  text-decoration: none;
}

.town__pin {
  display: grid;
  place-items: center;
  flex: 0 0 auto;
  width: 32px;
  height: 32px;
  font-size: 15px;
  border-radius: 50%;
  background: color-mix(in srgb, var(--jm-accent) 18%, var(--jm-card));
  color: var(--jm-accent-dim);
}

.town__body { min-width: 0; }
.town__body b {
  display: block;
  font-size: 14.5px;
  font-weight: 700;
  line-height: 1.2;
  letter-spacing: -.01em;
  color: var(--jm-heading);
  /* Doddaballapur is long and the tile is narrow. */
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.town__body i {
  display: block;
  font-style: normal;
  font-size: 11px;
  color: var(--jm-muted);
}

.town__go {
  margin-left: auto;
  font-size: 13px;
  color: var(--jm-accent-dim);
  transition: transform .18s ease;
}
.town:hover .town__go { transform: translateX(3px); }

.towns__note {
  display: flex;
  align-items: flex-start;
  justify-content: center;
  gap: 9px;
  margin: clamp(18px, 2.2vw, 26px) auto 0;
  max-width: 66ch;
  font-size: 13px;
  line-height: 1.6;
  text-align: left;
  color: var(--jm-muted);
}
.towns__note .jm-ico { flex: 0 0 auto; color: var(--jm-accent-dim); transform: translateY(2px); }

@media (max-width: 1100px) { .towns-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
@media (max-width: 760px)  { .towns-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 440px)  { .towns-grid { grid-template-columns: 1fr; } }


/* ==========================================================================
   44. A PHOTOGRAPH BESIDE THE COPY — .pgsplit
   --------------------------------------------------------------------------
   Added 2026-09-07: "all page develop random image". Several pages were a
   banner and two paragraphs — careers, gift cards, partners, franchise.

   It sits INSIDE the ref 02 wide card rather than beside it, so the picture
   is part of the card and not a second block floating next to one.

   `.lcard--text` puts running copy into two columns above 900px. That is
   right for a page of prose and wrong here: the copy is already sharing the
   width with a photograph, and two columns of it would be two very narrow
   ones. This layout has its own children, so the column rule is cancelled.
   ========================================================================== */

@media (min-width: 861px) {
  .pgsplit {
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(0, .58fr);
    align-items: center;
    gap: clamp(24px, 3.4vw, 52px);
  }
}

/* `.lcard p` is (0,1,1); this has to be at least as specific to widen it. */
.lcard.pgsplit p { max-width: 54ch; }

.pgsplit__pic { margin: 0; }
.pgsplit__pic img,
.pgsplit__pic .pgsplit__vid {   /* about.php's reception clip, 2026-09-30 */
  display: block;
  width: 100%;
  height: auto;
  aspect-ratio: 4 / 3;
  object-fit: cover;
  border-radius: var(--jm-r);
  background: var(--jm-card-2);
  box-shadow: 0 10px 30px var(--jm-shadow);
}

@media (max-width: 860px) {
  /* Under the copy, and shorter — a full-height photograph between the text
     and the cards below it just pushes everything off the screen. */
  .pgsplit__pic { margin-top: 20px; }
  .pgsplit__pic img,
  .pgsplit__pic .pgsplit__vid { aspect-ratio: 16 / 9; }
  .lcard.pgsplit p { max-width: none; }
}


/* ==========================================================================
   43. AREA-PAGE PHOTOGRAPHS
   --------------------------------------------------------------------------
   Added 2026-09-07: "to add more image 4 and spa room image … here also add
   extra picture". Four shots in a row, and a room card beside the therapist
   grid when that grid is short.

   The four are `aria-hidden` and carry empty alt text: they are decoration,
   they say nothing the page does not already say in words, and four
   near-identical descriptions of stock massage photographs would be four
   things for a screen reader to wade through on the way to the booking link.
   ========================================================================== */

.ashots {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: clamp(10px, 1.2vw, 16px);
  margin: clamp(16px, 2vw, 24px) 0 0;
  padding: 0;
  list-style: none;
}
/* Pico's `ul li{list-style:square}` is (0,0,2) — clear it on the `li`. */
.ashots li { margin: 0; padding: 0; list-style: none; }

.ashots img {
  display: block;
  width: 100%;
  height: auto;
  aspect-ratio: 4 / 3;
  object-fit: cover;
  border-radius: var(--jm-r);
  background: var(--jm-card-2);
  box-shadow: 0 2px 10px var(--jm-shadow);
  transition: transform .35s cubic-bezier(.2, .7, .3, 1), box-shadow .25s ease;
}
.ashots li:hover img {
  transform: translateY(-4px) scale(1.02);
  box-shadow: 0 16px 36px var(--jm-shadow-2);
}

/* The first shot is the wide one, as a bit of rhythm — otherwise four equal
   rectangles read as a contact sheet.

   >>> BUT THE ROW HAS TO STAY FLUSH ALONG THE BOTTOM. Giving column one
       1.4fr AND a 5/4 ratio made it ~100px taller than its neighbours, which
       then floated at the top of their cells with dead space underneath —
       the row looked unfinished rather than rhythmic.

       So the first image sets the row height (its own ratio, height auto)
       and the other three FILL it: `height: 100%` with `aspect-ratio: auto`,
       and `object-fit: cover` already on the base rule does the cropping.
       The `li` needs `display: grid` for a percentage height to resolve
       against it.                                                       <<< */
@media (min-width: 861px) {
  .ashots { grid-template-columns: 1.4fr 1fr 1fr 1fr; align-items: stretch; }
  .ashots li { display: grid; }
  .ashots li img { height: 100%; aspect-ratio: auto; }
  .ashots li:first-child img { height: auto; aspect-ratio: 5 / 4; }
}
@media (max-width: 860px) { .ashots { grid-template-columns: repeat(2, minmax(0, 1fr)); } }

/* --- the room card beside a short therapist grid -------------------------- */

/* >>> REBUILT 2026-09-07. The previous version gave `.models-grid` a single
       `minmax(0, 1fr)` column inside a `1fr` parent column, so with the one
       therapist an area actually has, ONE PROFILE CARD FILLED ~900px OF A
       1400px PAGE and its portrait came out taller than the viewport. It was
       fixing the opposite problem — a card marooned at a quarter width — and
       overshot.

       A profile card has a right size, and it is the size it is on the
       homepage. So the columns are CAPPED at 320px and the row is centred
       under its own centred heading, which makes one or two cards beside the
       room card read as deliberate rather than as a grid that failed.

       `auto` on the first column, so it measures the cards it holds rather
       than claiming the whole row. A card cannot know how many siblings it
       has, so the count arrives from PHP as .awho--n1 / .awho--n2 — see the
       note in includes/area-page.php.                                   <<< */
.awho--sparse {
  display: grid;
  grid-template-columns: auto minmax(0, 320px);
  justify-content: center;
  align-items: start;
  gap: clamp(18px, 2.4vw, 32px);
}
.awho--n1 .models-grid { grid-template-columns: minmax(0, 320px); }
.awho--n2 .models-grid { grid-template-columns: repeat(2, minmax(0, 320px)); }

/* `figure`, not `article`: Pico gives `article` a box at (0,0,1). */
.awho__room {
  margin: 0;
  overflow: hidden;
  border: 1px solid var(--jm-line);
  border-radius: var(--jm-r);
  background: var(--jm-card);
  box-shadow: 0 1px 2px var(--jm-shadow);
}
.awho__room img {
  display: block;
  width: 100%;
  height: auto;
  aspect-ratio: 4 / 3;
  object-fit: cover;
  background: var(--jm-card-2);
}
/* (0,1,1) — clears Pico's `figure figcaption` (0,0,2). */
.awho__room figcaption { padding: 14px 16px 16px; text-align: left; }
.awho__room b {
  display: block;
  margin-bottom: 5px;
  font-size: 15px;
  font-weight: 700;
  color: var(--jm-heading);
}
.awho__room span {
  display: block;
  font-size: 13px;
  line-height: 1.55;
  color: var(--jm-muted);
}

@media (max-width: 900px) {
  /* Stacked. `justify-items` rather than `justify-content`, or a 320px card
     in a 1fr column sits hard left with the room card under it — the two are
     the same block and must share an edge. */
  .awho--sparse { grid-template-columns: minmax(0, 1fr); justify-items: center; }
  .awho--sparse .models-grid,
  .awho--n1 .models-grid,
  .awho--n2 .models-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); width: 100%; }
  .awho__room { max-width: 420px; width: 100%; }
}
@media (max-width: 620px) {
  .awho--sparse .models-grid,
  .awho--n1 .models-grid,
  .awho--n2 .models-grid { grid-template-columns: minmax(0, 1fr); }
}


/* ==========================================================================
   42. THE THERAPIST PICKER — account/index.php only
   --------------------------------------------------------------------------
   Photo cards that are real radio buttons. Added 2026-09-07 on the client's
   note; `$jm_bf_pick` switches it on and it is true only on the account page,
   so the booking form is still six fields everywhere else.

   >>> TWO PICO TRAPS IN FOUR LINES OF MARKUP, both already in §5:

       `label:has([type=checkbox],[type=radio]) { width: fit-content }` is
       (0,1,1) — `:has()` takes the specificity of its most specific argument.
       Every card here is a label wrapping a radio, so without an override
       they all shrink-wrap to their own text and the grid collapses.

       And a bare `.bpick__card` would be (0,1,0), which LOSES. It has to be
       written one class deeper.

   The radio itself is moved off-screen rather than `display:none` —
   `display:none` takes it out of the tab order and off the accessibility
   tree, which would leave a picker no keyboard could reach.
   ========================================================================== */

.bpick {
  margin: 0 0 clamp(20px, 2.4vw, 28px);
  padding: 0;
  border: 0;
}

.bpick__lbl {
  padding: 0;
  margin-bottom: 12px;
  font-size: 11px;
  font-weight: 800;
  letter-spacing: .16em;
  text-transform: uppercase;
  color: var(--jm-accent-dim);
}

.bpick__grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(132px, 1fr));
  gap: 12px;
  margin: 0;
  padding: 0;
  list-style: none;
}
/* Pico's `ul li{list-style:square}` is (0,0,2) — clear it on the `li`. */
.bpick__grid > li { margin: 0; padding: 0; list-style: none; }

/* (0,2,0): beats Pico's `label:has([type=radio])` width rule — see above. */
.bpick .bpick__card {
  position: relative;
  display: block;
  width: auto;
  margin: 0;
  overflow: hidden;
  border: 2px solid var(--jm-line);
  border-radius: var(--jm-r);
  background: var(--jm-card);
  cursor: pointer;
  transition: border-color .18s ease, box-shadow .18s ease, transform .18s ease;
}

/* Off-screen, not display:none — a hidden radio must still be focusable. */
.bpick__card input[type="radio"] {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

.bpick__card img {
  display: block;
  width: 100%;
  height: auto;
  aspect-ratio: 4 / 5;
  object-fit: cover;
  background: var(--jm-card-2);
}

.bpick__body { display: block; padding: 10px 12px 12px; }
.bpick__body b {
  display: block;
  font-size: 14px;
  font-weight: 700;
  line-height: 1.2;
  color: var(--jm-heading);
}
.bpick__body i {
  display: block;
  margin-top: 2px;
  font-style: normal;
  font-size: 11.5px;
  line-height: 1.35;
  color: var(--jm-muted);
}

/* "No preference" has no photograph, so it needs its own height or it sits
   half as tall as everything beside it. */
.bpick .bpick__card--any {
  display: grid;
  place-items: center;
  min-height: 180px;
  text-align: center;
  background: color-mix(in srgb, var(--jm-accent) 8%, var(--jm-card));
}

/* The chosen state. `:has(:checked)` on the label is what makes this work
   without a script; the tick is hidden until then. */
.bpick__tick {
  position: absolute;
  top: 8px;
  right: 8px;
  display: grid;
  place-items: center;
  width: 26px;
  height: 26px;
  font-size: 13px;
  border-radius: 50%;
  background: var(--jm-accent);
  color: var(--jm-on-accent);
  opacity: 0;
  transform: scale(.6);
  transition: opacity .18s ease, transform .18s ease;
}
.bpick .bpick__card:has(:checked) {
  border-color: var(--jm-accent);
  box-shadow: 0 10px 26px var(--jm-shadow-2);
}
.bpick .bpick__card:has(:checked) .bpick__tick { opacity: 1; transform: none; }

/* The keyboard has to see the focus, and the radio itself is off-screen —
   so the ring goes on the card. */
.bpick .bpick__card:has(:focus-visible) {
  outline: 3px solid var(--jm-accent);
  outline-offset: 2px;
}
.bpick .bpick__card:hover { transform: translateY(-2px); border-color: var(--jm-accent-dim); }

.bpick__note {
  margin: 12px 0 0;
  font-size: 12.5px;
  color: var(--jm-muted);
}

/* The form on the account page is a plain card in the page flow, not the
   centred 940px block book.php uses. */
.acct-book { margin-bottom: clamp(26px, 3.4vw, 40px); }
.acct-book .bcard { max-width: none; margin: 0; }


/* ==========================================================================
   41. SITE SEARCH — search.php
   --------------------------------------------------------------------------
   The masthead has carried a search box since the site was started and it
   pointed at a file that did not exist: it 404'd on every page. Built
   2026-09-07.

   A GET form and a server-rendered list. No JavaScript, no index, and every
   result set has its own URL.
   ========================================================================== */

.srch__title {
  margin: 0 0 clamp(18px, 2.2vw, 26px);
  font-size: clamp(24px, 3vw, 38px);
  font-weight: 800;
  line-height: 1.15;
  letter-spacing: -.024em;
  color: var(--jm-heading);
}

.srch__form {
  display: flex;
  gap: 10px;
  margin: 0 0 clamp(20px, 2.6vw, 30px);
  max-width: 640px;
}
/* Pico sizes `input` and the `button[type=submit]` branch to 100% — (0,0,1)
   and (0,1,1). In a flex row that makes each fill the row in turn. The same
   trap as `button.near-go` in §15; the button needs the deeper selector. */
.srch__form input[type="search"] { flex: 1 1 auto; margin: 0; }
.srch__form .btn-solid { flex: 0 0 auto; }

.srch__hint,
.srch__lbl {
  margin: 0 0 14px;
  max-width: 62ch;
  font-size: 15px;
  line-height: 1.6;
  color: var(--jm-muted);
}
.srch__lbl {
  margin-top: clamp(20px, 2.4vw, 28px);
  font-size: 11px;
  font-weight: 800;
  letter-spacing: .16em;
  text-transform: uppercase;
  color: var(--jm-accent-dim);
}

/* The seed pills reuse §31's `.quick-row` / `.qpill`, but that row lives in a
   marquee and wraps nowhere. Here it has to wrap. */
.srch__seed { flex-wrap: wrap; justify-content: flex-start; }
.srch__seed li { margin: 0 10px 10px 0; }

.srch__group {
  display: flex;
  align-items: center;
  gap: 10px;
  margin: clamp(26px, 3vw, 36px) 0 12px;
  font-size: 12px;
  font-weight: 800;
  letter-spacing: .16em;
  text-transform: uppercase;
  color: var(--jm-accent-dim);
}
.srch__group span {
  display: grid;
  place-items: center;
  min-width: 22px;
  height: 22px;
  padding-inline: 6px;
  border-radius: var(--jm-pill);
  background: color-mix(in srgb, var(--jm-accent) 20%, var(--jm-card));
  font-size: 11px;
  color: var(--jm-accent-dim);
}

.sres { display: grid; gap: 8px; margin: 0; padding: 0; list-style: none; }
/* Pico's `ul li{list-style:square}` is (0,0,2) — clear it on the `li`. */
.sres li { margin: 0; padding: 0; list-style: none; }

.sres a {
  display: block;
  padding: 15px 18px;
  border: 1px solid var(--jm-line);
  border-radius: var(--jm-r);
  background: var(--jm-card);
  box-shadow: 0 1px 2px var(--jm-shadow);
  text-decoration: none;
  transition: border-color .16s ease, box-shadow .16s ease, transform .16s ease;
}
.sres a:hover,
.sres a:focus-visible {
  border-color: var(--jm-accent-dim);
  box-shadow: 0 10px 26px var(--jm-shadow);
  transform: translateY(-2px);
  text-decoration: none;
}
.sres b {
  font-size: 16px;
  font-weight: 700;
  letter-spacing: -.012em;
  color: var(--jm-heading);
}
.sres i {
  margin-left: 9px;
  font-style: normal;
  font-size: 11px;
  font-weight: 800;
  letter-spacing: .06em;
  text-transform: uppercase;
  color: var(--jm-accent-dim);
}
.sres span {
  display: block;
  margin-top: 4px;
  font-size: 14px;
  line-height: 1.55;
  color: var(--jm-muted);
}

@media (max-width: 520px) {
  .srch__form { flex-direction: column; }
  .srch__form .btn-solid { justify-content: center; }
}


/* ==========================================================================
   40. THE LEGAL DOCUMENTS — terms, privacy, refund, disclaimer
   --------------------------------------------------------------------------
   A numbered document inside the ref 02 wide card. Numbered because a legal
   page gets quoted back at you, and "clause 4" is easier to point at than
   "the bit about prices".

   The single-column override matters: `.lcard--text` puts running copy into
   two columns above 900px, which is right for a page of prose and wrong for a
   numbered list nobody wants to read up one side and down the other.
   ========================================================================== */

.doc .lcard__cols { columns: 1; }

.doc__meta {
  margin: 0 0 18px;
  font-size: 11.5px;
  font-weight: 800;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--jm-accent-dim);
}

/* `.lcard p` is (0,1,1), so these have to be at least that. */
.doc .doc__intro {
  margin: 0 0 clamp(24px, 3vw, 34px);
  max-width: 74ch;
  font-size: 16px;
  line-height: 1.7;
  color: var(--jm-body);
}

.doc__list {
  margin: 0;
  padding: 0;
  list-style: none;
  counter-reset: doc;
}
.doc__list > li {
  position: relative;
  margin: 0 0 clamp(22px, 2.6vw, 32px);
  padding-left: 46px;
  list-style: none;
}
.doc__list > li::before {
  counter-increment: doc;
  content: counter(doc);
  position: absolute;
  top: 0;
  left: 0;
  display: grid;
  place-items: center;
  width: 32px;
  height: 32px;
  border-radius: 50%;
  background: color-mix(in srgb, var(--jm-accent) 20%, var(--jm-card));
  font-size: 13px;
  font-weight: 800;
  color: var(--jm-accent-dim);
}

/* (0,2,1) — `.lcard :is(h2,h3)` is (0,1,1) and sets a flex row for the icon
   heading, which is wrong for a clause title. */
.doc .doc__list h3 {
  display: block;
  margin: 4px 0 8px;
  font-size: clamp(17px, 1.7vw, 20px);
  font-weight: 800;
  letter-spacing: -.014em;
  line-height: 1.3;
  color: var(--jm-heading);
}
.doc .doc__list p {
  margin: 0 0 10px;
  max-width: 74ch;
  font-size: 15px;
  line-height: 1.7;
  color: var(--jm-muted);
}

/* A clause the client still has to write. Deliberately loud — a visitor must
   never read a placeholder as though it were policy, and whoever is doing the
   legal review needs to find these in one glance. It uses the form-error
   colours, which are the only ones on the site that never take the brand's
   accent. */
.doc .doc__todo {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  margin: 0 0 12px;
  padding: 12px 15px;
  border: 1px dashed color-mix(in srgb, var(--jm-warn-dim) 45%, transparent);
  border-radius: var(--jm-r-sm);
  background: color-mix(in srgb, var(--jm-warn-dim) 7%, #FFFFFF);
  color: var(--jm-warn-dim);
  font-size: 14px;
}
.doc__todo .jm-ico { flex: 0 0 auto; transform: translateY(2px); }

.doc__points { margin: 10px 0 0; padding: 0; list-style: none; }
.doc__points li {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  margin: 0 0 8px;
  padding: 0;
  list-style: none;
  font-size: 14.5px;
  line-height: 1.6;
  color: var(--jm-body);
}
.doc__points .jm-ico {
  flex: 0 0 auto;
  font-size: 13px;
  color: var(--jm-accent-dim);
  transform: translateY(3px);
}

.doc .doc__foot {
  margin: clamp(24px, 3vw, 34px) 0 0;
  padding-top: 18px;
  border-top: 1px solid var(--jm-line);
  font-size: 14px;
  color: var(--jm-muted);
}


/* ==========================================================================
   39. THE SIGN-UP PAGE           ref 37 — board "page 5 home page"
   --------------------------------------------------------------------------
   Form on the left, a dark panel on the right saying what the account is for.
   The reference's right panel sells a free-token draw; ours says what this
   account actually does — see the note above $SIGNUP in config.php for the
   three things in that screenshot that are deliberately absent.
   ========================================================================== */

.signup {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, .82fr);
  align-items: stretch;
  gap: clamp(18px, 2.4vw, 30px);
  width: 100%;
  max-width: 1020px;
  margin-inline: auto;
}

/* `.authcard` centres itself and caps at 560px, which is right when it is
   alone and wrong inside this grid. (0,2,0) beats it. */
.signup .authcard { max-width: none; margin: 0; }

.signup__why {
  display: flex;
  flex-direction: column;
  padding: clamp(24px, 3vw, 34px);
  border-radius: var(--jm-r-lg);
  background:
    radial-gradient(90% 70% at 100% 0%,
      color-mix(in srgb, var(--jm-accent) 30%, transparent) 0%, transparent 62%),
    linear-gradient(160deg, var(--jm-ink-soft), var(--jm-ink));
  box-shadow: 0 14px 40px var(--jm-shadow-2);
  color: var(--jm-on-ink);
}

.signup__eyebrow {
  margin: 0 0 12px;
  font-size: 11px;
  font-weight: 800;
  letter-spacing: .18em;
  text-transform: uppercase;
  color: var(--jm-accent);
}

/* A <p>, not a heading: the page already has one h1 and this panel is an
   aside, so promoting it would put a second top-level heading on the page.

   Which means it needs its colour STATED. `.signup__why` sets
   `color: var(--jm-on-ink)` and everything in it inherits that — except a
   `<p>`, because Pico's own `p` rule sets `color` explicitly at (0,0,1), and
   an explicit declaration beats an inherited value however specific the
   ancestor was. Without this line the heading rendered near-black on
   near-black and only the accent half of it was readable. Any paragraph
   dropped onto a dark panel on this site has the same problem. */
.signup__title {
  margin: 0 0 22px;
  font-size: clamp(21px, 2.2vw, 28px);
  font-weight: 800;
  line-height: 1.15;
  letter-spacing: -.022em;
  color: var(--jm-on-ink);
}
.signup__title em { font-style: normal; color: var(--jm-accent); }

.signup__rows { display: grid; gap: 14px; margin: 0 0 24px; padding: 0; list-style: none; }
/* Pico's `ul li{list-style:square}` is (0,0,2) — clear it on the `li`. */
.signup__rows li {
  display: flex;
  align-items: flex-start;
  gap: 12px;
  margin: 0;
  padding: 0;
  list-style: none;
  font-size: 14px;
  line-height: 1.5;
  color: var(--jm-nav);
}
.signup__ico {
  display: grid;
  place-items: center;
  flex: 0 0 auto;
  width: 34px;
  height: 34px;
  font-size: 16px;
  border-radius: var(--jm-r-sm);
  background: color-mix(in srgb, var(--jm-accent) 20%, transparent);
  color: var(--jm-accent);
}

.signup__skip {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 9px;
  /* margin-top:auto pins it to the foot however long the list gets. */
  margin-top: auto;
  padding: 13px 22px;
  border: 1px solid var(--jm-ink-line-2);
  border-radius: var(--jm-pill);
  font-size: 12px;
  font-weight: 800;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--jm-on-ink);
  text-decoration: none;
  transition: border-color .18s ease, color .18s ease;
}
.signup__skip:hover,
.signup__skip:focus-visible {
  border-color: var(--jm-accent);
  color: var(--jm-accent);
  text-decoration: none;
}

.signup__foot {
  display: flex;
  align-items: center;
  gap: 8px;
  margin: 14px 0 0;
  font-size: 12px;
  line-height: 1.45;
  color: var(--jm-nav-dim);
}
.signup__foot .jm-ico { flex: 0 0 auto; color: var(--jm-accent); }

@media (max-width: 860px) {
  .signup { grid-template-columns: 1fr; }
  /* The form first: somebody who clicked "Sign up" has already been sold. */
  .signup__why { order: 1; }
}


/* ==========================================================================
   38. AT HOME OR IN STUDIO       ref 23 — board "start design home page 1"
   --------------------------------------------------------------------------
   Light two-column block: a heavy heading and two large contrasting pills on
   the left, a phone card on the right, soft circular shapes behind both.

   The reference's pills ask the visitor's gender. Here they ask the one thing
   a massage customer has to decide first — see the note above $PLACE.

   The two circles are the reference's own background shapes, drawn as
   radial-gradients on the section rather than as elements, so they cost
   nothing and cannot be tabbed to or read out.
   ========================================================================== */

.place {
  padding-block: clamp(44px, 6vw, 86px);
  background:
    radial-gradient(38% 52% at 88% 6%,
      color-mix(in srgb, var(--jm-accent) 16%, transparent) 0%, transparent 70%),
    radial-gradient(30% 40% at 4% 96%,
      color-mix(in srgb, var(--jm-accent) 11%, transparent) 0%, transparent 70%),
    var(--jm-card);
}

.place__grid {
  display: grid;
  grid-template-columns: minmax(0, 1.08fr) minmax(0, .72fr);
  align-items: center;
  gap: clamp(30px, 4.5vw, 72px);
}

/* (0,1,0) and stated: Pico's h2 is (0,0,1). */
.place__title {
  margin: 0 0 16px;
  font-size: clamp(30px, 4.2vw, 54px);
  font-weight: 800;
  line-height: 1.05;
  letter-spacing: -.03em;
  color: var(--jm-heading);
}
.place__title em { font-style: normal; color: var(--jm-accent-dim); }

.place__lede {
  margin: 0 0 clamp(24px, 3vw, 34px);
  max-width: 48ch;
  font-size: 15.5px;
  line-height: 1.62;
  color: var(--jm-muted);
}

/* --- the two answers ------------------------------------------------------ */

.place__opts {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 14px;
}

.place-opt {
  display: flex;
  align-items: center;
  gap: 13px;
  padding: 18px 22px;
  border-radius: var(--jm-r-lg);
  text-decoration: none;
  transition: transform .2s ease, box-shadow .2s ease;
}
.place-opt:hover,
.place-opt:focus-visible {
  transform: translateY(-3px);
  box-shadow: 0 16px 38px var(--jm-shadow-2);
  text-decoration: none;
}
.place-opt b { display: block; font-size: 16.5px; font-weight: 800; line-height: 1.2; }
.place-opt i {
  display: block;
  margin-top: 3px;
  font-style: normal;
  font-size: 12.5px;
  line-height: 1.4;
}
.place-opt__ico {
  display: grid;
  place-items: center;
  flex: 0 0 auto;
  width: 44px;
  height: 44px;
  font-size: 20px;
  border-radius: 50%;
}

/* The reference's two pills are two different colours. Two hues would be two
   hardcoded values, so these are the two the brand already owns: the accent
   fill and the ink fill. They are as distinct from each other as the
   reference's blue and pink, and they follow the theme. */
.place-opt--1 { background: var(--jm-accent); color: var(--jm-on-accent); }
.place-opt--1 .place-opt__ico { background: color-mix(in srgb, var(--jm-ink) 16%, transparent); }
.place-opt--1 i { color: color-mix(in srgb, var(--jm-on-accent) 72%, transparent); }
.place-opt--1:hover, .place-opt--1:focus-visible { background: var(--jm-accent-lit); color: var(--jm-on-accent); }

.place-opt--2 { background: var(--jm-ink); color: var(--jm-on-ink); }
.place-opt--2 .place-opt__ico { background: color-mix(in srgb, var(--jm-accent) 24%, transparent); color: var(--jm-accent); }
.place-opt--2 i { color: var(--jm-nav); }
.place-opt--2:hover, .place-opt--2:focus-visible { background: var(--jm-ink-soft); color: var(--jm-on-ink); }

/* --- the phone card ------------------------------------------------------- */

.place__art { display: grid; place-items: center; }

.place-ph {
  width: min(320px, 82vw);
  overflow: hidden;
  border-radius: 30px;
  background: var(--jm-card);
  box-shadow: 0 28px 64px var(--jm-shadow-2);
}
/* The class is not tied to a tag, so it dresses the <img> and — when
   $PLACE['video'] is filled in — the <video> that replaces it, identically.
   `object-fit: cover` crops either to the phone's slot.

   >>> THE SLOT IS SQUARE, NOT 4/5, AND THAT IS A CROPPING DECISION.
       2026-09-12: the client said the images were cropped too hard. They are
       right, and it is arithmetic rather than opinion — every file in
       assets/img/service-lg/ is 1200x900, a 4:3 LANDSCAPE, and `cover` keeps
       only as much width as the slot's ratio allows:

           4/5 slot  ->  keeps 60% of the photograph's width
           1/1 slot  ->  keeps 75%

       Squaring the slot hands back a quarter of what was being thrown away,
       costs 80px of mockup height, and changes nothing else.

       THE REMAINING 25% IS INHERENT TO A LANDSCAPE SOURCE IN A TALL CARD and
       cannot be fixed in CSS. Two things would fix it properly, and both need
       the client: portrait photography for the twelve treatments, or pointing
       this slot at the gallery set (560x750, near enough 4:5 to lose almost
       nothing) — which was NOT done here, because the bar underneath names
       the treatment and a gallery room shot is not that treatment.      <<< */
.place-ph__hero {
  display: block;
  width: 100%;
  height: auto;
  aspect-ratio: 1 / 1;
  object-fit: cover;
  background: var(--jm-card-2);
}
/* Decorative: the mockup is aria-hidden and must not behave like a player,
   so the video takes no clicks and no right-click menu of its own. */
.place-ph__hero:is(video) { pointer-events: none; }

.place-ph__bar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  padding: 13px 16px 11px;
}
.place-ph__bar b {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: 15.5px;
  font-weight: 700;
  color: var(--jm-heading);
}
.place-ph__bar .jm-ico { font-size: 15px; color: var(--jm-accent-dim); }
.place-ph__bar i {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-style: normal;
  font-size: 11.5px;
  color: var(--jm-muted);
}
/* The reference's "online" dot, in the accent rather than a hardcoded green. */
.place-ph__bar i::before {
  content: '';
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--jm-accent-dim);
}

.place-ph__h {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin: 0;
  padding: 8px 16px;
  border-top: 1px solid var(--jm-line);
  font-size: 13px;
  font-weight: 700;
  color: var(--jm-heading);
}
.place-ph__h span { font-size: 12px; font-weight: 800; color: var(--jm-accent-dim); }

.place-ph__grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 8px;
  padding: 4px 16px 16px;
}
.place-ph__grid img {
  display: block;
  width: 100%;
  height: auto;
  aspect-ratio: 1;
  object-fit: cover;
  border-radius: var(--jm-r-sm);
  background: var(--jm-card-2);
}

@media (max-width: 980px) {
  .place__grid { grid-template-columns: 1fr; }
  .place__lede { max-width: none; }
}
@media (max-width: 560px) {
  /* Two 150px pills with an icon, a title and a note in each is not a
     choice, it is a puzzle. */
  .place__opts { grid-template-columns: 1fr; }
}


/* ==========================================================================
   37. THE DISCLAIMER ROW — legal text beside an assurance card
   --------------------------------------------------------------------------
   Added 2026-09-06: *"Disclaimer. right side add littel more atrative
   design"*. The disclaimer had run the full width as one block of small grey
   text, which is the last thing on every page and read like the bottom of a
   receipt.

   The card beside it carries the entry warning's OWN seal and OWN three
   chips, from $GATE — so the first thing a visitor reads on their first visit
   and the last thing they read on every page after say the same three things
   in the same words. No new copy was written for it.
   ========================================================================== */

.legal-row {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  align-items: start;
  gap: clamp(24px, 4vw, 56px);
  margin-bottom: clamp(20px, 2.4vw, 28px);
}

/* `.footer-legal .disclaimer` (0,2,0) already sets the margin and the 90ch
   measure. Inside the grid the column does the constraining, and the bottom
   margin belongs to the row. */
.legal-row .disclaimer { margin: 0; max-width: 78ch; }

.assure {
  position: relative;
  width: min(280px, 100%);
  padding: 30px 22px 20px;
  border: 1px solid var(--jm-line);
  border-radius: var(--jm-r);
  background: var(--jm-card);
  box-shadow: 0 8px 26px var(--jm-shadow);
  text-align: center;
}

/* The seal breaks the top edge, exactly as it does on the entry warning. */
.assure__seal {
  position: absolute;
  top: -19px;
  left: 50%;
  transform: translateX(-50%);
  display: grid;
  place-items: center;
  width: 38px;
  height: 38px;
  border: 2px solid var(--jm-accent);
  border-radius: 50%;
  background: var(--jm-ink);
  font-family: var(--jm-display);
  font-size: 15px;
  letter-spacing: .02em;
  color: var(--jm-accent);
}

.assure__mark {
  display: block;
  margin-bottom: 14px;
  font-family: var(--jm-display);
  font-size: 19px;
  font-weight: 400;
  letter-spacing: .01em;
  text-transform: uppercase;
  color: var(--jm-heading);
}
.assure__mark em { font-style: normal; color: var(--jm-accent-dim); }

.assure__list { display: grid; gap: 8px; margin: 0; padding: 0; list-style: none; }
/* Pico's `ul li{list-style:square}` is (0,0,2) — clear it on the `li`. */
.assure__list li {
  display: flex;
  align-items: center;
  gap: 9px;
  margin: 0;
  padding: 8px 12px;
  list-style: none;
  border-radius: var(--jm-pill);
  background: color-mix(in srgb, var(--jm-accent) 12%, var(--jm-card));
  font-size: 12px;
  font-weight: 700;
  text-align: left;
  color: var(--jm-heading);
}
.assure__list .jm-ico { flex: 0 0 auto; font-size: 14px; color: var(--jm-accent-dim); }

@media (max-width: 860px) {
  .legal-row { grid-template-columns: 1fr; }
  .legal-row .disclaimer { max-width: none; }
  /* Centred rather than stranded against the left edge once it is alone. */
  .assure { width: min(320px, 100%); margin-inline: auto; }
}


/* ==========================================================================
   36. THE ACCOUNT BUTTONS — masthead and footer
   --------------------------------------------------------------------------
   Added 2026-09-06: *"header and footer below add login and sign in up
   button"*. The accounts had existed for a few hours and nothing on the site
   linked to them.

   >>> THE POINT OF THIS BLOCK IS HIERARCHY, NOT DECORATION. The masthead
       already carried a search, CALL NOW and BOOK NOW. Dropping two more
       equal-weight buttons beside them gives five, which is not a header any
       more. So the account pair is smaller, quieter and separated by a
       hairline: BOOK NOW (filled accent) reads first, CALL NOW (outlined)
       second, the account group third. The client asked for the design to
       stay balanced and this is what that meant in practice.           <<<

   Below 1320px the group leaves the bar entirely — five controls stop fitting
   beside the wordmark and the nav well before the burger appears at 1180.
   Everything in it is repeated inside the burger panel, so nothing is ever
   unreachable at any width.
   ========================================================================== */

.acct {
  display: inline-flex;
  align-items: center;
  gap: 12px;
  padding-right: 14px;
  margin-right: 2px;
  /* The hairline that separates "who you are" from "what you want to do". */
  border-right: 1px solid var(--jm-ink-line-2);
}

.acct__in {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  font-size: 12.5px;
  font-weight: 700;
  letter-spacing: .02em;
  color: var(--jm-nav);
  text-decoration: none;
  white-space: nowrap;
  transition: color .18s ease;
}
.acct__in:hover,
.acct__in:focus-visible { color: var(--jm-on-ink); text-decoration: none; }
.acct__in .jm-ico { font-size: 15px; color: var(--jm-accent); }

/* The sign-up is a pill, but a LIGHT one — an accent tint rather than an
   accent fill, so it cannot compete with BOOK NOW two controls along. */
.acct__up {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  padding: 9px 17px;
  border: 1px solid color-mix(in srgb, var(--jm-accent) 45%, transparent);
  border-radius: var(--jm-pill);
  background: color-mix(in srgb, var(--jm-accent) 15%, transparent);
  font-size: 12px;
  font-weight: 800;
  letter-spacing: .06em;
  color: var(--jm-accent);
  text-decoration: none;
  white-space: nowrap;
  transition: background-color .18s ease, border-color .18s ease, color .18s ease;
}
.acct__up:hover,
.acct__up:focus-visible {
  background: var(--jm-accent);
  border-color: var(--jm-accent);
  color: var(--jm-on-accent);
  text-decoration: none;
}
.acct__up .jm-ico { font-size: 15px; }

/* Signed in, the group is one control, so it needs no divider beside it. */
.acct:has(.acct__up--in) { border-right: 0; padding-right: 0; }

@media (max-width: 1320px) {
  /* Out of the bar; the burger panel carries the same links. */
  .acct { display: none; }
}


/* --- the footer bar ------------------------------------------------------- */

.facct {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 18px 24px;
  margin-top: clamp(8px, 1.4vw, 18px);
  padding: clamp(18px, 2.2vw, 26px) clamp(20px, 2.4vw, 30px);
  border: 1px solid var(--jm-line);
  border-radius: var(--jm-r);
  background: var(--jm-card);
  box-shadow: 0 1px 2px var(--jm-shadow);
}

.facct__copy b {
  display: block;
  margin-bottom: 3px;
  font-size: 16px;
  font-weight: 800;
  letter-spacing: -.012em;
  color: var(--jm-heading);
}
.facct__copy span {
  display: block;
  max-width: 62ch;
  font-size: 13.5px;
  line-height: 1.55;
  color: var(--jm-muted);
}

.facct__go { display: flex; flex-wrap: wrap; align-items: center; gap: 10px; }

.facct__in {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 12px 20px;
  border: 1px solid var(--jm-line);
  border-radius: var(--jm-pill);
  background: var(--jm-card);
  font-size: 12.5px;
  font-weight: 800;
  letter-spacing: .08em;
  color: var(--jm-heading);
  text-decoration: none;
  white-space: nowrap;
}
.facct__in:hover,
.facct__in:focus-visible {
  border-color: var(--jm-accent-dim);
  color: var(--jm-heading);
  text-decoration: none;
}
.facct__in .jm-ico { color: var(--jm-accent-dim); }

/* Filled here, where nothing else competes with it. */
.facct__up {
  display: inline-flex;
  align-items: center;
  gap: 9px;
  padding: 12px 24px;
  border-radius: var(--jm-pill);
  background: var(--jm-accent);
  color: var(--jm-on-accent);
  font-size: 12.5px;
  font-weight: 800;
  letter-spacing: .08em;
  text-decoration: none;
  white-space: nowrap;
  transition: background-color .18s ease;
}
.facct__up:hover,
.facct__up:focus-visible {
  background: var(--jm-accent-lit);
  color: var(--jm-on-accent);
  text-decoration: none;
}
.facct__up .jm-ico { transition: transform .18s ease; }
.facct__up:hover .jm-ico { transform: translateX(3px); }

@media (max-width: 620px) {
  .facct { flex-direction: column; align-items: stretch; }
  .facct__go { display: grid; grid-template-columns: 1fr; }
  .facct__in, .facct__up { justify-content: center; }
}


/* ==========================================================================
   35. THE TREATMENT CARDS on services.php
   --------------------------------------------------------------------------
   Rebuilt 2026-09-06: *"Swedish Massage section all to design very attractive
   animation user userable and readable"*. They were plain bordered text cards
   from ref 02; they are now photo-led, numbered, and animated.

   >>> EVERY ANIMATION HERE IS CSS. The site loads no JavaScript and this did
       not change that. The entrance is a SCROLL-DRIVEN animation
       (`animation-timeline: view()`), which Chromium has and Firefox and
       Safari do not — so the whole reveal sits inside `@supports`. In a
       browser without it the rule never applies and the cards are simply
       visible, which is the correct fallback and not a degraded one.

       That guard is not optional. `animation-fill-mode: both` on an animation
       whose timeline never advances leaves the element stuck on its FIRST
       keyframe — opacity 0. Without the @supports, every card on this page
       would be invisible in Firefox.                                    <<<

   READABILITY, since that was half the request: the body copy is 15.5px on a
   1.65 line height with a ~46ch measure, the heading carries its own number
   at a third of its weight, and the ticks are a real list rather than a
   paragraph of commas.
   ========================================================================== */

.svgrid {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: clamp(16px, 2vw, 28px);
  margin: 0;
  padding: 0;
  list-style: none;
}
/* Pico's `ul li{list-style:square}` is (0,0,2) — clear it on the `li`. */
.svgrid > li { margin: 0; padding: 0; list-style: none; }

/* Pico gives `article` a background, shadow, padding and margin at (0,0,1).
   All four are restated here rather than avoided, because this card wants a
   box — it just wants its own. */
.svcard {
  display: flex;
  flex-direction: column;
  height: 100%;
  margin: 0;
  padding: 0;
  overflow: hidden;
  border: 1px solid var(--jm-line);
  border-radius: var(--jm-r);
  background: var(--jm-card);
  box-shadow: 0 1px 2px var(--jm-shadow);
  transition: border-color .22s ease, box-shadow .22s ease, transform .22s ease;
}
.svcard:hover,
.svcard:focus-within {
  border-color: color-mix(in srgb, var(--jm-accent-dim) 55%, transparent);
  box-shadow: 0 18px 42px var(--jm-shadow-2);
  transform: translateY(-4px);
}

/* --- the photograph ------------------------------------------------------- */

.svcard__shot { position: relative; overflow: hidden; }
.svcard__shot img {
  display: block;
  width: 100%;
  height: auto;
  aspect-ratio: 16 / 10;
  object-fit: cover;
  background: var(--jm-card-2);
  transition: transform .5s cubic-bezier(.2, .7, .3, 1);
}
/* focus-within too, so the same thing happens when the card is tabbed to. */
.svcard:hover .svcard__shot img,
.svcard:focus-within .svcard__shot img { transform: scale(1.06); }

.svcard__mins {
  position: absolute;
  right: 12px;
  bottom: 12px;
  display: inline-flex;
  align-items: center;
  gap: 7px;
  padding: 7px 13px;
  border-radius: var(--jm-pill);
  background: color-mix(in srgb, var(--jm-card) 92%, transparent);
  -webkit-backdrop-filter: blur(6px);
  backdrop-filter: blur(6px);
  font-size: 11.5px;
  font-weight: 800;
  letter-spacing: .04em;
  color: var(--jm-heading);
  white-space: nowrap;
}
.svcard__mins .jm-ico { font-size: 13px; color: var(--jm-accent-dim); }

/* --- the body ------------------------------------------------------------- */

.svcard__body {
  display: flex;
  flex-direction: column;
  flex: 1 1 auto;
  padding: clamp(18px, 2vw, 24px);
}

/* (0,1,0) — clears Pico's h3 (0,0,1) and its `:is(p,ul,…)~:is(h1,…,h6)`
   sibling margin (0,0,2). */
.svcard__name {
  display: flex;
  align-items: baseline;
  gap: 11px;
  margin: 0 0 10px;
  font-size: clamp(19px, 1.8vw, 23px);
  font-weight: 800;
  letter-spacing: -.018em;
  line-height: 1.2;
  color: var(--jm-heading);
}
.svcard__name span {
  flex: 0 0 auto;
  font-family: var(--jm-display);
  font-size: 15px;
  font-weight: 400;
  letter-spacing: .02em;
  color: var(--jm-accent-dim);
  transition: color .22s ease;
}
.svcard:hover .svcard__name span { color: var(--jm-accent); }

/* `.svcard .svcard__text` (0,2,0) — a plain class would be (0,1,0) and Pico's
   own `p` rule plus the sibling-margin rule between them would decide it on
   source order. */
.svcard .svcard__text {
  margin: 0 0 16px;
  max-width: 46ch;
  font-size: 15.5px;
  line-height: 1.65;
  color: var(--jm-muted);
}

.svcard__lbl {
  margin: 0 0 8px;
  font-size: 10.5px;
  font-weight: 800;
  letter-spacing: .16em;
  text-transform: uppercase;
  color: var(--jm-accent-dim);
}

.svcard__for { margin: 0 0 18px; padding: 0; list-style: none; }
.svcard__for li {
  display: flex;
  align-items: baseline;
  gap: 9px;
  margin: 0 0 6px;
  padding: 0;
  list-style: none;
  font-size: 14px;
  line-height: 1.5;
  color: var(--jm-body);
}
.svcard__for .jm-ico {
  flex: 0 0 auto;
  font-size: 13px;
  color: var(--jm-accent-dim);
  transform: translateY(1px);
}

/* --- the foot ------------------------------------------------------------- */

.svcard__foot {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  /* margin-top:auto pins this to the bottom whatever the copy above does, so
     a row of cards has its buttons on one line. */
  margin-top: auto;
  padding-top: 14px;
  border-top: 1px solid var(--jm-line);
}

.svcard__price { margin: 0; }
.svcard__price span {
  display: block;
  font-size: 10px;
  font-weight: 800;
  letter-spacing: .16em;
  text-transform: uppercase;
  color: var(--jm-muted);
}
.svcard__price b {
  display: block;
  font-size: 16px;
  font-weight: 800;
  letter-spacing: -.01em;
  color: var(--jm-heading);
}

.svcard__cta {
  display: inline-flex;
  align-items: center;
  gap: 9px;
  padding: 12px 20px;
  border-radius: var(--jm-pill);
  background: var(--jm-accent);
  color: var(--jm-on-accent);
  font-size: 11.5px;
  font-weight: 800;
  letter-spacing: .12em;
  text-transform: uppercase;
  text-decoration: none;
  white-space: nowrap;
  transition: background-color .2s ease;
}
.svcard__cta:hover,
.svcard__cta:focus-visible {
  background: var(--jm-accent-lit);
  color: var(--jm-on-accent);
  text-decoration: none;
}
.svcard__cta .jm-ico { transition: transform .2s ease; }
.svcard:hover .svcard__cta .jm-ico { transform: translateX(4px); }

/* --- the scroll-driven reveal --------------------------------------------- */

@keyframes jm-card-in {
  from { opacity: 0; transform: translateY(26px) scale(.985); }
  to   { opacity: 1; transform: none; }
}

/* BOTH guards matter. @supports keeps the animation away from browsers that
   cannot advance its timeline — where `both` would freeze every card on the
   opacity-0 keyframe. The media query is the ordinary courtesy. */
@supports (animation-timeline: view()) {
  @media (prefers-reduced-motion: no-preference) {
    .svcard {
      animation: jm-card-in linear both;
      animation-timeline: view();
      /* Finish well before the card is centred, or it is still fading in by
         the time somebody is reading it. */
      animation-range: entry 0% entry 42%;
    }
  }
}

@media (max-width: 1100px) { .svgrid { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 700px)  {
  .svgrid { grid-template-columns: 1fr; }
  .svcard .svcard__text { max-width: none; }
}
@media (max-width: 420px) {
  /* The price and a 20px-padded pill will not share 300px. */
  .svcard__foot { flex-direction: column; align-items: stretch; }
  .svcard__cta { justify-content: center; }
}


/* ==========================================================================
   33. WHAT "VERIFIED" MEANS         ref 20 — board "Section6", second image
   --------------------------------------------------------------------------
   Two columns on the light ground: heading, lede and four bordered claim rows
   left; a circular badge ringed by three floating pills right; then a
   four-cell stat strip spanning both.

   The reference's badge is a 5.0 star rating. There is no review system on
   this site, so it carries the vetting claim instead — see the note above
   $VERIFIED in config.php. The dotted rings around it are two box-shadows and
   a border, not an image.
   ========================================================================== */

.vfd { padding-block: clamp(44px, 6vw, 84px); background: var(--jm-ground); }
/* 2026-10-09, live on eropspa.com: phones could drag the homepage sideways.
   The badge's ::after ring (inset -36px) ROTATES, and a rotated box's square
   bounding area counts as scrollable overflow even though it paints a circle —
   up to ~25px past the right edge at 393px, varying with the angle, so it came
   and went. `clip` (not `hidden`) clips the x-axis only and creates no scroll
   container, so nothing visible changes and the pills still overflow vertically. */
.vfd { overflow-x: clip; }

.vfd__grid {
  display: grid;
  grid-template-columns: minmax(0, 1.05fr) minmax(0, .8fr);
  align-items: center;
  gap: clamp(30px, 4.5vw, 70px) clamp(30px, 5vw, 80px);
}

/* --- left column ---------------------------------------------------------- */

.vfd__eyebrow {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  margin: 0 0 14px;
  font-size: 11.5px;
  font-weight: 800;
  letter-spacing: .19em;
  text-transform: uppercase;
  color: var(--jm-accent-dim);
}
/* The reference precedes its eyebrow with a short rule. */
.vfd__eyebrow span {
  width: 26px;
  height: 2px;
  border-radius: 2px;
  background: var(--jm-accent-dim);
}

/* (0,1,0) — Pico's `:is(p,ul,…)~:is(h1,…,h6)` (0,0,2) would put a large top
   margin on this, because the eyebrow above it is a <p>. */
.vfd__title {
  margin: 0 0 16px;
  font-size: clamp(28px, 3.8vw, 48px);
  font-weight: 800;
  line-height: 1.06;
  letter-spacing: -.028em;
  color: var(--jm-heading);
}
.vfd__title em { font-style: normal; color: var(--jm-accent-dim); }

.vfd__lede {
  margin: 0 0 clamp(22px, 2.8vw, 32px);
  max-width: 52ch;
  font-size: 15.5px;
  line-height: 1.62;
  color: var(--jm-muted);
}

.vfd-rows { display: grid; gap: 10px; margin: 0; padding: 0; list-style: none; }
/* Pico's `ul li{list-style:square}` is (0,0,2) — clear it on the `li`. */
.vfd-rows li {
  position: relative;
  margin: 0;
  padding: 15px 18px 15px 38px;
  list-style: none;
  border: 1px solid var(--jm-line);
  border-radius: var(--jm-r);
  background: var(--jm-card);
  box-shadow: 0 1px 2px var(--jm-shadow);
}
/* The reference's leading dot. A pseudo-element rather than a character, so
   it cannot be selected, read out or copied with the text. */
.vfd-rows li::before {
  content: '';
  position: absolute;
  top: 22px;
  left: 17px;
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--jm-accent-dim);
}
.vfd-rows b {
  display: block;
  margin-bottom: 3px;
  font-size: 15.5px;
  font-weight: 700;
  color: var(--jm-heading);
}
.vfd-rows span {
  display: block;
  font-size: 13.5px;
  line-height: 1.55;
  color: var(--jm-muted);
}

/* --- the badge ------------------------------------------------------------ */

.vfd__art {
  position: relative;
  display: grid;
  place-items: center;
  min-height: 300px;
}

.vfd-badge {
  position: relative;
  display: grid;
  place-items: center;
  width: min(250px, 62vw);
  aspect-ratio: 1;
  padding: 20px;
  border: 2px dashed color-mix(in srgb, var(--jm-accent-dim) 40%, transparent);
  border-radius: 50%;
  background:
    radial-gradient(circle at 50% 42%,
      var(--jm-card) 0%,
      color-mix(in srgb, var(--jm-accent) 16%, var(--jm-card)) 100%);
  /* The two outer rings, as shadows — no extra elements, no image. */
  box-shadow:
    0 0 0 14px color-mix(in srgb, var(--jm-accent) 9%, transparent),
    0 0 0 28px color-mix(in srgb, var(--jm-accent) 5%, transparent),
    0 18px 44px var(--jm-shadow-2);
  text-align: center;
}

/* --- the animated rings --------------------------------------------------
   The client asked for "advanced design with color full animation round".
   Two counter-rotating rings around the badge, both drawn in CSS:

     ::before  a CONIC GRADIENT through five stops of the accent, masked to a
               thin annulus so only the ring shows, turning clockwise;
     ::after   a dashed ring turning the other way, slower.

   Colour: five tones of the ONE accent, not five hues. Every colour on this
   site goes through a token — a rainbow here would be five hard-coded values
   and the end of theme switching, and it would be the only place on the site
   that is not charcoal and gold. On the gold palette the sweep reads as
   champagne-to-bronze-to-gold, which is as colourful as this brand gets.

   The mask is what makes it a ring rather than a filled disc, and it needs
   the -webkit- prefix: Safari has never shipped the unprefixed property.
   -------------------------------------------------------------------------- */

.vfd-badge::before,
.vfd-badge::after {
  content: '';
  position: absolute;
  border-radius: 50%;
  pointer-events: none;
}

.vfd-badge::before {
  inset: -20px;
  background: conic-gradient(from 0deg,
    var(--jm-accent-lit),
    var(--jm-accent),
    var(--jm-accent-dim),
    var(--jm-accent),
    var(--jm-accent-lit));
  -webkit-mask: radial-gradient(farthest-side, transparent calc(100% - 5px), #000 calc(100% - 4px));
          mask: radial-gradient(farthest-side, transparent calc(100% - 5px), #000 calc(100% - 4px));
  opacity: .9;
}

.vfd-badge::after {
  inset: -36px;
  border: 2px dashed color-mix(in srgb, var(--jm-accent-dim) 32%, transparent);
}

@media (prefers-reduced-motion: no-preference) {
  .vfd-badge::before { animation: jm-ring 11s linear infinite; }
  /* Reverse, and slower, so the two never appear locked together. */
  .vfd-badge::after  { animation: jm-ring 26s linear infinite reverse; }
  /* A slow breath on the outer glow, in step with neither ring. */
  .vfd-badge { animation: jm-badge-glow 6s ease-in-out infinite; }
  /* The three pills drift, on the section 7 keyframes that already exist. */
  .vfd-pill   { animation: jm-float 7s ease-in-out infinite; }
  .vfd-pill--2 { animation-duration: 9s;  animation-delay: -2s; }
  .vfd-pill--3 { animation-duration: 8s;  animation-delay: -4s; }
}

@keyframes jm-ring {
  from { transform: rotate(0deg); }
  to   { transform: rotate(360deg); }
}

@keyframes jm-badge-glow {
  0%, 100% {
    box-shadow:
      0 0 0 14px color-mix(in srgb, var(--jm-accent) 9%, transparent),
      0 0 0 28px color-mix(in srgb, var(--jm-accent) 5%, transparent),
      0 18px 44px var(--jm-shadow-2);
  }
  50% {
    box-shadow:
      0 0 0 18px color-mix(in srgb, var(--jm-accent) 14%, transparent),
      0 0 0 36px color-mix(in srgb, var(--jm-accent) 7%, transparent),
      0 18px 44px var(--jm-shadow-2);
  }
}
.vfd-badge b {
  display: block;
  font-family: var(--jm-display);
  font-size: clamp(42px, 6vw, 62px);
  font-weight: 400;
  line-height: 1;
  color: var(--jm-accent-dim);
}
.vfd-badge span {
  display: block;
  margin-top: 6px;
  font-size: 11px;
  font-weight: 800;
  letter-spacing: .16em;
  text-transform: uppercase;
  color: var(--jm-heading);
}
.vfd-badge i {
  display: block;
  margin-top: 5px;
  font-style: normal;
  font-size: 12px;
  line-height: 1.4;
  color: var(--jm-muted);
}

.vfd-pill {
  position: absolute;
  display: inline-flex;
  align-items: center;
  gap: 7px;
  margin: 0;
  padding: 8px 14px;
  border-radius: var(--jm-pill);
  background: var(--jm-card);
  box-shadow: 0 8px 22px var(--jm-shadow-2);
  font-size: 11.5px;
  font-weight: 700;
  color: var(--jm-heading);
  white-space: nowrap;
}
.vfd-pill .jm-ico { font-size: 14px; color: var(--jm-accent-dim); }
.vfd-pill--1 { top: 6%;  right: 0; }
.vfd-pill--2 { bottom: 22%; left: 0; }
.vfd-pill--3 { bottom: 2%;  right: 6%; }

/* --- the stat strip ------------------------------------------------------- */

.vfd-stats {
  grid-column: 1 / -1;
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: clamp(10px, 1.4vw, 18px);
  margin: 0;
  padding: clamp(18px, 2.2vw, 26px);
  list-style: none;
  border: 1px solid var(--jm-line);
  border-radius: var(--jm-r-lg);
  background: var(--jm-card);
  box-shadow: 0 2px 10px var(--jm-shadow);
}
/* A two-column grid, not a flex row: the icon spans both rows and the number
   sits ABOVE its label. As a flex row the number and the label were siblings
   on one line — "12 Treatments" reading as a sentence rather than as a
   figure with a caption. */
.vfd-stats li {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  align-items: center;
  column-gap: 12px;
  margin: 0;
  padding: 0;
  list-style: none;
}
.vfd-stats__ico {
  grid-row: 1 / span 2;
  display: grid;
  place-items: center;
  width: 42px;
  height: 42px;
  font-size: 19px;
  border-radius: var(--jm-r-sm);
  background: color-mix(in srgb, var(--jm-accent) 20%, var(--jm-card));
  color: var(--jm-accent-dim);
}
.vfd-stats b {
  font-size: clamp(20px, 2.2vw, 27px);
  font-weight: 800;
  line-height: 1;
  letter-spacing: -.02em;
  color: var(--jm-heading);
}
.vfd-stats li > span:last-child {
  display: block;
  margin-top: 2px;
  font-size: 11.5px;
  color: var(--jm-muted);
}
/* The number and its label share a column beside the icon. */
.vfd-stats li b + span { margin-top: 2px; }
.vfd-stats li > b { display: block; }

@media (max-width: 980px) {
  .vfd__grid { grid-template-columns: 1fr; }
  .vfd__lede { max-width: none; }
  .vfd-stats { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (max-width: 520px) {
  .vfd-stats { grid-template-columns: 1fr; }
  /* The pills hang off the badge; at this width that overflows the page. */
  .vfd-pill--1 { right: -2%; }
  .vfd-pill--2 { left: -2%; }
  .vfd-pill--3 { right: 2%; }
}


/* ==========================================================================
   34. ONE MESSAGE AWAY              ref 21 — "contact whatsapp and telegram"
   --------------------------------------------------------------------------
   One wide card on the light ground: copy and the two chat buttons on the
   left, a phone mockup on the right.

   The two channel colours are the brands' own — see the note beside
   --jm-whatsapp in §2. A WhatsApp button in JioMassage gold would stop
   reading as WhatsApp, which is the entire point of putting it there.
   ========================================================================== */

.msg { padding-block: clamp(40px, 5.5vw, 78px); background: var(--jm-ground); }

.msg__card {
  display: grid;
  grid-template-columns: minmax(0, 1.1fr) minmax(0, .68fr);
  align-items: center;
  gap: clamp(28px, 4vw, 60px);
  padding: clamp(24px, 3.2vw, 46px);
  border: 1px solid var(--jm-line);
  border-radius: var(--jm-r-lg);
  background:
    radial-gradient(80% 100% at 100% 0%,
      color-mix(in srgb, var(--jm-accent) 15%, transparent) 0%, transparent 62%),
    var(--jm-card);
  box-shadow: 0 14px 40px var(--jm-shadow);
}

.msg__pill {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  margin: 0 0 14px;
  padding: 7px 15px;
  border: 1px solid color-mix(in srgb, var(--jm-accent-dim) 32%, transparent);
  border-radius: var(--jm-pill);
  background: color-mix(in srgb, var(--jm-accent) 13%, var(--jm-card));
  font-size: 11px;
  font-weight: 800;
  letter-spacing: .15em;
  text-transform: uppercase;
  color: var(--jm-accent-dim);
}
.msg__pill span {
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--jm-accent-dim);
}

/* (0,1,0) — the pill above is a <p>, so Pico's sibling-margin rule applies. */
.msg__title {
  margin: 0 0 12px;
  font-size: clamp(26px, 3.4vw, 44px);
  font-weight: 800;
  line-height: 1.06;
  letter-spacing: -.028em;
  color: var(--jm-heading);
}
.msg__title em { font-style: normal; color: var(--jm-accent-dim); }

.msg__lede {
  margin: 0 0 18px;
  max-width: 46ch;
  font-size: 15px;
  line-height: 1.6;
  color: var(--jm-muted);
}

.msg__chips {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin: 0 0 20px;
  padding: 0;
  list-style: none;
}
/* Pico's `ul li{list-style:square}` is (0,0,2) — clear it on the `li`. */
.msg__chips li {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  margin: 0;
  padding: 8px 14px;
  list-style: none;
  border: 1px solid var(--jm-line);
  border-radius: var(--jm-pill);
  font-size: 12px;
  font-weight: 700;
  color: var(--jm-heading);
}
.msg__chips .jm-ico { font-size: 14px; color: var(--jm-accent-dim); }

/* --- the two chat buttons ------------------------------------------------- */

.msg__actions {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 12px;
  margin-bottom: 12px;
}

.msg-go {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 13px 18px;
  border-radius: var(--jm-pill);
  color: #FFFFFF;
  font-size: 14px;
  font-weight: 700;
  text-decoration: none;
  box-shadow: 0 8px 22px var(--jm-shadow);
  transition: transform .18s ease, box-shadow .18s ease;
}
.msg-go:hover,
.msg-go:focus-visible {
  transform: translateY(-2px);
  box-shadow: 0 12px 30px var(--jm-shadow-2);
  color: #FFFFFF;
  text-decoration: none;
}
.msg-go--whatsapp { background: var(--jm-whatsapp); }
/* Dark label on WhatsApp green (2026-10-09, Lighthouse: white on #25D366 is
   2:1). The span needs it too — it sets its own colour. */
.msg-go.msg-go--whatsapp,
.msg-go.msg-go--whatsapp span { color: var(--jm-ink); }
.msg-go--telegram { background: var(--jm-telegram); }

.msg-go__ico {
  display: grid;
  place-items: center;
  flex: 0 0 auto;
  width: 36px;
  height: 36px;
  font-size: 19px;
  border-radius: 50%;
  background: rgba(255, 255, 255, .22);
}

/* Same treatment as the floating rail: while $SITE['whatsapp'] / ['telegram']
   are empty these fall back to contact.php, and the dimming is what makes
   that visible on the page rather than only in config. */
.msg-go[data-pending] { opacity: .58; }

.msg__browse { width: fit-content; }

.msg__rule {
  height: 1px;
  border: 0;
  margin: clamp(20px, 2.4vw, 28px) 0 16px;
  background: var(--jm-line);
}

.msg__foot {
  display: inline-flex;
  align-items: center;
  gap: 12px;
  font-size: 13px;
  color: var(--jm-muted);
  text-decoration: none;
}
.msg__foot b { color: var(--jm-heading); font-weight: 700; }
.msg__foot:hover b,
.msg__foot:focus-visible b { color: var(--jm-accent-dim); }
.msg__foot .jm-ico { color: var(--jm-accent-dim); }

/* --- the phone ------------------------------------------------------------ */

.msg__phone { display: grid; place-items: center; }

.msg-ph {
  width: min(268px, 74vw);
  padding: 14px 12px 16px;
  border: 2px solid var(--jm-line);
  border-radius: 34px;
  background: var(--jm-card);
  box-shadow: 0 24px 56px var(--jm-shadow-2);
}
.msg-ph__notch {
  display: block;
  width: 70px;
  height: 5px;
  margin: 0 auto 12px;
  border-radius: var(--jm-pill);
  background: var(--jm-line);
}
.msg-ph__mark {
  margin: 0 0 14px;
  font-family: var(--jm-display);
  font-size: 15px;
  letter-spacing: .01em;
  text-transform: uppercase;
  text-align: center;
  color: var(--jm-heading);
}
.msg-ph__mark em { font-style: normal; color: var(--jm-accent-dim); }

.msg-ph__h {
  margin: 0 0 10px;
  font-size: 10.5px;
  font-weight: 800;
  letter-spacing: .16em;
  text-transform: uppercase;
  color: var(--jm-muted);
}

/* A <dl> in two columns: label left, value right, hairline under each pair.
   Pico has no opinion about <dl>, so this needs no defensive rules. */
.msg-ph__rows {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  gap: 0 10px;
  margin: 0 0 14px;
}
.msg-ph__rows dt,
.msg-ph__rows dd {
  margin: 0;
  padding: 8px 0;
  border-bottom: 1px solid var(--jm-line);
  font-size: 12px;
  line-height: 1.35;
}
.msg-ph__rows dt { color: var(--jm-muted); white-space: nowrap; }
.msg-ph__rows dd { color: var(--jm-heading); font-weight: 700; text-align: right; }

.msg-ph__send {
  display: block;
  padding: 11px;
  border-radius: var(--jm-pill);
  background: var(--jm-accent);
  color: var(--jm-on-accent);
  font-size: 11.5px;
  font-weight: 800;
  letter-spacing: .1em;
  text-transform: uppercase;
  text-align: center;
}

@media (max-width: 900px) {
  .msg__card { grid-template-columns: 1fr; }
  .msg__lede { max-width: none; }
  /* The phone leads on a narrow screen only when it is the whole width —
     stacked under the copy it reads as an afterthought, so it goes first. */
  .msg__phone { order: -1; }
}
@media (max-width: 480px) {
  .msg__actions { grid-template-columns: 1fr; }
  .msg__browse { width: 100%; justify-content: center; }
}


/* ==========================================================================
   32. ACCOUNTS — sign-in cards and the booking desk
   --------------------------------------------------------------------------
   Added 2026-09-06 with includes/auth.php. Nothing here was designed: the
   sign-in cards are book.php's `.bcard` narrowed, the tables are the pricing
   table's `.ptable`, and the buttons are the ones already on the site.

   These pages are all `noindex, nofollow`. They are also the only pages on
   the site that need a session cookie, which is why the public pages read the
   session through auth_user_quiet() and never start one.
   ========================================================================== */

.authwrap { display: grid; place-items: center; }

.authcard {
  width: 100%;
  max-width: 560px;
  margin-inline: auto;
}
/* One column, not the booking form's two: four fields at 260px each in a
   560px card leaves an email input too narrow to read an address in. */
.authcard .bform-grid { grid-template-columns: 1fr; }

/* --- the desk (and the customer's own account page) ----------------------- */

/* --- the admin bar (2026-09-07) ------------------------------------------
   The desk used to open with a plain heading and three buttons floating
   beside it, which read as a public page that had lost its way. A dark bar
   makes it unmistakably a tool.

   It is NOT the site masthead — that one is still above it, because staff
   should be one click from the live site at all times.
   ------------------------------------------------------------------------- */

.deskbar {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 16px 24px;
  margin-bottom: clamp(20px, 2.6vw, 30px);
  padding: 16px clamp(16px, 2vw, 24px);
  border-radius: var(--jm-r);
  background:
    radial-gradient(70% 120% at 100% 0%,
      color-mix(in srgb, var(--jm-accent) 26%, transparent) 0%, transparent 62%),
    var(--jm-ink);
  box-shadow: 0 10px 30px var(--jm-shadow-2);
}

.deskbar__id { display: flex; align-items: center; gap: 14px; min-width: 0; }

.deskbar__mark {
  font-family: var(--jm-display);
  font-size: 21px;
  letter-spacing: .01em;
  text-transform: uppercase;
  color: var(--jm-on-ink);
  white-space: nowrap;
}
.deskbar__mark em { font-style: normal; color: var(--jm-accent); }

/* The divider is the bar's own hairline, not a character — it disappears
   cleanly when the two halves wrap onto separate lines. */
.deskbar__who {
  padding-left: 14px;
  border-left: 1px solid var(--jm-ink-line-2);
  min-width: 0;
}
.deskbar__who b {
  display: block;
  font-size: 13px;
  font-weight: 800;
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--jm-accent);
}
.deskbar__who i {
  display: block;
  font-style: normal;
  font-size: 12.5px;
  color: var(--jm-nav);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.deskbar__tools { display: flex; flex-wrap: wrap; align-items: center; gap: 10px; }
.deskbar__tools form { display: flex; align-items: center; gap: 8px; margin: 0; }

/* The month picker sits on the ink, so it needs the dark-select handling from
   §5: the closed control is styled through Pico's variables, but the OPTION
   LIST is drawn by the browser and comes out white-on-white without
   `color-scheme`. This is the one dark <select> left on the site. */
.deskbar select {
  --pico-form-element-background-color: var(--jm-ink-soft);
  --pico-form-element-border-color:     var(--jm-ink-line-2);
  --pico-form-element-color:            var(--jm-on-ink);
  --pico-form-element-active-border-color: var(--jm-accent);
  width: auto;
  min-width: 130px;
  height: 42px;
  margin: 0;
  padding-block: 0;
  line-height: normal;
  font-size: 13px;
  color-scheme: var(--jm-scheme);
}
.deskbar select option,
.deskbar select optgroup {
  background-color: var(--jm-ink-soft);
  color: var(--jm-on-ink);
}
/* Pico's `button[type=submit] { width: 100% }` branch is (0,1,1).
   `.deskbar form .btn-solid` is (0,2,1) and outranks it — but ONLY for the
   properties it actually declares, and the first version declared `flex`,
   `padding` and `font-size` and NOT `width`. `flex: 0 0 auto` resolves its
   basis from `width`, which was still 100%, so the button stretched across
   the whole bar and sat on top of the Password link. Caught by screenshot.
   The lesson is the flex shorthand does not override a width; say `width`. */
.deskbar form .btn-solid {
  flex: 0 0 auto;
  width: auto;
  padding: 12px 20px;
  font-size: 12px;
}

.deskbar__act {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 11px 16px;
  border: 1px solid var(--jm-ink-line-2);
  border-radius: var(--jm-pill);
  font-size: 12px;
  font-weight: 800;
  letter-spacing: .08em;
  color: var(--jm-nav);
  text-decoration: none;
  white-space: nowrap;
  transition: border-color .18s ease, color .18s ease;
}
.deskbar__act:hover,
.deskbar__act:focus-visible {
  border-color: var(--jm-accent);
  color: var(--jm-accent);
  text-decoration: none;
}
.deskbar__act .jm-ico { font-size: 14px; }

@media (max-width: 700px) {
  .deskbar { flex-direction: column; align-items: stretch; }
  .deskbar__tools { display: grid; grid-template-columns: 1fr 1fr; }
  .deskbar__tools form { grid-column: 1 / -1; }
  .deskbar select { flex: 1 1 auto; min-width: 0; }
  .deskbar__act { justify-content: center; }
}

.desk__top {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  justify-content: space-between;
  gap: 16px;
  margin-bottom: clamp(22px, 3vw, 32px);
}

.desk__eyebrow {
  margin: 0 0 6px;
  font-size: 11px;
  font-weight: 800;
  letter-spacing: .18em;
  text-transform: uppercase;
  color: var(--jm-accent-dim);
}

/* (0,1,0) — Pico's h1 is (0,0,1), and the eyebrow above it is a <p>, so its
   `:is(p,ul,…)~:is(h1,…,h6)` rule (0,0,2) would add a large top margin. */
.desk__title {
  margin: 0;
  font-size: clamp(22px, 2.6vw, 32px);
  font-weight: 800;
  line-height: 1.15;
  letter-spacing: -.022em;
  color: var(--jm-heading);
}

.desk__tools { display: flex; flex-wrap: wrap; align-items: center; gap: 10px; }
.desk__tools form { display: flex; align-items: center; gap: 8px; margin: 0; }
/* Pico sizes selects and submit buttons to the full width of their container;
   both are (0,0,1)/(0,1,1). In a flex row that makes each of them fill the
   row in turn. Same trap as `button.near-go` in §15. */
.desk__tools select { width: auto; min-width: 150px; margin: 0; }
.desk__tools form .btn-solid { flex: 0 0 auto; }

.desk-stats {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: clamp(12px, 1.6vw, 20px);
  margin: 0 0 clamp(26px, 3.4vw, 40px);
  padding: 0;
  list-style: none;
}
/* Pico's `ul li{list-style:square}` is (0,0,2) — clear it on the `li`. */
.desk-stats li { margin: 0; padding: 0; list-style: none; }

/* Each stat is an in-page link to its own section: on a page this long the
   numbers are the natural table of contents, so they do that job too. The
   card styling therefore lives on the anchor, not the li. */
.desk-stats a {
  display: block;
  height: 100%;
  padding: 18px 20px;
  border: 1px solid var(--jm-line);
  border-radius: var(--jm-r);
  background: var(--jm-card);
  box-shadow: 0 1px 2px var(--jm-shadow);
  text-decoration: none;
  transition: border-color .18s ease, box-shadow .18s ease, transform .18s ease;
}
.desk-stats a:hover,
.desk-stats a:focus-visible {
  border-color: var(--jm-accent-dim);
  box-shadow: 0 10px 26px var(--jm-shadow);
  transform: translateY(-2px);
  text-decoration: none;
}

.desk-stats__ico {
  display: grid;
  place-items: center;
  width: 34px;
  height: 34px;
  margin-bottom: 12px;
  font-size: 16px;
  border-radius: var(--jm-r-sm);
  background: color-mix(in srgb, var(--jm-accent) 20%, var(--jm-card));
  color: var(--jm-accent-dim);
}

.desk-stats b {
  display: block;
  font-size: clamp(24px, 2.6vw, 34px);
  font-weight: 800;
  line-height: 1.05;
  letter-spacing: -.02em;
  color: var(--jm-heading);
}
/* >>> `:not(.desk-stats__ico)` IS LOAD-BEARING. The icon tile is a <span>
       too, so a bare `.desk-stats span` (0,1,1) MATCHED IT and outranked
       `.desk-stats__ico` (0,1,0) — the tile lost its `display: grid` and its
       16px font, so every stat icon rendered as a 12px glyph jammed into the
       top-left corner of a 34px box instead of centred in it. All four of
       them, on the dashboard, since the desk was built.

       Scoping the label rule so it cannot match is the fix used elsewhere in
       this file (see `.footer-col ul a`); raising the tile to (0,2,0) would
       also work but leaves a rule that still matches and still has to lose.

       ANY future `.thing span` rule sitting beside a `.thing__ico` span has
       exactly this bug. */
.desk-stats span:not(.desk-stats__ico) {
  display: block;
  margin-top: 4px;
  font-size: 12px;
  line-height: 1.4;
  color: var(--jm-muted);
}

/* --- the desk's tables --------------------------------------------------- */

/* `.ptable` gives the price table its scroll box and Pico's own borders. On
   the desk the tables are dense and read row-by-row, so they get a card
   around them and a header that stays legible against the stripes. */
.desk .ptable {
  border: 1px solid var(--jm-line);
  border-radius: var(--jm-r);
  background: var(--jm-card);
  box-shadow: 0 1px 2px var(--jm-shadow);
}
.desk .ptable table { margin: 0; }
.desk .ptable th {
  font-size: 11px;
  font-weight: 800;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--jm-muted);
  white-space: nowrap;
}
.desk .ptable td { font-size: 14px; }
/* The phone number is the whole point of a booking row — make it look it. */
.desk .ptable td a { color: var(--jm-accent-dim); font-weight: 700; }

.desk__h2 {
  margin: clamp(26px, 3.4vw, 40px) 0 14px;
  font-size: clamp(18px, 2vw, 24px);
  font-weight: 800;
  letter-spacing: -.016em;
  color: var(--jm-heading);
}

.desk__empty,
.desk__foot {
  margin: 0;
  font-size: 14px;
  line-height: 1.6;
  color: var(--jm-muted);
}
.desk__foot { margin-top: 14px; font-size: 13px; }

/* The data folder is web-servable — see jm_storage_exposed(). Same treatment
   as the legal pages' .doc__todo, and for the same reason: it must read as a
   warning about the site rather than as part of the site's own content, so it
   uses the form-error colours, the only ones that never take the accent.
   The colour is stated ON THE <p>, not inherited from a wrapper — Pico sets
   `color` on `p` explicitly and an explicit declaration beats an inherited
   value at any specificity (§5). */
.desk .desk__warn {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  margin: 0 0 18px;
  padding: 13px 16px;
  border: 1px dashed color-mix(in srgb, var(--jm-warn-dim) 45%, transparent);
  border-radius: var(--jm-r-sm);
  background: color-mix(in srgb, var(--jm-warn-dim) 7%, var(--jm-card));
  color: var(--jm-warn-dim);
  font-size: 14px;
  line-height: 1.6;
}
.desk__warn .jm-ico { flex: 0 0 auto; transform: translateY(3px); }
.desk__warn code    { font-size: 12.5px; }

.desk table code { font-size: 12.5px; }

/* --- messages ------------------------------------------------------------- */

.desk-msgs { display: grid; gap: 12px; margin: 0; padding: 0; list-style: none; }
.desk-msgs li {
  margin: 0;
  padding: 16px 18px;
  list-style: none;
  border: 1px solid var(--jm-line);
  border-radius: var(--jm-r);
  background: var(--jm-card);
  box-shadow: 0 1px 2px var(--jm-shadow);
}

.desk-msgs__meta {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 10px;
  margin: 0 0 8px;
  font-size: 13px;
  color: var(--jm-muted);
}
.desk-msgs__meta b { color: var(--jm-heading); font-weight: 700; }
.desk-msgs__meta span {
  padding: 3px 10px;
  border-radius: var(--jm-pill);
  background: color-mix(in srgb, var(--jm-accent) 18%, var(--jm-card));
  font-size: 11px;
  font-weight: 700;
  color: var(--jm-accent-dim);
}
.desk-msgs__meta i { font-style: normal; margin-left: auto; font-size: 12px; }

.desk-msgs__body {
  margin: 0 0 10px;
  font-size: 14.5px;
  line-height: 1.6;
  color: var(--jm-body);
}
.desk-msgs__reply { display: flex; flex-wrap: wrap; gap: 14px; margin: 0; font-size: 13px; }

@media (max-width: 900px) { .desk-stats { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 520px) { .desk-stats { grid-template-columns: 1fr; } }


/* ==========================================================================
   31. SECTION 13 — QUICK LINKS      ref 35 — board "section 13home"
   --------------------------------------------------------------------------
   A centred capitalised heading over a wrapping row of coloured pills, one
   per treatment, directly above the profile grid.

   The reference's four pill colours are yellow, red, black and grey — four
   literal hues, which on this site would be four hardcoded values and the end
   of theme switching. The four tones here are the accent, the ink and two
   neutrals, all from tokens, cycling in source order. Same effect, any
   palette.

   The reference's third row is three third-party ad banners. Not built, and
   not going to be — see the note above $QUICK in config.php.
   ========================================================================== */

.quick { padding-block: clamp(38px, 5vw, 68px) clamp(4px, 1vw, 12px); }

/* (0,1,0) and stated: Pico's h2 is (0,0,1). Nothing precedes it inside the
   shell, so the sibling-margin rule does not apply here, but the size and the
   tracking do have to be set. */
.quick__title {
  margin: 0 0 clamp(18px, 2.4vw, 28px);
  font-size: clamp(19px, 2.2vw, 30px);
  font-weight: 800;
  line-height: 1.2;
  letter-spacing: .04em;
  text-transform: uppercase;
  text-align: center;
  color: var(--jm-heading);
}

/* --- the marquee ---------------------------------------------------------
   The client asked for this row to move "like gif file". Same technique as
   the hero (§7), and the same two traps apply:

     · THE GAP GOES ON THE ITEM, NOT THE ROW. With `gap` on the flex row a
       copy measures n pills + (n−1) gaps, so sliding by one copy lands a gap
       short and the loop jumps. Each `li` carries its own margin-right, so a
       copy is exactly n × (pill + gap) and −33.3333% of a three-copy track is
       exactly one copy.
     · THREE COPIES, not two. The track slides by one copy; the other two have
       to keep the strip covered while it does.

   It bleeds past the shell on purpose — a strip that starts and stops inside
   the column reads as a broken carousel rather than as a moving band.
   ------------------------------------------------------------------------- */

.quick-marq {
  overflow: hidden;

  /* FULL-BLEED BY STRUCTURE, NOT BY `100vw`. The first version sat inside
     `.jm-shell` and broke out with `width:100vw; margin-left:50%;
     transform:translateX(-50%)`. That is a page-level horizontal-scroll bug
     waiting to happen: `100vw` INCLUDES the vertical scrollbar, so on any
     real browser that shows one the strip is ~15px wider than the document
     and the whole page scrolls sideways. `overflow:hidden` on this element
     does not help — it clips its children, not itself.
     Worse, the overflow probe cannot catch it, because headless captures run
     with `--hide-scrollbars` and there 100vw is exactly the client width.
     So the markup puts this element OUTSIDE the shell instead, where it is
     full width because its section is. Nothing to compensate for. */

  /* Fade both ends so pills enter and leave rather than being chopped. */
  -webkit-mask-image: linear-gradient(90deg, transparent, #000 6%, #000 94%, transparent);
  mask-image: linear-gradient(90deg, transparent, #000 6%, #000 94%, transparent);
}

.quick-track {
  display: flex;
  width: max-content;
  animation: jm-quick 46s linear infinite;
}

/* Stop it while somebody is trying to use it — these are links, and a moving
   target is a hostile one. focus-within covers the keyboard as well. */
.quick-marq:hover .quick-track,
.quick-marq:focus-within .quick-track { animation-play-state: paused; }

@keyframes jm-quick {
  from { transform: translateX(0); }
  to   { transform: translateX(-33.3333%); }   /* exactly one of three copies */
}

.quick-row {
  display: flex;
  flex: 0 0 auto;
  margin: 0;
  padding: 0;
  list-style: none;
}
/* Pico's `ul li{list-style:square}` is (0,0,2) — clear it on the `li`.
   The margin is the marquee's gap; see the note above. */
.quick-row li { margin: 0 10px 0 0; padding: 0; list-style: none; }

/* Reduced motion: no marquee at all. The spare copies come out and the one
   real row wraps and centres, which is what this section was before the
   client asked for movement. */
@media (prefers-reduced-motion: reduce) {
  .quick-marq {
    padding-inline: var(--jm-gutter);
    -webkit-mask-image: none;
    mask-image: none;
  }
  .quick-track { width: auto; animation: none; }
  .quick-track .quick-row + .quick-row { display: none; }
  .quick-row { flex-wrap: wrap; justify-content: center; }
  .quick-row li { margin: 0 10px 10px 0; }
}

/* --- "see all", under the strip ------------------------------------------ */

.quick__all { margin: clamp(18px, 2.2vw, 26px) 0 0; text-align: center; }
.quick__all a {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  font-size: 11.5px;
  font-weight: 800;
  letter-spacing: .13em;
  text-transform: uppercase;
  color: var(--jm-accent-dim);
  text-decoration: underline;
  text-underline-offset: 5px;
}
.quick__all a:hover,
.quick__all a:focus-visible { color: var(--jm-heading); }

.qpill {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 11px 22px;
  border: 1px solid transparent;
  border-radius: var(--jm-pill);
  font-size: 12.5px;
  font-weight: 800;
  letter-spacing: .04em;
  text-decoration: none;
  transition: transform .16s ease, box-shadow .16s ease, background-color .16s ease;
}
.qpill:hover,
.qpill:focus-visible {
  transform: translateY(-2px);
  box-shadow: 0 8px 20px var(--jm-shadow-2);
  text-decoration: none;
}

/* The four tones, cycling. 1 = accent fill, 2 = ink fill, 3 = soft accent
   tint, 4 = neutral chip. */
.qpill--1 { background: var(--jm-accent);  color: var(--jm-on-accent); }
.qpill--2 { background: var(--jm-ink);     color: var(--jm-on-ink);    }
.qpill--3 {
  background: color-mix(in srgb, var(--jm-accent) 18%, var(--jm-card));
  border-color: color-mix(in srgb, var(--jm-accent-dim) 30%, transparent);
  color: var(--jm-accent-dim);
}
.qpill--4 { background: var(--jm-chip); color: var(--jm-heading); }

/* Every fill above keeps its own label colour on hover — without this,
   `a:hover` from Pico repaints them all to the link colour. */
.qpill--1:hover, .qpill--1:focus-visible { background: var(--jm-accent-lit); color: var(--jm-on-accent); }
.qpill--2:hover, .qpill--2:focus-visible { background: var(--jm-ink-soft);   color: var(--jm-on-ink);    }
.qpill--3:hover, .qpill--3:focus-visible { color: var(--jm-accent-dim); }
.qpill--4:hover, .qpill--4:focus-visible { background: var(--jm-chip-lit);   color: var(--jm-heading);   }

/* A pill inside a marquee must not wrap: a two-line pill changes the copy's
   width, and the slide distance is a percentage of that width. */
.qpill { white-space: nowrap; }

@media (max-width: 560px) {
  .qpill { padding: 9px 16px; font-size: 11.5px; }
  .quick-row li { margin-right: 8px; }
}


/* ==========================================================================
   30. SECTION 12 — THIS WEEK'S PAIRING + THE BOOKING PROMO
                                      ref 34 — board "section 12 home"
   --------------------------------------------------------------------------
   A two-panel row above the gallery: a wide split card on the left, a filled
   promo card on the right.

   The reference's left panel is a contest between two people and its right
   panel sells a video feed; the structure is what is reused, carrying a
   choice between two TREATMENTS. See the note above $VERSUS in config.php.

   The split card is DARK, deliberately. It is the one panel on the page that
   has to hold two photographs edge to edge with text over the seam, and the
   colour pass turned sections 7–9 light precisely so the remaining dark bands
   would carry weight. It sits between the light Services panel and the light
   gallery.
   ========================================================================== */

.s12 { padding-block: clamp(40px, 5.5vw, 80px); background: var(--jm-ground); }

.s12__grid {
  display: grid;
  grid-template-columns: minmax(0, 1.75fr) minmax(0, 1fr);
  align-items: stretch;
  gap: clamp(16px, 2vw, 26px);
}

/* --- the split card ------------------------------------------------------- */

.vs {
  position: relative;
  padding: clamp(16px, 1.8vw, 22px);
  border-radius: var(--jm-r-lg);
  background: var(--jm-ink);
  box-shadow: 0 14px 40px var(--jm-shadow-2);
}

.vs__badge,
.vs__prize {
  position: absolute;
  z-index: 3;
  top: clamp(26px, 3vw, 34px);
  display: inline-flex;
  align-items: center;
  gap: 7px;
  margin: 0;
  padding: 6px 13px;
  border-radius: var(--jm-pill);
  background: color-mix(in srgb, var(--jm-ink) 78%, transparent);
  -webkit-backdrop-filter: blur(6px);
  backdrop-filter: blur(6px);
  font-size: 10.5px;
  font-weight: 800;
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--jm-on-ink);
  white-space: nowrap;
}
.vs__badge { left: clamp(26px, 3vw, 34px); }
.vs__prize { right: clamp(26px, 3vw, 34px); color: var(--jm-accent); }
.vs__badge i {
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--jm-accent);
}

/* --- the two photo halves ------------------------------------------------- */

.vs__halves {
  position: relative;
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 3px;                       /* the seam the reference has */
  overflow: hidden;
  border-radius: var(--jm-r);
}

/* `figure`, not `article`: Pico gives `article` a background, shadow, padding
   and margin at (0,0,1) that would box each half. */
.vs__half {
  position: relative;
  margin: 0;
  overflow: hidden;
  background: var(--jm-ink-soft);
}
.vs__half img,
.vs__half video {
  display: block;
  width: 100%;
  height: 100%;
  aspect-ratio: 4 / 3;
  object-fit: cover;
}
/* 2026-09-29: a portrait 9:16 clip in a 4:3 slot keeps under half its
   height, so the crop sits low — on the hands and the treatment, which is
   what the half is about. */
.vs__half video { object-position: 50% 72%; background: var(--jm-ink-soft); }

/* (0,1,1) — clears Pico's `figure figcaption` (0,0,2), which centres it and
   gives it a margin. The gradient is what keeps the label legible over a
   photograph nobody has vetted for contrast. */
.vs__half figcaption {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  padding: 40px 16px 14px;
  background: linear-gradient(180deg, transparent,
    color-mix(in srgb, var(--jm-ink) 88%, transparent));
  text-align: left;
}
.vs__half figcaption b {
  display: block;
  font-size: clamp(15px, 1.5vw, 19px);
  font-weight: 700;
  line-height: 1.2;
  color: var(--jm-on-ink);
}
.vs__half figcaption span {
  display: block;
  margin-top: 2px;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--jm-accent);
}

/* The title sits over the seam, as in the reference. */
.vs__title {
  position: absolute;
  z-index: 2;
  left: 50%;
  top: 34%;
  transform: translate(-50%, -50%);
  width: min(84%, 460px);
  margin: 0;
  font-family: var(--jm-serif);
  font-style: italic;
  font-size: clamp(21px, 2.7vw, 36px);
  line-height: 1.1;
  text-align: center;
  color: var(--jm-on-ink);
  text-shadow: 0 2px 16px color-mix(in srgb, var(--jm-ink) 82%, transparent);
}

.vs__disc {
  position: absolute;
  z-index: 2;
  left: 50%;
  top: 56%;
  transform: translate(-50%, -50%);
  display: grid;
  place-items: center;
  width: 54px;
  height: 54px;
  border-radius: 50%;
  background: var(--jm-accent);
  color: var(--jm-on-accent);
  font-size: 15px;
  font-weight: 800;
  letter-spacing: .04em;
  box-shadow: 0 0 0 5px color-mix(in srgb, var(--jm-ink) 55%, transparent);
}

.vs__clock {
  position: absolute;
  z-index: 2;
  right: 12px;
  bottom: 12px;
  display: inline-flex;
  align-items: center;
  gap: 7px;
  margin: 0;
  padding: 6px 12px;
  border-radius: var(--jm-pill);
  background: color-mix(in srgb, var(--jm-ink) 80%, transparent);
  -webkit-backdrop-filter: blur(6px);
  backdrop-filter: blur(6px);
  font-size: 11px;
  font-weight: 700;
  color: var(--jm-on-ink);
  white-space: nowrap;
}

/* --- the result bar ------------------------------------------------------- */

.vs__bar {
  overflow: hidden;
  height: 6px;
  margin-top: 14px;
  border-radius: var(--jm-pill);
  /* The right-hand share is the track; the left-hand share is painted over
     it, so the two always add to 100 without a second measured element. */
  background: var(--jm-ink-line-2);
}
.vs__bar span {
  display: block;
  height: 100%;
  border-radius: var(--jm-pill);
  background: var(--jm-accent);
}

.vs__tally {
  margin: 9px 0 0;
  font-size: 12px;
  color: var(--jm-nav);
}

/* --- the two vote buttons ------------------------------------------------- */

.vs__actions {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto minmax(0, 1fr);
  align-items: center;
  gap: 10px;
  margin-top: 14px;
}

/* `.vs .vs__go` (0,2,0), not `.vs__go`: Pico's `button[type=submit]` branch
   is (0,1,1) and would otherwise force `width:100%` on both of these inside
   a grid track that is already sized. Same trap as `button.near-go` in §15
   and `button.bgo` in §17 — the two halves of that one Pico selector have
   different specificities. */
.vs .vs__go {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 9px;
  width: 100%;
  margin: 0;
  padding: 14px 18px;
  border: 0;
  border-radius: var(--jm-pill);
  background: linear-gradient(180deg, var(--jm-accent-lit), var(--jm-accent));
  color: var(--jm-on-accent);
  font-size: 12px;
  font-weight: 800;
  letter-spacing: .06em;
  text-transform: uppercase;
  cursor: pointer;
  transition: filter .18s ease;
}
.vs .vs__go:hover,
.vs .vs__go:focus-visible {
  filter: brightness(1.06);
  background: linear-gradient(180deg, var(--jm-accent-lit), var(--jm-accent));
  color: var(--jm-on-accent);
}
.vs__go i {
  display: block;
  font-style: normal;
  font-size: 13px;
  letter-spacing: -.01em;
  text-transform: none;
}
.vs__go span { text-align: left; }

.vs__mid {
  font-size: 10.5px;
  font-weight: 800;
  letter-spacing: .12em;
  color: var(--jm-nav-dim);
}

.vs__sub {
  margin: 12px 0 0;
  font-size: 12.5px;
  line-height: 1.5;
  color: var(--jm-nav);
}

/* --- the promo card ------------------------------------------------------- */

.promo {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  overflow: hidden;
  padding: clamp(22px, 2.4vw, 30px);
  border-radius: var(--jm-r-lg);
  /* The reference's card is a flat purple gradient. Purple is not in the
     palette and a hardcoded hex would break theme switching, so this is the
     ink and the accent — the two colours the brand already owns. */
  min-height: 340px;
  background:
    radial-gradient(150% 110% at 108% -8%,
      var(--jm-accent) 0%,
      color-mix(in srgb, var(--jm-accent) 55%, transparent) 26%,
      transparent 66%),
    linear-gradient(150deg, var(--jm-ink-soft), var(--jm-ink));
  box-shadow: 0 14px 40px var(--jm-shadow-2);
  color: var(--jm-on-ink);
  text-decoration: none;
  transition: box-shadow .18s ease, transform .18s ease;
}
.promo:hover,
.promo:focus-visible {
  transform: translateY(-3px);
  box-shadow: 0 20px 50px var(--jm-shadow-2);
  color: var(--jm-on-ink);
  text-decoration: none;
}

.promo__pill {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  margin-bottom: 16px;
  padding: 6px 13px;
  border-radius: var(--jm-pill);
  background: color-mix(in srgb, var(--jm-on-ink) 15%, transparent);
  font-size: 10.5px;
  font-weight: 800;
  letter-spacing: .14em;
  text-transform: uppercase;
}
.promo__pill i {
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--jm-accent);
}

.promo__title {
  display: block;
  max-width: 20ch;
  margin-bottom: 10px;
  font-size: clamp(24px, 2.6vw, 34px);
  font-weight: 800;
  line-height: 1.08;
  letter-spacing: -.026em;
}

.promo__sub {
  display: block;
  max-width: 34ch;
  margin-bottom: 20px;
  font-size: 13.5px;
  line-height: 1.55;
  color: var(--jm-nav);
}

/* Directly under the copy, as in the reference — NOT `margin-top: auto`. The
   grid stretches this card to the height of the split card beside it, and an
   auto margin then parked the button alone at the bottom with a void above
   it. The photo stack is what fills the lower half. */
.promo__cta {
  display: inline-flex;
  align-items: center;
  gap: 9px;
  padding: 13px 24px;
  border-radius: var(--jm-pill);
  background: var(--jm-card);
  color: var(--jm-heading);
  font-size: 12.5px;
  font-weight: 800;
  letter-spacing: .1em;
  text-transform: uppercase;
}

/* --- the tilted stack ----------------------------------------------------- */

/* The reference's stack is three tilted phone-shaped cards, fanned so each
   one shows a sliver of the one behind. The source photographs are 4:3
   landscape, so the box is portrait and `object-fit: cover` does the crop. */
/* Inside the card, not hanging off it: `.promo` is `overflow: hidden` so that
   the gradient keeps its rounded corner, and a stack pushed past the edge is
   simply sliced off — which is what the first attempt did. */
.promo__stack {
  position: absolute;
  right: clamp(14px, 1.4vw, 20px);
  bottom: clamp(14px, 1.4vw, 20px);
  width: 148px;
  height: 196px;
  pointer-events: none;
}
.promo__shot {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  border-radius: var(--jm-r-sm);
  /* A hairline in the card's own ink separates the three where they overlap;
     without it the fan reads as one torn photograph. */
  outline: 3px solid var(--jm-ink);
  box-shadow: 0 10px 26px color-mix(in srgb, var(--jm-ink) 66%, transparent);
}
/* The opacities are high on purpose. The card behind them is near-black, so
   a photograph at 50% reads as a black rectangle rather than as a photograph
   — which is exactly what the first attempt looked like. The fan is separated
   by the outline and the rotation, not by fading the ones underneath. */
.promo__shot--1 { transform: rotate(-16deg) translate(-38px, -8px); opacity: .72; }
.promo__shot--2 { transform: rotate(-8deg)  translate(-19px, -4px); opacity: .88; }
.promo__shot--3 { transform: rotate(2deg); }

/* The fan reaches left towards the CTA. Below this the card is too narrow for
   both, so the copy gets the room and the stack steps back behind it. */
@media (max-width: 1360px) and (min-width: 1101px) {
  .promo__cta { position: relative; z-index: 1; }
  .promo__stack { opacity: .55; }
}

/* --- section 12: tablet + mobile ------------------------------------------ */

@media (max-width: 1100px) {
  .s12__grid { grid-template-columns: 1fr; }
  /* Side by side the promo is a tall column beside a wide card; stacked it
     only needs enough height for its own copy. */
  .promo { min-height: 250px; }
}

@media (max-width: 720px) {
  .vs__title { top: 30%; font-size: clamp(18px, 5vw, 26px); }
  .vs__disc { width: 44px; height: 44px; font-size: 13px; }
  .vs__badge, .vs__prize { font-size: 9.5px; padding: 5px 10px; }

  /* Two gold buttons and a "VS" will not fit on one line here. The buttons
     stack and the divider goes — the VS disc over the photos already says
     the same thing. */
  .vs__actions { grid-template-columns: 1fr; }
  .vs__mid { display: none; }

  .promo__stack { right: -50px; bottom: -40px; opacity: .5; }
  .promo__sub, .promo__title { max-width: none; }
}

@media (max-width: 480px) {
  /* Below this the two halves are ~150px wide and the captions collide with
     the seam. One above the other keeps both photographs readable. */
  .vs__halves { grid-template-columns: 1fr; }
  .vs__title { top: 50%; }
  .vs__disc { top: 50%; }
}


/* ==========================================================================
   29. BOOK DIRECTLY — the booking form on the homepage
   --------------------------------------------------------------------------
   The card itself is §17's `.bcard`, unchanged and rendered from the same
   partial book.php uses. All this section adds is the heading group above it
   and the tinted band behind it, so the form reads as a destination rather
   than as another card in a run of cards.
   ========================================================================== */

.hbook {
  background:
    radial-gradient(64% 84% at 50% 0%,
      color-mix(in srgb, var(--jm-accent) 18%, transparent) 0%, transparent 64%),
    var(--jm-ground);
}

.hbook__eyebrow {
  margin: 0 0 12px;
  font-size: 11.5px;
  font-weight: 800;
  letter-spacing: .19em;
  text-transform: uppercase;
  text-align: center;
  color: var(--jm-accent-dim);
}

/* (0,1,0) — Pico's `:is(p,ul,…)~:is(h1,…,h6)` (0,0,2) would otherwise put a
   large top margin on this, because the eyebrow above it is a <p>. */
.hbook__title {
  margin: 0 0 12px;
  font-size: clamp(26px, 3.4vw, 42px);
  font-weight: 800;
  line-height: 1.1;
  letter-spacing: -.024em;
  text-align: center;
  color: var(--jm-heading);
}

.hbook__lede {
  margin: 0 auto clamp(26px, 3.4vw, 40px);
  max-width: 60ch;
  font-size: 15.5px;
  line-height: 1.6;
  text-align: center;
  color: var(--jm-muted);
}


/* ==========================================================================
   27. Area page — the studio block
   ========================================================================== */

.area-studio .gcard { max-width: 440px; margin: 0; }
/* Stacked (below 861px): the card sat flush against the photo's foot. */
@media (max-width: 860px) {
  .area-studio .gcard { margin-bottom: 20px; }
}

/* The right-hand card — 2026-09-29. It was one 16px line beside a 590px
   photo, which read as an empty half. Now a white card on the tinted ground
   (the §24 radius, the §2 shadows) with a gold edge, the studio's own line as
   a serif lede, four fact rows and the booking button.
   Accent as TEXT is --jm-accent-dim throughout: this page is light and
   --jm-accent is ~1.9:1 on white. Selectors carry `.area-studio` so they
   outrank Pico's `p`/`h3`/`ul li` rules without !important. */
.area-studio .area-studio__note {
  position: relative;
  padding: clamp(24px, 3.2vw, 44px);
  background: var(--jm-card);
  border: 1px solid var(--jm-line);
  border-radius: var(--jm-r-lg);
  box-shadow: 0 1px 2px var(--jm-shadow), 0 18px 40px -22px var(--jm-shadow-2);
  overflow: hidden;
}
.area-studio .area-studio__note::before {          /* the gold edge */
  content: '';
  position: absolute;
  inset: 0 auto 0 0;
  width: 4px;
  background: linear-gradient(var(--jm-accent), var(--jm-accent-dim));
}
.area-studio .area-studio__eyebrow {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  margin: 0 0 14px;
  padding: 6px 12px;
  border-radius: var(--jm-pill);
  background: color-mix(in srgb, var(--jm-accent) 14%, var(--jm-card));
  font-size: 11.5px;
  font-weight: 800;
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--jm-accent-dim);
}
.area-studio .area-studio__title {
  margin: 0 0 12px;
  font-family: var(--jm-serif);
  font-size: clamp(26px, 2.6vw, 36px);
  font-weight: 700;
  line-height: 1.15;
  color: var(--jm-heading);
}
.area-studio .area-studio__title em { font-style: italic; color: var(--jm-accent-dim); }
.area-studio .area-studio__lede {
  margin: 0 0 22px;
  font-family: var(--jm-serif);
  font-size: clamp(17px, 1.5vw, 20px);
  line-height: 1.55;
  color: var(--jm-body);
}
.area-studio .area-studio__facts {
  display: grid;
  gap: 12px;
  margin: 0 0 26px;
  padding: 18px 0 0;
  border-top: 1px solid var(--jm-line);
  list-style: none;
}
.area-studio .area-studio__facts li {
  display: flex;
  align-items: center;
  gap: 12px;
  margin: 0;
  list-style: none;
  font-size: 15.5px;
  line-height: 1.45;
  color: var(--jm-heading);
}
.area-studio .area-studio__ico {
  display: grid;
  place-items: center;
  flex: 0 0 34px;
  width: 34px;
  height: 34px;
  border-radius: 50%;
  background: color-mix(in srgb, var(--jm-accent) 16%, var(--jm-card));
  color: var(--jm-accent-dim);
  font-size: 16px;
}
.area-studio .area-studio__acts {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 14px 22px;
}
.area-studio .area-studio__all {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  font-size: 12px;
  font-weight: 800;
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--jm-accent-dim);
}

@media (min-width: 861px) {
  /* Photo left, its blurb beside it. A lone portrait card with one line of
     text underneath leaves a very tall column of nothing next to it. */
  .area-studio {
    display: grid;
    grid-template-columns: minmax(0, 440px) minmax(0, 1fr);
    align-items: center;
    gap: clamp(24px, 4vw, 56px);
  }
  .area-studio h2 { grid-column: 1 / -1; margin-bottom: 0; }
  /* The card fills the photo's height, so the two columns end together. */
  .area-studio .area-studio__note {
    align-self: stretch;
    display: flex;
    flex-direction: column;
    justify-content: center;
  }
  .area-studio .area-studio__eyebrow { align-self: flex-start; }
}


/* ==========================================================================
   46. THE SERVICES VIDEO — .svfilm                        services.php only
   --------------------------------------------------------------------------
   Added 2026-09-07: the client sent a video and asked for it on this page.
   There is no reference on the board, so the block borrows the masthead's own
   split (.stop) rather than inventing a second one: copy left, media right,
   stacking under 900px.

   >>> NO PLAYER, NO SCRIPT. This is a native <video controls>. Every hosted
       embed — SproutVideo, YouTube, Vimeo — is a third-party iframe carrying
       its own JavaScript, which would end both the zero-JavaScript rule and
       the no-third-party rule on one page. The browser's own controls cost
       nothing and are already accessible.                                <<<

   The frame keeps a 16/9 box whether or not a poster exists, so the page does
   not reflow when the file finally lands. `background` under the video is the
   inset panel rather than black: with preload="none" and no poster, the box
   is empty until play, and a black rectangle in the middle of a light page
   reads as a broken image.
   ========================================================================== */

.svfilm {
  padding-block: clamp(34px, 4.4vw, 64px);
  background: var(--jm-ground);
  border-block: 1px solid var(--jm-line);
}

.svfilm__grid { display: grid; gap: clamp(22px, 3vw, 44px); }

.svfilm__title {
  margin: 0 0 14px;
  font-size: clamp(24px, 3vw, 40px);
  font-weight: 800;
  line-height: 1.1;
  letter-spacing: -.025em;
  color: var(--jm-heading);
}

/* Stated on the element, not inherited: Pico sets `color` on `p` explicitly
   and an explicit declaration beats an inherited one at any specificity.
   Same landmine as .signup__title — see section 5 of CLAUDE.md. */
.svfilm__lede {
  margin: 0 0 clamp(18px, 2.4vw, 26px);
  max-width: 46ch;
  font-size: clamp(15px, 1.1vw, 17px);
  line-height: 1.62;
  color: var(--jm-body);
}

.svfilm__frame {
  margin: 0;
  border-radius: var(--jm-r-lg);
  overflow: hidden;                     /* clips the video to the radius */
  background: var(--jm-card-2);
  box-shadow: 0 14px 40px var(--jm-shadow);
}

/* The <video> and the <iframe> are interchangeable in the same frame, so they
   are sized together — swapping one for the other must not move the layout.
   `border: 0` matters for the iframe only; browsers still default it to 2px
   inset, which draws a grey line inside the radius. */
.svfilm__frame video,
.svfilm__frame iframe {
  display: block;
  width: 100%;
  height: auto;
  aspect-ratio: 16 / 9;
  border: 0;
  object-fit: cover;
  background: var(--jm-card-2);
}

/* The third-party disclosure. Rendered ONLY under the embed — see the note
   above $SERVICES_VIDEO. Muted and small: it is a fact a visitor is entitled
   to, not a warning, and this is not the page's message. */
.svfilm__note {
  display: flex;
  gap: 9px;
  align-items: flex-start;
  margin: clamp(16px, 2vw, 22px) 0 0;
  max-width: 44ch;
  font-size: 13px;
  line-height: 1.55;
  color: var(--jm-muted);
}
.svfilm__note svg { flex: 0 0 auto; margin-top: 2px; color: var(--jm-accent-dim); }
.svfilm__note a   { color: var(--jm-accent-dim); text-decoration: underline; }

@media (min-width: 901px) {
  /* Media wider than the copy: the video is the point of the section, and a
     50/50 split makes a 16/9 frame look small beside three lines of text. */
  .svfilm__grid {
    grid-template-columns: minmax(0, .72fr) minmax(0, 1fr);
    align-items: center;
  }
  /* The clips row wants more room than one film did: six portrait players. */
  .svfilm--clips .svfilm__grid { grid-template-columns: minmax(0, .5fr) minmax(0, 1fr); align-items: start; }
  /* The six players are much taller than the copy; it rides along instead
     of floating in the middle of an empty column. */
  .svfilm--clips .svfilm__copy { position: sticky; top: 110px; padding-top: clamp(20px, 6vw, 90px); }
}

/* 2026-09-29 — six portrait treatment clips, 3 × 2 (2 × 3 on a phone). Each
   in a white card with the treatment's name as a link to its card below. */
.svclips {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: clamp(10px, 1.2vw, 16px);
  margin: 0;
  padding: 0;
}
.svclips > li.svclip { margin: 0; list-style: none; }
.svclip__frame {
  padding: 6px;
  border-radius: var(--jm-r-lg);
  background: var(--jm-card);
  box-shadow: 0 10px 28px var(--jm-shadow);
}
.svclip__frame video {
  display: block;
  width: 100%;
  height: auto;
  aspect-ratio: 9 / 16;
  object-fit: cover;
  border-radius: calc(var(--jm-r-lg) - 5px);
  background: var(--jm-ink);
}
.svfilm .svclip__name {
  display: block;
  margin: 8px 2px 0;
  font-size: 14px;
  font-weight: 700;
  color: var(--jm-heading);
  text-decoration: none;
}
.svfilm .svclip__name:hover,
.svfilm .svclip__name:focus-visible { color: var(--jm-accent-dim); }
@media (max-width: 560px) {
  .svclips { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}


/* ==========================================================================
   47. THE ACCOUNT PAGE — identity card and booking-request cards
   --------------------------------------------------------------------------
   Added 2026-09-07: "client needed he acount info name, email, phone number,
   auto user logo ... and Your booking requests smail section more atcrativen
   design".

   >>> THE MONOGRAM IS THE WHOLE AVATAR. No upload, no file storage, no
       Gravatar (a third-party request that leaks a hash of the customer's
       email). It is one <p> with one or two letters in it, and it can never
       fail to load, never need moderating and never cost a request.     <<<

   The request cards replace a five-column table. A table is right on the
   admin desk, where somebody scans fifty rows; here a customer has two or
   three and wants to read one, and the treatment was the third column in
   small type. Same data, same order — the admin desk keeps its table.
   ========================================================================== */

.acct-id {
  display: flex;
  gap: clamp(16px, 2.4vw, 28px);
  align-items: flex-start;
  margin: 0 0 clamp(26px, 3.4vw, 40px);
  padding: clamp(18px, 2.4vw, 26px);
  border: 1px solid var(--jm-line);
  border-radius: var(--jm-r-lg);
  background: var(--jm-card);
  box-shadow: 0 1px 2px var(--jm-shadow);
}

/* The disc. `aspect-ratio` rather than a matching height, so one initial and
   two initials give exactly the same circle. */
/* The monogram fallback. Sized to FILL `.acct-face__disc` since 2026-09-12,
   so an account with a photograph and one without are the same shape and the
   camera badge lands in the same place on both. */
.acct-id__face {
  display: grid;
  place-items: center;
  width: 100%;
  height: 100%;
  margin: 0;
  border-radius: 50%;
  /* A gradient rather than a flat fill — the disc is the biggest thing on the
     card and a solid block of accent was the dullest. Both stops are the
     accent family, so it still follows the theme. */
  background: linear-gradient(145deg, var(--jm-accent-lit), var(--jm-accent-dim));
  color: var(--jm-on-accent);
  font-family: var(--jm-display);
  font-size: clamp(30px, 3.4vw, 42px);
  line-height: 1;
  letter-spacing: .04em;
  user-select: none;
  border: 3px solid var(--jm-card);
  box-shadow: 0 0 0 2px var(--jm-accent), 0 6px 18px var(--jm-shadow);
}

.acct-id__body { min-width: 0; flex: 1 1 auto; }

/* (0,2,0) — beats `.desk__h2` so the card heading does not take the section
   heading's top margin and rule.

   2026-09-12, "inside page name need to colorfull": the serif display with
   the surname in the accent, the same two-tone language the brand headings
   took earlier the same day — applied to a person's name rather than to
   JioMassage. A one-word name renders with no accent half at all rather than
   being split somewhere arbitrary. */
.acct-id .acct-id__name {
  margin: 0 0 16px;
  font-family: var(--jm-serif);
  font-size: clamp(24px, 2.8vw, 34px);
  font-weight: 700;
  line-height: 1.12;
  letter-spacing: -.012em;
  color: var(--jm-heading);
}
/* accent-dim, not accent: the card is white and --jm-accent is ~1.9:1 on it. */
.acct-id .acct-id__name em { font-style: italic; color: var(--jm-accent-dim); }

.acct-id__rows,
.acct-req__rows {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
  gap: 12px clamp(16px, 2.4vw, 32px);
  margin: 0;
}
.acct-id__rows > div,
.acct-req__rows > div { min-width: 0; }

.acct-id__rows dt,
.acct-req__rows dt {
  margin: 0 0 3px;
  font-size: 11px;
  font-weight: 800;
  letter-spacing: .13em;
  text-transform: uppercase;
  color: var(--jm-muted);
}
.acct-id__rows dd,
.acct-req__rows dd {
  margin: 0;
  font-size: 15px;
  font-weight: 600;
  color: var(--jm-heading);
  overflow-wrap: anywhere;          /* a long email must not widen the grid */
}
.acct-id__rows dd a,
.acct-req__rows dd a { color: var(--jm-heading); text-decoration: underline; }
.acct-id__none { font-weight: 500; color: var(--jm-muted); }

.acct-id__note {
  display: flex;
  gap: 8px;
  align-items: flex-start;
  margin: 16px 0 0;
  padding-top: 14px;
  border-top: 1px solid var(--jm-line);
  font-size: 13px;
  line-height: 1.55;
  color: var(--jm-muted);
}
.acct-id__note svg { flex: 0 0 auto; margin-top: 2px; color: var(--jm-accent-dim); }
.acct-id__note a   { color: var(--jm-accent-dim); text-decoration: underline; }

@media (max-width: 560px) {
  /* The disc above the copy: side by side, a 72px circle leaves the email
     about nine characters of room. */
  .acct-id { display: block; }
  .acct-id__face { margin-bottom: 14px; }
}


/* --- the request cards ---------------------------------------------------- */

.acct-reqs {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(320px, 1fr));
  gap: clamp(14px, 1.8vw, 20px);
  margin: 0 0 18px;
  padding: 0;
}
/* Pico's `ul li{list-style:square}` is (0,0,2) — clear it ON THE LI. See §5. */
.acct-reqs li { list-style: none; }

.acct-req {
  padding: clamp(16px, 2vw, 22px);
  border: 1px solid var(--jm-line);
  border-radius: var(--jm-r-lg);
  background: var(--jm-card);
  box-shadow: 0 1px 2px var(--jm-shadow);
}

/* NO flex-wrap. A long treatment name ("Not sure yet — help me choose")
   pushed the reference pill onto a second line in one card and not the
   other, so two cards side by side had their labelled rows at different
   heights. The heading wraps inside its own box instead, and every card
   keeps the same rhythm. */
.acct-req__top {
  display: flex;
  gap: 12px;
  align-items: baseline;
  justify-content: space-between;
  margin-bottom: 14px;
}

.acct-req__name {
  flex: 1 1 auto;
  min-width: 0;                     /* or the heading refuses to wrap at all */
  margin: 0;
  font-size: clamp(16px, 1.5vw, 19px);
  font-weight: 800;
  line-height: 1.25;
  letter-spacing: -.015em;
  color: var(--jm-heading);
}

.acct-req__ref {
  flex: 0 0 auto;                   /* the pill never shrinks or wraps */
  display: inline-flex;
  gap: 7px;
  align-items: center;
  margin: 0;
  padding: 4px 10px;
  border-radius: var(--jm-pill);
  background: var(--jm-chip);
  white-space: nowrap;
}
.acct-req__ref span {
  font-size: 10px;
  font-weight: 800;
  letter-spacing: .13em;
  text-transform: uppercase;
  color: var(--jm-muted);
}
.acct-req__ref code {
  padding: 0;
  background: none;
  font-size: 12px;
  font-weight: 700;
  color: var(--jm-heading);
}

/* The therapist a request asked for. A portrait and two lines, on the card's
   own inset panel so it reads as a detail OF the request rather than as a
   second card inside it. */
.acct-req__ther {
  display: flex;
  gap: 11px;
  align-items: center;
  margin: 16px 0 0;
  padding: 10px 12px;
  border-radius: var(--jm-r);
  background: var(--jm-card-2);
}
.acct-req__ther img {
  flex: 0 0 auto;
  width: 42px;
  height: 42px;
  border-radius: 50%;
  object-fit: cover;
  object-position: center 22%;      /* faces sit above centre in a portrait */
  background: var(--jm-chip);
}
.acct-req__ther span { min-width: 0; }
.acct-req__ther b {
  display: block;
  font-size: 14px;
  font-weight: 800;
  line-height: 1.2;
  color: var(--jm-heading);
}
.acct-req__ther i {
  display: block;
  margin-top: 2px;
  font-size: 12px;
  font-style: normal;
  line-height: 1.4;
  color: var(--jm-muted);
}

/* No portrait to show. The row still renders, because "we will match you" is
   the answer to the question the photo would have answered — an empty space
   would just look like the picture failed to load. */
.acct-req__ther--any { background: none; padding: 10px 0 0; }

.acct-req__state {
  display: flex;
  gap: 8px;
  align-items: center;
  margin: 16px 0 0;
  padding-top: 13px;
  border-top: 1px solid var(--jm-line);
  font-size: 12.5px;
  color: var(--jm-muted);
}
/* Accent, not green. There is no booking-state machine on this site, so this
   dot marks "we have it", not "it is confirmed" — and green would say the
   second thing. It is also the only colour outside the palette we have. */
.acct-req__dot {
  flex: 0 0 auto;
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--jm-accent);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--jm-accent) 22%, transparent);
}


/* ==========================================================================
   48. pricing.php — one section instead of two
   --------------------------------------------------------------------------
   2026-09-07, the client: "page 3 div same section and don't write rate".

   The payment terms were their own `<section class="faq jm-shell">` under the
   price section, so they carried a second gutter and a second block of
   vertical padding and read as a separate page. They are now inside the same
   section, and `.faq` moves onto a <div> — it is a class, not a tag, so every
   accordion rule and every Pico variable re-map still applies.

   `.page__ask` is the single line that replaced the price column. It is the
   only place a price is mentioned on the page now, so it is given a little
   weight rather than set as fine print.
   ========================================================================== */

/* The standalone section padding is what made it a separate block. Inside
   .page, the section already has its own. */
.faq--inline { padding-block: 0; }

/* A second .page__h2 in the same section needs the air the section's own
   padding used to provide between the two blocks. */
.page__h2--next { margin-top: clamp(38px, 5vw, 64px); }

.page__ask {
  display: flex;
  gap: 10px;
  align-items: flex-start;
  margin: 18px 0 0;
  padding: 14px 16px;
  border: 1px solid var(--jm-line);
  border-left: 3px solid var(--jm-accent);
  border-radius: var(--jm-r);
  background: var(--jm-card);
  font-size: 15px;
  line-height: 1.6;
  color: var(--jm-heading);
}
.page__ask svg { flex: 0 0 auto; margin-top: 3px; color: var(--jm-accent-dim); }

/* Two-column variant of the price table — pricing.php, since the rate column
   came out on 2026-09-07.

   `.ptable` was written for THREE columns: 40% / 22% / the rest, with the
   LAST cell right-aligned because the last cell was the money. With two
   columns that right-align lands on Duration and strands it against the far
   edge of a very wide row, which reads as a broken table rather than a short
   one. Both rules are undone here and nowhere else — the admin desk's tables
   share `.ptable` and must not change.

   Written at (0,3,2) rather than (0,2,2): the rules being overridden are
   themselves (0,2,2), and winning on source order alone would break the day
   somebody moves a block in this file. */
.ptable.ptable--2col thead th:nth-child(1) { width: 50%; }
.ptable.ptable--2col thead th:nth-child(2) { width: auto; }
.ptable.ptable--2col thead th:last-child,
.ptable.ptable--2col tbody td:last-child { text-align: left; }

/* Nothing needs 620px of scroll box any more — two short columns fit a phone,
   and forcing the minimum would give the page a horizontal scrollbar it does
   not need. */
.ptable.ptable--2col table { min-width: 0; }

/* The therapist a request asked for, in the desk's bookings table.
   2026-09-07 — it was being stored and shown nowhere, and this is the row
   somebody works from when they ring the customer back. */
.desk .desk-ther {
  display: inline-flex;
  gap: 9px;
  align-items: center;
  text-decoration: none;
  color: var(--jm-heading);
  white-space: nowrap;
}
.desk .desk-ther img {
  width: 30px;
  height: 30px;
  border-radius: 50%;
  object-fit: cover;
  object-position: center 22%;      /* faces sit above centre in a portrait */
  background: var(--jm-chip);
}
/* >>> THE COLOUR IS STATED ON THE SPAN, NOT INHERITED FROM THE ANCHOR, and
       that is the point. `.desk .ptable td a` (0,2,2) paints every link in
       this table accent gold — deliberately, because the PHONE NUMBER is the
       whole reason a booking row exists and ringing it back is the job. A
       gold therapist name beside it competes for exactly that emphasis.

       `.desk .desk-ther` is only (0,2,0) and loses to that rule, so setting
       the colour on the anchor does nothing. Setting it on the child does:
       an explicit declaration beats an inherited value at any specificity —
       the same lesson as the Pico `p` landmine in section 5, used on purpose
       this time.                                                        <<< */
.desk .desk-ther span { font-weight: 700; color: var(--jm-heading); }
.desk .desk-ther:hover span,
.desk .desk-ther:focus-visible span { color: var(--jm-accent-dim); text-decoration: underline; }

/* "Any" is the common case and must not shout louder than a real preference. */
.desk .desk-ther__none { color: var(--jm-muted); font-style: italic; }

/* `.desk .ptable td` sets 14px with vertical-align: middle; a 30px portrait
   in a 14px row needs the cell to stop being padded for text alone. */
.desk .ptable td:has(.desk-ther) { padding-block: 8px; }


/* THE CUSTOMER'S OWN FACE, in the Name cell — 2026-09-12, the desk half of
   the /account/ photo upload. It reuses `.desk-ther`'s geometry exactly, so
   the two portraits in a row are the same size and sit on the same baseline;
   only the fallback is new, because a therapist always has a picture and a
   customer usually will not.

   NOT an anchor — there is no customer page for the desk to open. That is
   also why it needs none of the colour-override reasoning above it. */
.desk .desk-who {
  display: inline-flex;
  gap: 9px;
  align-items: center;
  white-space: nowrap;
}
.desk .desk-who__pic {
  width: 30px;
  height: 30px;
  border-radius: 50%;
  object-fit: cover;
  background: var(--jm-chip);
  border: 1px solid var(--jm-line);
}

/* The monogram, for every booking with no account behind it — which is every
   guest booking and everything written before accounts existed. Muted rather
   than accent: a row WITHOUT a photograph must not draw the eye harder than
   one with, and on this table most rows will be this one. */
.desk .desk-who__ini {
  display: grid;
  place-items: center;
  flex: 0 0 auto;
  width: 30px;
  height: 30px;
  border-radius: 50%;
  background: var(--jm-chip);
  color: var(--jm-muted);
  font-family: var(--jm-display);
  font-size: 12px;
  line-height: 1;
  letter-spacing: .04em;
  user-select: none;
}

.desk .ptable td:has(.desk-who) { padding-block: 8px; }


/* ==========================================================================
   49. FEEL THE DIFFERENCE            ref 38 — board "10101 image next"
   --------------------------------------------------------------------------
   Homepage section 17, between "Massage service near you" and the roster,
   where the client asked for it on 2026-09-07.

   A dark band carrying two columns: a copy card left, a bordered photo panel
   right. The reference's right panel is an escort advert with a lingerie
   photograph and a "30% OFF" badge — the SHAPE is what is reused. Read the
   note above $DIFFERENCE in config.php before touching the copy.

   >>> IT IS DARK ON PURPOSE, between two light sections. The colour pass of
       2026-09-06 turned 7, 8 and 9 light; this deliberately stays dark, as
       the reference is. Adding `jm-lit` to the section in index.php
       re-points the whole ink family and makes it light — one class, no
       other edit.                                                       <<< */

.feel {
  padding-block: clamp(48px, 6vw, 92px);
  background: var(--jm-ink);
  color: var(--jm-on-ink);
}

.feel__grid { display: grid; gap: clamp(22px, 3vw, 46px); }

@media (min-width: 981px) {
  /* Copy wider than the photo: the panel is a portrait and a 50/50 split
     would make the paragraphs a very narrow column. */
  .feel__grid {
    grid-template-columns: minmax(0, 1.15fr) minmax(0, .85fr);
    align-items: center;
  }
}

/* --- the copy card -------------------------------------------------------- */

.feel__card {
  padding: clamp(22px, 3vw, 40px);
  border: 1px solid var(--jm-ink-line-2);
  border-radius: var(--jm-r-lg);
  /* A shade off the band, as in the reference — the card has to read as a
     card without a second colour entering the palette. */
  background: var(--jm-ink-soft);
}

.feel__title {
  margin: 0 0 clamp(16px, 2vw, 24px);
  font-size: clamp(30px, 4.4vw, 58px);
  font-weight: 300;
  line-height: 1.05;
  letter-spacing: -.03em;
  color: var(--jm-on-ink);
}
.feel__title span { display: block; }
/* The one accent word, as the reference's gradient word is. A gradient here
   would be a second colour system; the accent already is the brand. */
.feel__title em { font-style: normal; font-weight: 800; color: var(--jm-accent); }

/* Pico sets `color` on `p` explicitly, so an ancestor's colour is not
   inherited — state it. Same landmine as `.signup__title`, section 5. */
.feel__card p {
  margin: 0 0 14px;
  max-width: 56ch;
  font-size: clamp(14.5px, 1.05vw, 16.5px);
  line-height: 1.7;
  color: var(--jm-nav);
}

.feel__strip {
  display: flex;
  gap: 12px;
  align-items: center;
  margin: clamp(18px, 2.4vw, 26px) 0 0;
  padding: 12px 14px;
  border: 1px solid var(--jm-ink-line);
  border-radius: var(--jm-r);
  background: var(--jm-ink);
}
.feel__strip img {
  flex: 0 0 auto;
  width: 42px;
  height: 42px;
  border-radius: 50%;
  object-fit: cover;
  background: var(--jm-ink-soft);
}
.feel__strip b {
  display: block;
  font-size: 14px;
  font-weight: 800;
  line-height: 1.25;
  color: var(--jm-accent);
}
.feel__strip i {
  display: block;
  margin-top: 2px;
  font-size: 13px;
  font-style: normal;
  line-height: 1.4;
  color: var(--jm-nav-dim);
}

.feel__cta { margin-top: clamp(18px, 2.4vw, 26px); }

/* --- the photo panel ------------------------------------------------------ */

.feel__shot {
  position: relative;
  margin: 0;
  overflow: hidden;
  border: 2px solid var(--jm-accent);
  border-radius: var(--jm-r-lg);
  background: var(--jm-ink-soft);
}
.feel__shot img {
  display: block;
  width: 100%;
  height: auto;
  aspect-ratio: 3 / 4;
  object-fit: cover;
}
/* A veil, so the display type and the badge stay legible whatever the
   photograph does. Drawn on the figure, not a second element. */
.feel__shot::after {
  content: '';
  position: absolute;
  inset: 0;
  pointer-events: none;
  background: linear-gradient(180deg,
              color-mix(in srgb, var(--jm-ink) 62%, transparent) 0%,
              transparent 42%,
              color-mix(in srgb, var(--jm-ink) 78%, transparent) 100%);
}

/* >>> THE BADGE CARRIES ITS OWN GROUND. The figure's veil is enough for the
       display type at the bottom, but not for three lines of small text at
       the top: over the pale half of a studio photograph the third line was
       simply not readable. A photograph is not a background you can rely on,
       and this one changes with $DIFFERENCE['shot'].                    <<< */
.feel__badge {
  position: absolute;
  top: 14px;
  left: 14px;
  z-index: 1;
  display: flex;
  gap: 10px;
  align-items: center;
  max-width: calc(100% - 28px);
  margin: 0;
  padding: 9px 14px 9px 12px;
  border: 1px solid var(--jm-ink-line-2);
  border-radius: var(--jm-r);
  background: color-mix(in srgb, var(--jm-ink) 86%, transparent);
}
.feel__badge b {
  font-family: var(--jm-display);
  font-size: clamp(30px, 3.6vw, 46px);
  line-height: .9;
  letter-spacing: -.01em;
  color: var(--jm-accent);
}
.feel__badge i {
  display: block;
  font-size: 12px;
  font-style: normal;
  font-weight: 800;
  letter-spacing: .13em;
  text-transform: uppercase;
  color: var(--jm-on-ink);
}
.feel__badge u {
  display: block;
  margin-top: 3px;
  max-width: 22ch;
  font-size: 11.5px;
  line-height: 1.35;
  text-decoration: none;
  /* --jm-nav, not --jm-nav-dim: this line states a commercial term and has
     to be readable, not decorative. */
  color: var(--jm-nav);
}

.feel__over {
  position: absolute;
  left: 18px;
  bottom: 42px;
  z-index: 1;
  padding: 0;
  font-family: var(--jm-display);
  font-size: clamp(28px, 3.4vw, 46px);
  line-height: .98;
  letter-spacing: .005em;
  text-align: left;
  color: var(--jm-on-ink);
}
.feel__over span { display: block; color: var(--jm-accent); }

.feel__tag {
  position: absolute;
  left: 18px;
  bottom: 16px;
  z-index: 1;
  font-size: 10.5px;
  font-weight: 800;
  letter-spacing: .16em;
  text-transform: uppercase;
  color: var(--jm-nav-dim);
}

@media (max-width: 980px) {
  /* The photo under the copy and shorter — a full portrait between the card
     and the roster below just pushes the page down. */
  .feel__shot img { aspect-ratio: 16 / 10; }
  .feel__shot { max-width: 560px; }
}


/* ==========================================================================
   50. FLASH OFFERS — therapists.php, foot of the page      NO REFERENCE
   --------------------------------------------------------------------------
   2026-09-07: "offers and promom code every 2 min change flash type design".

   >>> HOW IT ROTATES WITH NO JAVASCRIPT. Four cards share one grid cell and
       cross-fade on a single animation. The cycle is 480s — four slots of
       120s — and each card is delayed by its own slot, so exactly one is on
       screen at a time and it changes every two minutes, live, without a
       reload and without a line of script.

       THE KEYFRAME PERCENTAGES ARE QUARTERS, AND THAT IS WHY THE DECK IS
       FIXED AT FOUR. @keyframes cannot read a custom property, so the slot
       boundaries have to be literal. flash_offers() in config.php always
       returns exactly four for the same reason. Changing the count means
       changing both.                                                    <<<

   All four cards are in the DOM and none is aria-hidden: a screen reader
   reads the complete list in order, which is the whole content. The rotation
   is presentation, and it stops dead under prefers-reduced-motion — where
   the first card is simply shown and the rest are removed from the flow.
   ========================================================================== */

.flash {
  padding-block: clamp(44px, 5.5vw, 84px);
  background: var(--jm-ink);
  color: var(--jm-on-ink);
}

.flash__grid { display: grid; gap: clamp(24px, 3vw, 48px); }

@media (min-width: 941px) {
  .flash__grid {
    grid-template-columns: minmax(0, .9fr) minmax(0, 1.1fr);
    align-items: center;
  }
}

/* --- the copy column ------------------------------------------------------ */

.flash__eyebrow {
  display: inline-flex;
  gap: 8px;
  align-items: center;
  margin: 0 0 12px;
  padding: 5px 12px 5px 10px;
  border: 1px solid var(--jm-ink-line-2);
  border-radius: var(--jm-pill);
  background: var(--jm-ink-soft);
  font-size: 11px;
  font-weight: 800;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--jm-on-ink);
}
/* The only thing on the page that blinks, and it blinks slowly. A "live"
   dot that strobes is an accessibility problem, not a design. */
.flash__dot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--jm-accent);
  box-shadow: 0 0 0 0 color-mix(in srgb, var(--jm-accent) 55%, transparent);
}

.flash__title {
  margin: 0 0 14px;
  font-size: clamp(28px, 3.8vw, 50px);
  font-weight: 800;
  line-height: 1.05;
  letter-spacing: -.03em;
  color: var(--jm-on-ink);
}
.flash__title em { font-style: normal; color: var(--jm-accent); }

/* Pico sets `color` on `p` explicitly — an ancestor's colour is not
   inherited through it. See section 5 of CLAUDE.md. */
.flash__lede {
  margin: 0 0 clamp(18px, 2.2vw, 26px);
  max-width: 46ch;
  font-size: clamp(14.5px, 1.05vw, 16.5px);
  line-height: 1.65;
  color: var(--jm-nav);
}
.flash__note {
  margin: 16px 0 0;
  max-width: 46ch;
  font-size: 12.5px;
  line-height: 1.55;
  color: var(--jm-nav-dim);
}

/* --- the rotating deck ---------------------------------------------------- */

.flash__deck {
  display: grid;
  margin: 0;
  padding: 0;
  list-style: none;
  /* One cell. Every card is placed in it and the tallest sets the height, so
     the panel never resizes as the cards change — a box that grows and
     shrinks every two minutes drags the rest of the page with it. */
}
.flash__deck > .flash__card { grid-area: 1 / 1; }

/* >>> NO `padding: 0` HERE. THE CARDS *ARE* THE `li`s. Pico's
       `ul li{list-style:square}` is (0,0,2) and has to be cleared on the li
       — but `.flash__deck li` is (0,1,1) and `.flash__card` is (0,1,0), so a
       padding reset written here BEAT the card's own padding and set it to
       zero. The copy then ran flat into the card's bottom border.

       Measured, not spotted: the probe reported `padB=0px`. This is the
       third time today one of this project's own rules has outranked
       another one of its own — see `.desk-stats span` in section 5. When a
       component's root element is also a list item, reset only what the
       library actually sets.                                            <<< */
.flash__deck li { list-style: none; margin: 0; }

.flash__card {
  padding: clamp(22px, 2.8vw, 36px);
  border: 1px solid var(--jm-ink-line-2);
  border-radius: var(--jm-r-lg);
  background: var(--jm-ink-soft);
  opacity: 0;
}

.flash__tag {
  display: inline-flex;
  gap: 9px;
  align-items: center;
  margin: 0 0 14px;
  font-size: 11px;
  font-weight: 800;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--jm-accent);
}
.flash__ico {
  display: grid;
  place-items: center;
  width: 30px;
  height: 30px;
  border-radius: var(--jm-r-sm);
  background: color-mix(in srgb, var(--jm-accent) 18%, transparent);
  font-size: 16px;
  color: var(--jm-accent);
}

.flash__a {
  margin: 0 0 10px;
  font-size: clamp(22px, 2.6vw, 34px);
  font-weight: 800;
  line-height: 1.12;
  letter-spacing: -.025em;
  color: var(--jm-on-ink);
}
.flash__b {
  margin: 0;
  max-width: 46ch;
  font-size: clamp(14px, 1vw, 16px);
  line-height: 1.65;
  color: var(--jm-nav);
}

/* Only rendered when $PROMOS holds a real code — see config.php. */
.flash__code { margin: 0 0 10px; }
.flash__code code {
  display: inline-block;
  padding: 8px 18px;
  border: 1px dashed var(--jm-accent);
  border-radius: var(--jm-r);
  background: color-mix(in srgb, var(--jm-accent) 12%, transparent);
  font-size: clamp(20px, 2.4vw, 30px);
  font-weight: 800;
  letter-spacing: .14em;
  color: var(--jm-accent);
}

/* --- the motion ----------------------------------------------------------- */

@media (prefers-reduced-motion: no-preference) {
  .flash__card {
    /* 4 slots x 120s. The negative delay starts each card at its own phase
       instead of waiting one cycle before the deck begins. */
    animation: flash-cycle 480s linear infinite;
    animation-delay: calc(var(--i) * -120s);
  }
  .flash__dot { animation: flash-pulse 2.6s ease-out infinite; }
}

/* Visible for its own quarter, with a short fade at each end. 0-25% is
   slot 0; the fade eats 3% either side so two cards are never both solid. */
@keyframes flash-cycle {
  0%            { opacity: 0; transform: translateY(10px); }
  3%, 22%       { opacity: 1; transform: none; }
  25%, 100%     { opacity: 0; transform: translateY(-10px); }
}

@keyframes flash-pulse {
  0%   { box-shadow: 0 0 0 0 color-mix(in srgb, var(--jm-accent) 55%, transparent); }
  70%  { box-shadow: 0 0 0 9px color-mix(in srgb, var(--jm-accent) 0%, transparent); }
  100% { box-shadow: 0 0 0 0 color-mix(in srgb, var(--jm-accent) 0%, transparent); }
}

/* >>> WITHOUT MOTION THERE IS NO ROTATION, SO THERE MUST STILL BE CONTENT.
       Every card is opacity 0 by default — that is what makes the animation
       work — so a browser that never runs the animation would show an empty
       box. The first card is made solid and the rest are taken out of the
       flow entirely, which also stops the deck reserving four cards' worth
       of height for nothing.                                            <<< */
@media (prefers-reduced-motion: reduce) {
  .flash__card:first-child { opacity: 1; }
  .flash__card:not(:first-child) { display: none; }
}


/* ==========================================================================
   51. HELP CHOOSING — .assist        ref 39 — board "1010102", pricing.php
   --------------------------------------------------------------------------
   A soft tinted band: copy left, a photograph on the right that breaks past
   the band's lower edge, in front of an arch and two chevrons drawn in CSS.

   >>> IT IS AN ACCENT TINT, NOT THE REFERENCE'S PASTEL BLUE AND PINK. The
       colour decision is locked (charcoal + gold, 2026-09-06), so both the
       band and the arch are color-mix()ed off the palette and follow the
       theme. Using the reference's own colours would make this the one
       block on the site that is not the brand.                          <<<

   >>> THE PHOTOGRAPH OVERLAPS, IT IS NOT A CUT-OUT. The reference uses a
       masked PNG of a person whose shoes fall outside the band. Every image
       in this project is a rectangular stock placeholder, so the gesture is
       kept with a rounded panel pulled below the edge — `overflow: visible`
       on the band and a negative margin on the figure. If a real cut-out
       ever arrives, only the figure's rules change.                     <<< */

.assist {
  position: relative;
  /* Room at the foot for the photograph to hang into, so the block below is
     not pushed into it. */
  margin: clamp(30px, 4vw, 54px) 0 clamp(58px, 7vw, 96px);
  padding: clamp(26px, 3.6vw, 54px);
  border-radius: var(--jm-r-lg);
  background: color-mix(in srgb, var(--jm-accent) 14%, var(--jm-card));
  display: grid;
  gap: clamp(20px, 3vw, 40px);
}

@media (min-width: 861px) {
  .assist { grid-template-columns: minmax(0, 1fr) minmax(0, .85fr); align-items: center; }
}

/* --- copy ----------------------------------------------------------------- */

.assist__title {
  margin: 0 0 14px;
  font-size: clamp(24px, 3.2vw, 42px);
  font-weight: 800;
  line-height: 1.12;
  letter-spacing: -.03em;
  color: var(--jm-heading);
}
/* The second line on its own, as the reference's is. */
.assist__title span { display: block; color: var(--jm-accent-dim); }

/* Pico sets `color` on `p` explicitly — state it. See section 5. */
.assist__lede {
  margin: 0 0 clamp(18px, 2.2vw, 26px);
  max-width: 48ch;
  font-size: clamp(14.5px, 1.05vw, 16.5px);
  line-height: 1.68;
  color: var(--jm-body);
}

.assist__link {
  display: inline-flex;
  gap: 12px;
  align-items: center;
  font-size: 15px;
  font-weight: 700;
  color: var(--jm-heading);
  text-decoration: underline;
  text-underline-offset: 4px;
}
/* The circular "+", drawn rather than set as a glyph so it stays centred at
   any font size. Two bars, one rotated. */
.assist__plus {
  position: relative;
  flex: 0 0 auto;
  width: 34px;
  height: 34px;
  border-radius: 50%;
  background: var(--jm-ink);
}
.assist__plus::before,
.assist__plus::after {
  content: '';
  position: absolute;
  inset: 50% auto auto 50%;
  width: 13px;
  height: 2px;
  translate: -50% -50%;
  background: var(--jm-on-ink);
}
.assist__plus::after { rotate: 90deg; }
.assist__link:hover .assist__plus { background: var(--jm-accent-dim); }

/* --- the art -------------------------------------------------------------- */

.assist__art { position: relative; min-height: 210px; }

/* The arch: a rounded-top block behind the photograph, in a weaker tint of
   the same accent so it reads as depth rather than as a second colour. */
.assist__arch {
  position: absolute;
  right: 4%;
  top: -8%;
  width: 52%;
  height: 108%;
  border-radius: 999px 999px var(--jm-r) var(--jm-r);
  background: color-mix(in srgb, var(--jm-accent) 26%, var(--jm-card));
}

/* Two chevrons, as in the reference. One element, one ::before — a border
   trick, so there is no image and no extra markup. */
.assist__chev,
.assist__chev::before {
  position: absolute;
  left: 6%;
  top: 34%;
  width: 0;
  height: 0;
  border-block: 34px solid transparent;
  border-left: 30px solid color-mix(in srgb, var(--jm-accent) 34%, var(--jm-card));
}
.assist__chev::before { content: ''; left: 26px; top: -34px; }

.assist__shot {
  position: relative;
  z-index: 1;
  margin: 0 0 clamp(-46px, -5vw, -30px) auto;   /* hangs past the band's edge */
  width: min(74%, 320px);
  border-radius: var(--jm-r-lg);
  overflow: hidden;
  box-shadow: 0 18px 44px var(--jm-shadow-2);
}
.assist__shot img {
  display: block;
  width: 100%;
  height: auto;
  aspect-ratio: 4 / 5;
  object-fit: cover;
  background: var(--jm-card-2);
}

/* The small floating disc, as in the reference's avatar. */
.assist__disc {
  position: absolute;
  z-index: 2;
  right: 58%;
  top: 2%;
  width: clamp(54px, 6vw, 76px);
  height: clamp(54px, 6vw, 76px);
  border-radius: 50%;
  object-fit: cover;
  border: 4px solid var(--jm-card);
  box-shadow: 0 8px 22px var(--jm-shadow);
  background: var(--jm-card-2);
}

@media (max-width: 860px) {
  /* Stacked. The photograph stops hanging out — under the copy, a panel that
     overlaps the edge just collides with the heading below it. */
  .assist { margin-bottom: clamp(30px, 5vw, 48px); }
  .assist__art { min-height: 0; }
  .assist__shot { margin: 0 auto; width: min(100%, 300px); }
  .assist__arch { right: 2%; width: 44%; height: 100%; }
  .assist__disc { right: auto; left: 4%; top: 6%; }
}
@media (max-width: 520px) {
  /* The decoration is the first thing to go when there is no room for it. */
  .assist__arch, .assist__chev, .assist__disc { display: none; }
}


/* ==========================================================================
   52. SESSION-LENGTH TIERS — .tiers      ref 40 — board "101010212"
   --------------------------------------------------------------------------
   pricing.php, above the treatment table.

   The reference is an escort-service price list; the four-tier card grid
   underneath it is a generic pattern and is what has been reused. Read the
   note above pricing_tiers() in config.php before touching any of it.

   >>> "ADD ALL ANIMATION TYPES" — THERE ARE FOUR, AND ALL FOUR ARE CSS.
       1. a scroll-driven reveal (`animation-timeline: view()`),
       2. a staggered fade down each tick list,
       3. a hover lift on the card,
       4. a slow sheen across the flagged card's ribbon.
       No JavaScript, as everywhere else on this site.

   >>> THE @supports GUARD IS LOAD-BEARING, EXACTLY AS IT IS IN SECTION 35.
       `animation-fill-mode: both` on a timeline that never advances freezes
       every card on its first keyframe — which is `opacity: 0`. Without the
       guard the whole grid is invisible in Firefox. Do not remove it.  <<<
   ========================================================================== */

.tiers {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: clamp(12px, 1.4vw, 20px);
  margin: clamp(22px, 3vw, 36px) 0 clamp(26px, 3.4vw, 44px);
  padding: 0;
  list-style: none;
}
/* Pico's `ul li{list-style:square}` is (0,0,2) — cleared on the li. NOTE: no
   `padding: 0` here, because `.tier` IS the li and sets its own padding. That
   mistake cost the flash cards their bottom padding; see section 50. */
.tiers > li { list-style: none; margin: 0; }

.tier {
  position: relative;
  display: flex;
  flex-direction: column;
  padding: clamp(16px, 1.8vw, 24px);
  border: 1px solid var(--jm-line);
  border-radius: var(--jm-r-lg);
  background: var(--jm-card);
  box-shadow: 0 1px 2px var(--jm-shadow);
}

/* The flagged tier, as the reference's outlined card is. */
.tier--flag {
  border-color: var(--jm-accent);
  box-shadow: 0 10px 30px var(--jm-shadow);
}
.tier__flag {
  position: absolute;
  top: -1px;
  right: -1px;
  margin: 0;
  overflow: hidden;                 /* clips the sheen to the ribbon */
  padding: 5px 12px;
  border-radius: 0 var(--jm-r-lg) 0 var(--jm-r);
  background: var(--jm-accent);
  font-size: 10.5px;
  font-weight: 800;
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--jm-on-accent);
}

.tier__head {
  padding-bottom: 14px;
  margin-bottom: 14px;
  border-bottom: 1px solid var(--jm-line);
}

.tier__mins { display: flex; gap: 6px; align-items: baseline; margin: 0 0 2px; }
.tier__mins b {
  font-size: clamp(30px, 3.4vw, 44px);
  font-weight: 800;
  line-height: 1;
  letter-spacing: -.035em;
  color: var(--jm-heading);
  font-variant-numeric: tabular-nums;
}
.tier__mins span { font-size: 13px; font-weight: 600; color: var(--jm-muted); }

/* `.page__lede`-style paragraphs elsewhere are (0,1,0); this is (0,1,0) too
   and sits after them in the file, so it wins on order — stated explicitly
   rather than relied upon. */
.tier__n { margin: 0 0 14px; font-size: 12.5px; color: var(--jm-muted); }

/* Pico's `button[type=submit],…{width:100%}` does not reach an <a>, but the
   button here should still fill its card. */
.tier__cta { display: block; width: 100%; text-align: center; font-size: 12px; }

.tier__rows { margin: 0; padding: 0; list-style: none; }
.tier__rows li {
  display: flex;
  gap: 8px;
  align-items: flex-start;
  margin: 0 0 8px;
  list-style: none;
  font-size: 13px;
  line-height: 1.4;
}
.tier__rows li:last-child { margin-bottom: 0; }
.tier__rows svg { flex: 0 0 auto; margin-top: 2px; }

/* A tick is the point; a cross is context and must not compete with it. */
.tier__rows .is-yes { color: var(--jm-heading); }
.tier__rows .is-yes svg { color: var(--jm-accent-dim); }
.tier__rows .is-no { color: var(--jm-muted); }
.tier__rows .is-no svg { color: var(--jm-line); }
.tier__rows .is-no span { text-decoration: line-through; text-decoration-thickness: 1px; }

/* --- 3. the hover lift ---------------------------------------------------- */

@media (prefers-reduced-motion: no-preference) {
  .tier { transition: transform .25s cubic-bezier(.2,.7,.3,1), box-shadow .25s ease; }
  .tier:hover {
    transform: translateY(-4px);
    box-shadow: 0 18px 40px var(--jm-shadow-2);
  }
}

/* --- 1 + 2. the scroll-driven reveal and the staggered ticks -------------- */

@supports (animation-timeline: view()) {
  @media (prefers-reduced-motion: no-preference) {
    .tier {
      opacity: 0;
      animation: tier-in linear both;
      animation-timeline: view();
      animation-range: entry 8% cover 26%;
      /* Each card a little behind the one before it. A delay cannot be used
         on a scroll timeline, so the offset is in the range instead. */
      animation-delay: calc(var(--i) * 0s);
    }
    .tier:nth-child(2) { animation-range: entry 12% cover 30%; }
    .tier:nth-child(3) { animation-range: entry 16% cover 34%; }
    .tier:nth-child(4) { animation-range: entry 20% cover 38%; }

    .tier__rows li {
      opacity: 0;
      animation: tier-row-in linear both;
      animation-timeline: view();
      animation-range: entry 10% cover 32%;
    }
  }
}

@keyframes tier-in {
  from { opacity: 0; transform: translateY(22px) scale(.98); }
  to   { opacity: 1; transform: none; }
}
@keyframes tier-row-in {
  from { opacity: 0; transform: translateX(-6px); }
  to   { opacity: 1; transform: none; }
}

/* --- 4. the sheen on the flagged ribbon ----------------------------------- */

@media (prefers-reduced-motion: no-preference) {
  .tier__flag::after {
    content: '';
    position: absolute;
    inset: 0;
    background: linear-gradient(100deg, transparent 20%,
                color-mix(in srgb, var(--jm-on-accent) 45%, transparent) 50%,
                transparent 80%);
    translate: -120% 0;
    animation: tier-sheen 4.5s ease-in-out 1.2s infinite;
  }
}
@keyframes tier-sheen {
  0%, 62% { translate: -120% 0; }
  86%     { translate: 120% 0; }
  100%    { translate: 120% 0; }
}

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

@media (max-width: 1060px) { .tiers { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 560px)  { .tiers { grid-template-columns: minmax(0, 1fr); } }


/* ==========================================================================
   53. about.php — the derived figures row
   --------------------------------------------------------------------------
   2026-09-07: "about.php need to develop some new design, image use my own".

   The page had no photography at all. It now reuses three blocks that already
   existed and needed no new CSS — `.pgsplit` (§44) for the intro, `.ashots`
   (§45) for the studio strip, and `.stop__stats` (§28) for the figures. This
   section is only the spacing the figures row needs outside the services
   masthead it was written for: `.stop__stats` sets `margin: 0` because there
   it sits under a rule of its own.

   Every figure is a {token} stamped in from count() of a config array — see
   the counts block at the foot of config.php — so none of them can go stale
   and none is a claim anybody has to confirm before launch.
   ========================================================================== */

.about__figures {
  margin-block: clamp(26px, 3.4vw, 44px);
  padding-block: clamp(20px, 2.6vw, 30px);
  border-block: 1px solid var(--jm-line);
}

/* >>> CONSECUTIVE PARAGRAPHS IN A CARD RAN TOGETHER, EVERYWHERE. `.lcard p`
       is `margin: 0` — correct for the one-paragraph cards it was written
       for, and wrong the moment a card holds two, which reads as a single
       block of text with a stray line break in it. Found on about.php with
       three; careers.php and the three enquiry pages have two each and have
       had this since they were built.

       `.lcard p + p` is (0,1,2) and beats `.lcard p` (0,1,1), and it touches
       ONLY cards that actually have a second paragraph — nothing with a
       single one moves.                                                 <<< */
.lcard p + p { margin-top: 12px; }


/* ==========================================================================
   54. THE ACCOUNT PHOTO + THE SPA MANAGER BLOCK        account/index.php
   --------------------------------------------------------------------------
   2026-09-12: "this clent login need to update user pic and ours spa manager
   direct contact mobile and telegram and whatsapp".

   Two blocks, both on /account/, both light — the account page has been light
   since §47 and neither of these introduces a dark panel, so none of the
   `color-scheme` handling from §5 is needed here.

   NOTHING WAS DESIGNED. The photo control is §47's own card furniture; the
   manager rows are the shape of §19's help-centre contact tiles with §34's
   channel colours on the icon discs — both already approved.
   ========================================================================== */

/* --- the disc, when it holds a photograph --------------------------------- */

/* Exactly the geometry of `.acct-id__face` (§47), so an account with a photo
   and an account without are the same shape and the card never reflows when
   one is added. `object-fit: cover` because photo_store() already wrote a
   square — this is the belt in case a stored file predates that. */
/* --- the avatar and its camera badge ------------------------------------- */
/* 2026-09-12: "Change photo gooa atractive style use face book design icon
   also new and atrative design".

   The camera button on the lower-right of a round avatar — the pattern every
   social profile uses. THE PATTERN ONLY: no Facebook logo, wordmark or blue,
   which would be passing off another company's mark on a massage site. The
   glyph is this project's own stroke camera in its own gold. */

.acct-face { flex: 0 0 auto; }

.acct-face__disc {
  position: relative;
  width: clamp(84px, 8vw, 112px);
  aspect-ratio: 1;
}

/* >>> THE HEIGHT IS STATED, NOT DERIVED. `height: auto` + `aspect-ratio: 1`
       gives a perfect circle for an image that LOADS and an ellipse for one
       that does not: a broken <img> is sized by its alt text, and the ratio
       then stretches the box to match. Since this image is served by
       account/photo.php behind a session check, "does not load" is a real
       state — it is exactly what a signed-out or expired request produces.
       A stated height keeps the disc round whatever happens.            <<< */
.acct-id__pic {
  display: block;
  width: 100%;
  height: 100%;
  border-radius: 50%;
  object-fit: cover;
  background: var(--jm-chip);           /* while it loads, not a white hole */
  /* A ring with a gap, so the photo reads as deliberately framed. */
  border: 3px solid var(--jm-card);
  box-shadow: 0 0 0 2px var(--jm-accent), 0 6px 18px var(--jm-shadow);
  /* Alt text on a 112px disc is unreadable anyway; keeping it from spilling
     across the name beside it is the lesser of the two. */
  font-size: 10px;
  color: var(--jm-muted);
  overflow: hidden;
}

/* The camera badge. A <label for>, so it opens the file input that lives in
   the photo form further down the card — see the note in account/index.php. */
.acct-face__cam {
  position: absolute;
  right: -2px;
  bottom: -2px;
  display: grid;
  place-items: center;
  width: 36px;
  height: 36px;
  /* Pico shrink-wraps a label that wraps a checkbox or radio (§5). This one
     wraps nothing, but the width is stated so nothing can claim it. */
  margin: 0;
  border-radius: 50%;
  border: 3px solid var(--jm-card);
  background: var(--jm-accent);
  color: var(--jm-on-accent);
  cursor: pointer;
  box-shadow: 0 3px 10px var(--jm-shadow);
  transition: transform .18s ease, background-color .18s ease;
}
.acct-face__cam:hover { transform: scale(1.08); background: var(--jm-accent-lit); }
.acct-face__cam .jm-ico { font-size: 17px; }

/* The badge is a label, so the ring belongs on it when its input has focus —
   otherwise a keyboard user tabbing to the hidden-ish control sees nothing.
   `:has()` is already used elsewhere on this site (the topic chips, the
   therapist picker), so it is not a new dependency. */
.acct-id:has(#ac-photo:focus-visible) .acct-face__cam {
  outline: 2px solid var(--jm-accent-dim);
  outline-offset: 3px;
}

@media (max-width: 560px) {
  /* The card goes to one column at this width and the disc sits over the
     copy. `.acct-id__face` has the matching rule above. */
  .acct-face { margin-bottom: 14px; }
}

/* --- the control ---------------------------------------------------------- */

.acct-photo {
  margin-top: clamp(16px, 2vw, 22px);
  padding-top: clamp(14px, 1.8vw, 18px);
  border-top: 1px solid var(--jm-line);
}

/* 2026-09-12 — "Your photo" and "About you" were muted 11px, the same weight
   as small print, for what are the card's two section headings. Now they sit
   behind a short accent rule, matching the `dt` labels beside them.
   Stated, not inherited: Pico sets `color` on `p` explicitly and an explicit
   declaration beats an inherited one at any specificity. See §5. */
.acct-photo__title {
  display: flex;
  align-items: center;
  gap: 10px;
  margin: 0 0 12px;
  font-size: 11.5px;
  font-weight: 900;
  letter-spacing: .13em;
  text-transform: uppercase;
  color: var(--jm-accent-dim);
}
.acct-photo__title::before {
  content: '';
  flex: 0 0 auto;
  width: 20px;
  height: 2px;
  border-radius: 2px;
  background: var(--jm-accent);
}

.acct-photo__form {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 10px 12px;
  margin: 0;
}

/* THE FILE INPUT IS NOT HIDDEN, and that is deliberate.
   The usual trick — `opacity: 0` over a pretty label — throws away the one
   thing the native control does that nothing else can without JavaScript:
   it PRINTS THE NAME OF THE FILE YOU CHOSE. With no script there is no
   preview and no confirmation, so a customer who cannot see "selfie.jpg"
   beside the button has no way of knowing the file took. ::file-selector-button
   styles the button half and leaves that text alone. */
.acct-photo__file {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px 10px;
  /* Pico shrink-wraps any label wrapping a checkbox or radio (§5). This one
     wraps a FILE input, which that selector does not match — but the width is
     stated anyway so a future Pico release cannot quietly claim it. */
  width: auto;
  margin: 0;
  font-size: 13px;
  font-weight: 700;
  color: var(--jm-heading);
}
.acct-photo__file > .jm-ico { font-size: 17px; color: var(--jm-accent-dim); }

.acct-photo__file input[type="file"] {
  flex: 1 1 190px;
  min-width: 0;                 /* or a long filename widens the whole card */
  margin: 0;
  padding: 0;
  border: 0;
  background: none;
  box-shadow: none;
  font-size: 12px;
  color: var(--jm-muted);
}
.acct-photo__file input[type="file"]::file-selector-button {
  margin-right: 10px;
  padding: 8px 16px;
  border: 1px solid var(--jm-line);
  border-radius: var(--jm-pill);
  background: var(--jm-card-2);
  color: var(--jm-heading);
  font-family: inherit;
  font-size: 12px;
  font-weight: 700;
  letter-spacing: .04em;
  cursor: pointer;
  transition: background .18s ease, border-color .18s ease;
}
.acct-photo__file input[type="file"]:hover::file-selector-button {
  background: var(--jm-chip);
  border-color: var(--jm-accent);
}

/* Pico's `button[type=submit] { width: 100% }` is (0,1,1) and `.btn-solid` is
   only (0,1,0), so a plain class loses and this button would span the card.
   `button.acct-photo__go` ties on specificity and wins on source order — and
   `width` is declared OUTRIGHT rather than left to the flex shorthand, which
   is the mistake the deskbar's "Show" button made (§5, fourth appearance). */
button.acct-photo__go {
  width: auto;
  flex: 0 0 auto;
  padding: 11px 22px;
  font-size: 13px;
}

/* The remove button is a link in all but name: destructive, so it must not
   look as inviting as Save, and must not be a second solid pill beside it. */
.acct-photo__rm { margin: 10px 0 0; }
.acct-photo__rm button {
  width: auto;                  /* same Pico rule as above */
  display: inline-flex;
  align-items: center;
  gap: 7px;
  padding: 0;
  border: 0;
  background: none;
  box-shadow: none;
  font-family: inherit;
  font-size: 12px;
  font-weight: 700;
  letter-spacing: .04em;
  color: var(--jm-muted);
  text-decoration: underline;
  text-underline-offset: 3px;
  cursor: pointer;
}
.acct-photo__rm button:hover,
.acct-photo__rm button:focus-visible { color: var(--jm-heading); }
.acct-photo__rm .jm-ico { font-size: 15px; }

.acct-photo__hint {
  margin: 10px 0 0;
  font-size: 12px;
  line-height: 1.55;
  color: var(--jm-muted);
}

.acct-photo__who {
  display: flex;
  gap: 8px;
  align-items: flex-start;
  margin: 8px 0 0;
  font-size: 12px;
  line-height: 1.55;
  color: var(--jm-muted);
}
.acct-photo__who .jm-ico { flex: 0 0 auto; margin-top: 2px; color: var(--jm-accent-dim); }
.acct-photo__who b { font-weight: 700; color: var(--jm-heading); }

/* The outcome of the last upload. Accent for success rather than green: green
   is not in the palette, and a hard-coded hex here would be the one colour on
   the site that does not follow the theme. */
.acct-photo__flash {
  display: flex;
  gap: 9px;
  align-items: flex-start;
  margin: 0 0 12px;
  padding: 11px 14px;
  border: 1px solid var(--jm-accent);
  border-radius: var(--jm-r);
  background: var(--jm-chip);
  font-size: 13px;
  font-weight: 600;
  line-height: 1.5;
  color: var(--jm-heading);
}
.acct-photo__flash .jm-ico { flex: 0 0 auto; margin-top: 1px; color: var(--jm-accent-dim); }
/* A failure is the same box with the accent taken off it — it is information,
   not an emergency, and the message itself says what went wrong. */
.acct-photo__flash.is-bad { border-color: var(--jm-line); background: var(--jm-card-2); }
.acct-photo__flash.is-bad .jm-ico { color: var(--jm-muted); }

.acct-photo__off {
  display: flex;
  gap: 8px;
  align-items: flex-start;
  margin: 0;
  font-size: 13px;
  color: var(--jm-muted);
}
.acct-photo__off .jm-ico { flex: 0 0 auto; margin-top: 2px; }


/* --- the spa manager ------------------------------------------------------ */

.mgr {
  margin: 0 0 clamp(26px, 3.4vw, 40px);
  padding: clamp(18px, 2.4vw, 26px);
  border: 1px solid var(--jm-line);
  border-radius: var(--jm-r-lg);
  background: var(--jm-card);
  box-shadow: 0 1px 2px var(--jm-shadow);
}

.mgr__head { margin-bottom: clamp(14px, 1.8vw, 20px); }

.mgr__eyebrow {
  margin: 0 0 6px;
  font-size: 11px;
  font-weight: 800;
  letter-spacing: .16em;
  text-transform: uppercase;
  color: var(--jm-accent-dim);
}

/* (0,1,0) is enough — nothing in Pico sets a colour on h2, and the two-tone
   treatment is the same one $MODELS_HEAD and $SIGNUP use. */
.mgr__title {
  margin: 0 0 8px;
  font-family: var(--jm-serif);
  font-size: clamp(21px, 2.6vw, 28px);
  font-weight: 700;
  line-height: 1.18;
  color: var(--jm-heading);
}
.mgr__title em { font-style: italic; color: var(--jm-accent-dim); }

/* Pico sets `color` on `p` explicitly, so this is stated rather than left to
   inherit from `.mgr`. Same landmine as `.signup__title` in §5. */
.mgr__lede {
  margin: 0;
  max-width: 56ch;
  font-size: 14px;
  line-height: 1.6;
  color: var(--jm-muted);
}

.mgr__rows {
  margin: 0;
  padding: 0;
  border-top: 1px solid var(--jm-line);
}
/* Pico's `ul li { list-style: square }` is (0,0,2) and must be cleared ON THE
   LI — clearing it on the UL is inherited and loses. See §5. */
.mgr__rows li { list-style: none; }

.mgr__row { border-bottom: 1px solid var(--jm-line); }

.mgr__row a {
  display: flex;
  align-items: center;
  gap: clamp(12px, 1.6vw, 16px);
  padding: 14px 4px;
  color: var(--jm-heading);
  text-decoration: none;
  transition: padding-inline-start .18s ease;
}
.mgr__row a:hover,
.mgr__row a:focus-visible { padding-inline-start: 10px; text-decoration: none; }

/* The disc carries the channel's own colour, exactly as §34's two chat
   buttons do — a WhatsApp green that is not WhatsApp's green reads as a
   mistake. Both are tokens, so they are still declared in one place. */
.mgr__ico {
  display: grid;
  place-items: center;
  flex: 0 0 auto;
  width: clamp(38px, 4.4vw, 46px);
  aspect-ratio: 1;
  border-radius: 50%;
  font-size: 19px;
  color: #FFFFFF;
  background: var(--jm-accent-dim);         /* the phone: ours, so accent */
}
.mgr__row--whatsapp .mgr__ico { background: var(--jm-whatsapp); }
.mgr__row--telegram .mgr__ico { background: var(--jm-telegram); }

.mgr__body { display: grid; gap: 2px; min-width: 0; flex: 1 1 auto; }
.mgr__body b { font-size: 14px; font-weight: 700; }
.mgr__body i {
  font-style: normal;
  font-size: 12px;
  line-height: 1.45;
  color: var(--jm-muted);
}

/* The number itself, the only channel with a value to print. Tabular figures
   so it does not shimmer against the label above it. */
.mgr__value {
  font-size: 15px;
  font-weight: 700;
  letter-spacing: .02em;
  font-variant-numeric: tabular-nums;
  color: var(--jm-accent-dim);
}

.mgr__go { flex: 0 0 auto; font-size: 17px; color: var(--jm-muted); }
.mgr__row a:hover .mgr__go,
.mgr__row a:focus-visible .mgr__go { color: var(--jm-accent-dim); }

/* Unconfigured channel: dimmed, exactly as the floating rail and §34 do, and
   with its own line of copy saying where the button actually goes. The greying
   is the only thing on the page that says $SITE['telegram'] is still empty. */
.mgr__row.is-pending a { opacity: .6; }
.mgr__row.is-pending .mgr__ico { background: var(--jm-muted); }

.mgr__foot {
  display: flex;
  gap: 8px;
  align-items: flex-start;
  margin: 14px 0 0;
  font-size: 12px;
  line-height: 1.55;
  color: var(--jm-muted);
}
.mgr__foot .jm-ico { flex: 0 0 auto; margin-top: 2px; color: var(--jm-accent-dim); }

@media (max-width: 520px) {
  /* The arrow is decoration and the row is already a link; at this width it
     is competing with the note for the last 40px. */
  .mgr__go { display: none; }
}


/* --- "About you": bio, website, date of birth ----------------------------
   2026-09-12, "user also add website link and bio date ... image and icon".
   The <dt> labels gained an icon each; the three new fields are edited in a
   <details>, which is how every disclosure on this site works.            */

/* (0,1,1), same as the rule it follows, and later in the file — so it wins on
   source order. Scoped to `.acct-id__rows` on purpose: `.acct-req__rows` (the
   booking cards) shares the rule above and has no icons in its labels.

   2026-09-12, "Member since doing bold and color": the labels were 11px
   muted, i.e. the quietest text on the card, which made five useful headings
   read as small print. Bolder, a touch larger, and in the accent. */
.acct-id__rows dt {
  display: flex;
  align-items: center;
  gap: 7px;
  margin-bottom: 5px;
  font-size: 11.5px;
  font-weight: 900;
  letter-spacing: .12em;
  color: var(--jm-accent-dim);
}
.acct-id__rows dt .jm-ico {
  flex: 0 0 auto;
  font-size: 14px;
  /* Decorative — the label says the same thing in words two pixels away. */
  color: var(--jm-accent-dim);
}
/* The values gain a little weight to match, so the pair reads as a unit. */
.acct-id__rows dd { font-weight: 650; }

.acct-about {
  margin-top: clamp(16px, 2vw, 22px);
  padding-top: clamp(14px, 1.8vw, 18px);
  border-top: 1px solid var(--jm-line);
}

/* Stated, not inherited — Pico sets `color` on `p` explicitly. See §5. */
.acct-about__bio {
  margin: 0 0 12px;
  max-width: 70ch;
  font-size: 14.5px;
  line-height: 1.65;
  color: var(--jm-body);
  /* A bio is free text from a person: a 60-character unbroken string would
     otherwise widen the card past its own column. */
  overflow-wrap: anywhere;
}
/* 2026-09-12: "You have not added anything yet." was a bare italic line that
   read as an error. A dashed placeholder box says "there is room for
   something here" instead, which is what an empty optional field means. */
.acct-about__none {
  display: block;
  margin: 0 0 14px;
  padding: 14px 16px;
  border: 1px dashed var(--jm-line);
  border-radius: var(--jm-r);
  background: var(--jm-card-2);
  font-size: 13.5px;
  font-style: italic;
  color: var(--jm-muted);
}

/* --- the edit form -------------------------------------------------------- */

.acct-edit {
  /* Pico paints a summary through three variables of its own, and outranking
     `details[open]>summary:not([role]):not(:focus)` (0,3,2) honestly is not
     worth it. This is the library's intended seam — the same one .faq uses. */
  --pico-accordion-close-summary-color:  var(--jm-accent-dim);
  --pico-accordion-open-summary-color:   var(--jm-heading);
  --pico-accordion-active-summary-color: var(--jm-accent-dim);
  margin: 0;
  border-bottom: 0;
}

/* 2026-09-12 — a pill, not a line of text. "Edit your details" is the only
   control in this block and it was reading as body copy. */
.acct-edit summary {
  position: relative;
  display: inline-flex;
  align-items: center;
  gap: 8px;
  width: fit-content;
  padding: 9px 34px 9px 16px;
  border: 1px solid var(--jm-line);
  border-radius: var(--jm-pill);
  background: var(--jm-card-2);
  font-size: 13px;
  font-weight: 800;
  letter-spacing: .02em;
  line-height: 1.45;          /* Pico pins this to 1rem and clips descenders */
  list-style: none;
  cursor: pointer;
  transition: background-color .18s ease, border-color .18s ease;
}
.acct-edit summary:hover {
  background: var(--jm-chip);
  border-color: var(--jm-accent);
}
.acct-edit summary .jm-ico { font-size: 15px; }

/* Pico's chevron is a background-image with its colour baked into the data
   URI, so it can never follow the theme. Same replacement as .faq's. */
.acct-edit details summary::after,
.acct-edit summary::after {
  content: '';
  position: absolute;
  top: 50%;
  right: 8px;
  display: block;
  float: none;
  width: 7px;
  height: 7px;
  margin: 0;
  border-right: 2px solid currentColor;
  border-bottom: 2px solid currentColor;
  background: none;
  transform: translateY(-70%) rotate(45deg);
  transition: transform .22s ease;
}
.acct-edit[open] summary::after { transform: translateY(-25%) rotate(225deg); }

/* Matched at (0,3,2) so source order decides, exactly as .faq does. */
.acct-edit summary:focus-visible:not([role]) {
  outline: 2px solid var(--jm-accent-dim);
  outline-offset: -2px;
}

.acct-edit__form {
  margin: 8px 0 0;
  padding: clamp(14px, 1.8vw, 18px);
  border: 1px solid var(--jm-line);
  border-radius: var(--jm-r);
  background: var(--jm-card-2);
}

.acct-edit__pair {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
  gap: 0 clamp(14px, 2vw, 22px);
}

.acct-edit__field { margin: 0 0 14px; }
.acct-edit__field label {
  display: block;
  margin-bottom: 5px;
  font-size: 11px;
  font-weight: 800;
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--jm-muted);
}
.acct-edit__field i {
  display: block;
  margin-top: 5px;
  font-style: normal;
  font-size: 11.5px;
  line-height: 1.5;
  color: var(--jm-muted);
}

/* >>> THE :not()s ARE LOAD-BEARING, and the reason is in §5: a rule written
       to size TEXT inputs also matches a checkbox or a radio and stretches it
       to the width of its box, shoving its own label off the page. That cost
       89px of horizontal overflow on book.php once. There is no checkbox in
       this form today; there is no reason to leave the trap armed.      <<< */
.acct-edit__field input:not([type="radio"]):not([type="checkbox"]),
.acct-edit__field textarea {
  width: 100%;
  margin: 0;
  font-size: 14px;
  /* A LIGHT control on a LIGHT card, so the date picker and any option list
     the browser draws for itself are already correct — none of the
     `color-scheme` handling from §5 is needed here. Do not copy section 8's. */
}
.acct-edit__field textarea {
  min-height: 96px;
  line-height: 1.6;
  resize: vertical;
}

.acct-edit__privacy {
  display: flex;
  gap: 8px;
  align-items: flex-start;
  margin: 0 0 14px;
  font-size: 11.5px;
  line-height: 1.55;
  color: var(--jm-muted);
}
.acct-edit__privacy .jm-ico { flex: 0 0 auto; margin-top: 2px; color: var(--jm-accent-dim); }
.acct-edit__privacy a { color: var(--jm-accent-dim); text-decoration: underline; }

/* Pico's `button[type=submit] { width: 100% }` is (0,1,1). `.btn-solid` is
   (0,1,0) and loses; `button.acct-edit__go` ties and wins on source order.
   `width` is declared outright — the flex shorthand does NOT override a
   width, which is how the desk's "Show" button got through an override that
   looked correct (§5). */
button.acct-edit__go {
  width: auto;
  flex: 0 0 auto;
  padding: 11px 22px;
  font-size: 13px;
}


/* ==========================================================================
   55. AREA PAGES — the eight-card roster foot, and the studio strip
   --------------------------------------------------------------------------
   2026-09-12: "rooms pic and entrance and inside room interial also add   and
   therapist 4*2 8 profile create all".

   The roster grid itself needed no new CSS — `.models-grid` is already four
   across, so eight cards fill two rows exactly. What is here is the line that
   explains the two badges, and the room strip that replaced the single photo
   which used to sit beside a one-card grid.
   ========================================================================== */

.awho__foot {
  display: flex;
  gap: 9px;
  align-items: flex-start;
  margin: clamp(18px, 2.4vw, 26px) auto 0;
  max-width: 72ch;
  font-size: 13px;
  line-height: 1.6;
  /* Stated rather than inherited — Pico sets `color` on `p` explicitly, and
     `.models` is a dark section on some pages. Same landmine as §5. */
  color: var(--jm-muted);
}
.awho__foot .jm-ico { flex: 0 0 auto; margin-top: 2px; color: var(--jm-accent-dim); }

/* --- inside the studio ---------------------------------------------------- */

/* --------------------------------------------------------------------------
   REFORMATTED 2026-09-12 — "arrage good format design with font style
   uniqies", "all location do". One change, all twelve area pages.

   Two measured faults, not taste:

     · THE CARDS WERE UNEQUAL HEIGHT — 650px and 630px side by side, because
       the two captions are different lengths and the <figure> inside each
       stretched <li> did not fill it. The row ended ragged.
     · THE IMAGES WERE 727 x 545. Two photographs that size made the block
       958px tall for two pictures and two short captions.

   And the typography ask: an eyebrow, and a SERIF heading with an italic
   accent word — the site's own display treatment, used by the services panel,
   the gallery card titles and `.mgr__title`. NOT Anton; that is reserved for
   the wordmark and for the area banner heading 400px up the same page.
   -------------------------------------------------------------------------- */

.arooms__eyebrow {
  margin: 0 0 8px;
  font-size: 11px;
  font-weight: 800;
  letter-spacing: .17em;
  text-transform: uppercase;
  /* accent-as-TEXT on a light ground, so accent-dim — see §14–16. */
  color: var(--jm-accent-dim);
}

/* (0,1,0) is enough; nothing in Pico sets a colour on h2. */
.arooms__title {
  margin: 0 0 12px;
  font-family: var(--jm-serif);
  font-size: clamp(24px, 3vw, 38px);
  font-weight: 700;
  line-height: 1.14;
  letter-spacing: -.01em;
  color: var(--jm-heading);
}
.arooms__title em { font-style: italic; color: var(--jm-accent-dim); }

.arooms__lede {
  margin: 0 0 clamp(20px, 2.6vw, 30px);
  max-width: 64ch;
  font-size: 15px;
  line-height: 1.65;
  color: var(--jm-muted);
}

/* auto-fit, so the block is correct with TWO cells today and with three the
   moment $AREA_PAGE['entrance'] is filled in — no breakpoint has to change.
   `counter-reset` feeds the serif numeral on each caption, so adding that
   third photograph renumbers the rest by itself. */
.arooms__grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
  gap: clamp(14px, 2vw, 22px);
  margin: 0;
  padding: 0;
  counter-reset: aroom;
}
/* Pico's `ul li { list-style: square }` is (0,0,2) — cleared ON THE LI. §5.
   `display: grid` is what lets the figure inside fill the stretched li: a
   percentage height has nothing to resolve against otherwise, which is why
   the two cards were 650px and 630px. Same fix as `.ashots li`. */
.arooms__grid li { list-style: none; display: grid; }

.arooms__grid figure {
  /* Column flex so the caption can take the slack and every card in the row
     ends on the same line however long its text is. */
  display: flex;
  flex-direction: column;
  height: 100%;
  margin: 0;
  overflow: hidden;
  border: 1px solid var(--jm-line);
  border-radius: var(--jm-r-lg);
  background: var(--jm-card);
  box-shadow: 0 1px 2px var(--jm-shadow);
  transition: transform .28s cubic-bezier(.2, .7, .3, 1), box-shadow .25s ease;
}
.arooms__grid li:hover figure {
  transform: translateY(-3px);
  box-shadow: 0 14px 32px var(--jm-shadow-2);
}

.arooms__grid img {
  display: block;
  width: 100%;
  height: auto;
  /* 3:2, not 4:3. The files are 560x750 portraits and `cover` crops them
     either way; the flatter box is what stops two cells being 545px tall. */
  aspect-ratio: 3 / 2;
  object-fit: cover;
  background: var(--jm-card-2);
}

.arooms__grid figcaption {
  /* flex: 1 — the caption absorbs the difference in text length so the cards
     stay level, which is the whole point of the column flex above. */
  flex: 1 1 auto;
  display: block;
  padding: clamp(14px, 1.7vw, 18px);
}

/* The serif numeral. This is the "unique font" the client asked for, doing
   real work: it numbers the room photographs so a caption is not the only
   thing telling one cell from the next. */
.arooms__grid figcaption b {
  display: block;
  margin-bottom: 6px;
  font-size: 16px;
  font-weight: 800;
  color: var(--jm-heading);
}
.arooms__grid figcaption b::before {
  counter-increment: aroom;
  content: counter(aroom, decimal-leading-zero) ' ';
  margin-right: 8px;
  font-family: var(--jm-serif);
  font-style: italic;
  font-weight: 700;
  font-size: 19px;
  color: var(--jm-accent-dim);
}
.arooms__grid figcaption span {
  display: block;
  font-size: 13.5px;
  line-height: 1.65;
  color: var(--jm-muted);
}


/* ==========================================================================
   56. PROFILE PAGE — more photographs of her, and the studio she works from
   --------------------------------------------------------------------------
   2026-09-12: "profile.php inside page i need same girls image 4 and profile
   details about spa centre room pic and 4 create ervery page".

   The ROOM strip reuses `.ashots` (§43) exactly as the area pages do and
   needs no CSS at all. This section is the PORTRAIT strip, which reuses
   `.ashots` too but must undo two of its rules, plus the studio block.

   >>> THIS SECTION HAS TO BE AT THE FOOT OF THE FILE. It was first written
       up beside `.learn__mark` in §8 (~line 1200) and silently did nothing:
       the rules it overrides are in §43 at ~line 6450, BOTH are (0,1,0), and
       source order decides. The first portrait rendered 354x283 — landscape,
       head cropped — while its three neighbours were correctly 253x316.
       Caught by measuring the four boxes, not by looking at the page. If a
       §57 is ever added, it goes after this, not before it.             <<<
   ========================================================================== */

.pro-shots,
.pro-studio { margin-top: clamp(30px, 4vw, 52px); }

/* Stated, not inherited — Pico sets `color` on `p` explicitly (§5). */
.pro-shots__sub {
  margin: 0 0 clamp(14px, 1.8vw, 20px);
  max-width: 70ch;
  font-size: 14px;
  line-height: 1.6;
  color: var(--jm-muted);
}

/* >>> `.ashots` IS BUILT FOR LANDSCAPE ROOM SHOTS AND THESE ARE PORTRAITS.
       Two of its rules have to go, and both matter:

         · it forces `aspect-ratio: 4 / 3`, which on a 640x800 portrait crops
           the top and the bottom — that is, the head;
         · above 861px it gives column ONE 1.4fr at `5 / 4` and makes the
           other three fill that height. Deliberate rhythm for four room
           photographs, and simply wrong for four pictures of a person.

       So: four equal columns, every image 4/5, and the first-child exception
       undone. The rules being overridden sit inside `min-width: 861px`; these
       sit outside any media query, which is fine — a later rule of equal
       specificity wins wherever that query applies, and the narrow layout is
       set explicitly below.                                             <<< */
.pro-shots__grid li img,
.pro-shots__grid li:first-child img {
  height: auto;
  aspect-ratio: 4 / 5;
}

/* ONE COLUMN PER PHOTOGRAPH, from the count PHP puts in the class. `auto-fit`
   was the obvious choice and is wrong here: with five pictures it drops the
   fifth onto a row of its own at any width where only four tracks fit, and a
   lone portrait under a row of four reads as a mistake rather than as a fifth
   picture. Five across at 1160px is ~220px each, which is still larger than
   the same portraits on the homepage grid. */
.pro-shots__grid            { grid-template-columns: repeat(4, minmax(0, 1fr)); }
.pro-shots__grid--n2        { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.pro-shots__grid--n3        { grid-template-columns: repeat(3, minmax(0, 1fr)); }
.pro-shots__grid--n5        { grid-template-columns: repeat(5, minmax(0, 1fr)); }

@media (max-width: 1060px) {
  /* Five 220px portraits stop working before the other counts do, so this
     breakpoint is for n5 alone — three up, then two below. */
  .pro-shots__grid--n5 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}
@media (max-width: 860px) {
  /* Two up, matching `.ashots`' own narrow layout. The `--n*` modifiers are
     (0,1,0) like the base, so this needs the same specificity to beat them —
     hence every one named rather than a bare `.pro-shots__grid`. */
  .pro-shots__grid,
  .pro-shots__grid--n2,
  .pro-shots__grid--n3,
  .pro-shots__grid--n5 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

/* --- the studio block ----------------------------------------------------- */

.pro-studio__lede {
  margin: 0 0 clamp(16px, 2vw, 22px);
  max-width: 78ch;
  font-size: 15px;
  line-height: 1.7;
  color: var(--jm-body);
}

/* --- the studio table ----------------------------------------------------
   2026-09-12, "section table design create". Was a <dl> in a three-column
   grid; now `.ptable`, the component pricing.php and the admin desk use.

   `.ptable--kv` IS A KEY/VALUE TABLE, and it is self-contained rather than
   stacked on `--2col`, because it has to undo two things the PRICE table
   needs and this one does not:

     · `min-width: 620px` — right for twelve treatments against three
       columns, and it would make five short rows scroll sideways on a phone;
     · `tbody td:last-child { text-align: right }` — written when the last
       cell was the money, and here it would strand every value against the
       far edge of a very wide row. Exactly the fault `.ptable--2col` was
       created for on pricing.php.

   There is no <thead>: the labels are the row headers. `.ptable` already
   styles `tbody th`, so that needed nothing new.                            */

.ptable.ptable--kv table { min-width: 0; }

/* (0,2,3) — beats `.ptable tbody td:last-child` (0,1,2). */
.ptable.ptable--kv tbody td:last-child { text-align: left; }

.ptable.ptable--kv tbody th {
  width: 34%;
  /* The label is two or three words and must not wrap while the value column
     still has room; `anywhere` on the value side takes the strain instead. */
  white-space: nowrap;
  font-size: 12px;
  font-weight: 900;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--jm-accent-dim);
  vertical-align: top;
}
.ptable.ptable--kv tbody td {
  font-size: 14.5px;
  line-height: 1.55;
  color: var(--jm-heading);
  overflow-wrap: anywhere;
  /* The price table sets tabular figures for a money column; a sentence about
     basalt stones does not want them. */
  font-variant-numeric: normal;
}
.ptable.ptable--kv tbody td a { color: var(--jm-accent-dim); text-decoration: underline; }

.pro-studio__table { margin: 0 0 clamp(20px, 2.6vw, 30px); }

@media (max-width: 560px) {
  /* Stack: a 34% label column plus a sentence is unreadable at phone width. */
  .ptable.ptable--kv tbody th,
  .ptable.ptable--kv tbody td { display: block; width: auto; white-space: normal; }
  .ptable.ptable--kv tbody th { border-bottom: 0; padding-bottom: 2px; }
  .ptable.ptable--kv tbody td { padding-top: 0; }
}

/* (0,1,1) — clears Pico's own h3 sizing and its sibling-margin rule, which
   adds a large top margin to a heading that follows a paragraph (§5). */
.pro-studio h3.pro-studio__h3 {
  margin: 0 0 4px;
  font-size: clamp(17px, 1.8vw, 21px);
  font-weight: 800;
  letter-spacing: -.012em;
  color: var(--jm-heading);
}

/* Says the photographs are not of her particular room. The area pages carry
   the same sentence; keep the two in step. */
.pro-studio__note {
  display: flex;
  gap: 9px;
  align-items: flex-start;
  margin: clamp(14px, 1.8vw, 18px) 0 0;
  font-size: 13px;
  line-height: 1.6;
  color: var(--jm-muted);
}
.pro-studio__note .jm-ico { flex: 0 0 auto; margin-top: 2px; color: var(--jm-accent-dim); }


/* ==========================================================================
   57. THE 2026-09-12 HOMEPAGE PASS — colour on six headings, bigger service
       thumbnails, and animation on the cards
   --------------------------------------------------------------------------
   One long client message asking for colour on several titles, larger
   treatment images with motion, and shadow-and-lift on the profile cards.

   THREE RULES HELD THROUGHOUT, and they are why this is short rather than a
   rewrite:

     · every colour is a --jm-* token, so the eight themes still work;
     · accent-as-TEXT on a light ground is --jm-accent-dim (~5.2:1), never
       --jm-accent (~1.9:1) — the trap §14–16 exists for;
     · every animation is behind `prefers-reduced-motion: no-preference`,
       like the hero marquee and the section-7 bubbles.
   ========================================================================== */

/* --- 1. "Learn More About JioMassage" card titles ------------------------- */
/* They were the same near-black as the copy beneath them, so four cards read
   as four paragraphs. The icon beside each was already accent. */
.lcard h3 { color: var(--jm-accent-dim); }
/* The wide Memberships card's inner tiles keep the heading colour — they sit
   inside an already-accented card and a second gold would flatten it. */
.lcard__tiles h3 { color: var(--jm-heading); }

/* --- 2. bigger treatment thumbnails, with motion ------------------------- */
/* 64x48 -> 96x72. The source files are 260x260, so this is still downscaling
   and costs no new bytes — see the image-weight TODO. */
.svc-row__thumb {
  width: 96px;
  height: 72px;
  transition: transform .3s cubic-bezier(.2, .7, .3, 1), box-shadow .25s ease;
}
@media (prefers-reduced-motion: no-preference) {
  .svc-row:hover .svc-row__thumb,
  .svc-row:focus-visible .svc-row__thumb {
    transform: scale(1.06);
    box-shadow: 0 8px 22px color-mix(in srgb, var(--jm-ink) 55%, transparent);
  }
}
/* The row has more height now, so the arrow disc can grow with it. */
.svc-row__go { width: 30px; height: 30px; font-size: 14px; }

@media (max-width: 520px) {
  /* Three columns of text beside a 96px image does not fit a phone. */
  .svc-row__thumb { width: 72px; height: 54px; }
}

/* --- 3. the two members-only studio cards ------------------------------- */
/* "the title should be another color with animation like that". The locked
   pair is Indiranagar and Jayanagar — confirmed with the client 2026-09-12,
   who had said HSR Layout. `.gcard.is-locked` already exists on those two. */
.gcard.is-locked .gcard__name { color: var(--jm-accent-lit); }
.gcard.is-locked .gcard__no   { color: var(--jm-accent); }

@media (prefers-reduced-motion: no-preference) {
  /* A slow breath on the locked pair's title, so the eye finds the two cards
     that can be opened. Opacity and scale only — no colour cycling, which
     would need hard-coded hues. */
  .gcard.is-locked .gcard__name { animation: galLock 3.6s ease-in-out infinite; }
  /* Once revealed, the card is an ordinary photograph and should stop
     asking for attention. `:checked ~ .gcard__frame` is the same selector
     the reveal itself uses (§11). */
  .gcard .lock-switch:checked ~ .gcard__frame .gcard__name { animation: none; }
}
@keyframes galLock {
  0%, 100% { opacity: 1;   transform: scale(1); }
  50%      { opacity: .82; transform: scale(.985); }
}

/* --- 4. "Popular massage treatments in Bangalore" ----------------------- */
/* On the quick-links strip, which sits on the light ground. */
.quick__title em { font-style: normal; color: var(--jm-accent-dim); }

/* --- 5. the profile-grid heading, three tones --------------------------- */
/* Was accent on the middle word only. `<b>` and `<i>` carry the other two;
   both are reset to the heading's own weight and style so the markup is
   semantic emphasis rather than a bold-italic sandwich. */
.models__title b {
  font-weight: inherit;
  color: var(--jm-accent-dim);
}
.models__title i {
  font-style: normal;
  color: var(--jm-muted);
}

/* --- 6. the profile cards: shadow and lift ------------------------------ */
/* "the profiles are little animation format ... shadow little color for the
   images profile images above and down a little animation color and the
   shadow needed". A lift on the card, a slow zoom on the photograph, and an
   accent glow under it — all on the card's own hover/focus, so a keyboard
   reaches it too. */
.models-grid .mcard {
  transition: transform .3s cubic-bezier(.2, .7, .3, 1), box-shadow .3s ease;
}
.models-grid .mcard__photo { overflow: hidden; }
.models-grid .mcard__photo img {
  transition: transform .5s cubic-bezier(.2, .7, .3, 1);
}

@media (prefers-reduced-motion: no-preference) {
  /* `:focus-within` rather than `:focus-visible` — the focusable thing inside
     a card is the VIEW PROFILE link, not the card, so the card has to react
     to focus landing anywhere in it. */
  .models-grid li:hover .mcard,
  .models-grid li:focus-within .mcard {
    transform: translateY(-6px);
    box-shadow:
      0 18px 40px var(--jm-shadow-2),
      0 0 0 1px color-mix(in srgb, var(--jm-accent) 45%, transparent);
  }
  .models-grid li:hover .mcard__photo img,
  .models-grid li:focus-within .mcard__photo img { transform: scale(1.05); }
}

/* --- 7. the two "where would you like it" options ----------------------- */
/* "we need to edit these two tab differently animation format" — so the two
   move differently: the accent one rises, the ink one settles. Different
   motion rather than different colour, because the pair is already gold
   against near-black and a third colour would break the theme. */
.place-opt {
  transition: transform .28s cubic-bezier(.2, .7, .3, 1), box-shadow .28s ease;
}
@media (prefers-reduced-motion: no-preference) {
  .place-opt--1:hover,
  .place-opt--1:focus-visible {
    transform: translateY(-5px) scale(1.015);
    box-shadow: 0 16px 34px color-mix(in srgb, var(--jm-accent-dim) 45%, transparent);
  }
  .place-opt--2:hover,
  .place-opt--2:focus-visible {
    transform: translateY(2px);
    box-shadow:
      inset 0 0 0 1px color-mix(in srgb, var(--jm-accent) 60%, transparent),
      0 10px 26px var(--jm-shadow-2);
  }
  /* The icon disc turns on the way in — one small thing that is the same on
     both, so the pair still reads as a pair. */
  .place-opt__ico { transition: transform .35s cubic-bezier(.2, .7, .3, 1); }
  .place-opt:hover .place-opt__ico,
  .place-opt:focus-visible .place-opt__ico { transform: rotate(-8deg) scale(1.08); }
}

/* The lede is a full paragraph now, so it needs a readable measure rather
   than running the width of the column. */
.place__lede { max-width: 58ch; }


/* ==========================================================================
   58. FAVOURITES + THE RANKING RAILS          refs 41 + 42, 2026-09-23
   --------------------------------------------------------------------------
   The heart (three variants), the two rails beside the roster on
   therapists.php, and "Your favourites" on /account/. See
   includes/favourites.php.

   >>> THE HEART IS A <form> WITH A SUBMIT BUTTON, so Pico's
       `button[type=submit] { width: 100%; margin-bottom }` (0,1,1) applies
       and — the lesson of the desk's "Show" button in CLAUDE.md §5 — has to
       be undone by DECLARING width and margin, not by a flex shorthand.
       Every button rule below is `form.fav button[type="submit"]` (0,2,2).
       Signed out, the heart is an <a class="fav"> instead; both are styled
       from the same `.fav` rules.                                        <<<

   Placed at the foot, after §57, per the §56 note: several of these override
   earlier rules of equal specificity and must win on source order.
   ========================================================================== */

/* --- the heart: shared ---------------------------------------------------- */

form.fav { margin: 0; }

a.fav,
form.fav button[type="submit"] {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  width: auto;
  margin: 0;
  padding: 0;
  border: 1px solid var(--jm-line);
  border-radius: var(--jm-pill);
  background: var(--jm-card);
  color: var(--jm-heading);
  font: inherit;
  line-height: 1;
  text-decoration: none;
  cursor: pointer;
  box-shadow: none;
  transition: background-color .18s ease, color .18s ease, border-color .18s ease, transform .18s ease;
}
a.fav .jm-ico,
form.fav button[type="submit"] .jm-ico { font-size: 17px; }

/* Saved: the accent fill, and the heart itself filled rather than outlined —
   the shape change carries the state for anyone who cannot see the colour. */
form.fav.is-on button[type="submit"] {
  border-color: var(--jm-accent);
  background: var(--jm-accent);
  color: var(--jm-on-accent);
}
form.fav.is-on .jm-ico path { fill: currentColor; }

a.fav:hover,
a.fav:focus-visible,
form.fav button[type="submit"]:hover,
form.fav button[type="submit"]:focus-visible { border-color: var(--jm-accent-dim); }

@media (prefers-reduced-motion: no-preference) {
  a.fav:active,
  form.fav button[type="submit"]:active { transform: scale(.9); }
}

/* --- on a card's photo: the free bottom-right corner ---------------------- */

.fav--photo {
  position: absolute;
  right: 10px;
  bottom: 10px;
  z-index: 2;
}
a.fav.fav--photo,
form.fav.fav--photo button[type="submit"] { width: 40px; height: 40px; }
a.fav.fav--photo,
form.fav--photo:not(.is-on) button[type="submit"] {
  border-color: transparent;
  background: color-mix(in srgb, var(--jm-ink) 72%, transparent);
  color: var(--jm-on-ink);
}
a.fav.fav--photo:hover,
form.fav--photo:not(.is-on) button[type="submit"]:hover { color: var(--jm-accent); }

/* --- in a rail row --------------------------------------------------------- */

a.fav.fav--row,
form.fav.fav--row button[type="submit"] { width: 34px; height: 34px; }
a.fav--row .jm-ico,
form.fav.fav--row button[type="submit"] .jm-ico { font-size: 15px; }

/* --- profile.php's labelled button, under "Book a session" ---------------- */

/* (0,2,1) — `form.fav { margin: 0 }` (0,1,1) would otherwise eat the gap. */
form.fav.fav--wide,
a.fav.fav--wide { display: flex; margin-top: 10px; }
/* Saved, the wide button is a TINT, not a fill: directly under the gold
   "Book a session" a second gold slab reads as two primary actions. */
form.fav.fav--wide.is-on button[type="submit"] {
  border-color: color-mix(in srgb, var(--jm-accent-dim) 45%, transparent);
  background: color-mix(in srgb, var(--jm-accent) 18%, var(--jm-card));
  color: var(--jm-heading);
}
form.fav.fav--wide.is-on .jm-ico { color: var(--jm-accent-dim); }
a.fav.fav--wide,
form.fav.fav--wide button[type="submit"] {
  width: 100%;
  height: 46px;
  font-size: 14px;
  font-weight: 700;
}
form.fav--wide:not(.is-on) button[type="submit"] .jm-ico,
a.fav--wide .jm-ico { color: var(--jm-accent-dim); }

/* --- therapists.php: the roster beside the rails -------------------------- */

.team__cols {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 320px;
  gap: clamp(18px, 2vw, 28px);
  align-items: start;
}
/* The rail takes a column, so the roster drops from four across to three. */
.team__cols .models-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); }

.frail {
  position: sticky;
  top: calc(var(--jm-header-h) + 18px);
  display: grid;
  gap: 16px;
}

.frail__box {
  padding: 18px 18px 8px;
  border: 1px solid var(--jm-line);
  border-radius: var(--jm-r-lg);
  background: var(--jm-card);
  box-shadow: 0 1px 2px var(--jm-shadow), 0 10px 26px var(--jm-shadow);
}

/* (0,1,1) against Pico's heading-after-paragraph margin — see §5. */
.frail .frail__title {
  display: flex;
  align-items: center;
  gap: 8px;
  margin: 0 0 6px;
  font-size: 17px;
  font-weight: 800;
  letter-spacing: -.01em;
  color: var(--jm-heading);
}
/* accent-DIM, stated outright: this page is paper, and plain accent is
   ~1.9:1 on white. */
.frail__title .jm-ico { font-size: 17px; color: var(--jm-accent-dim); }

.frail__list { margin: 0; padding: 0; list-style: none; }

.frail__row {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto auto;
  align-items: center;
  gap: 10px;
  margin: 0;
  padding: 10px 0;
  list-style: none;
}
.frail__row + .frail__row { border-top: 1px solid var(--jm-line); }

.frail__link {
  display: flex;
  align-items: center;
  gap: 11px;
  min-width: 0;
  color: var(--jm-heading);
  text-decoration: none;
}
.frail__link img {
  flex: 0 0 auto;
  width: 48px;
  height: 48px;
  border-radius: 50%;
  object-fit: cover;
  object-position: 50% 20%;
  box-shadow: 0 0 0 2px var(--jm-card), 0 0 0 3px var(--jm-line);
}
.frail__who { display: grid; min-width: 0; }
.frail__who b,
.frail__who i {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.frail__who b { font-size: 14.5px; font-weight: 700; }
.frail__who i { font-size: 12.5px; font-style: normal; color: var(--jm-muted); }
.frail__link:hover b,
.frail__link:focus-visible b { color: var(--jm-accent-dim); }

.frail__n {
  font-size: 12px;
  font-weight: 800;
  color: var(--jm-accent-dim);
  white-space: nowrap;
}

/* (0,2,0) so it beats Pico's `p` colour, which is explicit — §5. */
.frail .frail__empty {
  margin: 4px 0 10px;
  padding: 12px 14px;
  border: 1px dashed var(--jm-line);
  border-radius: var(--jm-r);
  font-size: 13.5px;
  line-height: 1.5;
  color: var(--jm-muted);
}

.frail .frail__note {
  display: flex;
  gap: 8px;
  margin: 0;
  padding: 0 6px;
  font-size: 12.5px;
  line-height: 1.5;
  color: var(--jm-muted);
}
.frail__note .jm-ico { flex: 0 0 auto; margin-top: .15em; color: var(--jm-accent-dim); }

@media (max-width: 1180px) {
  .team__cols { grid-template-columns: minmax(0, 1fr); }
  /* Under the roster the two rails sit side by side while they fit. */
  .frail { position: static; grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .frail__note { grid-column: 1 / -1; }
}
@media (max-width: 900px) {
  .team__cols .models-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (max-width: 700px) {
  .frail { grid-template-columns: minmax(0, 1fr); }
}
@media (max-width: 470px) {
  .team__cols .models-grid { grid-template-columns: 1fr; }
}

/* --- /account/: "Your favourites" — ref 42's card ------------------------- */

.favs .desk__h2 {
  display: flex;
  align-items: center;
  gap: 10px;
}
.favs .desk__h2 .jm-ico { font-size: .9em; color: var(--jm-accent-dim); }
.favs__count {
  display: inline-grid;
  place-items: center;
  min-width: 28px;
  height: 28px;
  padding: 0 8px;
  border-radius: var(--jm-pill);
  background: var(--jm-accent);
  color: var(--jm-on-accent);
  font-size: 13px;
  font-weight: 800;
  letter-spacing: 0;
}

.favs__empty {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 14px;
  padding: 18px 20px;
  border: 1px dashed color-mix(in srgb, var(--jm-accent-dim) 55%, var(--jm-line));
  border-radius: var(--jm-r-lg);
  background: var(--jm-card);
}
.favs__empty p { margin: 0; color: var(--jm-muted); }

.favs__grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(210px, 1fr));
  gap: clamp(14px, 1.6vw, 20px);
  margin: 0;
  padding: 0;
  list-style: none;
}

.favcard {
  display: flex;
  flex-direction: column;
  margin: 0;
  overflow: hidden;
  list-style: none;
  border: 1px solid var(--jm-line);
  border-radius: var(--jm-r-lg);
  background: var(--jm-card);
  box-shadow: 0 1px 2px var(--jm-shadow);
  transition: transform .25s cubic-bezier(.2, .7, .3, 1), box-shadow .25s ease;
}
.favcard__photo {
  position: relative;
  aspect-ratio: 1 / 1;
  background: var(--jm-chip);
}
.favcard__photo img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: 50% 18%;
}

/* The inset breaks the photo's lower edge and sits over the tinted foot,
   as in the reference. In the flow, with equal negative margins either side,
   so the foot's own padding makes room for it. */
.favcard__inset {
  position: relative;
  z-index: 1;
  align-self: center;
  width: 76px;
  height: 76px;
  margin: -38px 0 -30px;
  border-radius: 50%;
  object-fit: cover;
  object-position: 50% 15%;
  border: 3px solid var(--jm-card);
  box-shadow: 0 6px 16px var(--jm-shadow-2);
}

.favcard__foot {
  display: grid;
  justify-items: center;
  gap: 3px;
  flex: 1 1 auto;
  padding: 38px 14px 16px;
  text-align: center;
  background: color-mix(in srgb, var(--jm-accent) 11%, var(--jm-card));
}
.favcard__name {
  font-size: 16.5px;
  font-weight: 800;
  color: var(--jm-heading);
  text-decoration: none;
}
.favcard__name:hover,
.favcard__name:focus-visible { color: var(--jm-accent-dim); }
.favcard__meta { font-size: 12.5px; color: var(--jm-muted); }
.favcard__book {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  margin-top: 8px;
  padding: 7px 14px;
  border: 1px solid color-mix(in srgb, var(--jm-accent-dim) 45%, transparent);
  border-radius: var(--jm-pill);
  background: var(--jm-card);
  font-size: 12.5px;
  font-weight: 800;
  color: var(--jm-accent-dim);
  text-decoration: none;
}
.favcard__book:hover,
.favcard__book:focus-visible { background: var(--jm-accent); border-color: var(--jm-accent); color: var(--jm-on-accent); }

@media (prefers-reduced-motion: no-preference) {
  .favcard:hover,
  .favcard:focus-within {
    transform: translateY(-4px);
    box-shadow: 0 14px 32px var(--jm-shadow-2);
  }
}


/* ==========================================================================
   60. HOMEPAGE PROFILE GRID — "VIEW MORE", FOUR AT A TIME      2026-09-23
   --------------------------------------------------------------------------
   *"click the more view button show more 4 image and click showe next 4"*.
   Zero JavaScript: a hidden checkbox per step sits BEFORE the grid, and each
   step's <label> is the button. Markup and the counting: index.php, §7b.

   >>> FOUR IS WRITTEN HERE AS WELL AS IN $MODELS_HEAD['per']. nth-child
       cannot read a PHP value, so if 'per' changes, the 5 / 8 / 12 / 16 / 20
       below change with it.                                              <<<

   >>> THE CHECKBOXES ARE PINNED TO THE BOTTOM OF `.mmore`. Clicking a label
       focuses its checkbox, and the browser scrolls a focused element into
       view — left at their natural place, above the grid, every press of
       "View more" would throw the visitor back up to the first card.     <<<
   ========================================================================== */

.mmore { position: relative; }
.mmore .mmore__t { top: auto; bottom: 0; left: 50%; }

/* Hidden until their step. (0,4,1). */
.mmore__grid.is-paged .models-grid > li:nth-child(n+5) { display: none; }

/* Revealed, cumulatively. (0,5,1) — beats the rule above. `--last` shows
   whatever remains, so the final press is always complete. */
.mmore__t--1:checked ~ .mmore__grid .models-grid > li:nth-child(-n+8),
.mmore__t--2:checked ~ .mmore__grid .models-grid > li:nth-child(-n+12),
.mmore__t--3:checked ~ .mmore__grid .models-grid > li:nth-child(-n+16),
.mmore__t--4:checked ~ .mmore__grid .models-grid > li:nth-child(-n+20),
.mmore__t--last:checked ~ .mmore__grid .models-grid > li { display: block; }

/* Newly shown cards rise in. An animation starts when an element goes from
   display:none to shown, so only the four just revealed move — the cards
   already on screen keep the same animation value and do not replay it. */
@media (prefers-reduced-motion: no-preference) {
  .mmore__grid.is-paged .models-grid > li:nth-child(n+5) {
    animation: mmore-in .5s cubic-bezier(.2, .7, .3, 1) both;
  }
  .mmore__grid.is-paged .models-grid > li:nth-child(4n+2) { animation-delay: .06s; }
  .mmore__grid.is-paged .models-grid > li:nth-child(4n+3) { animation-delay: .12s; }
  .mmore__grid.is-paged .models-grid > li:nth-child(4n+4) { animation-delay: .18s; }
}
@keyframes mmore-in { from { opacity: 0; transform: translateY(18px); } to { opacity: 1; transform: none; } }

/* --- the button: one label per step, only the current one shown ---------- */

.models__all .mmore__btn {
  display: none;
  align-items: center;
  gap: 10px;
  margin: 0;
  padding: 14px 16px 14px 30px;
  border: 1px solid var(--jm-accent);
  border-radius: var(--jm-pill);
  background: var(--jm-accent);
  color: var(--jm-on-accent);
  font-size: 12px;
  font-weight: 800;
  letter-spacing: .14em;
  text-transform: uppercase;
  cursor: pointer;
  box-shadow: 0 8px 22px color-mix(in srgb, var(--jm-accent-dim) 30%, transparent);
  transition: background-color .18s ease, transform .18s ease, box-shadow .18s ease;
}
.models__all .mmore__btn .jm-ico { transform: rotate(90deg); }   /* points down: "more below" */
.models__all .mmore__btn:hover {
  background: var(--jm-accent-lit);
  box-shadow: 0 12px 28px color-mix(in srgb, var(--jm-accent-dim) 40%, transparent);
}
@media (prefers-reduced-motion: no-preference) {
  .models__all .mmore__btn:hover { transform: translateY(-2px); }
}

/* How many are showing, as a chip inside the button. */
.mmore__n {
  padding: 4px 10px;
  border-radius: var(--jm-pill);
  background: color-mix(in srgb, var(--jm-on-accent) 12%, transparent);
  font-size: 11px;
  letter-spacing: .06em;
}

/* Step 1's button shows first. Each checked step hides its own button and
   shows the NEXT label — a sibling combinator, so it needs no rule per step. */
.models__all .mmore__btn:first-of-type { display: inline-flex; }
.mmore__t--1:checked ~ .mmore__bar .mmore__btn--1 + .mmore__btn,
.mmore__t--2:checked ~ .mmore__bar .mmore__btn--2 + .mmore__btn,
.mmore__t--3:checked ~ .mmore__bar .mmore__btn--3 + .mmore__btn,
.mmore__t--4:checked ~ .mmore__bar .mmore__btn--4 + .mmore__btn { display: inline-flex; }
/* >>> HIDE COMES AFTER SHOW, AT THE SAME (0,5,0). With steps 1 and 2 both
       checked, "step 1 is done, show the label after it" still matches
       label 2 — so label 2's own hide rule has to win the tie, which means
       equal specificity (the doubled class) and later in the file.     <<< */
.mmore__t--1:checked ~ .mmore__bar .mmore__btn.mmore__btn--1,
.mmore__t--2:checked ~ .mmore__bar .mmore__btn.mmore__btn--2,
.mmore__t--3:checked ~ .mmore__bar .mmore__btn.mmore__btn--3,
.mmore__t--4:checked ~ .mmore__bar .mmore__btn.mmore__btn--4,
.mmore__t--last:checked ~ .mmore__bar .mmore__btn.mmore__btn--last { display: none; }

/* Keyboard: the focus ring belongs on the visible button, not the hidden box. */
.mmore__t--1:focus-visible ~ .mmore__bar .mmore__btn--1,
.mmore__t--2:focus-visible ~ .mmore__bar .mmore__btn--2,
.mmore__t--3:focus-visible ~ .mmore__bar .mmore__btn--3,
.mmore__t--4:focus-visible ~ .mmore__bar .mmore__btn--4,
.mmore__t--last:focus-visible ~ .mmore__bar .mmore__btn--last {
  outline: 2px solid var(--jm-accent-dim);
  outline-offset: 3px;
}

/* "See the full team" — hidden while there is more to show, then it takes
   the button's place. Shown from the start if the grid needs no paging. */
.models__all .mmore__all { display: none; }
.mmore__grid:not(.is-paged) ~ .mmore__bar .mmore__all,
.mmore__t--last:checked ~ .mmore__bar .mmore__all { display: inline-flex; }


/* ==========================================================================
   61. REELS SHELF — homepage §19               ref 43, board "reals"
   --------------------------------------------------------------------------
   The client's YouTube Shorts, below "Our service areas". Markup, and the
   list of what was dropped from the reference: includes/reels.php.

   REVISED 2026-09-24: ONE SIDE-SCROLLING ROW AT EVERY WIDTH, with ‹ › arrows
   — "Show more" is gone, at the client's choice.

   >>> THE ARROWS ARE CSS `::scroll-button()`, NOT JAVASCRIPT. Chromium draws
       them and disables each one at its end of the row; browsers without it
       get no arrows and scroll the row as normal — trackpad, shift + wheel,
       touch, keyboard, and the thin scrollbar that is left visible on
       purpose so the row always reads as scrollable. The whole arrow block
       sits behind @supports, so nothing half-styled leaks out.         <<<

   >>> THE FIVE FRAME COLOURS ARE FIVE TONES OF THE PALETTE. The reference's
       frames are five hues; hard-coding them would break theme switching,
       the same call as the verified badge and the headline.            <<<
   ========================================================================== */

.reels { padding-block: clamp(44px, 5.4vw, 76px); background: var(--jm-card); }

/* --- heading row ------------------------------------------------------------ */

.reels__head {
  display: flex;
  align-items: center;
  gap: 14px;
  margin: 0 0 clamp(18px, 2.2vw, 26px);
}
.reels__logo {
  display: grid;
  place-items: center;
  flex: 0 0 auto;
  width: 44px;
  height: 44px;
  padding-left: 3px;
  border-radius: 50%;
  background: radial-gradient(circle at 35% 30%, var(--jm-accent-lit), var(--jm-accent) 60%, var(--jm-accent-dim));
  color: var(--jm-on-accent);
  font-size: 17px;
  box-shadow: 0 6px 16px color-mix(in srgb, var(--jm-accent-dim) 30%, transparent);
}
.reels__logo .jm-ico path,
.reel__pill .jm-ico path { fill: currentColor; }

.reels__titles { flex: 1 1 auto; min-width: 0; }
.reels .reels__title {
  margin: 0;
  font-size: clamp(20px, 2vw, 26px);
  font-weight: 800;
  letter-spacing: -.015em;
  color: var(--jm-heading);
}
.reels .reels__sub { margin: 2px 0 0; font-size: 13.5px; color: var(--jm-muted); }

.reels__all {
  display: inline-flex;
  align-items: center;
  flex: 0 0 auto;
  height: 40px;
  padding: 0 18px;
  border: 1px solid var(--jm-line);
  border-radius: var(--jm-pill);
  background: var(--jm-card);
  font-size: 13.5px;
  font-weight: 700;
  color: var(--jm-heading);
  text-decoration: none;
}
.reels__all:hover,
.reels__all:focus-visible { border-color: var(--jm-accent-dim); color: var(--jm-accent-dim); }
.reels__all.is-pending { border-style: dashed; color: var(--jm-muted); }

/* --- the scrolling row ------------------------------------------------------ */

/* The arrows are positioned against this. */
.reels__body { position: relative; }

.reels__grid {
  --reels-gap: clamp(12px, 1.4vw, 18px);
  display: grid;
  grid-auto-flow: column;
  /* Five cards fill the row on a desktop, so a sixth starts off-screen. */
  grid-auto-columns: calc((100% - 4 * var(--reels-gap)) / 5);
  gap: var(--reels-gap);
  margin: 0;
  padding: 0 0 12px;
  list-style: none;
  overflow-x: auto;
  overscroll-behavior-x: contain;
  scroll-snap-type: x mandatory;
  scroll-behavior: smooth;
  scrollbar-width: thin;
  scrollbar-color: color-mix(in srgb, var(--jm-accent-dim) 45%, transparent) transparent;
}
@media (prefers-reduced-motion: reduce) {
  .reels__grid { scroll-behavior: auto; }
}
.reels__grid:focus-visible { outline: 2px solid var(--jm-accent-dim); outline-offset: 4px; border-radius: var(--jm-r); }
.reels__grid > li { margin: 0; list-style: none; scroll-snap-align: start; }

/* --- the ‹ › arrows: Chromium's CSS scroll buttons ---------------------------- */

@supports selector(::scroll-button(*)) {
  .reels__grid::scroll-button(*) {
    position: absolute;
    top: calc(50% - 60px);
    z-index: 2;
    display: grid;
    place-items: center;
    width: 46px;
    height: 46px;
    border: 1px solid var(--jm-line);
    border-radius: 50%;
    background: var(--jm-card);
    color: var(--jm-heading);
    font-size: 24px;
    line-height: 1;
    cursor: pointer;
    box-shadow: 0 8px 22px var(--jm-shadow-2);
    transition: background-color .18s ease, color .18s ease, opacity .18s ease;
  }
  .reels__grid::scroll-button(left)  { content: "‹" / "Previous reels"; left: -18px; }
  .reels__grid::scroll-button(right) { content: "›" / "Next reels"; right: -18px; }
  .reels__grid::scroll-button(*):hover,
  .reels__grid::scroll-button(*):focus-visible {
    border-color: var(--jm-accent);
    background: var(--jm-accent);
    color: var(--jm-on-accent);
  }
  /* At either end of the row the button is disabled by the browser; hide it
     rather than show a control that does nothing. */
  .reels__grid::scroll-button(*):disabled { opacity: 0; pointer-events: none; }
}

/* --- the cards -------------------------------------------------------------- */

/* One tone per position, cycling every five. */
.reel--1 { --reel-c: var(--jm-accent-dim); }
.reel--2 { --reel-c: var(--jm-ink-soft); }
.reel--3 { --reel-c: color-mix(in srgb, var(--jm-accent) 70%, var(--jm-card)); }
.reel--4 { --reel-c: var(--jm-heading); }
.reel--5 { --reel-c: color-mix(in srgb, var(--jm-accent-dim) 55%, var(--jm-ink)); }

.reel__frame {
  position: relative;
  display: block;
  aspect-ratio: 5 / 7;
  padding: 8px 8px 0;
  overflow: hidden;
  border-radius: var(--jm-r-lg);
  background: var(--reel-c);
  text-decoration: none;
  transition: transform .28s cubic-bezier(.2, .7, .3, 1), box-shadow .28s ease;
}
.reel__frame img {
  display: block;
  width: 100%;
  height: calc(100% - 58px);
  object-fit: cover;
  border-radius: calc(var(--jm-r-lg) - 6px);
  transition: transform .5s cubic-bezier(.2, .7, .3, 1);
}

/* The reference's pill: full width across the frame's foot, a light tint of
   the frame's own tone. */
.reel__pill {
  position: absolute;
  left: 8px;
  right: 8px;
  bottom: 9px;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 7px;
  height: 40px;
  border-radius: var(--jm-pill);
  background: color-mix(in srgb, var(--reel-c) 12%, var(--jm-card));
  font-size: 14px;
  font-weight: 700;
  color: var(--jm-heading);
}
.reel__pill .jm-ico { font-size: 12px; }
.reel:not(.is-live) .reel__pill {
  font-weight: 600;
  font-style: italic;
  color: var(--jm-muted);
}

.reels .reel__title {
  display: -webkit-box;
  margin: 10px 2px 0;
  overflow: hidden;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  font-size: 15px;
  font-weight: 600;
  line-height: 1.35;
  color: var(--jm-heading);
}
.reels .reel__title.is-empty { font-weight: 500; color: var(--jm-muted); }

@media (prefers-reduced-motion: no-preference) {
  .reel.is-live .reel__frame:hover,
  .reel.is-live .reel__frame:focus-visible {
    transform: translateY(-4px);
    box-shadow: 0 16px 34px var(--jm-shadow-2);
  }
  .reel.is-live .reel__frame:hover img,
  .reel.is-live .reel__frame:focus-visible img { transform: scale(1.04); }
}
.reel.is-live .reel__frame:hover .reel__pill { background: var(--jm-accent); color: var(--jm-on-accent); }

/* --- heart · Like · Comment -------------------------------------------------- */

.reel__acts {
  display: flex;
  align-items: center;
  gap: 6px;
  margin: 8px 0 0;
}
.reel__act {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  height: 34px;
  padding: 0 12px;
  border: 1px solid var(--jm-line);
  border-radius: var(--jm-pill);
  font-size: 12.5px;
  font-weight: 700;
  color: var(--jm-heading);
  text-decoration: none;
}
.reel__act .jm-ico { font-size: 14px; color: var(--jm-accent-dim); }
.reel__act:hover,
.reel__act:focus-visible { border-color: var(--jm-accent-dim); color: var(--jm-accent-dim); }

/* The heart — the same `.fav` control as the therapist cards (§58), sized to
   sit in this row. (0,3,2), per the §58 note on Pico's submit width. */
a.fav.fav--reel,
form.fav.fav--reel button[type="submit"] { width: 34px; height: 34px; }
a.fav.fav--reel .jm-ico,
form.fav.fav--reel button[type="submit"] .jm-ico { font-size: 15px; }

.reels .reels__note { margin: 14px 0 0; font-size: 12.5px; color: var(--jm-muted); }

/* --- self-hosted reels (2026-09-29) ------------------------------------------
   The client's own 9:16 treatment clips play in the frame itself, so the
   frame takes the clip's shape and the "Play" pill gives way to the native
   controls — a pill over a controls bar would cover it. Same tinted frame. */
.reel--vid .reel__frame { aspect-ratio: 9 / 16; padding: 8px; }
.reel--vid .reel__frame video {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  border-radius: calc(var(--jm-r-lg) - 6px);
  background: var(--jm-ink);
}

/* --- Like · Comment · Share on a self-hosted reel (2026-09-29) ---------------
   Three equal pills under the video. The Like is a form (it POSTs), the
   Comment a link to reel.php, the Share a <details> popover — all three are
   drawn as .reel__act so they read as one row. */
.reels .reel__acts--v,
.reelpage .reel__acts--v { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 6px; }
.reel__acts--v > * { min-width: 0; }
.reel__acts--v .reel__act { justify-content: center; width: 100%; cursor: pointer; }

/* Pico: `button[type=submit]` is (0,1,1) and sets width 100%, a fill, a
   border and padding; and `form` has a bottom margin. (0,3,1) restates all of
   it so the button looks like its two neighbours. */
.reel__acts--v form.reel__like { margin: 0; }
.reel__acts--v form.reel__like button.reel__act {
  width: 100%;
  margin: 0;
  padding: 0 12px;
  border: 1px solid var(--jm-line);
  background: transparent;
  box-shadow: none;
  color: var(--jm-heading);
  line-height: 1;
}
.reel__acts--v form.reel__like button.reel__act:hover,
.reel__acts--v form.reel__like button.reel__act:focus-visible { border-color: var(--jm-accent-dim); color: var(--jm-accent-dim); }
.reel__acts--v form.reel__like.is-on button.reel__act {
  border-color: var(--jm-accent-dim);
  background: color-mix(in srgb, var(--jm-accent) 16%, var(--jm-card));
  color: var(--jm-accent-dim);
}
.reel__acts--v form.reel__like.is-on .jm-ico path { fill: currentColor; }

.reel__share { position: relative; margin: 0; }
.reel__share > summary.reel__act { list-style: none; }
/* Pico: `details[open] > summary { margin-bottom: … }` pushed the open pill
   out of line with its two neighbours. */
.reel__acts--v details.reel__share[open] > summary.reel__act { margin-bottom: 0; }
.reel__share > summary.reel__act::-webkit-details-marker { display: none; }
/* Pico's accordion chevron, (0,0,3) — see §5. Not wanted on a pill. */
.reels .reel__share > summary::after,
.reelpage .reel__share > summary::after { content: none; display: none; }
.reel__share[open] > summary.reel__act { border-color: var(--jm-accent-dim); color: var(--jm-accent-dim); }

/* Opens UPWARD, over the video: the shelf is a horizontal scroll container,
   which clips anything that hangs below the cards. */
.reel__share-menu {
  position: absolute;
  right: 0;
  bottom: calc(100% + 6px);
  z-index: 3;
  display: grid;
  min-width: 150px;
  padding: 6px;
  border: 1px solid var(--jm-line);
  border-radius: var(--jm-r);
  background: var(--jm-card);
  box-shadow: 0 12px 30px var(--jm-shadow-2);
}
.reel__share--page .reel__share-menu { bottom: auto; top: calc(100% + 6px); left: 0; right: auto; }
.reel__share-menu a {
  display: flex;
  align-items: center;
  gap: 9px;
  padding: 8px 10px;
  border-radius: var(--jm-r-sm);
  font-size: 13.5px;
  font-weight: 600;
  color: var(--jm-heading);
  text-decoration: none;
}
.reel__share-menu a .jm-ico { font-size: 16px; color: var(--jm-accent-dim); }
.reel__share-menu a:hover,
.reel__share-menu a:focus-visible { background: var(--jm-chip); }

/* --- the desk's reel-comment queue ------------------------------------------ */
.desk .desk-rc__acts { display: flex; flex-wrap: wrap; align-items: center; gap: 10px; margin-top: 10px; }
.desk .desk-rc__acts form { margin: 0; }
/* Pico's button[type=submit] width:100% — (0,3,2) and `width: auto` stated,
   the flex lesson from §5. */
.desk .desk-rc__acts form button[type="submit"] { width: auto; margin: 0; padding: 7px 16px; font-size: 13px; }
.desk .desk-rc__acts form button.desk-rc__hide[type="submit"] {
  border: 1px solid var(--jm-line);
  background: transparent;
  color: var(--jm-heading);
}
.desk .desk-rc__acts a { font-size: 13px; font-weight: 700; color: var(--jm-accent-dim); }
.desk .desk-rc__st { padding: 1px 8px; border-radius: var(--jm-pill); background: var(--jm-chip); }
.desk .desk-rc--pending { border-left: 3px solid var(--jm-accent-dim); padding-left: 12px; }
.desk .desk-rc--hidden { opacity: .6; }

/* --- reel.php --------------------------------------------------------------- */
.reelpage__crumb { margin-bottom: 18px; }
.reelpage__grid { display: grid; gap: clamp(20px, 3vw, 40px); align-items: start; }
@media (min-width: 821px) {
  .reelpage__grid { grid-template-columns: minmax(0, 360px) minmax(0, 1fr); }
}
.reelpage__video { max-width: 360px; margin-inline: auto; width: 100%; }
.reelpage .reelpage__body h1 { margin: 0 0 14px; }
.reelpage .reel__acts--v { max-width: 420px; }
.reelpage .reelpage__links { display: flex; flex-wrap: wrap; align-items: center; gap: 16px; margin: 20px 0 24px; }
.reelpage .reelpage__about { font-weight: 700; color: var(--jm-accent-dim); }
.reelpage__comments h2 { display: flex; align-items: center; gap: 10px; margin: 0 0 12px; font-size: 20px; }
.reelpage__n {
  display: inline-grid;
  place-items: center;
  min-width: 26px;
  height: 26px;
  padding: 0 8px;
  border-radius: var(--jm-pill);
  background: var(--jm-chip);
  font-size: 13px;
  color: var(--jm-heading);
}
.reelpage__list { margin: 0 0 16px; padding: 0; }
.reelpage__list > li { margin: 0; padding: 12px 0; list-style: none; border-top: 1px solid var(--jm-line); }
.lcard .reelpage__who { display: flex; gap: 10px; align-items: baseline; margin: 0 0 4px; font-size: 14px; color: var(--jm-heading); }
.lcard .reelpage__who time { font-size: 12.5px; color: var(--jm-muted); }
.lcard .reelpage__text { margin: 0; font-size: 14.5px; line-height: 1.6; color: var(--jm-body); overflow-wrap: anywhere; }
.lcard .reelpage__none { margin: 0 0 14px; color: var(--jm-muted); }
.lcard .reelpage__ok,
.lcard .reelpage__err {
  margin: 0 0 14px;
  padding: 10px 14px;
  border-radius: var(--jm-r);
  background: var(--jm-chip);
  color: var(--jm-heading);
}
.lcard .reelpage__err { border-left: 3px solid var(--jm-accent-dim); }
.reelpage__form { margin-top: 18px; padding-top: 16px; border-top: 1px solid var(--jm-line); }
.reelpage__form h3 { margin: 0 0 10px; font-size: 16px; }
.reelpage__form textarea { width: 100%; }
.reelpage__form small { display: block; margin-top: 6px; color: var(--jm-muted); }
.reelpage__form button.reelpage__send { width: auto; margin-top: 12px; }
.reelpage .reelpage__more { margin-top: 18px; }
.reelpage .reelpage__more a { font-weight: 700; color: var(--jm-accent-dim); }

/* --- widths ------------------------------------------------------------------ */

@media (max-width: 1180px) {
  .reels__grid { grid-auto-columns: minmax(190px, 30%); }
  /* The arrows would sit on the cards at the screen edge; the row swipes. */
  @supports selector(::scroll-button(*)) {
    .reels__grid::scroll-button(*) { display: none; }
  }
}
@media (max-width: 700px) {
  .reels__grid { grid-auto-columns: 62%; }
  .reels__head { flex-wrap: wrap; }
  .reels__all { order: 3; }
}


/* ==========================================================================
   62. HOMEPAGE READABILITY PASS                                2026-09-24
   --------------------------------------------------------------------------
   With the client's own copy going in (their Notion "Home page content"),
   they asked for it to be "very attractive, user readable". Measured first,
   not guessed: the treatment descriptions on the dark panel were 13px at a
   1.45 line height — the smallest running text on the page, on the darkest
   ground. Everything else was 14–15.5px.

   Each rule is scoped to a HOMEPAGE section (.learn, .svc, .gal, .why,
   .hbook) and outranks the base rule, so the same components on other pages
   — `.lcard` above all — do not move. Sizes only, plus one step more line
   height; no new colours and no new fonts.
   ========================================================================== */

.learn .lcard p { font-size: 16px; line-height: 1.65; }             /* was 15 */
.learn .ltile span { font-size: 15px; line-height: 1.55; }           /* was 14 */

.svc .svc-row__body b { font-size: 16px; }                           /* was 15 */
.svc .svc-row__body span { font-size: 14.5px; line-height: 1.55; }   /* was 13 */

.gal .gal__sub { font-size: 17px; line-height: 1.65; }               /* was 15 */

.why .why-list p { font-size: 15.5px; line-height: 1.65; }           /* was 14.5 */

.hbook .hbook__lede { font-size: 17px; line-height: 1.7; max-width: 62ch; }  /* was 15.5 */


/* ==========================================================================
   63. /account/ — SAVED REELS                                  2026-09-24
   --------------------------------------------------------------------------
   Reels saved from the homepage shelf (§61), listed above the saved
   therapists (§58) in "Your favourites". Small portrait cards: poster, title,
   the same heart. Poster opens the Short on YouTube.
   ========================================================================== */

.favs .favs__h3 {
  display: flex;
  align-items: center;
  gap: 8px;
  margin: 18px 0 12px;
  font-size: 15px;
  font-weight: 800;
  letter-spacing: .02em;
  color: var(--jm-heading);
}
.favs__h3 .jm-ico { color: var(--jm-accent-dim); }

.favs__reels {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
  gap: 14px;
  margin: 0 0 8px;
  padding: 0;
  list-style: none;
}
.favreel {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  align-items: start;
  gap: 8px;
  margin: 0;
  list-style: none;
}
.favreel__art {
  position: relative;
  grid-column: 1 / -1;
  display: block;
  aspect-ratio: 5 / 7;
  overflow: hidden;
  border-radius: var(--jm-r-lg);
  background: var(--jm-chip);
}
.favreel__art img { display: block; width: 100%; height: 100%; object-fit: cover; }
.favreel__play {
  position: absolute;
  left: 50%;
  top: 50%;
  display: grid;
  place-items: center;
  width: 46px;
  height: 46px;
  margin: -23px 0 0 -23px;
  padding-left: 3px;
  border-radius: 50%;
  background: var(--jm-accent);
  color: var(--jm-on-accent);
  font-size: 16px;
  box-shadow: 0 0 0 6px color-mix(in srgb, var(--jm-accent) 25%, transparent);
}
.favreel__play .jm-ico path { fill: currentColor; }
.favs .favreel__title {
  margin: 2px 0 0;
  font-size: 13.5px;
  font-weight: 600;
  line-height: 1.35;
  color: var(--jm-heading);
}


/* ==========================================================================
   64. THE CLIENT'S OWN COPY — three homepage blocks            2026-09-24
   --------------------------------------------------------------------------
   2b "Our story", 3b "Every treatment, in detail" and 9e "First massage?",
   all written from the client's Notion "Home page content". Built from
   approved components (the wide text card, the Learn More tiles, the FAQ
   accordion, the card grid), so this block is spacing, sizes and the two
   small links only — the §62 readable sizes, applied to the new text.
   ========================================================================== */

/* --- 2b. Our story --------------------------------------------------------- */
.story .lcard__cols p { max-width: 70ch; font-size: 16px; line-height: 1.7; }
.story .lcard__cols p + p { margin-top: 12px; }
.story__tiles { margin-top: 20px; }
/* The year is the headline of each tile. */
.story__tiles .ltile b {
  font-family: var(--jm-serif);
  font-size: 26px;
  font-style: italic;
  line-height: 1.1;
  color: var(--jm-accent-dim);
}
.story__tiles .ltile span { font-size: 14.5px; }

/* --- 3. The treatment panel, now carrying the guide's longer text --------- */
/* 2026-09-24, the client: *"user friendly and image and content not equal and
   reading word color not bright"*. MEASURED before changing anything:
     · every photo was 72px tall beside 94–139px of text — never equal;
     · the description grey was rgb(143,143,143), 6.0:1 on the ink: legal,
       but dim for three or four lines of reading on a dark panel;
     · three columns left ~290px of text per row — four or five short lines.
   So: TWO columns on a desktop (one below 900px), the photo STRETCHES to the
   full height of its row so image and text are always equal, and the
   description is near-white on-ink. All (0,2,0), after §57 and §62, so they
   win on specificity and on order. */
.svc .svc-list { columns: 2; }
@media (max-width: 900px) { .svc .svc-list { columns: 1; column-rule: none; } }

.svc .svc-row { align-items: stretch; gap: 18px; padding-block: 18px; }
/* `height: auto` releases the fixed 72px, and `contain: size` stops the
   image's OWN ratio from sizing the row — without it the first attempt made
   the photo 150px tall beside 106px of text, unequal the other way. With it,
   the text alone sets the row's height and the image stretches to fill it
   exactly; object-fit crops. */
.svc .svc-row__thumb {
  width: 150px;
  height: auto;
  contain: size;
  /* And the width/height ATTRIBUTES map to `aspect-ratio: auto 64/48`, which
     survives `contain: size` — measured: 150 wide gave exactly 113 tall
     (150 × ¾) beside 81–106px of text. `auto` alone drops the ratio. */
  aspect-ratio: auto;
  border-radius: var(--jm-r);
}
.svc .svc-row__body { align-self: center; }
/* The treatment NAME in the brand gold, 2026-09-24: *"svc-row__body heading
   need to different color"* — white name over near-white text read as one
   block. Gold on this ink is ~10:1. The hover, which used to turn the name
   gold, now turns it WHITE instead, so hovering still visibly changes it;
   (0,4,1) to beat the base hover rule (0,3,1). */
.svc .svc-row__body b { font-size: 17px; margin-bottom: 6px; color: var(--jm-accent); }
.svc .svc-row:hover .svc-row__body b,
.svc .svc-row:focus-visible .svc-row__body b { color: var(--jm-on-ink); }
.svc .svc-row__body span {
  font-size: 15px;
  line-height: 1.65;
  color: color-mix(in srgb, var(--jm-on-ink) 86%, transparent);
}
.svc .svc-row__go { align-self: center; }

@media (max-width: 520px) {
  .svc .svc-row { gap: 14px; }
  .svc .svc-row__thumb { width: 96px; }
}

/* --- 9e. First massage? ---------------------------------------------------- */
.first .page__lede { font-size: 17px; line-height: 1.65; }
.first .lcard p { font-size: 16px; line-height: 1.65; }
.first__grid { margin-top: 8px; }


/* ==========================================================================
   65. THERAPISTS ON SHIFT, INSIDE pricing.php                    2026-09-25
   --------------------------------------------------------------------------
   The client asked for the homepage's section 9 "below price". pricing.php
   is ONE `.page.jm-shell` section on purpose (2026-09-07, "page 3 div same
   section"), so the roster goes inside it as `.roster--inline`: no second
   gutter, no band padding, and the page's own gap above and below. Its
   background is already the page ground under `.jm-lit`, so it needs no
   override for that.
   ========================================================================== */
.roster.roster--inline {
  padding-block: 0;
  margin-block: clamp(38px, 5vw, 64px);
}

/* ==========================================================================
   66. REVIEW MODE — ?review=1                                     2026-09-25
   --------------------------------------------------------------------------
   Marks where the client's own copy (their Notion "Home page content") is on
   the page. Nothing here matches unless <body> has .jm-review, which only
   header.php adds and only for ?review=1 — visitors never see any of it.

   The two colours are deliberately NOT palette colours: a marker has to
   stand out against every theme, including the gold, so it cannot be a
   theme token. They are still tokens, defined once, here, and only inside
   review mode — so theme switching is untouched.
   ========================================================================== */
.jm-review {
  --jm-review-words: #e0217a;
  --jm-review-topic: #1f6fe0;
}
.jm-review [data-mine="words"] {
  background: color-mix(in srgb, var(--jm-review-words) 18%, transparent);
  outline: 2px solid var(--jm-review-words);
  outline-offset: 3px;
  border-radius: var(--jm-r-sm);
}
.jm-review [data-mine="topic"] {
  background: color-mix(in srgb, var(--jm-review-topic) 10%, transparent);
  outline: 2px dashed var(--jm-review-topic);
  outline-offset: 3px;
  border-radius: var(--jm-r-sm);
}
/* 2026-10-06: "pink gold" for what the latest pass added or changed. A blend
   of the review pink and the brand accent, so it reads as neither of the
   other two keys. */
/* An inset shadow, not `background`: a background would REPLACE a dark
   card's own (the offers coupon went pale pink with white text on it). The
   shadow tints over whatever the element already paints. */
.jm-review [data-mine="new"] {
  box-shadow: inset 0 0 0 100vmax color-mix(in srgb,
      color-mix(in srgb, var(--jm-review-words) 40%, var(--jm-accent)) 20%, transparent);
  outline: 2px solid color-mix(in srgb, var(--jm-review-words) 55%, var(--jm-accent));
  outline-offset: 3px;
  border-radius: var(--jm-r-sm);
}

.jm-review-bar {
  position: sticky;
  top: 0;
  z-index: 1000;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px 22px;
  padding: 10px 16px;
  font-size: 14px;
  line-height: 1.4;
  color: var(--jm-heading);
  background: var(--jm-card);
  border-bottom: 3px solid var(--jm-review-words);
  box-shadow: 0 2px 10px var(--jm-shadow);
}
.jm-review-bar span { display: inline-flex; align-items: center; gap: 8px; }
.jm-review-bar a { margin-left: auto; font-weight: 700; color: var(--jm-accent-dim); }
.jm-review-key {
  display: inline-block;
  width: 22px;
  height: 14px;
  outline-offset: 0;
}

/* ==========================================================================
   §67  AREA SEO TEXT  (area-page.php, 2026-09-29)
   The client's own copy for one area, as plain headings and paragraphs —
   "normal heading and paragraph", no cards. Only width and rhythm are set;
   the headings keep the page's own h2 and colour.
   ========================================================================== */
.aseo .aseo__body > * { max-width: 820px; }   /* the text, not the shell — left edge stays on the gutter */
.aseo .aseo__body h2 {
  margin: clamp(28px, 3.4vw, 40px) 0 12px;
  font-size: clamp(21px, 2.2vw, 27px);
  line-height: 1.25;
  color: var(--jm-heading);
}
.aseo .aseo__body h2:first-child { margin-top: 0; }
.aseo .aseo__body p {
  margin: 0 0 1em;
  font-size: 16.5px;
  line-height: 1.7;
  color: var(--jm-body);
}

/* ==========================================================================
   §68  AREA PAGES — BALANCED LINE BREAKS  (2026-09-29)
   "blance word start above check one by one". Scoped to body.pg-area (set
   by area-page.php), so no other page changes. Checked top to bottom:
     1. banner subline   — two ragged lines        -> balance
     2. intro card       — 3 paragraphs left, 2 right, so the right column
                           ended ~60px short: paragraphs may now flow across
                           the column break, which evens the two columns
     3. headings         — balance, so a wrap never leaves one word behind
     4. every paragraph  — pretty, so no single word ends a paragraph alone
                           ("back.", "26°C.", "scenes of somewhere else.")
     5. centred short copy (who-covers foot, section ledes) — balance
   text-wrap is ignored by browsers that lack it, which just keeps the old
   breaks — nothing can get worse.
   ========================================================================== */
.pg-area h1, .pg-area h2, .pg-area h3,
.pg-area .areas__sub,
.pg-area .models__lede,
.pg-area .awho__foot span,
.pg-area .bloc__sub { text-wrap: balance; }

.pg-area main p,
.pg-area main li,
.pg-area figcaption span { text-wrap: pretty; }

.pg-area .lcard.lcard--text .lcard__cols p { break-inside: auto; }

/* ==========================================================================
   §69  CONTACT — "VISIT OUR STUDIO" BAND  (contact.php, 2026-10-06)
   The client's welcome drink / shower / 100 Feet Road notes, as a section
   you scroll to (not a pop-up). The client's reception photo sits behind a
   dark ink veil so the copy keeps its contrast in every theme. Every <p> is
   given its own colour — Pico sets `p { color }` explicitly (see §5).
   Also: the sports "points" list on services.php reuses .svcard__for.
   ========================================================================== */
.cvisit {
  position: relative;
  isolation: isolate;
  overflow: hidden;
  margin-top: clamp(32px, 5vw, 64px);
  padding-block: clamp(48px, 7vw, 96px);
  color: var(--jm-on-ink);
  background: var(--jm-ink);
}
.cvisit__bg {
  position: absolute;
  inset: 0;
  z-index: -2;
  width: 100%;
  height: 100%;
  object-fit: cover;
}
.cvisit::before {
  content: '';
  position: absolute;
  inset: 0;
  z-index: -1;
  background:
    linear-gradient(100deg,
      color-mix(in srgb, var(--jm-ink) 94%, transparent) 0%,
      color-mix(in srgb, var(--jm-ink) 80%, transparent) 55%,
      color-mix(in srgb, var(--jm-ink) 50%, transparent) 100%);
}
.cvisit__in {
  display: grid;
  grid-template-columns: minmax(0, 1.1fr) minmax(0, 1fr);
  gap: clamp(28px, 4vw, 64px);
  align-items: center;
}
.cvisit__eyebrow {
  margin: 0 0 10px;
  font-size: 13px;
  font-weight: 700;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--jm-accent);
}
.cvisit .cvisit__title {
  margin: 0 0 14px;
  font-family: var(--jm-serif);
  font-size: clamp(30px, 4vw, 48px);
  line-height: 1.1;
  color: var(--jm-on-ink);
  text-wrap: balance;
}
.cvisit__title em { font-style: italic; color: var(--jm-accent); }
.cvisit .cvisit__lede {
  max-width: 48ch;
  margin: 0 0 26px;
  font-size: 17px;
  line-height: 1.6;
  color: color-mix(in srgb, var(--jm-on-ink) 86%, transparent);
}
.cvisit__btns { display: flex; flex-wrap: wrap; align-items: center; gap: 14px 22px; }
.cvisit .cvisit__call {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  font-weight: 700;
  color: var(--jm-on-ink);
  text-decoration: none;
}
.cvisit .cvisit__call:hover { color: var(--jm-accent); }
.cvisit__call svg { width: 18px; height: 18px; }

.cvisit__list {
  display: grid;
  gap: 12px;
  margin: 0;
  padding: 0;
}
.cvisit__list li {
  list-style: none;
  display: flex;
  gap: 14px;
  align-items: flex-start;
  margin: 0;
  padding: 16px 18px;
  border: 1px solid color-mix(in srgb, var(--jm-accent) 30%, transparent);
  border-radius: var(--jm-r);
  background: color-mix(in srgb, var(--jm-ink) 55%, transparent);
  backdrop-filter: blur(6px);
}
.cvisit__list b {
  display: block;
  margin-bottom: 2px;
  font-size: 16px;
  color: var(--jm-accent);
}
/* :not() — a plain `.cvisit__list span` would also match the icon tile
   (the .desk-stats bug in §5). */
.cvisit__list span:not(.cvisit__ico) { font-size: 15px; line-height: 1.5; color: color-mix(in srgb, var(--jm-on-ink) 88%, transparent); }
.cvisit__ico {
  flex: 0 0 40px;
  display: grid;
  place-items: center;
  width: 40px;
  height: 40px;
  border-radius: var(--jm-pill);
  color: var(--jm-on-accent);
  background: var(--jm-accent);
}
.cvisit__ico svg { width: 20px; height: 20px; }

@media (max-width: 860px) {
  .cvisit__in { grid-template-columns: 1fr; }
}

.svcard .svcard__points { margin-top: 10px; }
.svcard__points b { color: var(--jm-heading); }

/* ==========================================================================
   §70  OFFERS PAGE — OFFER GALLERY + HOURLY STUDIO COUPON  (2026-10-06)
   Two sections above "What you will and will not be charged". Zero JS:
     · gallery: radios (one per photo) switch the big picture; the thumbnails
       are their <label>s; the big picture links to a :target pop-up. With
       nothing picked, the big picture changes by itself every 5 s.
       EIGHT PHOTOS IS WRITTEN INTO THE nth-child RULES BELOW — change both.
     · coupon: the server picks studio/discount/code for this clock hour
       (includes/coupons.php). The countdown is an @property integer animated
       from --rem (seconds left, set inline) to 0 and printed with counters.
   ========================================================================== */

/* -- Gallery ------------------------------------------------------------- */
.ogal {
  display: grid;
  grid-template-columns: minmax(0, 0.9fr) minmax(0, 1.1fr);
  gap: clamp(24px, 3.4vw, 48px);
  align-items: center;
  margin: clamp(24px, 3vw, 36px) 0;
  padding: clamp(20px, 3vw, 36px);
  background: var(--jm-card);
  border: 1px solid var(--jm-line);
  border-radius: var(--jm-r-lg);
  box-shadow: 0 1px 2px var(--jm-shadow), 0 18px 40px -24px var(--jm-shadow);
}
.ogal__eyebrow, .hcoup__eyebrow {
  margin: 0 0 8px;
  font-size: 13px;
  font-weight: 700;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--jm-accent-dim);
}
.ogal .ogal__title {
  margin: 0 0 12px;
  font-family: var(--jm-serif);
  font-size: clamp(28px, 3.4vw, 42px);
  line-height: 1.1;
  color: var(--jm-heading);
  text-wrap: balance;
}
.ogal__title em, .hcoup__title em { font-style: italic; color: var(--jm-accent-dim); }
.ogal .ogal__lede { margin: 0 0 18px; font-size: 16px; line-height: 1.6; color: var(--jm-muted); }
.ogal__offers { display: grid; gap: 10px; margin: 0 0 22px; padding: 0; }
.ogal__offers li {
  list-style: none;
  display: flex;
  gap: 12px;
  align-items: flex-start;
  margin: 0;
  padding: 12px 14px;
  border-radius: var(--jm-r);
  background: color-mix(in srgb, var(--jm-accent) 9%, var(--jm-card));
}
.ogal__offers svg { flex: 0 0 20px; width: 20px; height: 20px; margin-top: 2px; color: var(--jm-accent-dim); }
.ogal__offers span { font-size: 15px; line-height: 1.45; color: var(--jm-body); }
.ogal__offers b { display: block; color: var(--jm-heading); }

.ogal__pics { position: relative; min-width: 0; }
.ogal__r { position: absolute; width: 1px; height: 1px; margin: 0; opacity: 0; pointer-events: none; }

.ogal__view {
  position: relative;
  aspect-ratio: 4 / 3;
  overflow: hidden;
  border-radius: var(--jm-r-lg);
  background: var(--jm-chip);
}
.ogal__fig {
  position: absolute;
  inset: 0;
  display: block;
  opacity: 0;
  visibility: hidden;
}
.ogal__fig img { width: 100%; height: 100%; object-fit: cover; display: block; }
.ogal .ogal__cap {
  position: absolute;
  left: 14px;
  bottom: 14px;
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 7px 14px;
  font-size: 14px;
  font-weight: 700;
  color: var(--jm-on-ink);
  background: color-mix(in srgb, var(--jm-ink) 72%, transparent);
  border-radius: var(--jm-pill);
  backdrop-filter: blur(4px);
}
.ogal__cap svg { width: 16px; height: 16px; color: var(--jm-accent); }

/* First picture shows by default; with motion allowed, all eight take turns. */
.ogal__fig:first-child { opacity: 1; visibility: visible; }
@media (prefers-reduced-motion: no-preference) {
  .ogal__fig { animation: og-cycle 40s linear infinite; }
  .ogal__fig:first-child { opacity: 0; visibility: hidden; }
  .ogal__fig:nth-child(2) { animation-delay: 5s; }
  .ogal__fig:nth-child(3) { animation-delay: 10s; }
  .ogal__fig:nth-child(4) { animation-delay: 15s; }
  .ogal__fig:nth-child(5) { animation-delay: 20s; }
  .ogal__fig:nth-child(6) { animation-delay: 25s; }
  .ogal__fig:nth-child(7) { animation-delay: 30s; }
  .ogal__fig:nth-child(8) { animation-delay: 35s; }
  .ogal__pics:hover .ogal__fig { animation-play-state: paused; }
}
@keyframes og-cycle {
  0%    { opacity: 0; visibility: hidden; }
  2%    { opacity: 1; visibility: visible; }
  12.5% { opacity: 1; visibility: visible; }
  14.5% { opacity: 0; visibility: hidden; }
  100%  { opacity: 0; visibility: hidden; }
}
/* Once a thumbnail is picked, the slideshow stops and that picture stays. */
.ogal__pics:has(.ogal__r:checked) .ogal__fig { animation: none; opacity: 0; visibility: hidden; }
#og-r1:checked ~ .ogal__view .ogal__fig:nth-child(1),
#og-r2:checked ~ .ogal__view .ogal__fig:nth-child(2),
#og-r3:checked ~ .ogal__view .ogal__fig:nth-child(3),
#og-r4:checked ~ .ogal__view .ogal__fig:nth-child(4),
#og-r5:checked ~ .ogal__view .ogal__fig:nth-child(5),
#og-r6:checked ~ .ogal__view .ogal__fig:nth-child(6),
#og-r7:checked ~ .ogal__view .ogal__fig:nth-child(7),
#og-r8:checked ~ .ogal__view .ogal__fig:nth-child(8) { animation: none; opacity: 1; visibility: visible; z-index: 1; }

.ogal__thumbs {
  display: grid;
  grid-template-columns: repeat(8, minmax(0, 1fr));
  gap: 8px;
  margin-top: 10px;
}
.ogal__thumbs label { display: block; margin: 0; cursor: pointer; border-radius: var(--jm-r-sm); }
.ogal__thumbs img {
  display: block;
  width: 100%;
  aspect-ratio: 1;
  object-fit: cover;
  border-radius: var(--jm-r-sm);
  opacity: .78;
  transition: opacity .2s ease, transform .2s ease;
}
.ogal__thumbs label:hover img { opacity: 1; transform: translateY(-2px); }
#og-r1:checked ~ .ogal__thumbs label:nth-child(1),
#og-r2:checked ~ .ogal__thumbs label:nth-child(2),
#og-r3:checked ~ .ogal__thumbs label:nth-child(3),
#og-r4:checked ~ .ogal__thumbs label:nth-child(4),
#og-r5:checked ~ .ogal__thumbs label:nth-child(5),
#og-r6:checked ~ .ogal__thumbs label:nth-child(6),
#og-r7:checked ~ .ogal__thumbs label:nth-child(7),
#og-r8:checked ~ .ogal__thumbs label:nth-child(8) { outline: 3px solid var(--jm-accent); outline-offset: 2px; }
#og-r1:focus-visible ~ .ogal__thumbs label:nth-child(1),
#og-r2:focus-visible ~ .ogal__thumbs label:nth-child(2),
#og-r3:focus-visible ~ .ogal__thumbs label:nth-child(3),
#og-r4:focus-visible ~ .ogal__thumbs label:nth-child(4),
#og-r5:focus-visible ~ .ogal__thumbs label:nth-child(5),
#og-r6:focus-visible ~ .ogal__thumbs label:nth-child(6),
#og-r7:focus-visible ~ .ogal__thumbs label:nth-child(7),
#og-r8:focus-visible ~ .ogal__thumbs label:nth-child(8) { outline: 3px solid var(--jm-ring); outline-offset: 2px; }
#og-r1:checked ~ .ogal__thumbs label:nth-child(1) img,
#og-r2:checked ~ .ogal__thumbs label:nth-child(2) img,
#og-r3:checked ~ .ogal__thumbs label:nth-child(3) img,
#og-r4:checked ~ .ogal__thumbs label:nth-child(4) img,
#og-r5:checked ~ .ogal__thumbs label:nth-child(5) img,
#og-r6:checked ~ .ogal__thumbs label:nth-child(6) img,
#og-r7:checked ~ .ogal__thumbs label:nth-child(7) img,
#og-r8:checked ~ .ogal__thumbs label:nth-child(8) img { opacity: 1; }

/* The pop-up. :target, so the browser's Back button closes it too. */
.ogal__pop {
  position: fixed;
  inset: 0;
  z-index: 2000;
  display: none;
  place-items: center;
  padding: 24px;
  background: color-mix(in srgb, var(--jm-ink) 90%, transparent);
}
.ogal__pop:target { display: grid; }
.ogal__shut { position: absolute; inset: 0; }
.ogal__pop figure { position: relative; z-index: 1; margin: 0; text-align: center; }
.ogal__pop img {
  display: block;
  max-width: min(92vw, 1100px);
  max-height: 80vh;
  width: auto;
  height: auto;
  margin: 0 auto;
  border-radius: var(--jm-r);
  box-shadow: 0 30px 80px -20px #000;
}
.ogal__pop figure figcaption {
  margin-top: 12px;
  font-family: var(--jm-serif);
  font-size: 20px;
  color: var(--jm-on-ink);
}
.ogal__x {
  position: absolute;
  top: 18px;
  right: 18px;
  z-index: 2;
  display: grid;
  place-items: center;
  width: 46px;
  height: 46px;
  border-radius: var(--jm-pill);
  color: var(--jm-on-accent);
  background: var(--jm-accent);
}
.ogal__x svg { width: 20px; height: 20px; }

/* -- Hourly studio coupon ----------------------------------------------- */
.hcoup {
  display: grid;
  grid-template-columns: minmax(0, 0.75fr) minmax(0, 1.25fr);
  margin: 0 0 clamp(32px, 4vw, 48px);
  overflow: hidden;
  color: var(--jm-on-ink);
  background:
    radial-gradient(120% 90% at 100% 0%, color-mix(in srgb, var(--jm-accent) 22%, transparent), transparent 60%),
    var(--jm-ink);
  border: 1px solid color-mix(in srgb, var(--jm-accent) 40%, transparent);
  border-radius: var(--jm-r-lg);
  box-shadow: 0 24px 50px -28px var(--jm-shadow);
}
.hcoup__photo { position: relative; min-height: 100%; }
.hcoup__photo img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
.hcoup__live {
  position: absolute;
  top: 16px;
  left: 16px;
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 6px 14px;
  font-size: 13px;
  font-weight: 700;
  letter-spacing: .06em;
  text-transform: uppercase;
  color: var(--jm-on-accent);
  background: var(--jm-accent);
  border-radius: var(--jm-pill);
}
.hcoup__live i { width: 8px; height: 8px; border-radius: 50%; background: var(--jm-on-accent); }
@media (prefers-reduced-motion: no-preference) {
  .hcoup__live i { animation: hc-pulse 1.4s ease-in-out infinite; }
}
@keyframes hc-pulse { 50% { opacity: .25; transform: scale(.7); } }

.hcoup__body { padding: clamp(22px, 3.4vw, 44px); }
.hcoup .hcoup__eyebrow { color: var(--jm-accent); }
.hcoup .hcoup__title {
  margin: 0 0 10px;
  font-family: var(--jm-serif);
  font-size: clamp(28px, 3.4vw, 42px);
  line-height: 1.1;
  color: var(--jm-on-ink);
}
.hcoup__title em { color: var(--jm-accent); }
.hcoup .hcoup__lede { margin: 0 0 20px; max-width: 58ch; line-height: 1.6; color: color-mix(in srgb, var(--jm-on-ink) 84%, transparent); }

.hcoup__ticket {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  gap: 0;
  border: 2px dashed color-mix(in srgb, var(--jm-accent) 70%, transparent);
  border-radius: var(--jm-r);
}
.hcoup__off {
  display: grid;
  place-content: center;
  padding: 18px 24px;
  text-align: center;
  border-right: 2px dashed color-mix(in srgb, var(--jm-accent) 70%, transparent);
}
.hcoup__off b { font-family: var(--jm-serif); font-size: clamp(44px, 6vw, 64px); line-height: 1; color: var(--jm-accent); }
.hcoup__off span { margin-top: 4px; font-size: 13px; text-transform: uppercase; letter-spacing: .08em; color: color-mix(in srgb, var(--jm-on-ink) 80%, transparent); }
.hcoup__where { padding: 16px 20px; display: grid; gap: 8px; align-content: center; }
.hcoup .hcoup__where p { margin: 0; color: var(--jm-on-ink); }
.hcoup .hcoup__studio { font-size: 17px; }
.hcoup__studio strong { color: var(--jm-accent); }
.hcoup .hcoup__code { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.hcoup__code span { font-size: 12px; text-transform: uppercase; letter-spacing: .1em; color: color-mix(in srgb, var(--jm-on-ink) 70%, transparent); }
.hcoup__code code {
  padding: 6px 14px;
  font-size: 18px;
  font-weight: 700;
  letter-spacing: .08em;
  color: var(--jm-on-accent);
  background: var(--jm-accent);
  border-radius: var(--jm-r-sm);
}
.hcoup .hcoup__valid { display: flex; align-items: center; gap: 8px; font-size: 14px; color: color-mix(in srgb, var(--jm-on-ink) 80%, transparent); }
.hcoup__valid svg { width: 16px; height: 16px; color: var(--jm-accent); }

/* The countdown. --jm-cs counts the seconds down; --jm-cm is the minutes. */
@property --jm-cs { syntax: '<integer>'; inherits: false; initial-value: 0; }
@property --jm-cm { syntax: '<integer>'; inherits: false; initial-value: 0; }
.hcoup .hcoup__timer { display: flex; align-items: baseline; gap: 12px; margin: 18px 0 0; color: var(--jm-on-ink); }
.hcoup__timer span { font-size: 14px; text-transform: uppercase; letter-spacing: .1em; color: color-mix(in srgb, var(--jm-on-ink) 70%, transparent); }
.hcoup__clock {
  --jm-cm: calc((var(--jm-cs) - 30) / 60);
  counter-reset: cm var(--jm-cm) cs calc(var(--jm-cs) - var(--jm-cm) * 60);
  animation: hc-count calc(var(--rem) * 1s) linear forwards;
  font-family: var(--jm-serif);
  font-size: 34px;
  font-variant-numeric: tabular-nums;
  color: var(--jm-accent);
}
.hcoup__clock::after { content: counter(cm, decimal-leading-zero) ':' counter(cs, decimal-leading-zero); }
@keyframes hc-count { from { --jm-cs: var(--rem); } to { --jm-cs: 0; } }
.hcoup .hcoup__ended {
  max-height: 0;
  margin: 0;
  overflow: hidden;
  opacity: 0;
  font-weight: 700;
  color: var(--jm-accent);
  animation: hc-end 1ms linear calc(var(--rem) * 1s) forwards;
}
@keyframes hc-end { to { max-height: 6em; margin-top: 8px; opacity: 1; } }

.hcoup__btns { display: flex; flex-wrap: wrap; gap: 12px; margin-top: 20px; }
.hcoup .hcoup__wa {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 12px 22px;
  font-size: 14px;
  font-weight: 700;
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--jm-on-ink);
  text-decoration: none;
  border: 1px solid color-mix(in srgb, var(--jm-on-ink) 40%, transparent);
  border-radius: var(--jm-pill);
}
.hcoup .hcoup__wa:hover { border-color: var(--jm-accent); color: var(--jm-accent); }
.hcoup__wa svg { width: 18px; height: 18px; }

.hcoup .hcoup__all { margin: 22px 0 8px; font-size: 13px; text-transform: uppercase; letter-spacing: .1em; color: color-mix(in srgb, var(--jm-on-ink) 70%, transparent); }
.hcoup__chips { display: flex; flex-wrap: wrap; gap: 8px; margin: 0; padding: 0; }
.hcoup__chips li { list-style: none; margin: 0; }
.hcoup__chips a {
  display: inline-block;
  padding: 5px 12px;
  font-size: 13px;
  color: color-mix(in srgb, var(--jm-on-ink) 85%, transparent);
  text-decoration: none;
  border: 1px solid color-mix(in srgb, var(--jm-on-ink) 25%, transparent);
  border-radius: var(--jm-pill);
}
.hcoup__chips .is-live a { color: var(--jm-on-accent); background: var(--jm-accent); border-color: var(--jm-accent); font-weight: 700; }
.hcoup .hcoup__small { margin: 16px 0 0; font-size: 13px; line-height: 1.5; color: color-mix(in srgb, var(--jm-on-ink) 62%, transparent); }

@media (max-width: 900px) {
  .ogal, .hcoup { grid-template-columns: 1fr; }
  .hcoup__photo { min-height: 0; aspect-ratio: 16 / 9; }
  .ogal__thumbs { grid-template-columns: repeat(4, minmax(0, 1fr)); }
}
@media (max-width: 520px) {
  .hcoup__ticket { grid-template-columns: 1fr; }
  .hcoup__off { border-right: 0; border-bottom: 2px dashed color-mix(in srgb, var(--jm-accent) 70%, transparent); }
}

/* -- The coupon riding into the booking form, and on the desk ----------- */
.bcard .bcoupon {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 8px;
  margin: 0 0 18px;
  padding: 10px 14px;
  font-size: 14px;
  color: var(--jm-heading);
  background: color-mix(in srgb, var(--jm-accent) 14%, var(--jm-card));
  border: 1px dashed var(--jm-accent-dim);
  border-radius: var(--jm-r);
}
.bcoupon svg { width: 18px; height: 18px; color: var(--jm-accent-dim); }
.bcoupon code { font-weight: 700; }
.desk .desk-coupon { color: var(--jm-accent-dim); font-weight: 700; white-space: nowrap; }
.desk .desk-coupon.is-bad { color: var(--jm-muted); text-decoration: line-through; }
.desk .desk-coupon-now td { font-weight: 700; background: color-mix(in srgb, var(--jm-accent) 14%, transparent); }

/* ==========================================================================
   §71  HOMEPAGE "PLAN A HAPPY CELEBRATION"  (index.php 9d2, 2026-10-06)
   "container inside title and below paragraph … bold and unique heading".
   One white card on the tinted ground: a gold rule down the left edge, a
   large bold serif heading with an italic accent word underlined by a soft
   gold band, and the paragraph at a comfortable 62ch / 17px / 1.75.
   ========================================================================== */
.celeb { margin-block: clamp(32px, 5vw, 64px); }
.celeb__card {
  position: relative;
  overflow: hidden;
  padding: clamp(26px, 4vw, 56px) clamp(22px, 4.5vw, 64px);
  background:
    radial-gradient(60% 90% at 0% 0%, color-mix(in srgb, var(--jm-accent) 12%, transparent), transparent 70%),
    var(--jm-card);
  border: 1px solid var(--jm-line);
  border-radius: var(--jm-r-lg);
  box-shadow: 0 1px 2px var(--jm-shadow), 0 20px 44px -26px var(--jm-shadow);
}
/* 2026-10-06, second pass: "don't like the centre — text left, one division
   for images". Two columns: copy left (left-aligned), a three-photo mosaic
   right. One column below 900px, photos under the text. */
.celeb__card {
  display: grid;
  grid-template-columns: minmax(0, 1.15fr) minmax(0, 1fr);
  gap: clamp(24px, 4vw, 56px);
  align-items: center;
}
.celeb__card::before {
  content: '';
  position: absolute;
  inset: 0 auto 0 0;
  width: 6px;
  background: linear-gradient(180deg, var(--jm-accent), var(--jm-accent-dim));
}
.celeb__pics {
  display: grid;
  grid-template-columns: 1.1fr 1fr;
  grid-template-rows: 1fr 1fr;
  gap: 12px;
  height: 100%;
  min-height: 420px;
}
.celeb__pic {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  border-radius: var(--jm-r);
  box-shadow: 0 14px 30px -18px var(--jm-shadow);
}
.celeb__pic--1 { grid-row: 1 / 3; }
@media (max-width: 900px) {
  .celeb__card { grid-template-columns: 1fr; }
  .celeb__pics { min-height: 0; height: auto; aspect-ratio: 4 / 3; }
}
.celeb .celeb__eyebrow {
  margin: 0 0 10px;
  font-size: 13px;
  font-weight: 700;
  letter-spacing: .16em;
  text-transform: uppercase;
  color: var(--jm-accent-dim);
}
.celeb .celeb__title {
  margin: 0 0 18px;
  font-family: var(--jm-serif);
  font-size: clamp(34px, 5vw, 60px);
  font-weight: 800;
  line-height: 1.04;
  letter-spacing: -.01em;
  color: var(--jm-heading);
  text-wrap: balance;
}
.celeb__title em {
  font-style: italic;
  color: var(--jm-accent-dim);
  background: linear-gradient(transparent 68%, color-mix(in srgb, var(--jm-accent) 35%, transparent) 68%);
  padding: 0 .08em;
}
.celeb .celeb__text {
  max-width: 64ch;
  margin: 0 0 14px;
  font-size: 17px;
  line-height: 1.75;
  color: var(--jm-body);
  text-wrap: pretty;
}
.celeb .btn-solid { margin-top: 10px; }
.celeb__pics { min-height: 360px; }

/* 2026-10-09, the client on a phone: "content not fitting the container" and
   the photos looked wrong. Measured: below 900px the single `1fr` column took
   its MIN-CONTENT width from the photo mosaic, so the column was wider than
   the card and `overflow: hidden` sliced the heading, the text and the photos
   on the right. `minmax(0, 1fr)` fixes the width; on phones the mosaic becomes
   one wide photo over two side-by-side ones, each at a shape that shows the
   picture instead of a sliver. */
@media (max-width: 900px) {
  .celeb__card { grid-template-columns: minmax(0, 1fr); }
  .celeb__card > * { min-width: 0; }
}
@media (max-width: 600px) {
  .celeb .celeb__title { font-size: clamp(30px, 8.6vw, 38px); }
  .celeb .celeb__text { font-size: 16px; line-height: 1.7; }
  .celeb__pics {
    grid-template-columns: 1fr 1fr;
    grid-template-rows: auto auto;
    min-height: 0;
    height: auto;
    aspect-ratio: auto;
    gap: 10px;
  }
  .celeb__pic--1 { grid-row: auto; grid-column: 1 / 3; aspect-ratio: 16 / 10; }
  .celeb__pic--2,
  .celeb__pic--3 { aspect-ratio: 1; }
}

/* ==========================================================================
   §72  HOMEPAGE "MASSAGE IN BANGALORE" — ENCYCLOPEDIA STYLE  (2026-10-06)
   "normal paragraph design like encyclopedia". One readable column: the
   lead paragraph slightly larger, then each of the client's sections as a
   serif h3 over a hairline and plain paragraphs. Written at (0,2,1)+ so
   `.lcard p` / `.lcard h3` (0,1,1) cannot override it.
   ========================================================================== */
.lcard .seo-wiki { max-width: 78ch; }
.lcard .seo-wiki p {
  max-width: none;            /* `.lcard p` caps card text at 48ch */
  margin: 0 0 14px;
  font-size: 16.5px;
  line-height: 1.75;
  color: var(--jm-body);
  text-wrap: pretty;
}
.lcard .seo-wiki .seo-wiki__lead { font-size: 18px; color: var(--jm-heading); }
.lcard .seo-wiki h3 {
  display: block;
  margin: 28px 0 12px;
  padding-bottom: 8px;
  font-family: var(--jm-serif);
  font-size: clamp(20px, 2vw, 24px);
  font-weight: 700;
  line-height: 1.25;
  color: var(--jm-heading);
  border-bottom: 1px solid var(--jm-line);
}

/* ==========================================================================
   §73  ONE TREATMENT IN ONE AREA  (treat-area-page.php, 2026-10-07)
   /bangalore/aroma-massage-in-jayanagar, and its card on the area page. The
   article reuses §67 (.aseo); this only adds the benefits list, the small
   meta line, the note and the "more" links. Light ground only, so accent
   as text is --jm-accent-dim (see CLAUDE.md, ~5.2:1 on white).
   ========================================================================== */
.lcard .ta__meta {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-top: 6px;
  font-size: 14.5px;
  font-weight: 600;
  color: var(--jm-accent-dim);
}
.lcard .ta__meta svg { width: 16px; height: 16px; flex: none; }
.lcard.pgsplit .btn-solid { margin-top: 14px; }
.lcard h2 a { color: inherit; text-decoration: none; }
.lcard h2 a:hover,
.lcard h2 a:focus-visible { color: var(--jm-accent-dim); text-decoration: underline; }

.aseo .aseo__body .ta__list {
  margin: 4px 0 18px;
  padding: 0;
  display: grid;
  gap: 12px;
}
.aseo .aseo__body .ta__list li {
  list-style: none;             /* on the li — Pico's ul li rule, §5 */
  display: flex;
  gap: 12px;
  align-items: flex-start;
  margin: 0;
  font-size: 16.5px;
  line-height: 1.65;
  color: var(--jm-body);
}
.aseo .aseo__body .ta__list b { color: var(--jm-heading); }
.ta__tick {
  flex: none;
  display: grid;
  place-items: center;
  width: 26px;
  height: 26px;
  margin-top: 1px;
  border-radius: var(--jm-pill);
  background: color-mix(in srgb, var(--jm-accent) 22%, var(--jm-card));
  color: var(--jm-accent-dim);
}
.ta__tick svg { width: 14px; height: 14px; }
.aseo .aseo__body .ta__note {
  font-size: 14.5px;
  font-style: italic;
  color: var(--jm-muted);
}
.aseo .aseo__body .ta__links {
  display: flex;
  flex-wrap: wrap;
  gap: 10px 22px;
  margin-top: 26px;
  padding-top: 18px;
  border-top: 1px solid var(--jm-line);
  font-size: 15px;
  font-weight: 600;
}
.ta__links a { color: var(--jm-accent-dim); }

/* The area page's own FAQ (Koramangala, 2026-10-07): the homepage accordion
   panel, one column, on the same left gutter as the .aseo text above it. */
.faq.afaq { display: block; }
.faq.afaq .faq__panel { max-width: 860px; }
.faq.afaq .afaq__title {
  max-width: 860px;
  margin: 0 0 18px;
  font-family: var(--jm-serif);
  font-size: clamp(24px, 2.8vw, 32px);
  line-height: 1.2;
  color: var(--jm-heading);
}

/* ==========================================================================
   §74  HOMEPAGE "MASSAGE IN BANGALORE" — COLOURFUL, READABLE  (2026-10-07)
   "the last section for paragraphs … very attractive colorful background or
   colorful text … everyone readability … background shadow border". The §72
   encyclopedia content, restyled. ONLY palette tokens (eight themes still
   work). Text stays --jm-heading / --jm-body on near-white tints, so
   contrast is unchanged; the gold is in the ground, the border, the shadow,
   the numerals and the accent words — never in body text.
   Scoped to .seo-glow (index.php): delete the class to undo it.
   ========================================================================== */
.seo-glow .lcard {
  /* narrower and centred, so the ~86ch text column fills the card instead
     of leaving an empty strip on the right (seen at 1639px) */
  max-width: 1080px;
  margin-inline: auto;
  position: relative;
  overflow: hidden;
  padding: clamp(26px, 4vw, 52px);
  border: 2px solid transparent;
  border-radius: var(--jm-r-lg);
  /* gradient BORDER: a padding-box fill over a border-box gradient */
  background:
    linear-gradient(160deg,
      color-mix(in srgb, var(--jm-accent) 12%, var(--jm-card)) 0%,
      var(--jm-card) 46%,
      color-mix(in srgb, var(--jm-accent) 8%, var(--jm-card)) 100%) padding-box,
    linear-gradient(135deg,
      var(--jm-accent-lit), var(--jm-accent) 40%,
      var(--jm-accent-dim) 70%, var(--jm-accent-lit)) border-box;
  box-shadow:
    0 2px 4px color-mix(in srgb, var(--jm-ink) 6%, transparent),
    0 24px 60px -24px color-mix(in srgb, var(--jm-accent-dim) 45%, transparent);
}
.seo-glow .lcard:hover { transform: none; }   /* a long text card should not jump */
/* soft gold glow in the top-right corner, behind the text */
.seo-glow .lcard::before {
  content: '';
  position: absolute;
  top: -140px;
  right: -140px;
  width: 420px;
  height: 420px;
  border-radius: 50%;
  background: radial-gradient(circle,
    color-mix(in srgb, var(--jm-accent) 26%, transparent), transparent 68%);
  pointer-events: none;
}
.seo-glow .lcard > * { position: relative; }

.seo-glow .seo-glow__eyebrow {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  margin: 0 0 12px;
  padding: 6px 14px;
  border-radius: var(--jm-pill);
  background: color-mix(in srgb, var(--jm-accent) 18%, var(--jm-card));
  border: 1px solid color-mix(in srgb, var(--jm-accent) 45%, transparent);
  font-size: 12px;
  font-weight: 700;
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--jm-accent-dim);
}
.seo-glow .seo-glow__eyebrow svg { width: 14px; height: 14px; }

.seo-glow .lcard h2 {
  margin: 0 0 22px;
  font-family: var(--jm-serif);
  font-size: clamp(30px, 4vw, 46px);
  font-weight: 700;
  line-height: 1.12;
  color: var(--jm-heading);
}
.seo-glow .lcard h2 em { font-style: italic; color: var(--jm-accent-dim); }
/* the city word shimmers in gold where background-clip:text is honoured —
   guarded, or it would be invisible text (the hero's lesson, CLAUDE.md) */
@supports ((-webkit-background-clip: text) or (background-clip: text)) {
  .seo-glow .lcard h2 em {
    background: linear-gradient(100deg,
      var(--jm-accent-dim) 0%, color-mix(in srgb, var(--jm-accent-dim) 70%, var(--jm-accent)) 50%,
      var(--jm-accent-dim) 100%);
    -webkit-background-clip: text;
    background-clip: text;
    color: transparent;
  }
}

.seo-glow .seo-wiki { max-width: 86ch; }
/* the lead: a pull-quote panel with a gold bar */
.seo-glow .seo-wiki .seo-wiki__lead {
  margin: 0 0 26px;
  padding: 20px 24px;
  border-left: 5px solid var(--jm-accent);
  border-radius: 0 var(--jm-r) var(--jm-r) 0;
  background: color-mix(in srgb, var(--jm-accent) 10%, var(--jm-card));
  font-size: 17.5px;
  line-height: 1.8;
  color: var(--jm-heading);
}
/* each of the client's sections: its own panel, alternating tints */
.seo-glow .seo-wiki__sec {
  margin: 0 0 16px;
  padding: 20px 24px 8px;
  border: 1px solid color-mix(in srgb, var(--jm-accent) 30%, var(--jm-line));
  border-radius: var(--jm-r);
  background: var(--jm-card);
  box-shadow: 0 8px 22px -14px color-mix(in srgb, var(--jm-accent-dim) 55%, transparent);
}
.seo-glow .seo-wiki__sec:nth-of-type(even) {
  background: color-mix(in srgb, var(--jm-accent) 7%, var(--jm-card));
}
.seo-glow .seo-wiki h3 {
  display: flex;
  align-items: center;
  gap: 12px;
  margin: 0 0 12px;
  padding: 0;
  border: 0;
  font-size: clamp(19px, 2vw, 23px);
  color: var(--jm-heading);
}
.seo-glow .seo-wiki__no {
  flex: none;
  display: grid;
  place-items: center;
  width: 34px;
  height: 34px;
  border-radius: 50%;
  background: linear-gradient(135deg, var(--jm-accent-lit), var(--jm-accent));
  box-shadow: 0 4px 10px -3px color-mix(in srgb, var(--jm-accent-dim) 70%, transparent);
  font-family: var(--jm-sans, inherit);
  font-size: 15px;
  font-weight: 800;
  color: var(--jm-on-accent);
}
.seo-glow .seo-wiki p { color: var(--jm-body); }
@media (max-width: 620px) {
  .seo-glow .seo-wiki .seo-wiki__lead { padding: 16px 16px; font-size: 16.5px; }
  .seo-glow .seo-wiki__sec { padding: 16px 16px 4px; }
}

/* §74b — the same card on the LOCATION pages (2026-10-07, "use all the
   location page … same design"). area-page.php keeps `.aseo` on the section
   so §73's list/note rules still apply; these lines undo the parts of §67
   that were written for bare text on the page ground. */
.seo-glow.aseo .aseo__body > * { max-width: none; }
.seo-glow .seo-wiki .seo-wiki__sec p b { color: var(--jm-heading); }
.seo-glow .seo-glow__cta { margin: 22px 0 0; }
.seo-glow .seo-wiki .wchips { margin-bottom: 16px; }

/* ==========================================================================
   §75  WHITEFIELD'S OWN BLOCKS  (area-page.php, 2026-10-07)
   "a different layout" for /bangalore/spa-in-whitefield.php: the need
   chooser, the treatment guide and the home-visit area chips. Rendered only
   when a $TREAT_AREA row carries 'chooser' / 'guide' / 'chips'.
   ========================================================================== */
.wchoose .wchoose__title,
.wguide .wchoose__title {
  margin: 0 0 10px;
  font-family: var(--jm-serif);
  font-size: clamp(26px, 3.2vw, 38px);
  line-height: 1.15;
  color: var(--jm-heading);
  text-wrap: balance;
}
.wchoose__lede {
  max-width: 76ch;
  margin: 0 0 26px;
  font-size: 16.5px;
  line-height: 1.7;
  color: var(--jm-body);
  text-wrap: pretty;
}
.wchoose__grid {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 18px;
  margin: 0;
  padding: 0;
}
.wchoose__grid > li,
.wguide__grid > li,
.wchips > li { list-style: none; margin: 0; }   /* on the li — Pico §5 */
.wchoose__tile {
  display: flex;
  flex-direction: column;
  padding: 22px 20px 18px;
  border: 1px solid color-mix(in srgb, var(--jm-accent) 28%, var(--jm-line));
  border-top: 4px solid var(--jm-accent);
  border-radius: var(--jm-r);
  background: var(--jm-card);
  box-shadow: 0 10px 26px -18px color-mix(in srgb, var(--jm-accent-dim) 60%, transparent);
  transition: transform .18s ease, box-shadow .18s ease;
}
.wchoose__tile:hover,
.wchoose__tile:focus-within {
  transform: translateY(-3px);
  box-shadow: 0 18px 34px -18px color-mix(in srgb, var(--jm-accent-dim) 70%, transparent);
}
.wchoose__ico {
  display: grid;
  place-items: center;
  width: 46px;
  height: 46px;
  margin-bottom: 14px;
  border-radius: 50%;
  background: color-mix(in srgb, var(--jm-accent) 18%, var(--jm-card));
  color: var(--jm-accent-dim);
  font-size: 20px;
}
.wchoose__tile h3 {
  margin: 0 0 6px;
  font-size: 18px;
  line-height: 1.3;
  color: var(--jm-heading);
}
.wchoose__tile p {
  margin: 0 0 14px;
  font-size: 15px;
  line-height: 1.6;
  color: var(--jm-body);
}
.wchoose__tile .wchoose__links {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin: auto 0 0;
}
.wchoose__links a {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 6px 12px;
  border-radius: var(--jm-pill);
  background: color-mix(in srgb, var(--jm-accent) 14%, var(--jm-card));
  font-size: 13px;
  font-weight: 600;
  color: var(--jm-accent-dim);
  text-decoration: none;
}
.wchoose__links a:hover,
.wchoose__links a:focus-visible { background: var(--jm-accent); color: var(--jm-on-accent); }
.wchoose__links svg { width: 13px; height: 13px; }
.wchoose__acts {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 12px 20px;
  margin: 26px 0 0;
  font-size: 14.5px;
  font-weight: 600;
  color: var(--jm-accent-dim);
}
.wchoose__acts span { display: inline-flex; align-items: center; gap: 7px; }
.wchoose__acts svg { width: 16px; height: 16px; }

.wguide__grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 16px;
  margin: 0;
  padding: 0;
}
.wguide__item {
  display: flex;
  gap: 16px;
  align-items: flex-start;
  padding: 16px;
  border: 1px solid var(--jm-line);
  border-radius: var(--jm-r);
  background: var(--jm-card);
  box-shadow: var(--jm-shadow, 0 1px 2px color-mix(in srgb, var(--jm-ink) 8%, transparent));
}
.wguide__item img {
  flex: none;
  width: 96px;
  height: 96px;
  object-fit: cover;
  border-radius: var(--jm-r-sm);
}
.wguide__item h3 {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 4px 10px;
  margin: 0 0 6px;
  font-size: 17.5px;
  line-height: 1.3;
  color: var(--jm-heading);
}
.wguide__item h3 span {
  font-size: 12.5px;
  font-weight: 600;
  letter-spacing: .04em;
  color: var(--jm-accent-dim);
}
.wguide__item p {
  margin: 0 0 8px;
  font-size: 15px;
  line-height: 1.6;
  color: var(--jm-body);
}
.wguide__item a {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: 13.5px;
  font-weight: 600;
  color: var(--jm-accent-dim);
}
.wguide__item a svg { width: 13px; height: 13px; }

.wchips {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin: 4px 0 18px;
  padding: 0;
}
.wchips > li {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 7px 13px;
  border: 1px solid color-mix(in srgb, var(--jm-accent) 40%, var(--jm-line));
  border-radius: var(--jm-pill);
  background: var(--jm-card);
  font-size: 14px;
  font-weight: 600;
  color: var(--jm-heading);
}
.wchips svg { width: 14px; height: 14px; color: var(--jm-accent-dim); }

@media (max-width: 1100px) {
  .wchoose__grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (max-width: 760px) {
  .wguide__grid { grid-template-columns: minmax(0, 1fr); }
}
@media (max-width: 520px) {
  .wchoose__grid { grid-template-columns: minmax(0, 1fr); }
  .wguide__item img { width: 72px; height: 72px; }
}

/* ==========================================================================
   §76  LOCATION-PAGE BLOCKS  (area-page.php 'blocks', 2026-10-07)
   "different template style" per location page: tiles (four looks),
   timeline, compare, steps, band, combo. Each is used on one or two pages.
   Palette tokens only; text stays --jm-heading / --jm-body on light grounds
   and --jm-on-ink on the one dark band.
   ========================================================================== */
.ablk .ablk__title {
  margin: 0 0 10px;
  font-family: var(--jm-serif);
  font-size: clamp(26px, 3.2vw, 38px);
  line-height: 1.15;
  color: var(--jm-heading);
  text-wrap: balance;
}
.ablk .ablk__lede {
  max-width: 74ch;
  margin: 0 0 26px;
  font-size: 16.5px;
  line-height: 1.7;
  color: var(--jm-body);
  text-wrap: pretty;
}
.ablk ul, .ablk ol { margin: 0; padding: 0; }
.ablk li { list-style: none; margin: 0; }          /* Pico §5: on the li */
.ablk .ablk__k {
  margin: 0 0 6px;
  font-size: 11.5px;
  font-weight: 800;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--jm-accent-dim);
}
.ablk__ico {
  display: inline-grid;
  place-items: center;
  flex: none;
  width: 40px;
  height: 40px;
  border-radius: 50%;
  background: color-mix(in srgb, var(--jm-accent) 18%, var(--jm-card));
  color: var(--jm-accent-dim);
  font-size: 18px;
}

/* tiles — shared grid, four looks */
.ablk__tiles {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(230px, 1fr));
  gap: 16px;
}
.ablk__tiles > li {
  display: flex;
  flex-direction: column;
  padding: 20px;
  border: 1px solid var(--jm-line);
  border-radius: var(--jm-r);
  background: var(--jm-card);
}
.ablk__tiles h3 { margin: 12px 0 6px; font-size: 18px; line-height: 1.3; color: var(--jm-heading); }
.ablk__tiles p { margin: 0 0 12px; font-size: 15px; line-height: 1.6; color: var(--jm-body); }
.ablk__tiles .ablk__links { display: flex; flex-wrap: wrap; gap: 8px; margin: auto 0 0; }
.ablk__links a {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 6px 12px;
  border-radius: var(--jm-pill);
  border: 1px solid color-mix(in srgb, var(--jm-accent) 45%, var(--jm-line));
  font-size: 13px;
  font-weight: 600;
  color: var(--jm-accent-dim);
  text-decoration: none;
}
.ablk__links a:hover,
.ablk__links a:focus-visible { background: var(--jm-accent); border-color: var(--jm-accent); color: var(--jm-on-accent); }
.ablk__links svg { width: 13px; height: 13px; }
/* problem (Indiranagar): six across three, gold left edge */
.ablk--problem .ablk__tiles { grid-template-columns: repeat(3, minmax(0, 1fr)); }
.ablk--problem .ablk__tiles > li { border-left: 4px solid var(--jm-accent); }
/* time (MG Road): a tinted strip with a big eyebrow */
.ablk--time .ablk__tiles > li { background: color-mix(in srgb, var(--jm-accent) 9%, var(--jm-card)); }
.ablk--time .ablk__k { font-size: 13px; }
/* travel (Majestic): dashed ticket edge */
.ablk--travel .ablk__tiles > li { border: 2px dashed color-mix(in srgb, var(--jm-accent) 55%, var(--jm-line)); }
/* desk (Electronic City): the body part in large type */
.ablk--desk .ablk__k { font-family: var(--jm-serif); font-size: 26px; letter-spacing: 0; text-transform: none; color: var(--jm-heading); }
.ablk--desk .ablk__tiles > li { box-shadow: 0 10px 24px -18px color-mix(in srgb, var(--jm-accent-dim) 65%, transparent); }

/* timeline (HSR Layout) */
.ablk__line { position: relative; display: grid; gap: 14px; max-width: 860px; }
.ablk__line::before {
  content: '';
  position: absolute;
  left: 43px; top: 8px; bottom: 8px;
  width: 2px;
  background: linear-gradient(var(--jm-accent-lit), var(--jm-accent));
}
.ablk__line > li { position: relative; display: flex; gap: 20px; align-items: flex-start; }
.ablk__year {
  flex: none;
  display: grid;
  place-items: center;
  width: 88px;
  height: 40px;
  border-radius: var(--jm-pill);
  background: var(--jm-accent);
  font-weight: 800;
  font-size: 15px;
  color: var(--jm-on-accent);
  position: relative;
}
.ablk__line h3 { margin: 6px 0 4px; font-size: 18px; color: var(--jm-heading); }
.ablk__line p { margin: 0; font-size: 15.5px; line-height: 1.6; color: var(--jm-body); }

/* compare (HSR Layout, Marathahalli) */
.ablk__cols { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 18px; }
.ablk__col {
  display: flex;
  flex-direction: column;
  padding: 24px;
  border: 1px solid var(--jm-line);
  border-top: 4px solid var(--jm-accent);
  border-radius: var(--jm-r);
  background: var(--jm-card);
}
.ablk__col--b { border-top-color: var(--jm-accent-dim); background: color-mix(in srgb, var(--jm-accent) 6%, var(--jm-card)); }
.ablk__col h3 { display: flex; align-items: center; gap: 12px; margin: 0 0 14px; font-size: 20px; color: var(--jm-heading); }
.ablk__col ul { display: grid; gap: 10px; margin-bottom: 20px; }
.ablk__col li { display: flex; gap: 10px; align-items: flex-start; font-size: 15.5px; line-height: 1.55; color: var(--jm-body); }
.ablk__col li svg { flex: none; width: 16px; height: 16px; margin-top: 3px; color: var(--jm-accent-dim); }
.ablk__col .btn-solid { margin-top: auto; align-self: flex-start; }
.ablk .ablk__note { max-width: 74ch; margin: 18px 0 0; font-size: 15px; font-style: italic; color: var(--jm-muted); }

/* steps (JP Nagar, Hebbal, Rajajinagar) — numbered by a counter */
.ablk__steps { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 16px; counter-reset: ablk; }
.ablk__steps > li {
  counter-increment: ablk;
  position: relative;
  padding: 52px 20px 20px;
  border: 1px solid var(--jm-line);
  border-radius: var(--jm-r);
  background: var(--jm-card);
}
.ablk__steps > li::before {
  content: counter(ablk);
  position: absolute;
  top: 16px; left: 20px;
  display: grid;
  place-items: center;
  width: 30px; height: 30px;
  border-radius: 50%;
  background: linear-gradient(135deg, var(--jm-accent-lit), var(--jm-accent));
  font-weight: 800;
  color: var(--jm-on-accent);
}
.ablk__steps h3 { margin: 0 0 6px; font-size: 17px; line-height: 1.3; color: var(--jm-heading); }
.ablk__steps p { margin: 0; font-size: 15px; line-height: 1.6; color: var(--jm-body); }

/* band (MG Road) — the one dark block */
.ablk--band { padding-block: clamp(40px, 6vw, 72px); background: var(--jm-ink); }
.ablk__bandin { display: grid; grid-template-columns: 1.1fr 1fr; gap: clamp(24px, 4vw, 56px); align-items: center; }
.ablk--band .ablk__title { color: var(--jm-on-ink); }
.ablk--band .ablk__lede { color: color-mix(in srgb, var(--jm-on-ink) 82%, transparent); margin-bottom: 0; }
.ablk--band .ablk__k { color: var(--jm-accent); }
.ablk--band ul { display: grid; gap: 12px; }
.ablk--band li { display: flex; gap: 12px; align-items: center; font-size: 16px; color: var(--jm-on-ink); }
.ablk--band .ablk__ico { width: 32px; height: 32px; background: var(--jm-accent); color: var(--jm-on-accent); }
.ablk--band .ablk__ico svg { width: 15px; height: 15px; }

/* combo (Yelahanka) */
.ablk__combo {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: clamp(24px, 4vw, 56px);
  align-items: center;
  padding: clamp(22px, 3.5vw, 40px);
  border: 2px solid transparent;
  border-radius: var(--jm-r-lg);
  background:
    linear-gradient(var(--jm-card), var(--jm-card)) padding-box,
    linear-gradient(135deg, var(--jm-accent-lit), var(--jm-accent-dim)) border-box;
}
.ablk__pair { display: flex; align-items: center; gap: 12px; }
.ablk__pair img { width: 140px; height: 140px; object-fit: cover; border-radius: 50%; border: 4px solid var(--jm-card); box-shadow: 0 10px 24px -14px color-mix(in srgb, var(--jm-ink) 50%, transparent); }
.ablk__plus { font-family: var(--jm-serif); font-size: 44px; font-weight: 700; color: var(--jm-accent-dim); }
.ablk--combo .ta__list { display: grid; gap: 10px; margin: 0 0 20px; }
.ablk--combo .ta__list li { display: flex; gap: 12px; align-items: flex-start; font-size: 15.5px; line-height: 1.55; color: var(--jm-body); }

@media (max-width: 1100px) {
  .ablk__steps { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .ablk--problem .ablk__tiles { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (max-width: 860px) {
  .ablk__cols, .ablk__bandin { grid-template-columns: minmax(0, 1fr); }
  .ablk__combo { grid-template-columns: minmax(0, 1fr); }
  .ablk__pair { justify-content: center; }
}
/* ==========================================================================
   §77  GUEST REVIEWS — GOOGLE-REVIEW STYLE  (includes/reviews.php, 2026-10-07)
   Google's own pattern: a summary card (big number, five stars, count) beside
   review cards (initial avatar, name, date, stars, text, "Posted on Google").
   Until real reviews exist the right column holds the prompts. Stars are the
   accent gold; text stays --jm-heading / --jm-body. No Google logo or brand
   colours — the pattern, not the mark.
   ========================================================================== */
.grv .grv__eyebrow {
  margin: 0 0 6px;
  font-size: 12px;
  font-weight: 800;
  letter-spacing: .16em;
  text-transform: uppercase;
  color: var(--jm-accent-dim);
}
.grv .grv__title {
  margin: 0 0 10px;
  font-family: var(--jm-serif);
  font-size: clamp(28px, 3.6vw, 42px);
  line-height: 1.12;
  color: var(--jm-heading);
}
.grv .grv__title em { font-style: italic; color: var(--jm-accent-dim); }
.grv .grv__lede { max-width: 70ch; margin: 0 0 28px; font-size: 16.5px; line-height: 1.7; color: var(--jm-body); }
.grv__grid { display: grid; grid-template-columns: minmax(260px, 340px) minmax(0, 1fr); gap: 22px; align-items: start; }
.grv__sum {
  position: sticky;
  top: 96px;
  padding: 28px 26px;
  border: 2px solid transparent;
  border-radius: var(--jm-r-lg);
  background:
    linear-gradient(170deg, color-mix(in srgb, var(--jm-accent) 12%, var(--jm-card)), var(--jm-card) 60%) padding-box,
    linear-gradient(135deg, var(--jm-accent-lit), var(--jm-accent-dim)) border-box;
  box-shadow: 0 18px 40px -24px color-mix(in srgb, var(--jm-accent-dim) 70%, transparent);
  text-align: center;
}
.grv .grv__big {
  margin: 0;
  font-family: var(--jm-serif);
  font-size: 64px;
  font-weight: 700;
  line-height: 1;
  color: var(--jm-heading);
}
.grv .grv__stars { margin: 8px 0 6px; font-size: 26px; letter-spacing: 3px; line-height: 1; }
.grv__star { color: color-mix(in srgb, var(--jm-muted) 35%, var(--jm-card)); }
.grv__star.is-on { color: var(--jm-accent); }
.grv .grv__stars--empty .grv__star { color: color-mix(in srgb, var(--jm-accent) 40%, var(--jm-card)); }
.grv .grv__count { margin: 0 0 18px; font-size: 14.5px; color: var(--jm-muted); }
.grv .grv__empty-h { margin: 10px 0 8px; font-family: var(--jm-serif); font-size: 22px; color: var(--jm-heading); }
.grv .grv__empty-p { margin: 0 0 18px; font-size: 15px; line-height: 1.6; color: var(--jm-body); }
.grv .grv__acts { display: grid; gap: 12px; justify-items: center; margin: 0; }
.grv__read { display: inline-flex; align-items: center; gap: 6px; font-size: 14px; font-weight: 600; color: var(--jm-accent-dim); }
.grv__read svg { width: 14px; height: 14px; }

.grv__cards { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 16px; margin: 0; padding: 0; }
.grv__cards > li, .grv__prompts li { list-style: none; margin: 0; }   /* Pico §5 */
.grv__card {
  display: flex;
  flex-direction: column;
  padding: 20px;
  border: 1px solid var(--jm-line);
  border-radius: var(--jm-r);
  background: var(--jm-card);
  box-shadow: 0 1px 2px color-mix(in srgb, var(--jm-ink) 8%, transparent);
}
.grv__who { display: flex; align-items: center; gap: 12px; }
.grv__avatar {
  display: grid;
  place-items: center;
  width: 42px; height: 42px;
  border-radius: 50%;
  background: linear-gradient(135deg, var(--jm-accent-lit), var(--jm-accent));
  font-weight: 800;
  color: var(--jm-on-accent);
}
.grv .grv__name { margin: 0; font-weight: 700; font-size: 15.5px; color: var(--jm-heading); }
.grv .grv__when { margin: 0; font-size: 13px; color: var(--jm-muted); }
.grv .grv__stars--sm { margin: 12px 0 8px; font-size: 18px; letter-spacing: 2px; }
.grv .grv__text { margin: 0 0 12px; font-size: 15.5px; line-height: 1.65; color: var(--jm-body); }
.grv .grv__tags { display: flex; flex-wrap: wrap; gap: 8px; margin: 0 0 10px; }
.grv__tags span {
  display: inline-flex; align-items: center; gap: 5px;
  padding: 4px 10px;
  border-radius: var(--jm-pill);
  background: color-mix(in srgb, var(--jm-accent) 12%, var(--jm-card));
  font-size: 12.5px; font-weight: 600; color: var(--jm-accent-dim);
}
.grv__tags svg { width: 12px; height: 12px; }
.grv .grv__src { margin: auto 0 0; font-size: 12px; color: var(--jm-muted); }

.grv__prompts {
  padding: 26px;
  border: 1px dashed color-mix(in srgb, var(--jm-accent) 55%, var(--jm-line));
  border-radius: var(--jm-r-lg);
  background: color-mix(in srgb, var(--jm-accent) 5%, var(--jm-card));
}
.grv .grv__prompts-h { margin: 0 0 16px; font-weight: 700; font-size: 17px; color: var(--jm-heading); }
.grv__prompts ul { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 14px; margin: 0; padding: 0; }
.grv__prompts li { display: flex; gap: 14px; align-items: flex-start; padding: 16px; border-radius: var(--jm-r); background: var(--jm-card); border: 1px solid var(--jm-line); }
.grv__pico {
  flex: none; display: grid; place-items: center;
  width: 40px; height: 40px; border-radius: 50%;
  background: color-mix(in srgb, var(--jm-accent) 18%, var(--jm-card));
  color: var(--jm-accent-dim); font-size: 18px;
}
.grv__prompts h3 { margin: 0 0 4px; font-size: 16px; color: var(--jm-heading); }
.grv__prompts p { margin: 0; font-size: 14.5px; line-height: 1.55; color: var(--jm-body); }

@media (max-width: 900px) {
  .grv__grid { grid-template-columns: minmax(0, 1fr); }
  .grv__sum { position: static; }
}
@media (max-width: 620px) {
  .grv__cards, .grv__prompts ul { grid-template-columns: minmax(0, 1fr); }
}

@media (max-width: 560px) {
  .ablk__steps, .ablk--problem .ablk__tiles { grid-template-columns: minmax(0, 1fr); }
  .ablk__pair img { width: 104px; height: 104px; }
  .ablk__year { width: 70px; }
  .ablk__line::before { left: 34px; }
}

/* ==========================================================================
   §78  ICON COLOURS BY MEANING  (2026-10-07)
   The client: "colorful template color use for icon and its unique icon
   colors … don't ask, analyse and choose". Until now every icon on the site
   was the same gold in the same pale-gold disc, so a pin, a tick, a clock
   and a shield read as one thing. Each MEANING now has its own hue, chosen
   to sit beside charcoal + gold (deep jewel tones, not primaries):
     teal    — place      pin
     green   — yes / go   check, phone, whatsapp, thumb
     indigo  — trust      shield, badge, lock, eye
     rose    — people     user, users, heart, camera
     plum    — info       help, comment, doc, mail, send, share, search
     amber   — time       clock, play
     gold    — value      star, tag, card, rupee   (the brand accent, unchanged)
   Every hue is a token (the only literals are these definitions), its
   foreground is ≥ 4.5:1 on its own 14% tint, and the disc background is a
   color-mix of the same hue — so an icon and its circle always match.
   Works by jm_icon() adding .jm-ico--<name> and :has() on the wrapper.
   SCOPE: icon wrappers on LIGHT grounds only. Dark grounds keep their gold
   (the MG Road band, the visit band, the WhatsApp button, the contact rail,
   flash offers). Delete this section and every icon is gold again.
   ========================================================================== */
:root {
  --jm-hue-teal:   #0E7468;
  --jm-hue-green:  #1E7A3C;
  --jm-hue-indigo: #3F3DB8;
  --jm-hue-rose:   #B23A5A;
  --jm-hue-plum:   #7A3A9E;
  --jm-hue-amber:  #A85A0C;
  --jm-hue-gold:   var(--jm-accent-dim);
}

/* 1) each wrapper learns its icon's hue */
:is(.lcard__ico, .ablk__ico, .wchoose__ico, .grv__pico, .area-studio__ico, .why-list__ico,
    .creach__ico, .stop__float__ico, .vfd-stats__ico, .ta__tick):has(> :is(.jm-ico--pin)) { --ico: var(--jm-hue-teal); }
:is(.lcard__ico, .ablk__ico, .wchoose__ico, .grv__pico, .area-studio__ico, .why-list__ico,
    .creach__ico, .stop__float__ico, .vfd-stats__ico, .ta__tick):has(> :is(.jm-ico--check, .jm-ico--phone, .jm-ico--whatsapp, .jm-ico--thumb)) { --ico: var(--jm-hue-green); }
:is(.lcard__ico, .ablk__ico, .wchoose__ico, .grv__pico, .area-studio__ico, .why-list__ico,
    .creach__ico, .stop__float__ico, .vfd-stats__ico, .ta__tick):has(> :is(.jm-ico--shield, .jm-ico--badge, .jm-ico--lock, .jm-ico--eye)) { --ico: var(--jm-hue-indigo); }
:is(.lcard__ico, .ablk__ico, .wchoose__ico, .grv__pico, .area-studio__ico, .why-list__ico,
    .creach__ico, .stop__float__ico, .vfd-stats__ico, .ta__tick):has(> :is(.jm-ico--user, .jm-ico--users, .jm-ico--heart, .jm-ico--camera)) { --ico: var(--jm-hue-rose); }
:is(.lcard__ico, .ablk__ico, .wchoose__ico, .grv__pico, .area-studio__ico, .why-list__ico,
    .creach__ico, .stop__float__ico, .vfd-stats__ico, .ta__tick):has(> :is(.jm-ico--help, .jm-ico--comment, .jm-ico--doc, .jm-ico--mail, .jm-ico--send, .jm-ico--share, .jm-ico--search)) { --ico: var(--jm-hue-plum); }
:is(.lcard__ico, .ablk__ico, .wchoose__ico, .grv__pico, .area-studio__ico, .why-list__ico,
    .creach__ico, .stop__float__ico, .vfd-stats__ico, .ta__tick):has(> :is(.jm-ico--clock, .jm-ico--play)) { --ico: var(--jm-hue-amber); }
:is(.lcard__ico, .ablk__ico, .wchoose__ico, .grv__pico, .area-studio__ico, .why-list__ico,
    .creach__ico, .stop__float__ico, .vfd-stats__ico, .ta__tick):has(> :is(.jm-ico--star, .jm-ico--tag, .jm-ico--card, .jm-ico--rupee)) { --ico: var(--jm-hue-gold); }

/* 2) discs: the glyph in its hue, the circle in a 14% tint of it, a hairline
      ring of 30% — written at (0,3,0) so it beats each component's own
      (0,1,0)–(0,2,0) colour rule; an icon with no hue (arrow…) keeps gold. */
body :is(.ablk__ico, .wchoose__ico, .grv__pico, .area-studio__ico, .why-list__ico,
    .creach__ico, .stop__float__ico, .vfd-stats__ico, .ta__tick)[class] {
  color: var(--ico, var(--jm-accent-dim));
  background: color-mix(in srgb, var(--ico, var(--jm-accent)) 14%, var(--jm-card));
  box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--ico, var(--jm-accent)) 30%, transparent);
}
/* the card-heading icons were bare glyphs — they get the same tinted disc,
   sized to sit beside the heading text */
body .lcard__ico[class] {
  flex: none;
  width: 38px;
  height: 38px;
  border-radius: 50%;
  font-size: 19px;
  color: var(--ico, var(--jm-accent-dim));
  background: color-mix(in srgb, var(--ico, var(--jm-accent)) 14%, var(--jm-card));
  box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--ico, var(--jm-accent)) 30%, transparent);
}

/* 3) inline pins in location lines read as places too */
body :is(.acard__pin, .rcard__where, .gcard__meta, .grv__tags span, .wchips > li) .jm-ico--pin { color: var(--jm-hue-teal); }
body :is(.ta__meta, .wchoose__acts span) .jm-ico--clock { color: var(--jm-hue-amber); }

/* 3b) MOTION — 2026-10-07, "icon will be highlight … pop up … when they come".
       Two effects, CSS only, and only for visitors who have not asked for
       reduced motion:
         POP-IN   each disc grows in (50% → 100%) as it scrolls into view.
                  Scroll-driven (animation-timeline: view(), Chromium);
                  @supports-guarded, because fill-mode both on a timeline
                  that never runs would freeze it at opacity 0 — the same
                  trap as the services cards (see CLAUDE.md).
         HIGHLIGHT  hover or keyboard focus anywhere on the card: the disc
                  lifts, tilts, fills a little stronger and sends out one
                  soft ring in its own colour.
       Pop-in animates the separate `scale` property and the highlight uses
       `transform`, so the finished pop-in never blocks the hover. */
@media (prefers-reduced-motion: no-preference) {
  body :is(.lcard__ico, .ablk__ico, .wchoose__ico, .grv__pico, .area-studio__ico, .why-list__ico,
      .creach__ico, .stop__float__ico, .vfd-stats__ico)[class] {
    transition: transform .28s cubic-bezier(.34, 1.56, .64, 1), background-color .2s ease;
  }
  body :is(.lcard, .ablk__tiles > li, .ablk__col, .wchoose__tile, .grv__prompts li, .area-studio__facts li,
      .why-list li, .creach, .vfd-stats li):is(:hover, :focus-within)
    :is(.lcard__ico, .ablk__ico, .wchoose__ico, .grv__pico, .area-studio__ico, .why-list__ico,
      .creach__ico, .vfd-stats__ico)[class] {
    transform: translateY(-2px) scale(1.14) rotate(-6deg);
    background: color-mix(in srgb, var(--ico, var(--jm-accent)) 24%, var(--jm-card));
    animation: jm-ico-ping .9s ease-out 1;
  }
  @supports (animation-timeline: view()) {
    body :is(.lcard__ico, .ablk__ico, .wchoose__ico, .grv__pico, .area-studio__ico, .why-list__ico,
        .creach__ico, .vfd-stats__ico)[class] {
      animation: jm-ico-pop linear both;
      animation-timeline: view();
      animation-range: entry 10% entry 70%;
    }
  }
}
@keyframes jm-ico-pop {
  from { scale: .5; opacity: 0; }
  to   { scale: 1;  opacity: 1; }
}
@keyframes jm-ico-ping {
  from { box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--ico, var(--jm-accent)) 30%, transparent),
                     0 0 0 0 color-mix(in srgb, var(--ico, var(--jm-accent)) 45%, transparent); }
  to   { box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--ico, var(--jm-accent)) 30%, transparent),
                     0 0 0 12px transparent; }
}

/* §79 — /bangalore/ hub (2026-10-07): branch cards and "spa near me" groups,
   two more looks for the §76 tiles. */
/* fixed counts, not auto-fit: 7 branches in 4 columns = 4 + 3, and 6
   regions in 3 = 3 + 3. auto-fit gave 5 + 2 and 5 + 1 — lonely last rows. */
.ablk--branch .ablk__tiles { grid-template-columns: repeat(4, minmax(0, 1fr)); }
.ablk--region .ablk__tiles { grid-template-columns: repeat(3, minmax(0, 1fr)); }
@media (max-width: 1100px) {
  .ablk--branch .ablk__tiles { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .ablk--region .ablk__tiles { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (max-width: 600px) {
  .ablk--branch .ablk__tiles,
  .ablk--region .ablk__tiles { grid-template-columns: minmax(0, 1fr); }
}
.ablk--branch .ablk__tiles > li { border-top: 4px solid var(--jm-accent); }
.ablk--branch .ablk__k { display: inline-block; padding: 4px 10px; border-radius: var(--jm-pill);
  background: color-mix(in srgb, var(--jm-accent) 16%, var(--jm-card)); }
.ablk--branch h3 a { color: var(--jm-heading); text-decoration: none; }
.ablk--branch h3 a:hover, .ablk--branch h3 a:focus-visible { color: var(--jm-accent-dim); text-decoration: underline; }
.ablk .ablk__where { display: flex; align-items: center; gap: 6px; margin: 0 0 8px; font-size: 14px; font-weight: 600; color: var(--jm-hue-teal); }
.ablk__where svg { width: 15px; height: 15px; }
.ablk--region .ablk__tiles > li { background: color-mix(in srgb, var(--jm-hue-teal) 6%, var(--jm-card)); }
.ablk--region h3 { margin-top: 0; }
.ablk--region .ablk__links a svg { color: var(--jm-hue-teal); }

/* 4) dark grounds keep the brand gold — restated after (2) */
body .ablk--band .ablk__ico[class] { background: var(--jm-accent); color: var(--jm-on-accent); box-shadow: none; }

/* §80 — keyword links between the location pages (2026-10-07). The client:
   link every location page to the others by its URL keyword. Pills like
   .wchips, but each one is a link; the pin is teal (place, §78). The links
   inside the first card's paragraphs ({{slug|anchor}} in $AREA_COPY) are
   underlined in accent-ink so they read as links in running text. */
.akw { padding-block: 40px 8px; }
.akw .akw__title {
  margin: 0 0 16px;
  font-family: var(--jm-serif);
  font-size: clamp(22px, 2.4vw, 28px);
  color: var(--jm-heading);
  text-wrap: balance;
}
.akw__list { display: flex; flex-wrap: wrap; gap: 10px; margin: 0; padding: 0; }
.akw__list > li { list-style: none; margin: 0; }   /* on the li — Pico §5 */
.akw__list a {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  padding: 8px 15px;
  border: 1px solid color-mix(in srgb, var(--jm-accent) 40%, var(--jm-line));
  border-radius: var(--jm-pill);
  background: var(--jm-card);
  font-size: 14.5px;
  font-weight: 600;
  color: var(--jm-heading);
  text-decoration: none;
  transition: border-color .2s, background-color .2s, color .2s;
}
.akw__list a:hover,
.akw__list a:focus-visible {
  border-color: var(--jm-accent-dim);
  background: color-mix(in srgb, var(--jm-accent) 12%, var(--jm-card));
  color: var(--jm-accent-dim);
}
.akw__list svg { width: 14px; height: 14px; flex: none; color: var(--jm-hue-teal, var(--jm-accent-dim)); }

.lcard--wide p:not([class]) a {
  color: var(--jm-accent-dim);
  font-weight: 600;
  text-decoration: underline;
  text-underline-offset: 3px;
}
.lcard--wide p:not([class]) a:hover, .lcard--wide p:not([class]) a:focus-visible { color: var(--jm-heading); }
/* §80b — the location pages' FIRST heading (2026-10-07, the client: "Body
   spa in Indiranagar, on 100 Feet Road need heading atractive design").
   The .seo-glow display treatment, sized one step down because it sits
   just under the banner h1: an eyebrow pill, a serif heading with the area
   name in accent italic, and a short gold gradient rule. Written at (0,2,0)
   because `.lcard h2` / `.lcard p` are (0,1,1) — CLAUDE.md §5. All tokens. */
.lcard .aintro__eyebrow {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  margin: 0 0 14px;
  padding: 6px 14px;
  border-radius: var(--jm-pill);
  background: color-mix(in srgb, var(--jm-accent) 18%, var(--jm-card));
  border: 1px solid color-mix(in srgb, var(--jm-accent) 45%, transparent);
  font-size: 12px;
  font-weight: 700;
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--jm-accent-dim);
}
.lcard .aintro__eyebrow svg { width: 14px; height: 14px; color: var(--jm-hue-teal, var(--jm-accent-dim)); }
.lcard .aintro__title {
  display: block;
  margin: 0 0 24px;
  padding-bottom: 16px;
  position: relative;
  font-family: var(--jm-serif);
  font-size: clamp(28px, 3.4vw, 42px);
  font-weight: 700;
  line-height: 1.15;
  letter-spacing: -.01em;
  color: var(--jm-heading);
  text-wrap: balance;
}
.lcard .aintro__title em { font-style: italic; color: var(--jm-accent-dim); }
.lcard .aintro__title::after {
  content: "";
  position: absolute;
  left: 0;
  bottom: 0;
  width: 84px;
  height: 4px;
  border-radius: var(--jm-pill);
  background: linear-gradient(90deg, var(--jm-accent-dim), var(--jm-accent), transparent);
}
/* the area word shimmers in gold where background-clip:text is honoured;
   guarded, or it would be invisible text (the hero's lesson, CLAUDE.md) */
@supports ((-webkit-background-clip: text) or (background-clip: text)) {
  @media (prefers-reduced-motion: no-preference) {
    .lcard .aintro__title em {
      background: linear-gradient(100deg, var(--jm-accent-dim) 0%, var(--jm-accent-dim) 35%,
                  var(--jm-accent) 50%, var(--jm-accent-dim) 65%, var(--jm-accent-dim) 100%);
      background-size: 250% 100%;
      -webkit-background-clip: text;
      background-clip: text;
      color: transparent;
      animation: aintro-glint 6s ease-in-out infinite;
    }
  }
}
@keyframes aintro-glint { 0% { background-position: 100% 0; } 100% { background-position: 0 0; } }

/* §80c — Every Word Capitalised in the location pages' headings
   (2026-10-07, the client: "Your room in Indiranagar, The studio here, Body
   spa treatments in Indiranagar, A session in Indiranagar, Who covers this
   area, Inside the studio, What our guests say. use all the words first
   latter capital"). Display only: the source text, and so what Google and
   screen readers read, is unchanged. Scoped to body.pg-area (set only by
   area-page.php) and to <main>, so the homepage and footer are untouched.
   Delete this rule to undo. */
body.pg-area main :is(h2, h3) { text-transform: capitalize; }

/* §81 — 2026-10-09, phones on the live site. `.btn-solid` / `.btn-outline`
   are nowrap with a fixed 42px height, so a long label ("Book a massage in
   Koramangala") made a 328px button that pushed the page 5px sideways at
   360px. On small screens a button may wrap onto two lines instead. */
@media (max-width: 520px) {
  .btn-solid,
  .btn-outline {
    max-width: 100%;
    height: auto;
    min-height: 42px;
    padding-block: 9px;
    white-space: normal;
    text-align: center;
    line-height: 1.25;
  }
}

/* ==========================================================================
   82. HOMEPAGE, PHONES AND HEADINGS — 2026-10-09, the client's review on a
       Vivo V60. Everything below is additive; delete a block to undo it.
   ========================================================================== */

/* --- a) "Massage services in Bangalore": photo above the text on phones ---
   Desktop is unchanged: `display: contents` keeps the <img> itself the flex
   item, so §64's equal-height trick still works. Below 640px the row stacks,
   the <picture> serves the 1200px landscape file from service-lg/, and the
   arrow disc goes (the whole row is already the link). */
.svc .svc-row__pic { display: contents; }
@media (max-width: 640px) {
  .svc .svc-row { flex-direction: column; align-items: stretch; gap: 14px; padding-block: 20px; }
  .svc .svc-row__thumb,
  .svc-row__thumb {
    width: 100%;
    height: auto;
    contain: none;
    aspect-ratio: 16 / 10;
    object-fit: cover;
    border-radius: var(--jm-r);
  }
  .svc .svc-row__body { align-self: stretch; }
  .svc .svc-row__go { display: none; }
}

/* --- b) "Inside our spas": bigger, two-tone heading; a quieter place line --- */
.gal .gal__title { font-size: clamp(30px, 4.2vw, 52px); }
.gal .gal__title em { font-style: normal; color: var(--jm-accent-dim); }
.gal .gcard__no {
  font-size: 11px;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--jm-accent-lit);
}
/* The place line was a centred pin + "Area, Bangalore" in gold, which read as
   a button. Now a small tracked caption between two hairlines. */
.gal .gcard__meta {
  gap: 10px;
  margin: 2px 0 10px;
  font-size: 11.5px;
  font-weight: 700;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--jm-muted);
}
.gal .gcard__meta::before,
.gal .gcard__meta::after {
  content: '';
  flex: 0 1 34px;
  height: 1px;
  background: color-mix(in srgb, var(--jm-accent-dim) 45%, transparent);
}
.gal .gcard__link {
  font-family: var(--jm-serif);
  font-size: clamp(20px, 1.9vw, 24px);
  color: var(--jm-heading);
}

/* --- c) Therapist portraits on phones: the whole picture, not a face crop --
   The roster card cropped a 4:5 portrait into 4:3, and the profile grid blew
   a 260px file up to the full width of the phone. Both now show the photo at
   its own 4:5 shape, framed inside the card at a size the file can carry. */
@media (max-width: 560px) {
  .rcard__photo {
    width: min(68%, 250px);
    height: auto;
    min-height: 0;
    aspect-ratio: 4 / 5;
    margin: 18px auto 0;
    border-radius: var(--jm-r);
    object-position: 50% 20%;
  }
}
@media (max-width: 470px) {
  .models-grid .mcard__photo {
    width: min(78%, 280px);
    margin: 16px auto 0;
    border-radius: var(--jm-r);
    overflow: hidden;
  }
}

/* --- e) The mobile menu button ---------------------------------------------
   2026-10-09, the client: "3 line … one line it's down … not good … change it
   unique". THE BUG: `.burger span` (0,1,1) also matched the visually-hidden
   "Menu" text, beat `.sr-only` (0,1,0) on `position`, and turned it into a
   FOURTH line, sitting in a second grid row under the icon. Everything here
   targets only the icon span (`[aria-hidden]`), and resets the label to the
   proper visually-hidden state.
   THE DESIGN: a rounded square with a gold hairline, three gold bars of
   different lengths aligned to the right (the short one in the middle), which
   turn into an X while the menu is open. Pure CSS, as before. */
.site-header .burger {
  width: 46px;
  height: 46px;
  flex-basis: 46px;
  border-radius: 14px;
  border: 1px solid color-mix(in srgb, var(--jm-accent) 55%, transparent);
  background:
    linear-gradient(160deg, color-mix(in srgb, var(--jm-accent) 18%, transparent), transparent 60%),
    var(--jm-ink-soft);
  box-shadow: inset 0 1px 0 color-mix(in srgb, var(--jm-on-ink) 8%, transparent);
  color: var(--jm-accent);
  transition: border-color .2s ease, background-color .2s ease;
}
.site-header .burger .sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
  background: none;
}
.site-header .burger > span[aria-hidden] {
  position: relative;
  width: 20px;
  height: 14px;
  background:
    linear-gradient(currentColor, currentColor) right center / 12px 2px no-repeat;
  transition: background-size .2s ease;
}
.site-header .burger > span[aria-hidden]::before,
.site-header .burger > span[aria-hidden]::after {
  left: auto;
  right: 0;
  width: 20px;
  height: 2px;
  border-radius: 2px;
  transition: transform .25s ease, top .25s ease, width .25s ease;
}
.site-header .burger > span[aria-hidden]::before { top: 0; }
.site-header .burger > span[aria-hidden]::after  { top: 12px; width: 16px; }
.site-header .burger:hover > span[aria-hidden] { background-size: 20px 2px; }

/* Open: an X. */
#hdr-nav:checked ~ .site-header__inner .burger {
  border-color: var(--jm-accent);
  background: color-mix(in srgb, var(--jm-accent) 16%, var(--jm-ink-soft));
}
#hdr-nav:checked ~ .site-header__inner .burger > span[aria-hidden] { background-size: 0 2px; }
#hdr-nav:checked ~ .site-header__inner .burger > span[aria-hidden]::before { top: 6px; transform: rotate(45deg); }
#hdr-nav:checked ~ .site-header__inner .burger > span[aria-hidden]::after  { top: 6px; width: 20px; transform: rotate(-45deg); }

/* --- f) The client's logo + a new mobile menu panel (2026-10-09) ----------
   Logo: header (height-led, so the bar does not grow), the foot of the mobile
   menu, and a dark plate in the footer's 18+ card. Menu: the panel was a list
   split by 1px hairlines ("poor lines"); it is now rounded rows with a gold
   chevron, location chips, the two account links side by side, CALL / BOOK
   side by side, and the logo underneath. Desktop navigation is untouched —
   every rule below the logo sizes sits inside max-width: 1180px. */
.brand--logo { display: flex; align-items: center; }
.brand--logo picture { display: block; line-height: 0; }
.brand__logo {
  display: block;
  width: auto;
  height: clamp(46px, 4.4vw, 60px);
  max-width: none;
}
@media (max-width: 560px) { .brand__logo { height: 44px; } }

.assure__logo {
  display: block;
  margin: 6px -8px 16px;
  padding: 14px 16px 12px;
  border-radius: var(--jm-r);
  background:
    radial-gradient(80% 120% at 50% 0%, color-mix(in srgb, var(--jm-accent) 22%, transparent), transparent 70%),
    var(--jm-ink);
  line-height: 0;
}
.assure__logo-img { display: block; width: 100%; height: auto; }

@media (max-width: 1180px) {
  nav.main-nav > ul {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 8px;
    padding-block: 14px 20px;
  }
  nav.main-nav > ul > li { grid-column: 1 / -1; border-top: 0; }
  nav.main-nav > ul > li.nav-acct,
  nav.main-nav > ul > li.nav-cta { grid-column: auto; }
  nav.main-nav > ul > li.nav-acct--full { grid-column: 1 / -1; }
  .main-nav .nav-search { border-bottom: 0; }
  .main-nav .nav-search form { padding-block: 4px 8px; }

  /* the rows */
  nav.main-nav > ul > li:not(.nav-cta):not(.nav-acct):not(.nav-search) > a {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 14px 16px;
    border: 1px solid var(--jm-ink-line);
    border-radius: 12px;
    background: var(--jm-ink-soft);
    font-size: 13.5px;
    color: var(--jm-on-ink);
  }
  nav.main-nav > ul > li:not(.nav-cta):not(.nav-acct):not(.nav-search) > a::after {
    content: '';
    width: 7px;
    height: 7px;
    margin-left: auto;
    border-top: 2px solid var(--jm-accent);
    border-right: 2px solid var(--jm-accent);
    transform: rotate(45deg);
  }
  nav.main-nav > ul > li > a[aria-current="page"] {
    border-color: color-mix(in srgb, var(--jm-accent) 60%, transparent);
    background: color-mix(in srgb, var(--jm-accent) 12%, var(--jm-ink-soft));
    color: var(--jm-accent);
  }

  /* Locations: the areas as chips under their row */
  .main-nav .nav-drop { gap: 6px; margin: 8px 0 2px; padding: 0; }
  .main-nav .nav-drop a {
    display: block;
    padding: 9px 12px;
    border: 1px solid var(--jm-ink-line-2);
    border-radius: var(--jm-pill);
    font-size: 11.5px;
    text-align: center;
    color: var(--jm-nav);
  }
  .main-nav .nav-drop .nav-drop__all a {
    border-color: color-mix(in srgb, var(--jm-accent) 55%, transparent);
    color: var(--jm-accent);
  }

  /* Log in / Sign up: two quiet pills */
  nav.main-nav > ul > li.nav-acct > a {
    display: block;
    margin-top: 6px;
    padding: 11px 10px;
    border: 1px solid var(--jm-ink-line-2);
    border-radius: var(--jm-pill);
    font-size: 12.5px;
    text-align: center;
    color: var(--jm-on-ink);
  }
  /* CALL NOW / BOOK NOW side by side (scoped to .nav-cta: the search GO
     button is a .btn-solid too, and must keep its own width) */
  .main-nav .nav-cta .btn-outline,
  .main-nav .nav-cta .btn-solid { width: 100%; margin-block: 4px 0; height: 46px; }

  /* Pico's `nav ul:first-of-type { margin-left: -.5rem }` (0,1,2) shifted the
     whole panel 8px left; and its `nav li` padding/inline-block squeezed the
     location chips into each other. */
  nav.main-nav > ul:first-of-type { margin: 0; }
  nav.main-nav .nav-drop li { display: block; margin: 0; padding: 0; }
  nav.main-nav .nav-drop a { line-height: 1.25; }
  /* …and Pico's `nav li :where(a)` gives every link a NEGATIVE margin (the
     8px left shift and the rows overlapping each other). */
  nav.main-nav > ul > li { margin: 0; padding: 0; }
  nav.main-nav > ul > li > a,
  nav.main-nav .nav-drop li > a { margin: 0; }
  nav.main-nav > ul > li.nav-acct > a { margin-top: 6px; }
  nav.main-nav > ul > li > .nav-drop { margin-top: 8px; }

  /* the logo under the buttons */
  .main-nav .nav-logo {
    display: block;
    margin-top: 10px;
    padding-top: 16px;
    text-align: center;
  }
  .main-nav .nav-logo picture { display: inline-block; line-height: 0; }
  .main-nav .nav-logo__img { width: 150px; height: auto; opacity: .95; }
}

/* --- g) Whitefield's opening block in the shared location card (2026-10-09)
   The four tiles now sit INSIDE the white .lcard, so they take a soft gold
   tint instead of a second white, and the card's own padding replaces the
   section's. `.lcard p` (0,1,1) would zero the lede's margin, hence (0,2,0). */
.wchoose__card { padding: clamp(24px, 3.4vw, 44px); }
.wchoose__card .wchoose__lede { max-width: 82ch; margin: 0 0 24px; font-size: 16px; color: var(--jm-body); }
.wchoose__card .wchoose__tile {
  background: color-mix(in srgb, var(--jm-accent) 7%, var(--jm-card));
  box-shadow: none;
}
.wchoose__card .wchoose__tile p { margin: 0 0 14px; }
.wchoose__card .wchoose__tile .wchoose__links { margin: auto 0 0; }
.wchoose__card .wchoose__acts { margin: 24px 0 0; }

/* --- h) Therapist cards: tap the photo for her second photo (2026-10-09) ---
   Homepage only ($jm_flip). The checkbox sits INSIDE the card at the photo's
   top-left, visually hidden: a label click focuses its checkbox and the
   browser scrolls to it, so it must already be where the eye is. */
.models-grid .mcard { position: relative; }
.mflip {
  position: absolute;
  top: 12px;
  left: 12px;
  width: 1px;
  height: 1px;
  margin: 0;
  opacity: 0;
  pointer-events: none;
}
.mcard__photo--two .mcard__flip {
  position: absolute;
  inset: 0;
  display: block;
  margin: 0;
  cursor: pointer;
}
.mcard__photo--two .mcard__flip img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  transition: opacity .35s ease, transform .5s cubic-bezier(.2, .7, .3, 1);
}
.mcard__photo--two .mcard__img2 { opacity: 0; }
.mflip:checked ~ .mcard__photo .mcard__img1 { opacity: 0; }
.mflip:checked ~ .mcard__photo .mcard__img2 { opacity: 1; }
.mflip:focus-visible ~ .mcard__photo { outline: 3px solid var(--jm-accent); outline-offset: 2px; }

/* Two dots, bottom centre: which photo is showing. */
.mcard__dots {
  position: absolute;
  left: 50%;
  bottom: 12px;
  display: flex;
  gap: 6px;
  padding: 5px 8px;
  border-radius: var(--jm-pill);
  background: color-mix(in srgb, var(--jm-ink) 55%, transparent);
  transform: translateX(-50%);
}
.mcard__dots i {
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: color-mix(in srgb, var(--jm-on-ink) 45%, transparent);
  transition: background-color .25s ease, width .25s ease;
}
.mcard__dots i:first-child,
.mflip:checked ~ .mcard__photo .mcard__dots i:last-child { width: 16px; border-radius: 4px; background: var(--jm-accent); }
.mflip:checked ~ .mcard__photo .mcard__dots i:first-child { width: 7px; border-radius: 50%; background: color-mix(in srgb, var(--jm-on-ink) 45%, transparent); }
/* Badges and the heart stay above the tappable photo. */
.mcard__photo--two .mbadge,
.mcard__photo--two form.fav,
.mcard__photo--two .fav { z-index: 2; }

/* --- i) Lighthouse contrast fix (2026-10-09): the phone mockup's search
   line was nav-dim grey on the light ink-line, 2.9:1. --- */
.why-phone .why-phone__find { color: var(--jm-body); }

/* --- j) Social row under the footer logo (2026-10-09) ---------------------
   Six round icons, gold on a soft tint; a live account lifts and fills gold
   on hover. An account with no address yet ($SOCIAL 'url' empty) is dimmed
   and not clickable. */
.social {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 6px;
  margin: 0 -6px 16px;          /* the card is 280px: six 34px discs fit one row */
  padding: 0;
  list-style: none;
}
.social li { margin: 0; padding: 0; list-style: none; }
.social__a {
  display: grid;
  place-items: center;
  width: 34px;
  height: 34px;
  border: 1px solid color-mix(in srgb, var(--jm-accent-dim) 45%, transparent);
  border-radius: 50%;
  background: color-mix(in srgb, var(--jm-accent) 10%, var(--jm-card));
  font-size: 17px;
  color: var(--jm-accent-dim);
  text-decoration: none;
  transition: transform .18s ease, background-color .18s ease, color .18s ease, border-color .18s ease;
}
a.social__a:hover,
a.social__a:focus-visible {
  transform: translateY(-2px);
  border-color: var(--jm-accent);
  background: var(--jm-accent);
  color: var(--jm-on-accent);
}
.social__a--soon { opacity: .45; cursor: default; }

/* The row lives in its own panel BESIDE the logo card (the client: "right
   side some space is there"): the footer's legal row becomes disclaimer |
   logo card | follow panel on desktop, and stacks on phones. */
/* Footer, right of the disclaimer: [logo + social] [18+ promise card]. */
.legal-side {
  display: flex;
  align-items: stretch;
  gap: 20px;
}
.fbrand {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  width: 300px;
  padding: 22px 20px 20px;
  border-radius: var(--jm-r);
  background:
    radial-gradient(90% 70% at 50% 0%, color-mix(in srgb, var(--jm-accent) 22%, transparent), transparent 70%),
    var(--jm-ink);
  box-shadow: 0 8px 26px var(--jm-shadow);
  text-align: center;
}
.fbrand__logo { display: block; width: 100%; line-height: 0; }
.fbrand__logo picture { display: block; }
.fbrand__img { display: block; width: 100%; height: auto; }
.footer-legal .fbrand__title {
  margin: 14px 0 12px;
  font-size: 11.5px;
  font-weight: 800;
  letter-spacing: .16em;
  text-transform: uppercase;
  color: var(--jm-accent);
}
.fbrand .social { margin: 0; gap: 6px; flex-wrap: nowrap; }
.fbrand .social__a {
  width: 38px;
  height: 38px;
  border-color: color-mix(in srgb, var(--jm-accent) 45%, transparent);
  background: color-mix(in srgb, var(--jm-accent) 10%, var(--jm-ink));
  color: var(--jm-accent);
}
.fbrand .social__a--soon { opacity: .5; }
/* The promise card no longer holds the logo: the seal, a short heading and
   the three points, vertically centred beside the logo panel. */
.legal-side .assure { display: flex; flex-direction: column; justify-content: center; }
/* Two panels need ~600px; below 1100 the disclaimer goes full width above
   them instead of being squeezed into a narrow column. */
@media (max-width: 1100px) {
  .legal-row { grid-template-columns: minmax(0, 1fr); }
  .legal-row .disclaimer { max-width: none; }
  .legal-side { justify-content: center; }
}
@media (max-width: 860px) {
  /* 34px gap: the 18+ seal breaks the card's top edge by 19px. */
  .legal-side { flex-direction: column; align-items: center; gap: 34px; }
  .fbrand,
  .legal-side .assure { width: min(340px, 100%); }
}

/* --- d) "Our service areas": bigger names, and the branch's Google stars --- */
.acard__name { font-size: clamp(21px, 1.7vw, 23px); }
.acard__stars {
  display: flex;
  align-items: center;
  gap: 6px;
  margin: 2px 0 4px;
  font-size: 12.5px;
  color: var(--jm-muted);
}
.acard__stars b { color: var(--jm-heading); }
/* Five stars filled to the real rating: --rate 4.6 fills 92%. */
.acard__starbar {
  font-size: 15px;
  letter-spacing: 1px;
  background: linear-gradient(90deg,
    var(--jm-accent) calc(var(--rate, 0) / 5 * 100%),
    color-mix(in srgb, var(--jm-muted) 35%, transparent) 0);
  -webkit-background-clip: text;
          background-clip: text;
  color: transparent;
}