/* packages.html centerpiece styles (skeleton: hero / whats-included /
   packages / add-ons / reviews / pricing-faq / form). Shared framework
   lives in css/patterns.css (arp-). Concept: the monument rate card. A
   full-bleed fixed-image hero with centered cream type, a menu-style price
   index that hands its pick to the inquiry form, arch-topped package plates, and the
   add-ons as the page's one dark band: a click-through carousel, count-agnostic
   (services.js reads the slides at runtime), skinned in Ariebella's palette. */

/* every flowing section fills the window; taller content still grows past it.
   services.css loads only on this page, so the other pattern pages keep their
   natural section heights. The canvas sections (form, footer) are untouched. */
.arp-sec{min-height:100vh;display:flex;flex-direction:column;justify-content:center;}

/* --- hero: the monument. The wide booth photograph fills the window and holds
   still (fixed attachment) behind centered cream type. Chosen from the
   fixed-image variant round. ------------------------------------------------- */
.svc-hero{padding:0;}
.svc-hero-fixed{
  position:relative;min-height:100vh;width:100%;
  display:flex;align-items:center;justify-content:center;text-align:center;
  padding:90px 24px;
  /* The scrim is deeper than the kit's (.52/.38/.58). The kit was sized for a
     dark hero photo; this client's is pale wood plus a white shirt, so the
     centre stop (where all the copy sits) measured 2.3-2.7:1 against the cream
     type. These stops put the kicker, h1, lede, prices and the ghost button
     all above WCAG AA at 1440 and at every phone width. */
  background:
    linear-gradient(rgba(30,29,26,.68), rgba(30,29,26,.65) 45%, rgba(30,29,26,.72)),
    url("../images/ch-band-greenery.jpg") center 38% / cover no-repeat;
  background-attachment:fixed,fixed;
}
.svc-hero-center{max-width:820px;}
.svc-hero-center .arp-kicker{color:rgba(249,248,246,.72);letter-spacing:.3em;margin-bottom:26px;}
.svc-hero-center .arp-h1{font-size:84px;line-height:1.06;color:var(--cream);}
.svc-hero-center .arp-orn{margin:30px 0 24px;font-size:13px;color:rgba(249,248,246,.85);}
.svc-hero-center .arp-orn::before,.svc-hero-center .arp-orn::after{background:rgba(249,248,246,.35);}
.svc-hero-center .arp-lede{max-width:520px;margin-left:auto;margin-right:auto;color:rgba(249,248,246,.85);}
.svc-hero-center .arp-actions{margin-top:38px;justify-content:center;}
.svc-hero-ghost{background:transparent;color:var(--cream);border:1px solid rgba(249,248,246,.5);}
.svc-hero-ghost:hover{filter:none;border-color:var(--cream);background:rgba(249,248,246,.08);}
.svc-hero-cue{position:absolute;left:50%;bottom:30px;width:1px;height:56px;overflow:hidden;}
.svc-hero-cue::after{content:"";position:absolute;left:0;top:-100%;width:1px;height:100%;background:rgba(249,248,246,.75);animation:svc-cue 2.6s ease-in-out infinite;}
@keyframes svc-cue{0%{top:-100%;}55%{top:100%;}100%{top:100%;}}

/* load choreography: the monument type rises into place */
/* from{} is .001 not 0 because .svc-hero-center > * uses fill-mode `both`:
   during animation-delay the element takes this FROM state, so it is what
   first paint sees. At 0 Chrome emits no LCP entry and PageSpeed cannot
   score the page (intermittent here: the delays are only .08-.24s, so it
   depends on whether first paint lands inside the delay window). */
@keyframes svc-rise{from{opacity:.001;transform:translateY(26px);}to{opacity:1;transform:none;}}
.svc-hero-center > *{animation:svc-rise .85s ease both;}
.svc-hero-center > :nth-child(1){animation-delay:.08s;}
.svc-hero-center > :nth-child(2){animation-delay:.16s;}
.svc-hero-center > :nth-child(3){animation-delay:.24s;}
.svc-hero-center > :nth-child(4){animation-delay:.32s;}
.svc-hero-center > :nth-child(5){animation-delay:.4s;}

/* --- whats-included: the broadside; three giant serif lines on taupe --------
   hovering a line dims the siblings, warms the row, and unfolds its description */
.svc-bro-head{max-width:640px;margin:0 auto 44px;text-align:center;}
.svc-broadside .arp-h2{font-size:30px;line-height:1.2;letter-spacing:.06em;text-transform:uppercase;}
.svc-bro-rule{width:64px;height:1px;background:rgba(30,29,26,.35);margin:26px auto 0;transform:scaleX(0);transition:transform 1s ease .4s;}
.svc-bro-head.in .svc-bro-rule{transform:scaleX(1);}
.svc-bro-head .arp-lede{margin-top:22px;font-size:15px;}
.svc-bro-list{border-top:1px solid rgba(30,29,26,.22);}
.svc-bro-row{position:relative;border-bottom:1px solid rgba(30,29,26,.22);padding:30px 20px;text-align:center;transition:opacity .45s ease,background .45s ease;}
.svc-bro-list:hover .svc-bro-row{opacity:.32;}
.svc-bro-list .svc-bro-row:hover{opacity:1;background:rgba(249,248,246,.5);}
.sec .svc-bro-row h3{font-family:var(--f-title);font-weight:400;font-size:52px;line-height:1.15;color:var(--ink);transition:letter-spacing .6s ease;}
.svc-bro-row:hover h3{letter-spacing:.02em;}
.svc-bro-desc{max-height:0;overflow:hidden;opacity:0;transition:max-height .55s cubic-bezier(.22,.7,.3,1),opacity .45s ease;}
/* 90px capped the reveal at 3 lines and cut the last line off the attendant
   row's description (needs 111px at every width above 901 — the 520px measure
   below pins the wrap, so this is width-independent). Raised with headroom;
   only the collapse animation needs a number here, nothing reads it as a size. */
.svc-bro-row:hover .svc-bro-desc{max-height:132px;opacity:1;}
.sec .svc-bro-desc p{max-width:520px;margin:12px auto 0;font-size:14.5px;line-height:1.7;letter-spacing:.03em;color:rgba(30,29,26,.72);}

/* --- packages: matted plates with arch-top 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-cards{display:flex;flex-wrap:wrap;justify-content:center;gap:34px;margin-top:64px;align-items:stretch;}
.svc-cards > .svc-card{flex:0 1 calc((100% - 2 * 34px) / 3 - 0.5px);min-width:240px;}
.svc-card{position:relative;background:var(--white);border:1px solid var(--line);padding:16px 16px 81px;text-align:center;display:flex;flex-direction:column;}
.svc-card-img,
.svc-card-video {height:250px;overflow:hidden;background:var(--taupe);border-radius:400px 400px 0 0;}
.svc-card-img img,
.svc-card-video video {width:100%;height:100%;object-fit:cover;transition:transform 1.5s ease;}
.svc-card:hover .svc-card-img img,
.svc-card:hover .svc-card-video video {transform:scale(1.04);}
.svc-card .arp-no{margin-top:26px;}
.svc-pill{position:absolute;top:-14px;left:50%;transform:translateX(-50%);background:var(--ink);color:var(--cream);font-family:var(--f-label);font-size:9.5px;letter-spacing:.22em;text-transform:uppercase;padding:9px 18px;white-space:nowrap;z-index:1;}
.sec .svc-card-name{font-family:var(--f-title);font-weight:400;font-size:28px;line-height:1.15;color:var(--ink);margin-top:8px;padding:0 16px;}
.sec .svc-card-price{font-family:var(--f-title);font-size:40px;line-height:1;color:var(--ink);margin-top:14px;}
.svc-card-price small{display:block;margin-top:8px;font-family:var(--f-label);font-size:9.5px;letter-spacing:.24em;text-transform:uppercase;color:rgba(30,29,26,.5);}
.sec .svc-card-blurb{margin:18px 16px 0;font-size:13.5px;line-height:1.7;letter-spacing:.03em;color:rgba(30,29,26,.72);}
.svc-card ul{list-style:none;margin:22px 0 auto;padding:0 16px;text-align:left;}
.svc-card li{padding:11px 2px;border-top:1px solid var(--line);font-size:13.5px;line-height:1.6;letter-spacing:.03em;color:rgba(30,29,26,.8);}
.svc-card li:last-child{border-bottom:1px solid var(--line);}
.svc-card .btn{margin-top:26px;align-self:center;}
.svc-card .arp-card-link{position:absolute;left:16px;right:16px;bottom:38px;margin:0 auto;display:block;max-width:max-content;}
.svc-card.is-featured{background:var(--ink);border-color:var(--ink);}
.svc-card.is-featured .arp-no{color:rgba(249,248,246,.5);}
.svc-card.is-featured .svc-card-name,.svc-card.is-featured .svc-card-price{color:var(--cream);}
.svc-card.is-featured .svc-pill{background:var(--taupe);color:var(--ink);}
.svc-card.is-featured .svc-card-price small{color:rgba(249,248,246,.55);}
.svc-card.is-featured .svc-card-blurb{color:rgba(249,248,246,.75);}
.svc-card.is-featured li{color:rgba(249,248,246,.85);border-color:rgba(249,248,246,.18);}
.svc-card.is-featured .arp-card-link{color:var(--cream);border-color:rgba(249,248,246,.35);}
.svc-card.is-featured .arp-card-link:hover{border-color:var(--cream);}
.sec .svc-pkg-note{margin:48px auto 0;max-width:680px;text-align:center;font-size:13.5px;line-height:1.8;letter-spacing:.03em;color:rgba(30,29,26,.65);}
.svc-pkg-note a{color:var(--ink);}

/* --- add-ons: the page's one dark band; a click-through carousel ------------ */
/* garden-party stationery on ink: cream serif names and prices, taupe as the
   single warm accent (index numeral, active dot, filled add mark, arrow hover,
   the corner tag). Structure mirrors design-01; the skin is Ariebella's. */
.svc-addons-head{max-width:640px;margin:0 auto clamp(40px,5vw,60px);text-align:center;}
.svc-addons-head .arp-kicker{color:rgba(249,248,246,.55);}
.svc-addons-head .arp-h2{color:var(--cream);}
.svc-addons-head .arp-lede{margin-top:8px;color:rgba(249,248,246,.76);}
.svc-addons-head .arp-orn{margin:22px auto;color:rgba(249,248,246,.55);}
.svc-addons-head .arp-orn::before,.svc-addons-head .arp-orn::after{background:rgba(249,248,246,.22);}

/* click-through carousel: one slide per add-on, count-agnostic */
.svc-carousel{margin-top:8px;}
.svc-carousel-viewport{overflow:hidden;}
.svc-carousel-track{display:flex;transition:transform .6s cubic-bezier(.2,.7,.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 rgba(249,248,246,.16);
  background:color-mix(in srgb, var(--cream) 5%, #1e1d1a);
  overflow:hidden;transition:opacity .6s ease;
}
.svc-slide[aria-hidden="true"]{opacity:.2;}

.svc-slide-media{position:relative;overflow:hidden;height:clamp(360px,38vw,480px);background:var(--taupe);}
.svc-slide-media img,
.svc-slide-media video {display:block;width:100%;height:100%;object-fit:cover;}
.svc-slide-tag{
  position:absolute;top:18px;left:18px;background:var(--taupe);color:var(--ink);
  padding:8px 16px;font-family:var(--f-label);font-size:9.5px;letter-spacing:.22em;text-transform:uppercase;
}

.svc-slide-body{display:flex;flex-direction:column;justify-content:center;padding:clamp(30px,4vw,60px);}
.svc-slide-index{font-family:var(--f-label);font-size:10.5px;letter-spacing:.24em;text-transform:uppercase;color:rgba(249,248,246,.5);margin-bottom:20px;}
.svc-slide-index b{color:var(--taupe);font-weight:400;}
.svc-slide-top{display:flex;align-items:baseline;justify-content:space-between;gap:20px;}
.sec .svc-slide-name{font-family:var(--f-title);font-weight:400;font-size:clamp(30px,3.4vw,46px);line-height:1.06;color:var(--cream);}
.svc-slide-price{font-family:var(--f-title);font-weight:400;font-size:clamp(30px,3.4vw,46px);line-height:1;color:var(--cream);white-space:nowrap;}
.sec .svc-slide-blurb{margin-top:20px;max-width:46ch;font-size:15px;line-height:1.78;letter-spacing:.03em;color:rgba(249,248,246,.72);}

.svc-addon-add{
  align-self:flex-start;margin-top:30px;display:inline-flex;align-items:center;gap:12px;
  padding:0;background:none;border:0;cursor:pointer;
  font-family:var(--f-label);font-size:10.5px;letter-spacing:.18em;text-transform:uppercase;
  color:var(--cream);transition:color .3s;
}
.svc-addon-add:hover{color:var(--taupe);}
.svc-addon-add:focus-visible{outline:2px solid var(--taupe);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(249,248,246,.4);border-radius:50%;font-size:18px;line-height:1;
  transition:transform .4s cubic-bezier(.2,.7,.2,1),background .3s,color .3s,border-color .3s;
}
.svc-addon-add:hover .svc-addon-add-i{border-color:var(--taupe);}
.svc-slide.is-added .svc-addon-add-i{background:var(--taupe);border-color:var(--taupe);color:var(--ink);transform:rotate(45deg);}

/* nav: arrows flanking the dots (JS hides the row when there is one slide) */
.svc-carousel-nav{margin-top:clamp(26px,3vw,40px);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(249,248,246,.35);color:var(--cream);
  font-size:24px;line-height:1;display:inline-flex;align-items:center;justify-content:center;
  transition:background .35s,color .35s,border-color .35s;
}
.svc-carousel-arrow:hover{background:var(--taupe);color:var(--ink);border-color:var(--taupe);}
.svc-carousel-arrow:focus-visible{outline:2px solid var(--taupe);outline-offset:3px;}
.svc-carousel-dots{display:flex;align-items:center;gap:12px;}
.svc-carousel-dots button{
  width:9px;height:9px;border-radius:50%;border:0;padding:0;cursor:pointer;
  background:rgba(249,248,246,.3);transition:background .3s,transform .3s;
}
.svc-carousel-dots button.is-live{background:var(--taupe);transform:scale(1.3);}

.svc-addons-foot{margin-top:clamp(32px,4vw,48px);display:flex;align-items:center;justify-content:space-between;gap:24px;flex-wrap:wrap;}
.svc-addons-note{max-width:44ch;font-size:12.5px;line-height:1.6;letter-spacing:.03em;color:rgba(249,248,246,.58);}

/* --- reviews: the home cinematic testimonials (cin- in style.css/script.js) - */

/* --- pricing faq: the head column keeps the reader company ------------------ */
@media (max-width:900px){
  /* On phones the hero is 82vh (owner, 2026-09-07), short of the 100vh
     .arp-sec gives every other section, so the section below peeks above the
     fold. BOTH boxes have to carry that number. .arp-sec is a centred flex
     column, so a child shorter than its section is centred and leaves a band
     of the section's cream background above AND below the photo, which is what
     shipped until this was fixed: 82vh child inside a 100vh section, 60px of
     cream at each end. The photo cannot cover such a band, because on mobile it
     is the position:fixed ::before below (iOS ignores fixed attachment) and it
     is contained by this box's clip-path, so it stops exactly where this box
     stops. The section sets the height; flex:1 then grows the child to whatever
     the section actually resolves to, which also holds if content ever pushes
     the section taller than 82vh. Change the two together or the band returns. */
  .svc-hero{padding:0;min-height:82vh;}
  /* iOS ignores fixed attachment: the photo moves to a pinned ::before layer,
     the scrim stays on the box so it travels with the section. */
  .svc-hero-fixed{flex:1;min-height:82vh;padding:100px 20px 64px;overflow:hidden;clip-path:inset(0);background:none;}
  .svc-hero-fixed::before{content:"";position:fixed;inset:0;z-index:0;
    background:linear-gradient(rgba(30,29,26,.68), rgba(30,29,26,.65) 45%, rgba(30,29,26,.72)),
      url("../images/ch-band-greenery.jpg") center 38% / cover no-repeat;}
  .svc-hero-fixed > *{position:relative;z-index:1;}
  /* the scroll cue is anchored to the section's bottom edge, not flow content
     (see the same note on .occ-hero-corner) */
  .svc-hero-fixed > .svc-hero-cue{position:absolute;}
  .svc-hero-center .arp-h1{font-size:clamp(36px,10vw,50px);}
  /* broadside: no hover on touch, so the descriptions sit open */
  .svc-bro-head{margin-bottom:32px;}
  .svc-bro-row{padding:24px 8px;}
  .sec .svc-bro-row h3{font-size:clamp(26px,7.4vw,34px);}
  /* The :hover selector above (.svc-bro-row:hover .svc-bro-desc, 0-3-0) OUTRANKS
     a bare .svc-bro-desc (0-1-0), so this "sit open" rule never applied the
     moment a phone produced a hover — and iOS DOES: tapping an element that
     carries :hover styles sticks the hover state on until you tap elsewhere.
     The cap then re-clipped copy the visitor had just been reading. Measured in
     WebKit with hover applied, attendant row (247 chars): 360w needed 184px,
     390w 160px, 440w 135px, all against the 132px cap = 52px / 28px / 3px cut
     (the setup row cut 3px at 360w too). Desktop is unaffected and still capped:
     at every width 901-1920 in both engines the rows measure 111px and 86px,
     because .svc-bro-desc p is max-width:520px and stops wrapping further.
     Matching the hover selector here (equal specificity, later in the file)
     restores the touch behaviour this block's own comment describes. */
  .svc-bro-desc,
  .svc-bro-row:hover .svc-bro-desc{max-height:none;opacity:1;}
  .svc-bro-list:hover .svc-bro-row{opacity:1;}
  .svc-cards{gap:40px;margin-top:48px;}
  .svc-cards > .svc-card{flex:1 1 100%;}
  .svc-slide{grid-template-columns:1fr;}
  .svc-slide-media{height:260px;}
  /* THE ADD-ONS RUN THE PACKAGES' LOGIC ON PHONES (owner, 2026-09-22): one
     native swipe track, the card centred, its neighbours peeking, the same
     bottom bar. The desktop carousel slides a translated track and dims the
     cards either side to 20%, which is why widening anything here did nothing
     visible: the neighbour was a dimmed card behind a hidden viewport. Both
     are switched off below, its arrows and dots give way to the bar, and the
     text is pinned to the top of the card so nothing jumps between slides. */
  .svc-carousel-viewport{overflow:visible;}
  .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);
  }
  .svc-carousel-track::-webkit-scrollbar{display:none;}
  .svc-slide{flex:0 0 var(--pk-card); min-width:0; scroll-snap-align:center;}
  .svc-slide[aria-hidden="true"]{opacity:1;}
  .svc-carousel-nav{display:none;}
  .svc-addons{overflow-x:clip;}
  .svc-addons > .arp-wrap{padding-inline:0;}
  .svc-addons > .arp-wrap > .svc-addons-head,
  .svc-addons > .arp-wrap > .svc-addons-foot{padding-inline:20px;}
  .svc-slide{align-content:start;}
  .svc-slide-body{justify-content:flex-start;}
  /* The add-on carousel is a chain of flex/grid items (.arp-wrap in the column
     .arp-sec, then .svc-slide in .svc-carousel-track, then the slide's own two
     cells). Every level defaults to min-width:auto, so none of them would
     shrink below the slide's min-content width and the section rendered 877px
     wide inside a 390px viewport, giving the page 487px of horizontal scroll.
     Scoped to .svc-addons: the other .arp-wrap sections lay out correctly. */
  .svc-addons .arp-wrap,
  .svc-addons .svc-slide,
  .svc-addons .svc-slide-media,
  .svc-addons .svc-slide-body{min-width:0;}
  /* min-width:0 alone is not enough for the wrap itself: it is a flex item of
     the column .arp-sec, and with the shared `width:auto` its cross size is
     still resolved against the carousel track's min-content (6 slides at
     flex:0 0 100%, shrink 0), so it measured 412px inside a 390px viewport and
     gave the whole page 22px of horizontal scroll. An explicit 100% pins it to
     the section instead. Same rendering at every width; only .svc-addons. */
  .svc-addons .arp-wrap{width:100%;}
  .svc-slide-top{flex-wrap:wrap;gap:8px;}
  .svc-addons-foot{flex-direction:column;align-items:stretch;text-align:center;}
  .svc-addons-foot .btn{width:100%;}
}

@media (prefers-reduced-motion: reduce){
  .svc-hero-center > *{animation:none;}
  .svc-hero-cue::after{animation:none;}
  .svc-card-img img,
  .svc-card-video video {transition:none;}
  .svc-bro-rule,.svc-bro-row,.sec .svc-bro-row h3,.svc-bro-desc{transition:none;}
  .svc-bro-rule{transform:scaleX(1);}
  .svc-bro-desc{max-height:none;opacity:1;}
  .svc-carousel-track{transition:none;}
}

/* ---------- package cards: count-aware layout (see the JS in services.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-cards.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-cards.is-slider > article {
    flex: 0 0 calc((100% - 2 * 34px) / 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; }

/* PHONES: THE PACKAGE CARDS ARE A SWIPE TRACK (owner, 2026-09-22). Native
   scrolling only, no gesture code: the track can scroll sideways and NOT
   vertically (overflow-y hidden, never auto, the lesson of the desktop rail
   above), and touch-action stays at its default, so a vertical swipe over a
   card scrolls the PAGE and a sideways one slides the cards, seamlessly. The
   arrow bar is for people who do not think to swipe: fixed to the bottom of
   the screen while the section is on screen (services.js), never on desktop,
   which keeps its own rail. Any card count from two up. */
@media (max-width: 900px) {
  .svc-cards[data-bc-pkg-list="package"] {
    display: flex; flex-wrap: nowrap; justify-content: flex-start; align-items: stretch;
    gap: 6px; margin-top: 40px;
    /* Every card centres in the track, with the ones either side 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 and
       the ends sit ~34px off centre (measured). A vw card is absolute, and
       the padding percentage resolves against the WRAP, so the sum is exact:
       padding + card/2 lands on the track's centre at either end. The arrows
       still step by one card, because the script measures the step from two
       cards' offsets rather than assuming one. */
    /* FULL BLEED: the track spans the viewport rather than sitting inside the
       wrap's 20px gutter, and that 40px is what buys both a wider card and a
       peek you can actually see. The card was 68vw inside the gutter with a
       30px peek, which showed nothing but the neighbour's own white padding
       (rendered and looked at, 2026-09-22). At 84vw of the viewport the
       neighbours show ~26px each, most of it their photo, and the card is
       50px wider. */
    --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: inside packages.html's flex-column sections
       a scroll container reported its whole content width and grew the wrapper
       to 1472px on a 390px phone (cards 1260px wide). width 0 + min-width 100%
       is the standard cure; the location page never saw it (block sections). */
    width: 0; min-width: 100%;
  }
  .svc-cards[data-bc-pkg-list="package"]::-webkit-scrollbar { display: none; }
  .svc-cards[data-bc-pkg-list="package"] > .svc-card { flex: 0 0 var(--pk-card); min-width: 0; scroll-snap-align: center; }
  /* One package: nothing to peek at, so it takes the full width and the
     centring padding comes off. :only-of-type, NOT :only-child — the inert
     <template data-bc-pkg-item> is a sibling, so an only card is never an
     only child and the rule would never fire. */
  /* Tighter side padding here than the desktop card's 16px: it widens the text
     column AND puts more of the neighbour's photo into the peek. */
  .svc-cards[data-bc-pkg-list="package"] > .svc-card { padding-inline: 11px; }
  /* THE NEIGHBOURS HAVE TO BE VISIBLE. Cards carry .reveal, and script.js only
     adds .in when a card intersects the VIEWPORT, which a card parked off to
     the side never does: the peek was a card at opacity 0, so it read as blank
     page (owner, 2026-09-22, and it is why widening the peek alone did
     nothing). In the track they are always shown; the section around them
     still reveals on scroll. */
  .svc-cards[data-bc-pkg-list="package"] > .svc-card.reveal { opacity: 1; transform: none; }
  .svc-cards[data-bc-pkg-list="package"] > .svc-card:only-of-type { flex-basis: 100%; }
  /* FULL BLEED, the deterministic way: this one section drops the wrap's 20px
     gutter and the heading and note take it back themselves, so the track
     spans the screen with no negative margins. Margins were tried first and
     cannot work here: the shell around the track grows to the track's width,
     so calc(50% - 50vw) resolves against a parent that is already 100vw and
     computes to zero, leaving the whole track 20px right of centre (measured,
     2026-09-22). The clip is a belt: a desktop browser under 900px counts its
     scrollbar in vw. Clip, not hidden, so nothing becomes a scroll container. */
  .sec:has(.svc-cards[data-bc-pkg-list="package"]) { overflow-x: clip; }
  .sec:has(.svc-cards[data-bc-pkg-list="package"]) > .arp-wrap { padding-inline: 0; }
  .sec:has(.svc-cards[data-bc-pkg-list="package"]) > .arp-wrap > .arp-head,
  .sec:has(.svc-cards[data-bc-pkg-list="package"]) > .arp-wrap > .svc-pkg-note { padding-inline: 20px; }
  .svc-cards[data-bc-pkg-list="package"]:has(> .svc-card:only-of-type) { padding-inline: 0; }
  /* Each card its OWN height here (owner, 2026-09-22: equal heights "just
     leaves a ton of blank space"). Two sources, both measured on Charisma at
     390: every card stretched to the tallest one's 1364px, so the <ul>'s
     margin-bottom:auto pushed the button down by up to 122px; and .svc-card
     reserves 81px of bottom padding for the absolutely positioned
     .arp-card-link, which a card whose call to action is an in-flow button
     does not have, leaving 82px under it. flex-start fixes the first; the
     :has() test fixes the second only for the cards that really lack the link,
     and a browser without :has() simply keeps the old padding. Desktop still
     stretches, where equal heights are the design. */
  .svc-cards[data-bc-pkg-list="package"] { align-items: flex-start; }
  .svc-cards[data-bc-pkg-list="package"] > .svc-card:not(:has(.arp-card-link)) { padding-bottom: 28px; }
}
.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(--cream); box-shadow: 0 10px 28px rgba(0, 0, 0, .28);
    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(249, 248, 246, .45);
    font-size: 20px; line-height: 1; display: inline-flex; align-items: center; justify-content: center;
  }
  .svc-pkg-mbtn:active { background: rgba(249, 248, 246, .14); }
  .svc-pkg-mcount { font-family: var(--f-label); font-size: 11px; letter-spacing: .2em; min-width: 52px; text-align: center; }
}
/* The two arrows hang 22px past the 1200px canvas on purpose, and above 1243px
   that overhang lands in a canvas gutter. At 1200 to 1243 there is not enough
   gutter left and it became 22px of horizontal PAGE scroll (the arrows only
   exist at 4+ packages, so no earlier build hit it). Clipped at the section,
   which is viewport-wide, so this cuts exactly where the viewport edge already
   did and nothing changes at 1244px and up. Same remedy, same reasoning as
   #packages-callout in css/occasion.css; clip, not hidden, so the section
   never becomes a scroll container. */
#packages { overflow-x: clip; }

/* 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 with a
   heading and no cards. 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. This kit ships
   demo add-on cards, so the rule is inert here; it bites in a CLIENT BUILD
   whose price list has no add-ons, or whose client later clears them all.
   Never delete #addons from a build to "tidy up" a client with no add-ons
   today: that is the one-way door this rule exists to replace. */
#addons:not(:has([data-bc-pkg])) { display: none; }


/* 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; }
