/* ---------------------------------------------------------------------------
 * Version:        0.4.0
 * Last edited by: Manara Studio
 * Date:           2026-09-19
 * Status:         Testing
 * Purpose:        Layout for the services hub (templates/services.php, spec 5.2: pillar index
 *                 with the spotlight stage) and the single service page
 *                 (templates/service.php, spec 5.3). hub-* and svc-* classes only, plus the
 *                 layout of shared components inside them.
 * Changelog:
 *   0.11.0 2026-10-11  Manara Studio  Owner's mother: the intro's numbered options row (.svc-options, Waxing's three
 *                              waxes), the priced branch hub list on cream (.hub--priced), package cards white with emerald prices, slider buttons take the
 *                              shared 8px corner. Block "0.11.0" at the end.
 *   0.10.0 2026-10-10  Manara Studio  Branch prices: row asides, package and Unggulan prices, the list's branch note,
 *                              and the branch services hub (/services/<branch-slug>/). Block "0.10.0" at the end.
 *   0.9.0  2026-10-06  Manara Studio  Unggulan, opened rows, photo slider, lash chart. Block "0.9.0".
 *   0.7.0  2026-09-23  Manara Studio  Bound Ledger block appended at the end.
 *   0.6.0  2026-09-23  Manara Studio  Living Ledger block appended at the end (counter, pinned-index reading, row hairline
 *                              draw, unfolding rows, sticky cluster titles below 1024px).
 *   0.4.0  2026-09-19  Manara Studio  SEO round: spacing for the hero "Tersedia di" branch line.
 *   0.3.0  2026-09-17  Manara Studio  Owner: below 1024px the hub is a stacked index without photos
 *                              (tablet: name + tagline + count; phone: name only). See the 0.3.0
 *                              block at the end.
 *   0.2.0  2026-09-17  Manara Studio  Smaller hub names, instant stage swap, ask rows, bolder catalogue.
 *   0.1.0  2026-09-14  Manara Studio  First build.
 * Maintainer notes:
 *   - Requires base.css (tokens, .band, .wrap, .frame, .rows/.row, .btn-*, .link-arrow, .chip,
 *     .coord, .sec-head, .breadcrumb, .faq). Shared components are styled there, never here.
 *   - Tokens only. 0px corners, 1px hairlines in var(--rule), no shadows, no gradients. Lime
 *     appears only as the focus ring inside the dark bundle card.
 *   - Type steps 12/14/16/20/28/40/64/104 at 600px and 1024px, no clamp(). The one spec-pinned
 *     exception is the hub pillar name at 88px from 1280px.
 *   - Hub spotlight (assets/js/services.js toggles the classes): nothing here may change size or
 *     position on hover, focus, .is-active, .is-focusing or .is-tracking. Only opacity,
 *     clip-path, text-decoration-color and transforms of the arrow icon change.
 *   - .hub-stage__frame keeps the .frame.r-4x5 markup but is re-laid as a one-cell grid: every
 *     figure sits in the same cell (stacked without absolute positioning), each image carries the
 *     4:5 ratio and the caption sits under it. clip-path on the figure clips its caption with it,
 *     so the caption must live inside the figure's box.
 *   - .svc-list__aside and .faq-section__aside are sticky at 1024px+: never set overflow on
 *     .svc-list, .svc-list__grid or any other ancestor.
 *   - Band seam: service.php lets two dark bands touch when needed to keep #katalog cream; the
 *     rule "band seam" draws a hairline between them. Cream bands never touch.
 *   - The bundle card is a dark card on a cream band with its own dark context tokens. If the
 *     band toggle ever puts it on a dark band, it gets a hairline border instead.
 * --------------------------------------------------------------------------- */

/* =========================================================================
   Services hub
   ========================================================================= */

/* ---------- hub: hero ---------- */
.hub-hero { padding-block: var(--s-7) var(--s-8); }
.hub-hero__grid {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: var(--s-5);
}
.hub-hero__grid > * { min-width: 0; }
.hub-hero__foot { margin-top: var(--s-4); max-width: 62ch; }

@media (min-width: 600px) {
  .hub-hero { padding-block: var(--s-8) var(--s-9); }
}
@media (min-width: 1024px) {
  .hub-hero { padding-block: var(--s-9); }
  .hub-hero__grid {
    grid-template-columns: minmax(0, 7fr) minmax(0, 5fr);
    column-gap: var(--s-8);
    align-items: end;
  }
}

/* ---------- hub: pillar index (dark band, flush under the hero, top hairline) ---------- */
.hub { padding-top: 0; }
.hub-grid { position: relative; }

.hub-list {
  margin: 0;
  padding: 0;
  list-style: none;
  border-top: 1px solid var(--rule);
}
.hub-item {
  min-width: 0;
  border-bottom: 1px solid var(--rule);
}

/* phone: code | name, then tagline, count + arrow, and the photo full width */
.hub-link {
  display: grid;
  grid-template-columns: 40px minmax(0, 1fr) auto;
  grid-template-areas:
    "code  name    name"
    ".     tagline tagline"
    ".     count   arrow"
    "media media   media";
  column-gap: var(--s-3);
  row-gap: 0;
  align-items: baseline;
  padding-block: var(--s-5) var(--s-6);
  color: inherit;
  text-decoration: none;
  transition: opacity .35s var(--ease);
}
.hub-link__code { grid-area: code; }
.hub-link__name {
  grid-area: name;
  min-width: 0;
  font-size: 40px;
  font-weight: 200;
  line-height: .95;
  letter-spacing: -.01em;
  text-transform: uppercase;
  text-wrap: balance;
  overflow-wrap: break-word;
  text-decoration-line: underline;
  text-decoration-color: transparent;
  text-decoration-thickness: 1px;
  text-underline-offset: .12em;
  transition: text-decoration-color .35s var(--ease);
}
.hub-link__tagline {
  grid-area: tagline;
  margin-top: var(--s-3);
  max-width: 44ch;
}
.hub-link__count {
  grid-area: count;
  margin-top: var(--s-4);
  color: var(--meta);
}
.hub-link__arrow {
  grid-area: arrow;
  display: inline-grid;
  place-items: center;
  align-self: center;
  justify-self: end;
  width: 20px;
  height: 20px;
  margin-top: var(--s-4);
}
.hub-link__arrow .i {
  width: 16px;
  height: 16px;
  transition: transform .35s var(--ease);
}
.hub-link__media {
  grid-area: media;
  display: block;
  margin-top: var(--s-5);
}
.hub-link__media img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/* hover and keyboard focus: underline + arrow nudge, no size or position change */
.hub-link:hover .hub-link__name,
.hub-link:focus-visible .hub-link__name { text-decoration-color: currentColor; }
.hub-link:hover .hub-link__arrow .i,
.hub-link:focus-visible .hub-link__arrow .i { transform: translateX(4px); }

/* the stage mirrors the list at 1024px+ only */
.hub-stage { display: none; }

/* phone and tablet: the item nearest the viewport centre stays full, the rest step back */
@media (max-width: 1023px) {
  /* Dim only non-text parts and the large name, so 12-14px tagline/count text keeps AA contrast. */
  .hub-list.is-tracking .hub-item:not(.is-active) :is(.hub-link__code, .hub-link__arrow, .hub-link__media) { opacity: .55; }
  .hub-list.is-tracking .hub-item:not(.is-active) .hub-link__name { opacity: .7; }
}

/* tablet: photo 5 | code + text 7 */
@media (min-width: 600px) {
  .hub-link {
    grid-template-columns: minmax(0, 5fr) 40px minmax(0, 7fr) auto;
    grid-template-rows: auto auto minmax(0, 1fr);
    grid-template-areas:
      "media code name    name"
      "media .    tagline tagline"
      "media .    count   arrow";
    column-gap: var(--s-4);
    padding-block: var(--s-6);
  }
  .hub-link__media {
    align-self: start;
    margin-top: 0;
    margin-right: var(--s-3);
  }
  .hub-link__count,
  .hub-link__arrow { align-self: end; }
}

/* desktop: list 7 | sticky stage 5 */
@media (min-width: 1024px) {
  .hub-grid {
    display: grid;
    grid-template-columns: minmax(0, 7fr) minmax(0, 5fr);
    column-gap: var(--s-8);
    align-items: start;
  }
  .hub-list { grid-column: 1; }

  .hub-link {
    grid-template-columns: 56px minmax(0, 1fr) auto;
    grid-template-rows: auto;
    grid-template-areas:
      "code name    name"
      ".    tagline tagline"
      ".    count   arrow";
    column-gap: var(--s-5);
    padding-block: var(--s-6);
  }
  .hub-link__name { font-size: 64px; }
  .hub-link__count { align-self: baseline; }
  .hub-link__arrow { align-self: center; }
  .hub-link__media { display: none; }

  .hub-list.is-focusing .hub-item:not(.is-active) .hub-link { opacity: .28; }

  .hub-stage {
    display: block;
    grid-column: 2;
    grid-row: 1;
    position: sticky;
    top: calc(var(--header-h) + var(--s-6));
    align-self: start;
    padding-top: var(--s-6);
  }
}

@media (min-width: 1280px) {
  .hub-link__name { font-size: 88px; }
}

/* ---------- hub: spotlight stage ---------- */
.hub-stage .hub-stage__frame {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  aspect-ratio: auto;
  overflow: visible;
  background: transparent;
}
.hub-stage__item {
  grid-area: 1 / 1;
  min-width: 0;
  margin: 0;
  opacity: 0;
  clip-path: inset(100% 0 0 0);
  transition: clip-path .6s var(--ease), opacity .6s var(--ease);
}
.hub-stage__item.is-active {
  z-index: 1;
  opacity: 1;
  clip-path: inset(0);
}
.hub-stage__item img {
  display: block;
  width: 100%;
  height: auto;
  aspect-ratio: 4 / 5;
  object-fit: cover;
}

/* ---------- hub: catalogue call to action ---------- */
.hub-catalog__grid {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: var(--s-6);
}
.hub-catalog__grid > * { min-width: 0; }
.hub-catalog__lead .body { margin-top: var(--s-5); }

@media (min-width: 1024px) {
  .hub-catalog__grid {
    grid-template-columns: minmax(0, 7fr) minmax(0, 5fr);
    column-gap: var(--s-8);
    align-items: end;
  }
  .hub-catalog__action { justify-self: start; }
}

/* =========================================================================
   Single service
   ========================================================================= */

/* ---------- band seam: two dark bands in a row get a hairline between them ---------- */
.wxp-service .site-main > .band:not(.band--cream) + .band:not(.band--cream) {
  border-top: 1px solid var(--rule);
}

/* ---------- 1. hero ---------- */
.svc-hero { padding-block: var(--s-6) var(--s-8); }
.svc-hero .breadcrumb { margin-bottom: var(--s-6); }
.svc-hero__grid {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: var(--s-7);
}
.svc-hero__grid > * { min-width: 0; }
.svc-hero .display { overflow-wrap: break-word; }
.svc-hero .sub { margin-top: var(--s-5); }
.svc-hero .coord { margin-top: var(--s-5); }
.svc-hero .cta-row { margin-top: var(--s-6); }
.svc-hero__where { margin-top: var(--s-5); max-width: 40ch; }
/* "Booking Semi-Permanent Makeup via WhatsApp" is wider than a phone: let the pill wrap */
.svc-hero .btn-wa {
  max-width: 100%;
  padding-block: var(--s-2);
  line-height: 1.25;
  text-align: left;
  white-space: normal;
}
.svc-hero__media {
  width: 100%;
  margin: 0;
}

@media (min-width: 600px) {
  .svc-hero { padding-block: var(--s-7) var(--s-9); }
  .svc-hero__media { max-width: 480px; }
}
@media (min-width: 1024px) {
  .svc-hero { padding-block: var(--s-8) var(--s-9); }
  .svc-hero .breadcrumb { margin-bottom: var(--s-7); }
  .svc-hero__grid {
    grid-template-columns: minmax(0, 7fr) minmax(0, 5fr);
    column-gap: var(--s-8);
    align-items: end;
  }
  .svc-hero .sub { margin-top: var(--s-6); }
  .svc-hero__media { justify-self: end; }
}

/* ---------- 2. intro + promises ---------- */
.svc-intro__text {
  max-width: 30ch;
  font-size: 28px;
  font-weight: 300;
  line-height: 1.3;
  letter-spacing: -.01em;
  text-wrap: pretty;
}
.svc-intro__text p { margin: 0; }
.svc-intro__text p + p { margin-top: .6em; }
.svc-intro__text + .svc-intro__head { margin-top: var(--s-8); }

.svc-promises {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  margin: var(--s-6) 0 0;
  padding: 0;
  list-style: none;
  border-top: 1px solid var(--rule);
}
.svc-promise {
  display: grid;
  align-content: start;
  gap: var(--s-3);
  min-width: 0;
  padding: var(--s-5) 0 var(--s-6);
  border-bottom: 1px solid var(--rule);
}
.svc-promise .title { text-wrap: balance; }

@media (min-width: 768px) {
  .svc-promises { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  .svc-promise {
    padding: var(--s-5) var(--s-6) var(--s-6) 0;
    border-bottom: 0;
  }
  .svc-promise:not(:nth-child(3n+1)) {
    padding-left: var(--s-6);
    border-left: 1px solid var(--rule);
  }
  .svc-promise:nth-child(3n) { padding-right: 0; }
  .svc-promise:nth-child(n+4) { border-top: 1px solid var(--rule); }
}
@media (min-width: 1024px) {
  .svc-intro__text { font-size: 40px; }
  .svc-intro__text + .svc-intro__head { margin-top: var(--s-9); }
  .svc-promises { margin-top: var(--s-7); }
}

/* ---------- 3. treatment list with a sticky cluster index ---------- */
.svc-list__grid {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: var(--s-7);
}
.svc-list__grid > * { min-width: 0; }
.svc-list__aside .meta { margin-top: var(--s-4); max-width: 34ch; }
.svc-clusters { display: none; }
.svc-cluster + .svc-cluster { margin-top: var(--s-7); }
.svc-cluster__title { padding-bottom: var(--s-4); }
.svc-cluster .row__aside {
  color: var(--meta);
  text-align: right;
}

@media (min-width: 1024px) {
  .svc-list__grid {
    grid-template-columns: minmax(0, 4fr) minmax(0, 8fr);
    column-gap: var(--s-8);
    align-items: start;
  }
  .svc-list__aside {
    position: sticky;
    top: calc(var(--header-h) + var(--s-6));
    align-self: start;
  }
  .svc-clusters {
    display: block;
    margin-top: var(--s-7);
  }
  .svc-clusters__list {
    margin: 0;
    padding: 0;
    list-style: none;
    border-top: 1px solid var(--rule);
  }
  .svc-clusters__link {
    display: flex;
    justify-content: space-between;
    align-items: baseline;
    gap: var(--s-4);
    min-height: 48px;
    padding: 12px 0;
    border-bottom: 1px solid var(--rule);
    color: inherit;
    font-size: 14px;
    line-height: 1.5;
    text-decoration: none;
  }
  .svc-clusters__name {
    min-width: 0;
    text-decoration-thickness: 1px;
  }
  .svc-clusters__link .ordinal { flex: none; }
  /* 0.6.1: the hover underline is now wxp.js's direction-aware .u-line (it grows from the side
     the pointer enters). This rule remains only as the no-JavaScript fallback. */
  .svc-clusters__link:hover .svc-clusters__name,
  .svc-clusters__link:focus-visible .svc-clusters__name { text-decoration-line: underline; }
}

/* ---------- 4. bundles: dark cards on a cream band ---------- */
.svc-bundle-list {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: var(--s-4);
  margin: var(--s-7) 0 0;
  padding: 0;
  list-style: none;
}
.svc-bundle {
  --rule: var(--line);
  --meta: var(--meta-dark, rgba(247, 244, 236, .64));
  display: flex;
  flex-direction: column;
  gap: var(--s-4);
  min-width: 0;
  min-height: 280px;
  padding: var(--s-5);
  background: var(--ground);
  color: var(--cream);
}
.band--cream .svc-bundle :focus-visible { outline-color: var(--lime); }
.svc-bundles:not(.band--cream) .svc-bundle { border: 1px solid var(--rule); }
.svc-bundle__name {
  font-size: 20px;
  font-weight: 500;
  line-height: 1.25;
  letter-spacing: -.005em;
  text-wrap: balance;
}
.svc-bundle__foot {
  margin-top: auto;
  padding-top: var(--s-4);
  border-top: 1px solid var(--rule);
}

@media (min-width: 600px) {
  .svc-bundle-list { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (min-width: 1024px) {
  .svc-bundle-list {
    grid-template-columns: repeat(4, minmax(0, 1fr));
    gap: var(--s-5);
    margin-top: var(--s-8);
  }
}

/* ---------- 5. related service ---------- */
.svc-related__grid {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: var(--s-7);
}
.svc-related__grid > * { min-width: 0; }
.svc-related .body { margin-top: var(--s-5); }
.svc-related .link-arrow { margin-top: var(--s-4); }
.svc-related__media { margin: 0; }

@media (min-width: 600px) {
  .svc-related__media { max-width: 480px; }
}
@media (min-width: 1024px) {
  .svc-related__grid {
    grid-template-columns: minmax(0, 7fr) minmax(0, 5fr);
    column-gap: var(--s-8);
    align-items: center;
  }
  .svc-related__media { max-width: none; }
}

/* ---------- 6. gallery: replaced in 0.9.0 by the tabbed slider (see "0.9.0" at the end) ---------- */

/* ---------- 7. before booking ---------- */
.svc-before__grid {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: var(--s-6);
}
.svc-before__grid > * { min-width: 0; }
.svc-before__text p { margin: 0; }
.svc-before__text p + p { margin-top: 1em; }

@media (min-width: 1024px) {
  .svc-before__grid {
    grid-template-columns: minmax(0, 4fr) minmax(0, 8fr);
    column-gap: var(--s-8);
    align-items: start;
  }
}

/* ---------- 9. catalogue close (#katalog, always cream, always last) ---------- */
.svc-catalog__grid {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: var(--s-7);
}
.svc-catalog__grid > * { min-width: 0; }
.svc-catalog__title {
  font-size: 40px;
  font-weight: 200;
  line-height: .95;
  letter-spacing: -.01em;
  text-transform: uppercase;
  text-wrap: balance;
  overflow-wrap: break-word;
}
.svc-catalog__lead .body { margin-top: var(--s-5); }
.svc-catalog__btn {
  display: flex;
  justify-content: center;
  width: 100%;
  min-height: 64px;
}
.svc-catalog__branches {
  margin: var(--s-5) 0 0;
  padding: 0;
  list-style: none;
  border-top: 1px solid var(--rule);
}
.svc-catalog__branch {
  display: grid;
  grid-template-columns: 40px minmax(0, 1fr) auto;
  column-gap: var(--s-3);
  align-items: center;
  min-height: 56px;
  padding: var(--s-3) 0;
  border-bottom: 1px solid var(--rule);
}
.svc-catalog__name {
  min-width: 0;
  font-size: 16px;
  font-weight: 500;
  line-height: 1.35;
}
.svc-catalog__empty { margin-top: var(--s-4); }

@media (min-width: 600px) {
  .svc-catalog__title { font-size: 64px; }
}
@media (min-width: 1024px) {
  .svc-catalog__grid {
    grid-template-columns: minmax(0, 7fr) minmax(0, 5fr);
    column-gap: var(--s-8);
    align-items: end;
  }
  .svc-catalog__title { font-size: 104px; }
  .svc-catalog__branch { grid-template-columns: 56px minmax(0, 1fr) auto; }
}

/* ---------- motion ---------- */
@media (prefers-reduced-motion: reduce) {
  .hub-link,
  .hub-link__name,
  .hub-link__arrow .i,
  .hub-stage__item { transition: none; }
  .hub-link:hover .hub-link__arrow .i,
  .hub-link:focus-visible .hub-link__arrow .i { transform: none; }
}

/* Four-column asides are ~277px wide at 1024px: step the 64px head down to 40px so uppercase words never split. */
@media (min-width: 1024px) {
  .svc-list__aside .head, .svc-before__grid > .head { font-size: 40px; }
}

/* ==========================================================================
   0.2.0 (2026-09-17; owner feedback)
   1. Services hub: smaller pillar names and a tighter list.
   2. Stage photo swaps INSTANTLY on hover/focus, then settles out of a brief exposure flash.
   3. Treatment rows and paket open the branch chooser ("ask" mode) from anywhere on the row.
   4. Bolder catalogue close: Fraunces lowercase at display scale over a ledger of branches; each
      row band-flips to forest on hover and downloads that branch's catalogue.
   ========================================================================== */

/* 1. smaller hub index */
.hub-link { padding-block: var(--s-4) var(--s-5); }
.hub-link__name { font-size: 28px; }
@media (min-width: 600px) {
  .hub-link { padding-block: var(--s-5); }
}
@media (min-width: 1024px) {
  .hub-link { padding-block: var(--s-4); }
  .hub-link__name { font-size: 40px; }
}
@media (min-width: 1280px) {
  .hub-link__name { font-size: 40px; }
}

/* 2. instant stage swap */
.hub-stage__item,
.hub-stage__item.is-active { clip-path: none; transition: none; }
@keyframes wxp-stage-flash {
  from { filter: brightness(1.45) saturate(.4) contrast(1.1); }
  to { filter: none; }
}
@media (prefers-reduced-motion: no-preference) {
  .hub-stage__item.is-active img { animation: wxp-stage-flash .55s var(--ease) both; }
}

/* 3. whole treatment row opens the branch chooser */
.svc-cluster .row { position: relative; }
.row__ask {
  appearance: none; margin: 0; padding: 0; border: 0; background: none;
  font: inherit; color: inherit; text-align: left; cursor: pointer;
}
.row__ask::before { content: ""; position: absolute; inset: 0; }
.row__ask:focus-visible { outline: none; }
.svc-cluster .row:has(.row__ask:focus-visible) { outline: 2px solid var(--focus, var(--lime)); outline-offset: 2px; }
.svc-cluster .row .row__note,
.svc-cluster .row .row__aside { pointer-events: none; }

/* 4. bolder catalogue close */
.svc-catalog { padding-block: var(--s-9); }
.svc-catalog__lead { max-width: none; }
.svc-catalog__title {
  font-family: var(--f-display);
  font-size: 64px;
  font-weight: 360;
  line-height: .9;
  letter-spacing: -.03em;
  text-transform: lowercase;
  font-optical-sizing: auto;
  font-variation-settings: "opsz" 144;
  text-wrap: balance;
}
.svc-catalog__sub { margin-top: var(--s-5); max-width: 44ch; color: var(--meta); }
.svc-catalog__ledger { list-style: none; margin: var(--s-8) 0 0; padding: 0; border-top: 1px solid var(--ink); }
.svc-catalog__ledger > li { min-width: 0; }
.svc-catalog__row {
  position: relative;
  isolation: isolate;
  display: grid;
  grid-template-columns: 40px minmax(0, 1fr) 48px;
  grid-template-areas: "ord name icon" "ord region icon" "ord cue icon";
  align-items: center;
  column-gap: var(--s-4);
  min-height: 96px;
  padding: var(--s-5) 0;
  border-bottom: 1px solid var(--ink);
  color: var(--ink);
  text-decoration: none;
  transition: color .45s var(--ease);
}
.svc-catalog__row::before {
  content: ""; position: absolute; inset: 0 calc(-1 * var(--s-4)); z-index: -1;
  background: var(--ground);
  transform: scaleX(0); transform-origin: left center;
  transition: transform .55s var(--ease);
}
.svc-catalog__row .ordinal { grid-area: ord; align-self: start; padding-top: .35em; }
.svc-catalog__name { grid-area: name; min-width: 0; font-size: 28px; font-weight: 200; line-height: 1; letter-spacing: -.01em; text-transform: uppercase; overflow-wrap: break-word; }
.svc-catalog__region { grid-area: region; margin-top: var(--s-2); }
.svc-catalog__cue { grid-area: cue; margin-top: var(--s-3); }
.svc-catalog__icon {
  grid-area: icon; justify-self: end;
  display: inline-grid; place-items: center; width: 48px; height: 48px;
  border: 1px solid currentColor;
}
.svc-catalog__icon .i { width: 20px; height: 20px; }
.svc-catalog__row.is-soon { color: var(--meta); }
a.svc-catalog__row:hover,
a.svc-catalog__row:focus-visible { color: var(--cream); }
a.svc-catalog__row:hover::before,
a.svc-catalog__row:focus-visible::before { transform: scaleX(1); }
a.svc-catalog__row:hover .svc-catalog__region,
a.svc-catalog__row:focus-visible .svc-catalog__region { color: rgba(247, 244, 236, .72); }
a.svc-catalog__row:focus-visible { outline-offset: 4px; }
@keyframes wxp-drop {
  0% { transform: none; opacity: 1; }
  45% { transform: translateY(8px); opacity: 0; }
  46% { transform: translateY(-10px); opacity: 0; }
  100% { transform: none; opacity: 1; }
}
@media (prefers-reduced-motion: no-preference) {
  a.svc-catalog__row:hover .svc-catalog__icon .i,
  a.svc-catalog__row:focus-visible .svc-catalog__icon .i { animation: wxp-drop .7s var(--ease) both; }
}
@media (prefers-reduced-motion: reduce) {
  .svc-catalog__row, .svc-catalog__row::before { transition: none; }
}
@media (min-width: 600px) {
  .svc-catalog__title { font-size: 104px; }
}
@media (min-width: 1024px) {
  .svc-catalog { padding-block: var(--s-10); }
  .svc-catalog__row {
    grid-template-columns: 64px minmax(0, 1fr) minmax(0, 14rem) auto 64px;
    grid-template-areas: "ord name region cue icon";
    min-height: 128px;
  }
  .svc-catalog__row .ordinal { align-self: center; padding-top: 0; }
  .svc-catalog__name { font-size: 40px; }
  .svc-catalog__region, .svc-catalog__cue { margin-top: 0; }
  .svc-catalog__cue { padding-inline: var(--s-5); }
  .svc-catalog__icon { width: 64px; height: 64px; }
  .svc-catalog__icon .i { width: 24px; height: 24px; }
}

/* ==========================================================================
   0.3.0 (2026-09-17; owner): below 1024px the hub is a stacked index, no photos.
   Phone: code | NAME | arrow box. Tablet: code | NAME over tagline | count | arrow box.
   Unlike the menu (bare 32px heads), each row ends in a square arrow door and answers a touch with
   a cream band flip (:active), because touch has no hover. The desktop spotlight stage is untouched.
   The photos stay in the markup for the desktop layout; lazy images inside display:none never load.
   ========================================================================== */
@media (max-width: 1023px) {
  .hub-link__media,
  .hub-link__tagline,
  .hub-link__count { display: none; }

  /* No photos to spotlight, so the scroll-tracking dim is switched off. */
  .hub-list.is-tracking .hub-item:not(.is-active) :is(.hub-link__code, .hub-link__arrow, .hub-link__name) { opacity: 1; }

  .hub-link {
    position: relative;
    isolation: isolate;
    grid-template-columns: 32px minmax(0, 1fr) 44px;
    grid-template-rows: auto;
    grid-template-areas: "code name arrow";
    align-items: center;
    column-gap: var(--s-3);
    min-height: 88px;
    padding-block: var(--s-4);
  }
  .hub-link::before {
    content: "";
    position: absolute;
    z-index: -1;
    top: 0;
    bottom: 0;
    left: calc(var(--gutter) * -1);
    right: calc(var(--gutter) * -1);
    background: var(--cream);
    opacity: 0;
    transition: opacity .2s var(--ease);
  }
  .hub-link__name {
    font-size: 28px;
    line-height: 1;
  }
  .hub-link__arrow {
    width: 44px;
    height: 44px;
    margin: 0;
    border: 1px solid var(--rule);
    transition: background-color .3s var(--ease), color .3s var(--ease), border-color .3s var(--ease);
  }
  .hub-link:hover .hub-link__arrow,
  .hub-link:focus-visible .hub-link__arrow {
    background: var(--cream);
    border-color: var(--cream);
    color: var(--ground);
  }
  .hub-link:active { color: var(--ground); }
  .hub-link:active::before { opacity: 1; }
  .hub-link:active .hub-link__tagline,
  .hub-link:active .hub-link__count { color: rgba(5, 38, 22, .72); }
  .hub-link:active .hub-link__arrow { border-color: var(--ground); }
}

@media (min-width: 600px) and (max-width: 1023px) {
  .hub-link__tagline,
  .hub-link__count { display: block; }
  .hub-link {
    grid-template-columns: 56px minmax(0, 1fr) auto 56px;
    grid-template-areas:
      "code name    count arrow"
      ".    tagline count arrow";
    column-gap: var(--s-5);
    row-gap: var(--s-2);
    min-height: 128px;
    padding-block: var(--s-5);
  }
  .hub-link__code { align-self: baseline; }
  .hub-link__name { align-self: baseline; font-size: 40px; }
  .hub-link__tagline { align-self: start; margin-top: 0; }
  .hub-link__count { align-self: center; margin-top: 0; }
  .hub-link__arrow { width: 56px; height: 56px; }
}

@media (max-width: 1023px) and (prefers-reduced-motion: reduce) {
  .hub-link::before,
  .hub-link__arrow { transition: none; }
}

/* ---------- 0.6.0 Living Ledger (owner-chosen overdrive, 2026-09-23) ----------
 * The numbered treatment list, read like an instrument. Markup: templates/service.php (#perawatan).
 * Behaviour: assets/js/ledger.js. Owner picked this over "Cinematic chapter" and "Grows from your
 * touch" on 2026-09-23.
 *   1. Counter: a Fraunces figure rolls to the treatment at the reading line. Big in the sticky
 *      aside at 1024px+, small inside each cluster title below 1024px, where titles are sticky.
 *      Ordinals are NEVER lime (DESIGN.md): the counter is cream on dark, ink on cream.
 *   2. Pinned index: the current cluster is marked (lime name on dark, as DESIGN.md allows for
 *      "the pinned-index item"; underline on cream) and a --focus line fills through it.
 *   3. Rows draw their own hairline as they arrive (scroll-driven, compositor-only). Browsers
 *      without animation-timeline keep today's static rule.
 *   4. Rows unfold in place: WhatsApp pill (ask mode) + "Buat janji" line (Zenwel booking mode).
 * The digits are generated here in `content`. That is not the "no text in CSS content" case:
 * numerals are universal and never translated, and generating them keeps 0-9 strips out of the
 * page text that search engines, TranslatePress and screen readers see.
 * STICKY: the aside and (below 1024px) the cluster titles are sticky. No ancestor may set
 * overflow. .odo__col and .row__more-inner clip, but they are descendants, never ancestors.
 */

/* 1. the odometer */
.odo {
  --odo-h: 1.1em;
  display: inline-flex;
  font-family: var(--f-display);
  font-weight: 400;
  font-variation-settings: "opsz" 144;
  font-feature-settings: "lnum", "tnum";
  font-variant-numeric: lining-nums tabular-nums;
  line-height: var(--odo-h);
  letter-spacing: -.01em;
}
.odo__col { display: block; height: var(--odo-h); overflow: hidden; }
.odo__strip { display: block; transform: translateY(calc(var(--d, 0) * -1 * var(--odo-h))); }
.odo__strip::before { content: "0\A 1\A 2\A 3\A 4\A 5\A 6\A 7\A 8\A 9"; display: block; white-space: pre; }
@media (prefers-reduced-motion: no-preference) {
  /* expo-out, no overshoot: the site settles, it never bounces (DESIGN.md, the rail's spring) */
  .odo__strip { transition: transform .7s var(--ease); }
}
.odo--lg { font-size: 64px; }
.odo--sm { font-size: 20px; color: var(--meta); flex: none; }

.ledger-count { display: none; }
@media (min-width: 1024px) {
  .ledger-count { display: flex; align-items: baseline; gap: var(--s-3); margin-top: var(--s-6); }
  .ledger-count__total {
    font-size: 14px; letter-spacing: .02em;
    font-variant-numeric: tabular-nums;
    color: var(--meta);
  }
  .ledger-count + .svc-clusters { margin-top: var(--s-5); }
  .odo--sm { display: none; }
}
/* a short laptop screen: keep the whole sticky aside in view */
@media (min-width: 1024px) and (max-height: 700px) {
  .odo--lg { font-size: 40px; }
  .ledger-count { margin-top: var(--s-4); }
}

/* 2. the pinned index reads the current cluster */
@media (min-width: 1024px) {
  .svc-clusters__link { position: relative; }
  .svc-clusters__link::after {
    content: "";
    position: absolute; left: 0; right: 0; bottom: -1px;
    height: 1px;
    background: var(--focus);
    transform: scaleX(var(--p, 0)); transform-origin: left center;
    opacity: 0;
    pointer-events: none;
  }
  .svc-clusters__link.is-current::after { opacity: 1; }
  .band:not(.band--cream) .svc-clusters__link.is-current .svc-clusters__name { color: var(--lime); }
  /* 0.6.1: .u-line (wxp.js hover line) forces text-decoration off, so cream marks the current
     cluster by weight: lime never goes on cream, and small emerald text fails AA. */
  .band--cream .svc-clusters__link.is-current .svc-clusters__name { font-weight: 500; }
}
@media (min-width: 1024px) and (prefers-reduced-motion: no-preference) {
  /* a short linear smoothing between scroll frames; long enough to hide steps, short enough to feel attached */
  .svc-clusters__link::after { transition: transform .15s linear, opacity .3s var(--ease); }
  .svc-clusters__name { transition: color .3s var(--ease); }
}

/* 3 + 4. rows: a fourth column for the drawn +/- (.pm, shared with the FAQ), and the unfold */
.svc-cluster .row {
  grid-template-columns: 40px minmax(0, 1fr) auto 16px;
  row-gap: 0;
}
@media (min-width: 768px) {
  .svc-cluster .row { grid-template-columns: 56px minmax(0, 1fr) 160px 16px; }
}
.row__pm { grid-column: 4; grid-row: 1; align-self: start; margin-top: 3px; }
.svc-cluster .row.is-open .row__pm::after { transform: rotate(0deg); }
.svc-cluster .row:hover .row__pm { color: var(--cream); }
.band--cream .svc-cluster .row:hover .row__pm { color: var(--ink); }

.row__more {
  grid-column: 2 / -1; grid-row: 2;
  display: grid; grid-template-rows: 0fr;
  position: relative; z-index: 1; /* above the whole-row toggle surface (.row__ask::before) */
}
.row__more-inner { min-height: 0; overflow: hidden; }
.row__more .cta-row { padding: var(--s-4) 0 var(--s-1); }
.svc-cluster .row.is-open .row__more { grid-template-rows: 1fr; }
@media (prefers-reduced-motion: no-preference) {
  .row__more { transition: grid-template-rows .45s var(--ease); }
  .row__more .cta-row {
    opacity: 0; transform: translateY(-6px);
    transition: opacity .3s var(--ease), transform .45s var(--ease);
  }
  .svc-cluster .row.is-open .row__more .cta-row { opacity: 1; transform: none; transition-delay: .08s; }
}

@keyframes wxp-rule-draw {
  from { transform: scaleX(0); }
  to { transform: scaleX(1); }
}
@supports (animation-timeline: view()) {
  @media (prefers-reduced-motion: no-preference) {
    .svc-cluster .row { border-bottom-color: transparent; }
    .svc-cluster .row::after {
      content: "";
      position: absolute; left: 0; right: 0; bottom: -1px;
      height: 1px;
      background: var(--rule);
      transform-origin: left center;
      pointer-events: none;
      animation: wxp-rule-draw linear both;
      animation-timeline: view();
      animation-range: entry 10% cover 30%;
    }
  }
}

/* 1b. below 1024px the cluster titles stick under the header and carry the small counter */
.svc-cluster__title { display: flex; align-items: baseline; justify-content: space-between; gap: var(--s-4); }
.svc-cluster__name { min-width: 0; }
@media (max-width: 1023px) {
  .svc-cluster__title {
    position: sticky; top: var(--header-h); z-index: 2;
    padding-block: var(--s-3);
    background: var(--ground);
    border-bottom: 1px solid var(--rule);
  }
  .band--cream .svc-cluster__title { background: var(--cream); }
  .svc-cluster .rows { border-top: 0; }
}
@media (min-width: 601px) and (max-width: 782px) {
  .admin-bar .svc-cluster__title { top: calc(var(--header-h) + 46px); }
}
@media (min-width: 783px) and (max-width: 1023px) {
  .admin-bar .svc-cluster__title { top: calc(var(--header-h) + 32px); }
}

/* ---------- 0.7.0 Bound Ledger (owner-chosen overdrive for the whole service page, 2026-09-23) ----------
 * The Living Ledger stops being one section and becomes the page: one bound, numbered document.
 * Markup: templates/service.php. Behaviour: assets/js/bound.js (ticks, folio roll-in).
 *   Title page: the service's record number hangs beside the lowercase title as its folio; a
 *     contents line under the actions lists the chapters (two-digit, so chapters never look like
 *     the three-digit record ordinals).
 *   Reading rule: a 1px lime line over the header's bottom hairline fills with the page's scroll,
 *     ticking at each chapter. Lime is legal: it only ever sits on the forest header.
 *   Chapter rules: each chapter opens with a hairline that draws itself and a Fraunces folio.
 *   Promises: full-width ruled entries, headline large, rule drawn in.
 *   Package cards open with the site's photo shutter. The page closes on a double rule.
 * Everything that moves is a scroll-driven transform or clip-path (compositor-only) inside
 * @supports + prefers-reduced-motion: no-preference. Firefox and reduced motion get the static page.
 */

/* title page */
.svc-hero__title { display: flex; align-items: baseline; gap: calc(var(--h1) * .28); }
.svc-hero__title .display { min-width: 0; }
.svc-folio {
  flex: none;
  font-family: var(--f-display);
  font-size: var(--h1);
  font-weight: 360;
  line-height: .92;
  letter-spacing: -.02em;
  font-variation-settings: "opsz" 144;
  font-feature-settings: "lnum", "tnum";
  font-variant-numeric: lining-nums tabular-nums;
  color: var(--meta);
}
@media (prefers-reduced-motion: no-preference) {
  .site-main > section:first-child .svc-folio { animation: wxp-mask-rise 1.1s var(--ease) .06s both; }
}

/* contents line */
.svc-contents { margin-top: var(--s-6); }
.svc-contents__list {
  display: grid; grid-template-columns: repeat(2, minmax(0, 1fr));
  margin: 0; padding: 0; list-style: none;
  border-top: 1px solid var(--rule);
}
.svc-contents__link {
  display: flex; align-items: baseline; gap: var(--s-2);
  min-height: 44px; padding: 12px var(--s-4) 12px 0;
  border-bottom: 1px solid var(--rule);
  color: inherit; text-decoration: none;
  font-size: 12px; font-weight: 500; line-height: 1.35; letter-spacing: .12em; text-transform: uppercase;
}
.svc-contents__no,
.svc-contents__count {
  font-size: 14px; font-weight: 400; letter-spacing: .02em; text-transform: none;
  font-variant-numeric: tabular-nums;
  color: var(--meta);
}
.svc-contents__name { min-width: 0; }
@media (min-width: 768px) {
  /* a three-column table, not a wrapping row: columns align like a ledger, and six chapters
     never wrap into five plus one orphan (measured at 1366px, where the hero lead is ~480px). */
  .svc-contents__list {
    grid-template-columns: repeat(3, max-content);
    column-gap: var(--s-7);
    border-top: 0;
  }
  .svc-contents__link { padding-right: 0; border-bottom: 0; }
}

/* reading rule */
@keyframes wxp-read { from { transform: scaleX(0); } to { transform: scaleX(1); } }
.reading-rule { display: none; }
@supports (animation-timeline: scroll()) {
  .reading-rule {
    display: block;
    position: fixed; left: 0; right: 0; top: var(--header-h); z-index: 61;
    height: 1px;
    pointer-events: none;
  }
  .reading-rule__fill {
    position: absolute; inset: 0;
    background: var(--lime);
    transform-origin: left center;
    animation: wxp-read linear both;
    animation-timeline: scroll(root block);
  }
  /* ticks rise UP into the forest header, so they never sit on a cream band */
  .reading-rule__tick {
    position: absolute; bottom: 0;
    width: 1px; height: 6px; margin-left: -.5px;
    background: var(--meta-on-dark);
  }
  .reading-rule__tick.is-passed { background: var(--lime); }
}
@media (prefers-reduced-motion: no-preference) {
  .reading-rule__tick { transition: background-color .3s var(--ease); }
}
@media (min-width: 601px) and (max-width: 782px) { .admin-bar .reading-rule { top: calc(var(--header-h) + 46px); } }
@media (min-width: 783px) { .admin-bar .reading-rule { top: calc(var(--header-h) + 32px); } }

/* chapter rules */
.chapter-rule { display: flex; align-items: center; gap: var(--s-4); margin-bottom: var(--s-7); }
.chapter-rule__line { flex: 1 1 auto; height: 1px; background: var(--rule); transform-origin: left center; }
.odo--folio { font-size: 28px; color: var(--meta); flex: none; }

/* promises as full-width ruled entries */
.svc-promises { display: block; border-top: 0; }
.svc-promise {
  position: relative;
  display: grid; gap: var(--s-3);
  padding: var(--s-5) 0 var(--s-6);
  border: 0;
}
.svc-promise::before {
  content: ""; position: absolute; left: 0; right: 0; top: 0;
  height: 1px; background: var(--rule);
  transform-origin: left center;
}
.svc-promise:last-child { border-bottom: 1px solid var(--rule); }
.svc-promise .title {
  font-size: 28px; font-weight: 300; line-height: 1.05; letter-spacing: -.01em;
  text-transform: uppercase;
}
@media (min-width: 768px) {
  .svc-promises { grid-template-columns: none; }
  .svc-promise {
    grid-template-columns: minmax(0, 7fr) minmax(0, 5fr);
    column-gap: var(--s-7); align-items: baseline;
    padding: var(--s-6) 0;
    border-bottom: 0;
  }
  .svc-promise:last-child { border-bottom: 1px solid var(--rule); }
  .svc-promise:not(:nth-child(3n+1)) { padding-left: 0; border-left: 0; }
  .svc-promise:nth-child(3n) { padding-right: 0; }
  .svc-promise:nth-child(n+4) { border-top: 0; }
}
@media (min-width: 1024px) { .svc-promise .title { font-size: 40px; } }

/* the sign-off: the last catalogue row's ink rule + this one, 3px apart = the ledger's double rule */
.svc-signoff__rule { display: block; height: 1px; margin-top: 3px; background: var(--ink); transform-origin: left center; }
.svc-signoff .cta-row { margin-top: var(--s-7); }

/* what moves */
@keyframes wxp-card-open { from { clip-path: inset(14% 0 14% 0); } to { clip-path: inset(0); } }
@supports (animation-timeline: view()) {
  @media (prefers-reduced-motion: no-preference) {
    .chapter-rule__line,
    .svc-promise::before,
    .svc-signoff__rule {
      animation: wxp-rule-draw linear both;
      animation-timeline: view();
      animation-range: entry 10% cover 30%;
    }
    .svc-bundle {
      animation: wxp-card-open linear both;
      animation-timeline: view();
      animation-range: entry 5% cover 30%;
    }
    .svc-bundle:nth-child(4n+2) { animation-range: entry 12% cover 36%; }
    .svc-bundle:nth-child(4n+3) { animation-range: entry 19% cover 42%; }
    .svc-bundle:nth-child(4n+4) { animation-range: entry 26% cover 48%; }
  }
}
@media (prefers-reduced-motion: no-preference) {
  .odo--folio .odo__strip { transition-duration: .9s; }
}

/* ---------- 0.9.0 Unggulan, opened rows, photo slider, lash styles (owner round, 2026-10-06) ----------
 * The owner's reference is dandelion.id: one treatment told as a story ("Apa itu …?"), its photos
 * shown one at a time, a chart to choose a lash style. All of it stays inside the Bound Ledger:
 * every addition is a numbered chapter, ruled with 1px hairlines, square and flat; the WhatsApp
 * pill keeps the only curve.
 * Markup: templates/service.php, parts/slider.php, parts/lash-styles.php.
 * Behaviour: assets/js/slider.js (swipe is native scroll-snap; JS adds arrows, counter and tabs).
 *   Unggulan: the featured treatment's photos stay pinned beside its text at 1024px+, like a
 *     plate facing its page.
 *   Slider: one photo at a time in a mount shaped like the set's first photo (--slider-r, set by
 *     parts/slider.php). Photos are never cropped (object-fit: contain): before/after pairs keep
 *     their own shape; single photos are prepared at 4:5 and fill their mount.
 *   Tabs: a ruled table like the contents line; the current tab is lime on dark, ink on cream,
 *     the others meta (lime never appears on cream).
 */

/* facts: a ruled definition list, in the Unggulan chapter and inside opened rows */
.facts { margin: 0; border-top: 1px solid var(--rule); }
.facts__row {
  display: grid; grid-template-columns: minmax(0, 1fr); row-gap: 2px;
  padding: 12px 0;
  border-bottom: 1px solid var(--rule);
}
.facts__label {
  color: var(--meta);
  font-size: 12px; font-weight: 500; line-height: 1.35; letter-spacing: .12em; text-transform: uppercase;
}
.facts__value { margin: 0; font-size: 16px; line-height: 1.45; }
.facts--compact .facts__row { padding: 10px 0; }
.facts--compact .facts__value { font-size: 14px; line-height: 1.5; }
@media (min-width: 600px) {
  .facts__row { grid-template-columns: 160px minmax(0, 1fr); column-gap: var(--s-5); align-items: baseline; }
  .facts--compact .facts__row { grid-template-columns: 128px minmax(0, 1fr); }
}

/* Unggulan: title, photos, then the text on phones; photos pinned left of the text at 1024px+ */
.svc-feature__grid {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  grid-template-areas: "title" "media" "body";
  row-gap: var(--s-6);
}
.svc-feature__grid > * { min-width: 0; }
/* no photos yet (BIAB): no empty media row, so no doubled gap under the title */
.svc-feature__grid:not(.has-media) { grid-template-areas: "title" "body"; }
.svc-feature__title { grid-area: title; }
.svc-feature__media { grid-area: media; }
.svc-feature__body { grid-area: body; display: grid; align-content: start; row-gap: var(--s-6); }
.svc-feature__lead { color: inherit; }
.svc-feature__lead p { margin: 0; }
.svc-feature__lead p + p { margin-top: .6em; }
.svc-feature__why .title { margin-bottom: var(--s-4); }
.svc-feature__benefits {
  margin: 0; padding: 0; list-style: none;
  border-top: 1px solid var(--rule);
}
.svc-feature__benefits li {
  padding: 14px 0;
  border-bottom: 1px solid var(--rule);
  font-size: 16px; line-height: 1.45;
}
.svc-feature__body .cta-row { margin-top: var(--s-2); }
/* "Booking Sulam Alis Ombre Powder via WhatsApp" is wider than a phone: let the pill wrap.
   The catalogue sign-off pill gets the same rule: since 0.7.0 "Booking Eyelash Extension via
   WhatsApp" and "Booking Semi-Permanent Makeup via WhatsApp" ran past a 375px screen (measured
   2026-10-06 in the harness). */
.svc-feature .btn-wa,
.svc-signoff .btn-wa {
  max-width: 100%;
  padding-block: var(--s-2);
  line-height: 1.25;
  text-align: left;
  white-space: normal;
}
@media (min-width: 1024px) {
  .svc-feature__grid.has-media {
    grid-template-columns: minmax(0, 5fr) minmax(0, 7fr);
    grid-template-areas: "media title" "media body";
    grid-template-rows: auto 1fr;
    column-gap: var(--s-8);
  }
  .svc-feature__grid.has-media .svc-feature__media {
    position: sticky;
    top: calc(var(--header-h) + var(--s-6));
    align-self: start;
  }
  .svc-feature__grid:not(.has-media) {
    grid-template-columns: minmax(0, 4fr) minmax(0, 8fr);
    grid-template-areas: "title body";
    column-gap: var(--s-8);
    align-items: start;
  }
}

/* slider: one photo at a time, swiped natively, mounted at 4:5 */
.slider { display: grid; row-gap: var(--s-4); min-width: 0; }
.slider__track {
  display: flex;
  margin: 0; padding: 0; list-style: none;
  overflow-x: auto; overflow-y: hidden;
  scroll-snap-type: x mandatory;
  overscroll-behavior-x: contain;
  scrollbar-width: none;
}
.slider__track::-webkit-scrollbar { display: none; }
.slider__track:focus-visible { outline: 2px solid var(--focus); outline-offset: 3px; }
.slider__slide { flex: 0 0 100%; min-width: 0; scroll-snap-align: start; scroll-snap-stop: always; }
.slider__figure { margin: 0; }
.slider__frame {
  position: relative; display: block;
  aspect-ratio: var(--slider-r, .8); /* the set's first photo, set inline by parts/slider.php */
  overflow: hidden;
  background: rgba(var(--cream-rgb), .06);
}
.band--cream .slider__frame { background: rgba(5, 38, 22, .06); }
.slider__img {
  position: absolute; inset: 0;
  width: 100%; height: 100%;
  object-fit: contain;
}
.slider__caption {
  padding-top: 10px;
  max-width: 62ch;
  font-size: 14px; line-height: 1.5;
  color: var(--meta);
}
.slider__bar { display: flex; align-items: center; gap: var(--s-4); min-height: 44px; }
.slider__count {
  flex: none;
  font-size: 14px; line-height: 1; letter-spacing: .02em;
  font-variant-numeric: tabular-nums;
  color: var(--meta);
}
.slider__nav { display: none; gap: var(--s-2); margin-left: auto; }
.js .slider__nav { display: flex; }
.slider__btn {
  display: inline-grid; place-items: center;
  width: 44px; height: 44px; flex: none;
  padding: 0; border: 1px solid var(--rule); border-radius: 0;
  background: transparent; color: inherit;
  cursor: pointer;
  transition: background-color .3s var(--ease), color .3s var(--ease), border-color .3s var(--ease);
}
.slider__btn .i { width: 18px; height: 18px; }
.slider__btn:hover { background: var(--cream); color: var(--ground); border-color: var(--cream); }
.band--cream .slider__btn:hover { background: var(--ground); color: var(--cream); border-color: var(--ground); }
.slider.is-single .slider__bar { display: none; }
@media (prefers-reduced-motion: no-preference) {
  .slider__track { scroll-behavior: smooth; }
  /* `scale`, not `transform`, like every other lightbox tile */
  .slider__frame .slider__img { transition: scale .6s var(--ease); }
  .slider__frame:hover .slider__img { scale: 1.03; }
}
/* desktop: the mount never grows taller than the window under the header */
@media (min-width: 1024px) {
  .slider { width: min(100%, calc((100vh - var(--header-h) - 220px) * var(--slider-r, .8))); }
}

/* gallery chapter: heading + tabs aside, the slider beside it */
.svc-gallery__layout {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  row-gap: var(--s-6);
}
.svc-gallery__layout > * { min-width: 0; }
.slider-panel + .slider-panel { margin-top: var(--s-8); }
.js .slider-panel + .slider-panel { margin-top: 0; }
.slider-panel[hidden] { display: none; }
.slider-panel__title { margin-bottom: var(--s-4); color: var(--meta); }
.js .svc-gallery__layout.has-tabs .slider-panel__title {
  position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0;
  overflow: hidden; clip: rect(0 0 0 0); clip-path: inset(50%); white-space: nowrap; border: 0;
}
.slider-tabs { margin-top: var(--s-6); }
.slider-tabs__list {
  display: grid; grid-template-columns: repeat(2, minmax(0, 1fr));
  margin: 0; padding: 0; list-style: none;
  border-top: 1px solid var(--rule);
}
.slider-tabs__list > li { min-width: 0; }
.slider-tabs__tab {
  display: flex; align-items: baseline; justify-content: space-between; gap: var(--s-3);
  width: 100%; min-height: 48px;
  padding: 12px var(--s-4) 12px 0;
  border: 0; border-bottom: 1px solid var(--rule); border-radius: 0;
  background: none; color: var(--meta);
  text-align: left; text-decoration: none;
  font: inherit; font-size: 12px; font-weight: 500; line-height: 1.35; letter-spacing: .12em; text-transform: uppercase;
  cursor: pointer;
  transition: color .3s var(--ease);
}
.slider-tabs__name { min-width: 0; }
.slider-tabs__count {
  flex: none;
  font-size: 14px; font-weight: 400; letter-spacing: .02em; text-transform: none;
  font-variant-numeric: tabular-nums;
}
.slider-tabs__tab:hover,
.slider-tabs__tab[aria-selected="true"] { color: var(--cream); }
.slider-tabs__tab[aria-selected="true"] .slider-tabs__name { color: var(--lime); }
.band--cream .slider-tabs__tab:hover,
.band--cream .slider-tabs__tab[aria-selected="true"],
.band--cream .slider-tabs__tab[aria-selected="true"] .slider-tabs__name { color: var(--ink); }
.slider-tabs__tab:focus-visible { outline: 2px solid var(--focus); outline-offset: -2px; }
@media (min-width: 1024px) {
  .svc-gallery__layout {
    grid-template-columns: minmax(0, 4fr) minmax(0, 8fr);
    column-gap: var(--s-8);
    align-items: start;
  }
  .svc-gallery__aside { position: sticky; top: calc(var(--header-h) + var(--s-6)); align-self: start; }
  .slider-tabs { margin-top: var(--s-7); }
  .slider-tabs__list { grid-template-columns: minmax(0, 1fr); }
  .slider-tabs__tab { padding-right: 0; }
}

/* opened rows: description, facts and the treatment's photos above the booking doors */
.row-detail { display: grid; row-gap: var(--s-4); padding-top: var(--s-4); }
.row-detail__text p { margin: 0; }
.row-detail__text p + p { margin-top: 1em; }
.row-detail__photos {
  display: flex; flex-wrap: wrap; gap: var(--s-2);
  margin: 0; padding: 0; list-style: none;
}
.row-detail__photos figure { margin: 0; }
.row-detail__photos .lb-trigger__badge { display: none; }
/* whole photos at one height: a square crop would cut a before/after pair in half */
.row-detail__thumb { display: block; height: 72px; background: rgba(var(--cream-rgb), .06); }
.band--cream .row-detail__thumb { background: rgba(5, 38, 22, .06); }
.row-detail__thumb img { display: block; width: auto; height: 100%; }
@media (min-width: 768px) {
  .row-detail__thumb { height: 96px; }
}
@media (prefers-reduced-motion: no-preference) {
  .row__more .row-detail {
    opacity: 0; transform: translateY(-6px);
    transition: opacity .3s var(--ease), transform .45s var(--ease);
  }
  .svc-cluster .row.is-open .row__more .row-detail { opacity: 1; transform: none; transition-delay: .08s; }
}

/* lash styles: a ruled chart of drawn eyes, closed and open */
.lash-chart {
  display: grid; grid-template-columns: minmax(0, 1fr);
  margin: var(--s-7) 0 0; padding: 0; list-style: none;
  border-top: 1px solid var(--rule);
}
.lash-style {
  display: grid; align-content: start; row-gap: var(--s-3);
  /* drawing, name, text (takes the slack), booking door: the doors line up across the columns */
  grid-template-rows: auto auto 1fr auto;
  min-width: 0;
  padding: var(--s-6) 0;
  border-bottom: 1px solid var(--rule);
}
.lash-style__ask { justify-self: start; }
.lash-style .lash-art { margin-bottom: var(--s-3); }
.lash-style__text { color: var(--meta); }
.lash-art {
  display: grid; grid-template-columns: repeat(2, minmax(0, 1fr));
  column-gap: var(--s-5); align-items: end;
  max-width: 480px;
  /* dark band: a dark pupil ringed in cream with a cream glint; cream band: an ink pupil */
  --pupil: var(--ground);
  --glint: var(--cream);
}
.band--cream .lash-art { --pupil: var(--ink); --glint: var(--cream); }
.lash-art svg { display: block; width: 100%; height: auto; overflow: visible; }
.lash-art path,
.lash-art circle { vector-effect: non-scaling-stroke; }
.lash-art__lid { fill: none; stroke: currentColor; stroke-width: 1.5; stroke-linecap: round; stroke-linejoin: round; }
.lash-art__crease { fill: none; stroke: currentColor; stroke-width: 1; stroke-linecap: round; opacity: .32; }
.lash-art__lash { fill: none; stroke: currentColor; stroke-width: 1; stroke-linecap: round; }
.lash-art__lash--spike { stroke-width: 1.35; }
.lash-art__iris { fill: currentColor; fill-opacity: .1; stroke: currentColor; stroke-width: 1; }
.lash-art__pupil { fill: var(--pupil); stroke: currentColor; stroke-width: 1; }
.lash-art__glint { fill: var(--glint); stroke: none; }
@media (min-width: 768px) {
  .lash-chart { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  .lash-style { padding: var(--s-6) var(--s-6) var(--s-7) 0; border-bottom: 0; }
  .lash-style + .lash-style { padding-left: var(--s-6); border-left: 1px solid var(--rule); }
  .lash-chart { border-bottom: 1px solid var(--rule); }
  /* one fixed drawing width, so the first column (no left padding) never draws bigger eyes */
  .lash-art { width: 164px; }
}
@media (min-width: 1024px) {
  .lash-art { width: 300px; }
}

/* what moves (0.9.0): the facts and benefit rules draw in like every other ledger rule */
@supports (animation-timeline: view()) {
  @media (prefers-reduced-motion: no-preference) {
    .svc-feature__benefits li,
    .svc-feature .facts__row,
    .lash-style { border-bottom-color: transparent; position: relative; }
    .svc-feature__benefits li::after,
    .svc-feature .facts__row::after,
    .lash-style::after {
      content: "";
      position: absolute; left: 0; right: 0; bottom: -1px;
      height: 1px;
      background: var(--rule);
      transform-origin: left center;
      pointer-events: none;
      animation: wxp-rule-draw linear both;
      animation-timeline: view();
      animation-range: entry 10% cover 30%;
    }
  }
}
@media (min-width: 768px) {
  .lash-style::after { display: none; }
}

/* ---------- 0.10.0 branch prices (owner direction 2026-10-10) ----------
 * Prices follow DESIGN.md Price Rows: a Fraunces figure right-aligned in the row's aside, the unit
 * (per jari, per kuku, Paket 6 sesi) under it in 12px caps. On service pages every price is gated
 * to a branch ([data-for], inc/prices.php) and appears only after the visitor picks that branch.
 */

/* row aside: price, then its unit and label, right-aligned */
.row__aside { display: grid; justify-items: end; align-content: start; row-gap: 2px; }
.row__aside .branch-price { display: grid; justify-items: end; row-gap: 2px; }
.row__aside .price--row { line-height: 1.1; }
.row__aside .unit,
.row__aside .label { white-space: nowrap; }
.svc-cluster .row__aside .label { color: var(--meta); }

/* the list aside names the branch whose prices the rows show */
.svc-list__price-note { margin-top: var(--s-4); max-width: 34ch; }
.svc-list__price-note .link-arrow { min-height: 0; margin-left: 2px; vertical-align: baseline; }
div.svc-list__price-note .meta { margin: 0; }
.svc-list__price-links { display: flex; flex-wrap: wrap; column-gap: var(--s-5); margin-top: var(--s-1); }
.svc-list__price-links .link-arrow { min-height: 44px; margin: 0; }

/* package cards: the price follows the contents, lime on the card's forest; the door stays at the foot */
.svc-bundle { --price: var(--lime); }
.svc-bundle .branch-price { display: flex; align-items: baseline; gap: var(--s-2); }
.band--cream .svc-bundle .price--row { color: var(--price); }

/* Unggulan: the featured treatment's price, large */
.svc-feature__price { display: grid; row-gap: var(--s-1); margin: 0; }
.svc-feature__price .label { color: var(--meta); }

/* ---------- the branch services hub: /services/<branch-slug>/ ----------
 * The same hub (photos, spotlight, index), with each service's "mulai dari" price in its own grid
 * area. Only .hub-link--priced rows change their grid, so the plain /services/ hub is untouched.
 */
.hub-hero__switch { margin-top: var(--s-3); }
.hub-link__price {
  grid-area: price;
  display: flex; flex-wrap: wrap; align-items: baseline; column-gap: var(--s-2);
}
.hub-link__price .label { color: var(--meta); white-space: nowrap; }
.hub-link__price .price { white-space: nowrap; }
@media (max-width: 599px) {
  .hub-link.hub-link--priced {
    grid-template-areas:
      "code name  arrow"
      ".    price arrow";
    row-gap: var(--s-1);
  }
}
@media (max-width: 1023px) {
  .hub-link:active .hub-link__price .price { color: var(--ink); }
}
@media (min-width: 600px) and (max-width: 1023px) {
  .hub-link.hub-link--priced {
    grid-template-areas:
      "code name    price arrow"
      ".    tagline count arrow";
  }
  .hub-link__price { align-self: baseline; justify-content: flex-end; }
}
@media (min-width: 1024px) {
  .hub-link.hub-link--priced {
    grid-template-areas:
      "code name    name"
      ".    tagline tagline"
      ".    price   price"
      ".    count   arrow";
  }
  .hub-link__price { margin-top: var(--s-4); }
}

/* ==========================================================================
   0.11.0 (2026-10-11; owner's mother)
   The intro's options row (service field options): numbered columns ruled like the rest of the
   ledger, one column on phones, three across from 768px. The priced branch hub list is a cream
   band of its own, so it gets its top padding back. Slider buttons share the 8px corner.
   ========================================================================== */
.svc-options {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: var(--s-5) var(--s-6);
  margin: var(--s-7) 0 0;
  padding: 0;
  list-style: none;
}
.svc-options > * { min-width: 0; }
.svc-option {
  display: grid;
  align-content: start;
  gap: var(--s-3);
  padding-top: var(--s-4);
  border-top: 1px solid var(--rule);
}
.svc-option__no {
  font-family: var(--f-display);
  font-size: 20px;
  line-height: 1;
  color: var(--meta);
  font-variant-numeric: lining-nums tabular-nums;
}
.svc-option__name {
  font-family: var(--f-display);
  font-size: 28px;
  font-weight: 400;
  line-height: 1.1;
  letter-spacing: -.01em;
  overflow-wrap: break-word;
}
.svc-option__text { color: var(--meta); }
@media (min-width: 768px) {
  .svc-options { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}
@media (min-width: 1024px) {
  .svc-options { margin-top: var(--s-8); }
  .svc-option__name { font-size: 40px; }
}

.svc-options + .svc-intro__head { margin-top: var(--s-8); }
@media (min-width: 1024px) {
  .svc-options + .svc-intro__head { margin-top: var(--s-9); }
}

.hub.hub--priced { padding-top: var(--section-pad); }

.slider__btn { border-radius: var(--r-ctl); }

/* Package cards carry prices, so they turn white with ink text and emerald prices (were forest cards
   with lime prices). A hairline keeps the white card distinct from the cream band. */
.svc-bundle,
.svc-bundles:not(.band--cream) .svc-bundle {
  --rule: var(--line-cream);
  --meta: rgba(5, 38, 22, .72);
  --price: #007A36; /* emerald darkened for AA at 20px on white (5.5:1; #009843 is 3.8:1) */
  --focus: var(--emerald);
  background: #fff;
  color: var(--ink);
  border: 1px solid var(--line-cream);
}
.band--cream .svc-bundle :focus-visible { outline-color: var(--emerald); }

