/* services.css — page-scoped styles for packages.html only (linked after
   /pages.css; never linked from any other page). Every selector is prefixed
   .svc- or scoped under a .svc- section class, so this file is inert
   elsewhere. Palette + fonts come from styles.css; the add-on carousel's
   classes (.svc-carousel*, .svc-slide*, data-pick, data-addon-cta) keep their
   pages.js contract. */

/* ---------- hero: the velvet moment; fixed carved-doors backdrop under an ink
   wash, copy in paper and gold, the rate card floating right as a lit paper
   panel. Fixed-image technique mirrors styles.css .ed/.fixbg exactly,
   including the touch fallback (background-attachment:fixed is dead on iOS:
   clip-path makes the section the containing block that crops the
   position:fixed ::before layer). ---------- */
.svc-hero{
  overflow:hidden;display:flex;align-items:center;
  min-height:min(830px,calc(100vh - 78px));
  color:var(--paper);background-color:#211B14;
  background-image:linear-gradient(100deg,rgba(33,27,20,.94) 0%,rgba(33,27,20,.78) 44%,rgba(33,27,20,.38) 100%),url(images/ss-booth-signature.webp);
  background-size:auto,cover;background-position:center,center 38%;background-attachment:fixed,fixed;
}
.svc-hero>.wrap{width:100%}
@media(hover:none){
  .svc-hero{background-image:none;clip-path:inset(0)}
  .svc-hero::before{content:"";position:fixed;inset:0;z-index:0;pointer-events:none;background-color:#211B14;background-image:linear-gradient(100deg,rgba(33,27,20,.94) 0%,rgba(33,27,20,.78) 44%,rgba(33,27,20,.38) 100%),url(images/ss-booth-signature.webp);background-size:auto,cover;background-position:center,center 38%}
  .svc-hero .wrap{position:relative;z-index:1}
}
.svc-hero-grid{display:grid;grid-template-columns:1.08fr .92fr;gap:72px;align-items:center}
.svc-hero h1{font-size:clamp(2.4rem,4.4vw,3.4rem)}
.svc-hero h1 em{color:var(--gold-pale)}
.svc-hero .eyebrow{color:var(--gold-pale)}
.svc-hero .eyebrow::before{background:var(--gold-pale)}
.svc-hero .lead{max-width:44ch;color:rgba(250,246,239,.8)}
.svc-hero .hero-note{color:rgba(250,246,239,.62)}
.svc-hero .btn-ghost{color:var(--paper);border-color:rgba(250,246,239,.4)}
.svc-hero .btn-ghost:hover{color:var(--gold-pale);border-color:var(--gold-pale);transform:none;box-shadow:none}
.svc-hero-vis{position:relative;display:flex;justify-content:flex-end}
.svc-rate{
  /* no z-index here: an explicit one would create a stacking context and pull
     the ::before offset frame above the card's own background */
  position:relative;width:min(400px,100%);color:var(--ink);
  background:rgba(250,246,239,.96);border:1px solid var(--line);padding:34px 36px 58px;
  box-shadow:0 40px 90px rgba(0,0,0,.45);
}
.svc-rate::before{content:"";position:absolute;inset:12px -12px -12px 12px;border:1px solid var(--gold-pale);z-index:-1}
.svc-rate .svc-rate-loc{position:absolute;bottom:20px;left:0;right:0;text-align:center;font-size:.6rem;font-weight:700;color:#A79A87;letter-spacing:.3em}
.svc-rate .k{font-size:.64rem;font-weight:700;letter-spacing:.3em;text-transform:uppercase;color:var(--gold-deep);margin-bottom:4px}
.svc-rate .t{font-family:"Cormorant Garamond",Georgia,"Times New Roman",serif;font-weight:600;font-size:1.62rem;letter-spacing:.04em;margin-bottom:16px}
.svc-rate ul{list-style:none;margin:0;padding:0}
.svc-rate li{display:flex;align-items:baseline;gap:10px;padding:11px 0}
/* The name WRAPS at every width (layout audit 2026-09-18). It was
   white-space:nowrap with a ≤880px override that let it wrap only on phones,
   which was measured against the kit's short placeholder names. The card is
   width:min(400px,100%), so it never grows with the viewport: at 881px and up
   it is always a 400px card with a 328px content box, and "THE SIGNATURE
   EXPERIENCE" alone measures 268.9px of nowrap min-content. With the price
   (73.5px) and two 10px gaps that is 372.4px, so the row squeezed .dots to
   0px and pushed the price 35.3px past the card's right padding, landing it
   0.7px inside the border with no breathing room. Wrapping is the kit's own
   fix (it is what the ≤880px rule already did); it just has to apply at every
   width, because no viewport width ever widens this card. */
.svc-rate li .nm{font-family:"Cormorant Garamond",Georgia,"Times New Roman",serif;font-weight:600;font-size:1.16rem;letter-spacing:.03em}
.svc-rate li .dots{flex:1;border-bottom:1px dotted var(--gold-pale);transform:translateY(-4px)}
.svc-rate li b{font-weight:600;color:var(--gold-deep);white-space:nowrap}
.svc-rate .fine{margin-top:12px;font-size:.78rem;color:var(--ink-soft)}
/* the hero's ticker band, dark to match */
.band.s-hero{background:#211B14;border-top-color:rgba(250,246,239,.14)}
.band.s-hero .wrap{color:rgba(250,246,239,.68)}
@media(prefers-reduced-motion:no-preference){
  .svc-hero-copy{animation:edfade 1s ease both .25s}
  .svc-hero-vis{animation:edrise 1s cubic-bezier(.2,.6,.2,1) both .05s}
}
@media(max-width:880px){
  /* minmax(0,1fr), not 1fr (layout audit 2026-08-09): a bare 1fr track floors
     at its min-content, and the rate rows' nowrap name + price put that floor
     at 336px, so below 390px viewport the whole column (h1 box included) sat
     fixed at 336px wide and clipped against the hero's overflow:hidden: 4px of
     card and 16px of its gold offset frame gone at 360, worse below. Zero
     effect at any width where 336px already fit. */
  .svc-hero-grid{grid-template-columns:minmax(0,1fr);gap:56px}
  .svc-hero-vis{margin-top:10px;justify-content:center}
  /* the rate-row name wrap used to live here; it is on the base rule now
     (see the note above .svc-rate li .nm) because this card never grows */
}
@media(max-width:400px){
  /* the longest row (name + dots + price) needs 264px; card side padding of
     36px left it 2px short inside a 360-wide viewport's 304px column. 24px
     buys the row its line back with no other geometry change. */
  .svc-rate{padding:34px 24px 58px}
}

/* ---------- whats-included: editorial split + numbered hairline list ---------- */
.svc-inc-grid{display:grid;grid-template-columns:.95fr 1.05fr;gap:64px;align-items:start}
.svc-inc-list{list-style:none;margin:6px 0 0;padding:0}
.svc-inc-list li{display:flex;gap:26px;border-top:1px solid var(--line);padding:30px 4px}
.svc-inc-list li:last-child{border-bottom:1px solid var(--line)}
.svc-inc-list .n{
  flex:none;width:60px;
  font-family:"Cormorant Garamond",Georgia,"Times New Roman",serif;font-style:italic;font-weight:500;
  font-size:2.9rem;color:var(--gold);line-height:1;
}
.svc-inc-list h3{font-family:"Cormorant Garamond",Georgia,"Times New Roman",serif;font-weight:600;font-size:1.42rem;letter-spacing:.03em;margin-bottom:8px}
.svc-inc-list p{color:var(--ink-soft);font-size:.96rem;max-width:52ch}
.svc-inc-list li:nth-child(2){transition-delay:.12s}
.svc-inc-list li:nth-child(3){transition-delay:.24s}
.svc-callout{position:relative;margin-top:46px;background:var(--paper-2);padding:30px 32px}
.svc-callout::after{content:"";position:absolute;inset:12px -12px -12px 12px;border:1px solid var(--gold-pale);pointer-events:none;z-index:-1}
.svc-callout .k{font-size:.64rem;font-weight:700;letter-spacing:.3em;text-transform:uppercase;color:var(--gold-deep);margin-bottom:12px}
.svc-callout p+p{color:var(--ink-soft);font-size:.97rem}
.svc-callout b{color:var(--ink)}
@media(max-width:880px){.svc-inc-grid{grid-template-columns:1fr;gap:44px}.svc-callout{margin-top:36px}}

/* ---------- packages: three-up menu cards, inset-frame photos ---------- */
/* Reconciled list: the card count is the client's package count, not the
   demo's. Flex-wrap + justify-content:center keeps a trailing row of 1 or 2
   centred instead of stranded; a full row renders identically to the grid. */
.svc-pkgs .booths{display:flex;flex-wrap:wrap;justify-content:center;gap:26px;align-items:stretch}
.svc-pkgs .booths > .booth{flex:0 1 calc((100% - 2 * 26px) / 3 - 0.5px);min-width:240px;}
.svc-pkgs .booth{padding:30px 28px}
.svc-pkgs .booth .ph{position:relative;overflow:hidden;height:220px;margin:-30px -28px 24px}
.svc-pkgs .booth .ph::after{content:"";position:absolute;inset:10px;border:1px solid rgba(250,246,239,.55);pointer-events:none;z-index:1}
.svc-pkgs .booth .ph img,
.svc-pkgs .booth .ph video {width:100%;height:100%;margin:0;object-fit:cover;object-position:50% 30%;display:block;transition:transform .8s cubic-bezier(.2,.6,.2,1)}
.svc-pkgs .booth:hover .ph img,
.svc-pkgs .booth:hover .ph video {transform:scale(1.045)}
.svc-keepsake{position:relative;margin-top:40px;background:#fff;border:1px solid var(--line);padding:24px 28px;max-width:none}
.svc-keepsake::before{content:"";position:absolute;left:0;top:0;bottom:0;width:3px;background:var(--gold)}
@media(min-width:981px){.svc-pkgs .booth.is-featured{margin-top:-18px;box-shadow:0 22px 44px rgba(43,38,32,.12)}}
@media(max-width:980px){.svc-pkgs .booths > .booth{flex:1 1 100%}}

/* ---------- add-ons: the dark moment; a click-through carousel of upgrades ---------- */
.svc-addons{position:relative;background:var(--ink);color:var(--paper);overflow:hidden}
.svc-addons::before{content:"";position:absolute;inset:0;background:radial-gradient(900px 420px at 50% 0%,rgba(165,130,78,.18),transparent 65%);pointer-events:none}
.svc-addons .wrap{position:relative}
.svc-addons .sec-eyebrow{color:var(--gold-pale)}
.svc-addons h2 em{color:var(--gold-pale)}
.svc-addons-head{max-width:640px;margin-bottom:clamp(36px,5vw,58px)}
.svc-addons .sec-lead{color:rgba(250,246,239,.75);max-width:54ch}

.svc-carousel-viewport{overflow:hidden}
.svc-carousel-track{display:flex;transition:transform .6s cubic-bezier(.2,.6,.2,1);will-change:transform}
.svc-slide{flex:0 0 100%;display:grid;grid-template-columns:minmax(0,.92fr) minmax(0,1.08fr);border:1px solid var(--line-dark);background:rgba(250,246,239,.04);transition:opacity .6s ease}
.svc-slide[aria-hidden="true"]{opacity:.16}
.svc-slide-media{position:relative;overflow:hidden;height:clamp(340px,38vw,470px)}
.svc-slide-media img,
.svc-slide-media video {width:100%;height:100%;object-fit:cover;object-position:50% 35%;display:block}
.svc-slide-media::after{content:"";position:absolute;inset:12px;border:1px solid rgba(250,246,239,.32);pointer-events:none}
.svc-slide-tag{position:absolute;top:20px;left:20px;z-index:1;background:var(--gold);color:var(--ink);font-size:.6rem;font-weight:700;letter-spacing:.24em;text-transform:uppercase;padding:8px 16px}
.svc-slide-body{display:flex;flex-direction:column;justify-content:center;padding:clamp(28px,4vw,56px)}
.svc-slide-index{font-size:.66rem;font-weight:700;letter-spacing:.28em;text-transform:uppercase;color:rgba(250,246,239,.5);margin-bottom:20px}
.svc-slide-index b{color:var(--gold-pale);font-weight:700}
.svc-slide-top{display:flex;align-items:baseline;justify-content:space-between;gap:20px}
.svc-slide-name{font-family:"Cormorant Garamond",Georgia,"Times New Roman",serif;font-weight:600;font-size:clamp(1.7rem,2.8vw,2.5rem);letter-spacing:.02em;line-height:1.05;color:var(--paper)}
.svc-slide-price{font-family:"Cormorant Garamond",Georgia,"Times New Roman",serif;font-weight:600;font-size:clamp(1.7rem,2.8vw,2.4rem);color:var(--gold-pale);white-space:nowrap}
.svc-slide-blurb{margin-top:20px;max-width:46ch;color:rgba(250,246,239,.72);font-size:1rem;line-height:1.7}
.svc-addon-add{align-self:flex-start;margin-top:28px;display:inline-flex;align-items:center;gap:12px;padding:0;background:none;border:0;cursor:pointer;font-size:.72rem;font-weight:700;letter-spacing:.22em;text-transform:uppercase;color:var(--paper);transition:color .3s}
.svc-addon-add:hover{color:var(--gold-pale)}
.svc-addon-add:focus-visible{outline:3px solid var(--gold);outline-offset:5px}
.svc-addon-add-i{width:30px;height:30px;flex:none;display:inline-flex;align-items:center;justify-content:center;border:1px solid rgba(250,246,239,.4);border-radius:50%;font-size:18px;line-height:1;transition:transform .4s cubic-bezier(.2,.6,.2,1),background .3s,color .3s,border-color .3s}
.svc-addon-add:hover .svc-addon-add-i{border-color:var(--gold-pale)}
.svc-slide.is-added{border-color:var(--gold)}
.svc-slide.is-added .svc-addon-add-i{background:var(--gold);border-color:var(--gold);color:var(--ink);transform:rotate(45deg)}

.svc-carousel-nav{margin-top:clamp(24px,3vw,38px);display:flex;align-items:center;justify-content:center;gap:22px}
.svc-carousel-arrow{width:48px;height:48px;flex:none;border-radius:50%;cursor:pointer;background:none;border:1px solid rgba(250,246,239,.35);color:var(--paper);font-size:22px;line-height:1;display:inline-flex;align-items:center;justify-content:center;transition:background .3s,color .3s,border-color .3s}
.svc-carousel-arrow:hover{background:var(--gold);border-color:var(--gold);color:var(--ink)}
.svc-carousel-arrow:focus-visible{outline:3px solid var(--gold);outline-offset:3px}
/* flex-wrap added 2026-08-08 (layout audit). The kit shipped this carousel with
   five slides; this build runs FIFTEEN, and pages.js builds one dot per slide, so
   the dot row is a fixed 303px (15 x 9px + 14 x 12px gap) that cannot shrink. The
   arrows either side are flex:none, so on a phone the whole centred nav row was
   443px inside a ~334px wrap and both arrows hung off the edges: at 390 the prev
   arrow was clipped to 22 of its 48px and the next arrow lost 27px, at 360 only
   6-7px of each remained, and at 320 both were entirely off-screen and untappable.
   Nothing scrolled sideways because #backdrops clips overflow-x, which is exactly
   why it stayed invisible to a page-overflow check. Letting the dots wrap lets
   them take the shrink instead, so both arrows stay fully on screen and every dot
   stays reachable. No effect at 768px and up, where the row already fits on one
   line. */
.svc-carousel-dots{display:flex;align-items:center;gap:12px;flex-wrap:wrap;justify-content:center}
.svc-carousel-dots button{width:9px;height:9px;border-radius:50%;border:0;padding:0;cursor:pointer;background:rgba(250,246,239,.3);transition:background .3s,transform .3s}
.svc-carousel-dots button.is-live{background:var(--gold-pale);transform:scale(1.3)}

.svc-addons-foot{margin-top:clamp(30px,4vw,46px);display:flex;align-items:center;justify-content:space-between;gap:24px;flex-wrap:wrap}
.svc-addons-note{max-width:44ch;font-size:.82rem;line-height:1.6;color:rgba(250,246,239,.58)}
.svc-addons-foot .btn{background:var(--gold);color:var(--ink)}
.svc-addons-foot .btn:hover{background:var(--gold-pale)}
@media(max-width:900px){
  .svc-slide{grid-template-columns:1fr}
  .svc-slide-media{height:260px}
  .svc-addons-foot{flex-direction:column;align-items:flex-start}
  .svc-addons-foot .btn{width:100%}
}
@media(prefers-reduced-motion:reduce){.svc-carousel-track{transition:none}}

/* ---------- faq: light polish only ---------- */
.s-pricing-faq summary{transition:color .25s}
.s-pricing-faq summary:hover{color:var(--gold-deep)}

/* ---------- package cards: count-aware layout (see the JS in pages.js) ----
   Four or more package cards turn the row into a one-row slider with arrows.
   At three or fewer nothing here applies and the list renders as designed.
   Recovered from live San Diego 2026-07-28; canonical copy in design-01. */
@media (min-width: 901px) {
  .svc-pkgs .booths.is-slider {
    display: flex; justify-content: flex-start; flex-wrap: nowrap;
    /* BOTH axes hidden, NOT auto: the arrows are the only way the rail moves.
       As an auto scroller with x-mandatory snap it captured trackpad gestures,
       and a lone overflow-x forces overflow-y to compute to auto, so the
       hover/pill headroom (padding-top pulled back by margin) left ~26px of
       vertical overflow: the rail latched the wheel and froze PAGE scrolling
       over the whole section (found live on a client build 2026-08-01). hidden blocks
       user scrolling on both axes; the arrows' scrollTo() keeps working. */
    overflow: hidden;
    padding-top: 22px; margin-top: -22px;
  }
  .svc-pkgs .booths.is-slider > .booth {
    flex: 0 0 calc((100% - 2 * 26px) / 3);
  }
}
.svc-pkg-shell { position: relative; }
.svc-pkg-arrow {
  position: absolute; top: 50%; transform: translateY(-50%); z-index: 5;
  width: 48px; height: 48px; border-radius: 50%; cursor: pointer;
  background: #fff; border: 1px solid rgba(0, 0, 0, .25); color: inherit;
  font-size: 24px; line-height: 1; display: none;
  align-items: center; justify-content: center;
  box-shadow: 0 6px 18px rgba(0, 0, 0, .14);
  transition: background .35s, color .35s, border-color .35s;
}
@media (min-width: 901px) { .svc-pkg-shell .svc-pkg-arrow { display: inline-flex; } }
.svc-pkg-arrow:hover { background: #111; color: #fff; border-color: #111; }
.svc-pkg-arrow:focus-visible { outline: 2px solid currentColor; outline-offset: 3px; }
.svc-pkg-prev { left: -22px; }
.svc-pkg-next { right: -22px; }

/* ---------- #addons: the slot that always ships ---------------------------
   THE ADD-ON SLOT ALWAYS SHIPS, and hides itself until the client actually has
   an add-on, so a price list with none never renders an empty band. The inert
   <template data-bc-pkg-item> lives in a separate DocumentFragment, so :has()
   cannot see it, and the section reappears on its own the moment
   src/site_prices.js clones a real card. Never delete #addons from a build to
   "tidy up" a client who has no add-ons today: that is the one-way door this
   rule exists to replace. */
#addons:not(:has([data-bc-pkg])){display:none}

/* #addons on a LIGHT ground. The .svc-* block above was written for "the dark
   moment" that this design's showcase carousel (#backdrops) owns, so every one
   of its foregrounds is --paper and every accent is --gold-pale, the tint that
   only reads on ink. Reused unchanged on a light band, the lede, index, name,
   blurb, Add control, arrows, dots and note would all render paper-on-paper,
   which is to say invisible. So the light band restates them: --gold-deep replaces
   --gold-pale for TEXT (this design pairs gold-deep with light ground and
   gold-pale with dark; plain --gold stays where it is a FILL), --ink and
   --ink-soft replace --paper, and the ink-alpha washes
   mirror the paper-alpha ones. Every rule is scoped to #addons, which ships
   hidden, so none of it can touch #backdrops or any existing band.
   Keep this in step with the .svc-* block above: a new declaration there that
   assumes paper-on-ink needs its light twin here, or it disappears the first
   time a client adds an add-on. */
#addons{background:var(--paper);color:var(--ink)}
#addons::before{background:radial-gradient(900px 420px at 50% 0%,rgba(165,130,78,.10),transparent 65%)}
#addons .sec-eyebrow{color:var(--gold-deep)}
#addons h2 em{color:var(--gold-deep)}
#addons .sec-lead{color:var(--ink-soft)}
#addons .svc-slide{border-color:var(--line);background:rgba(43,38,32,.03)}
#addons .svc-slide-media::after{border-color:rgba(43,38,32,.16)}
#addons .svc-slide-index{color:rgba(43,38,32,.5)}
#addons .svc-slide-index b{color:var(--gold-deep)}
#addons .svc-slide-name{color:var(--ink)}
#addons .svc-slide-price{color:var(--gold-deep)}
#addons .svc-slide-blurb{color:var(--ink-soft)}
#addons .svc-addon-add{color:var(--ink)}
#addons .svc-addon-add:hover{color:var(--gold-deep)}
#addons .svc-addon-add-i{border-color:rgba(43,38,32,.35)}
#addons .svc-addon-add:hover .svc-addon-add-i{border-color:var(--gold)}
#addons .svc-carousel-arrow{border-color:rgba(43,38,32,.28);color:var(--ink)}
#addons .svc-carousel-arrow:hover{background:var(--gold);border-color:var(--gold);color:var(--ink)}
#addons .svc-carousel-dots button{background:rgba(43,38,32,.25)}
#addons .svc-carousel-dots button.is-live{background:var(--gold)}
#addons .svc-addons-note{color:rgba(43,38,32,.6)}


/* The accent note was removed from the add-ons footer (owner, 2026-08-27).
   The footer is a flex row at justify-content: space-between, so with the note
   gone its one remaining child (the button) would jump from the right edge to
   the left. Guarded on the note being ABSENT, so a footer that still carries
   one keeps the original two-up layout untouched. */
.svc-addons-foot:not(:has(.svc-addons-note)) { justify-content: flex-end; }

/* The rate card's value column is a TICK, drawn as inline SVG, never the "check
   mark" character. Every font on these sites is subsetted and none of the seven
   files carries U+2713, so a text tick falls back to a system face mid row, the
   same fault the capital n-tilde had. currentColor means it inherits the gold
   from the <b> and needs no colour of its own. The label stays in the DOM for
   screen readers, hidden the standard clip way rather than display:none, which
   would take it out of the accessibility tree too. */
.svc-rate li .svc-tick{flex:none;width:16px;height:12px;stroke:currentColor;fill:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;display:block}
.svc-rate-sr{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}

/* PRICE AND ITS COVERAGE CAPTION (measured on INK, 2026-09-24).
   Two separate faults, and the second one was only found after the first fix
   looked right in the numbers and still looked wrong on screen.

   1. THE CAPTION COLLIDED. The price is Cormorant Garamond at 36.8px and the
      face uses OLD STYLE figures, so 4, 9, 7 and 3 drop below the baseline.
      With line-height:1 the line box was 36.8px around a 44.6px inline box, so
      the caption block began 3.9px ABOVE where the price ink ended.
      line-height 1.25 contains the glyph.

   2. THE PRICE SAT TOO LOW under the heading. Box geometry said the gaps were
      6.7px above and 6.7px below, balanced. They were not: h3 line-height is
      1.7, so the heading carries about 14px of INVISIBLE LEADING below its last
      line that a getBoundingClientRect measurement counts as nothing. Measured
      on rendered pixels at 2x, the real ink gaps were 34px above the price and
      11px below it.
      DO NOT MEASURE THIS WITH BOUNDING BOXES. Screenshot it and find the ink
      rows; box maths cannot see leading and will tell you a lopsided pair of
      gaps is even.
      A negative margin on the heading absorbs its own trailing leading. Swept
      against ink: -6 gave 28, -12 gave 22, -16 gave 18, -20 gives 14 above and
      11 below, which is the pair that reads level. Slightly more above is
      correct, since the heading is a separate block.

   Third trap, for whoever changes the price size: .booth is display:block, so
   the h3's bottom margin and the price's top margin COLLAPSE to the larger of
   the two. Nudging the price's margin alone moves nothing. The heading margin
   is the lever. */
.svc-pkgs .booth h3{margin-bottom:-20px}
.svc-pkgs .booth .price{line-height:1.25;margin-top:6px}
.svc-pkgs .booth .price small{line-height:1.35;margin-top:6px}

/* ============================================================================
   PHONES: THE PACKAGE CARDS ARE A SWIPE TRACK
   Ported from Charisma (owner, 2026-09-22) to design-05, 2026-09-24. Desktop is
   untouched: every rule here is inside max-width 900px, and design-05's own
   901px+ slider rail keeps working exactly as it did.

   Native scrolling only, no gesture code. The track scrolls sideways and NOT
   vertically (overflow-y hidden, never auto), and touch-action stays default,
   so a vertical swipe over a card scrolls the PAGE and a sideways one slides
   the cards. The bottom bar is for people who do not think to swipe.
   ========================================================================= */
@media (max-width: 900px) {
  .svc-pkgs .booths[data-bc-pkg-list="package"] {
    display: flex; flex-wrap: nowrap; justify-content: flex-start;
    gap: 6px; margin-top: 40px;
    /* Each card centres with its neighbours peeking. The side padding is what
       lets the FIRST and LAST card centre too: with snap-align centre and no
       padding the browser clamps those two to the ends and card one still hugs
       the left. The card is sized in vw ON PURPOSE. A percentage flex-basis
       resolves against the track's CONTENT box, which this very padding
       shrinks, so the two chase each other; a vw card is absolute and the sum
       lands exactly on centre at either end. */
    --pk-card: 84vw;
    padding: 22px calc((100% - var(--pk-card)) / 2) 8px;
    overflow-x: auto; overflow-y: hidden;
    scroll-snap-type: x mandatory; -webkit-overflow-scrolling: touch;
    scrollbar-width: none;
    /* No intrinsic width of its own, or a scroll container inside a flex
       section reports its whole content width and grows the wrapper past the
       viewport. width 0 + min-width 100% is the standard cure. */
    width: 0; min-width: 100%;
    /* Each card its OWN height here: stretching them all to the tallest leaves
       a lot of blank space under the short ones. Desktop still stretches, where
       equal heights are the design. */
    align-items: flex-start;
    /* The height is set by the script to the CENTRED card's height, so a short
       card does not leave the tallest card's worth of blank paper under it
       (measured 216px on Sacred Seasons: cards 987, 957 and 771 tall). The
       transition is what stops the page below jumping when the nearest card
       changes mid swipe. overflow-y is hidden, so a taller neighbour is
       clipped to the same baseline, which is only ever a ~26px sliver of the
       peek. With the script absent the track keeps its natural height and this
       does nothing, which is the old behaviour. */
    transition: height .28s ease;
  }
  .svc-pkgs .booths[data-bc-pkg-list="package"]::-webkit-scrollbar { display: none; }
  .svc-pkgs .booths[data-bc-pkg-list="package"] > .booth {
    flex: 0 0 var(--pk-card); min-width: 0; scroll-snap-align: center;
  }
  /* The card's side padding and the photo's negative margin MUST move together.
     .ph bleeds to the card edge with margin-inline:-28px against the card's
     28px padding; change one alone and the photo overshoots or insets. */
  .svc-pkgs .booths[data-bc-pkg-list="package"] > .booth { padding-inline: 18px; }
  .svc-pkgs .booths[data-bc-pkg-list="package"] > .booth .ph { margin-inline: -18px; }
  /* THE NEIGHBOURS HAVE TO BE VISIBLE. Cards carry .reveal, and site.js only
     adds the shown class when a card intersects the VIEWPORT, which a card
     parked off to the side never does. Without this the peek is a card at
     opacity 0, which reads as blank paper and makes a wider peek look broken.
     The section around them still reveals on scroll. */
  .svc-pkgs .booths[data-bc-pkg-list="package"] > .booth.reveal { opacity: 1; transform: none; }
  /* One package: nothing to peek at, so it takes the full width and the
     centring padding comes off. :only-of-type, NOT :only-child, because the
     inert package template is a sibling and an only card is never an only
     child. */
  .svc-pkgs .booths[data-bc-pkg-list="package"] > .booth:only-of-type { flex-basis: 100%; }
  .svc-pkgs .booths[data-bc-pkg-list="package"]:has(> .booth:only-of-type) { padding-inline: 0; }
  /* FULL BLEED, the deterministic way: the section drops the wrap's 28px gutter
     and the heading takes it back itself, so the track spans the screen with no
     negative margins. Negative margins cannot work here, because the wrapper
     around a track grows to the track's width, so calc(50% - 50vw) resolves
     against a parent that is already 100vw and computes to zero. Clip, not
     hidden, so the section never becomes a scroll container. */
  #packages { overflow-x: clip; }
  #packages > .wrap { padding-inline: 0; }
  #packages > .wrap > .reveal { padding-inline: 28px; }
}

@media (max-width: 900px) and (prefers-reduced-motion: reduce) {
  .svc-pkgs .booths[data-bc-pkg-list="package"] { transition: none; }
}

/* The swipe bar: back, a "2 / 3" counter read from the DOM so a client adding a
   package can never make it lie, forward. Fixed to the bottom of the screen
   while the track is on screen (pages.js). Never on desktop. */
.svc-pkg-mnav { display: none; }
@media (max-width: 900px) {
  .svc-pkg-mnav {
    position: fixed; left: 50%; bottom: calc(18px + env(safe-area-inset-bottom, 0px)); z-index: 50;
    transform: translateX(-50%);
    display: flex; align-items: center; gap: 14px; padding: 8px 10px; border-radius: 999px;
    background: var(--ink); color: var(--paper); box-shadow: 0 10px 28px rgba(43, 38, 32, .3);
    opacity: 0; pointer-events: none; transition: opacity .25s;
  }
  .svc-pkg-mnav.is-on { opacity: 1; pointer-events: auto; }
  .svc-pkg-mnav.in-editor { bottom: 84px; }   /* above the site editor's toolbar in its phone view */
  .svc-pkg-mbtn {
    width: 40px; height: 40px; border-radius: 50%; cursor: pointer;
    background: transparent; color: inherit; border: 1px solid rgba(250, 246, 239, .45);
    display: inline-flex; align-items: center; justify-content: center; padding: 0;
  }
  .svc-pkg-mbtn:active { background: rgba(250, 246, 239, .14); }
  /* SVG chevrons, never the arrow CHARACTERS. Every font on this site is
     subsetted and none carries U+2190 or U+2192, so a text arrow would fall
     back to a system face inside the pill, the same fault the capital n-tilde
     had. Charisma's bar uses the characters; its fonts are a different subset. */
  .svc-pkg-mbtn svg { width: 15px; height: 13px; stroke: currentColor; fill: none; stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round; display: block; }
  .svc-pkg-mcount { font-family: "DM Sans", sans-serif; font-size: 11px; letter-spacing: .2em; min-width: 52px; text-align: center; }
}

/* ============================================================================
   PHONES: THE ADD-ON CAROUSELS RUN THE PACKAGE TRACK'S LOGIC
   Ported from Charisma (owner, 2026-09-22) to design-05, 2026-09-24, after the
   package track. Desktop untouched: everything is inside max-width 900px.

   The desktop carousel translates the track and dims the slides either side to
   .16 behind a hidden viewport, which is why widening anything on a phone did
   nothing visible: the neighbour was a dimmed card behind a clipped window.
   Both are switched off here and the track becomes an ordinary native scroll
   container, exactly like the package track above.

   transform:none needs !important because pages.js writes the translate as an
   INLINE style on every slide change, and inline beats a plain rule. The JS
   keeps running and its writes are simply inert at this width.
   ========================================================================= */
@media (max-width: 900px) {
  .svc-addons .svc-carousel-viewport { overflow: visible; }
  .svc-addons .svc-carousel-track {
    transform: none !important;
    display: flex; flex-wrap: nowrap; align-items: flex-start; gap: 6px;
    overflow-x: auto; overflow-y: hidden;
    scroll-snap-type: x mandatory; -webkit-overflow-scrolling: touch;
    scrollbar-width: none;
    width: 0; min-width: 100%;
    --pk-card: 84vw;
    padding-inline: calc((100% - var(--pk-card)) / 2);
    transition: height .28s ease;
  }
  .svc-addons .svc-carousel-track::-webkit-scrollbar { display: none; }
  .svc-addons .svc-slide { flex: 0 0 var(--pk-card); min-width: 0; scroll-snap-align: center; align-content: start; }
  /* The desktop carousel dims everything but the active slide. In a track the
     neighbours ARE the peek, so they stay lit. */
  .svc-addons .svc-slide[aria-hidden="true"] { opacity: 1; }
  .svc-addons .svc-slide-body { justify-content: flex-start; }
  /* The desktop arrows and dots give way to the bottom bar. */
  .svc-addons .svc-carousel-nav { display: none; }
  /* Full bleed, same deterministic method as the package track: the section
     drops the wrap's gutter and the head and foot take it back themselves. */
  .svc-addons { overflow-x: clip; }
  .svc-addons > .wrap { padding-inline: 0; }
  .svc-addons > .wrap > .svc-addons-head,
  .svc-addons > .wrap > .svc-addons-foot { padding-inline: 28px; }
  /* The slide sits in a chain of flex and grid items, every level defaulting to
     min-width:auto, so none of them would shrink below the slide's min-content
     width. On Charisma that rendered the section 877px wide inside a 390px
     viewport and gave the page 487px of horizontal scroll. */
  .svc-addons .svc-carousel, .svc-addons .svc-carousel-viewport,
  .svc-addons .svc-slide-media, .svc-addons .svc-slide-body { min-width: 0; }
}
@media (max-width: 900px) and (prefers-reduced-motion: reduce) {
  .svc-addons .svc-carousel-track { transition: none; }
}
