/* Rate cards + comparison table + a la carte for packages.html (the only
   page that links this file). Same design tokens as styles.css; nothing
   here reuses the home page's section layouts — only the shared type
   system (serif display + script accents + Work Sans labels), palette,
   buttons, and image treatments. */

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

.rates { background: var(--cream); padding: clamp(3.5rem, 8vw, 6.5rem) clamp(1.25rem, 4vw, 3rem); }
.rates-head { text-align: center; margin-bottom: clamp(2.5rem, 6vw, 4rem); }
.rates-head h2 { font-family: var(--serif); font-weight: 300; font-size: clamp(2.2rem, 4.5vw, 3.2rem); line-height: 1; }
.rates-head .script { display: block; font-size: clamp(2.2rem, 4.5vw, 3.4rem); line-height: 0.9; }
.rates-head .eyebrow { color: var(--rose); margin-bottom: 1.6rem; }

.rate-cards {
  --rc-gap: clamp(1.25rem, 3vw, 2.25rem);
  max-width: 1100px;
  margin: 0 auto;
  /* FLEX, not grid, on purpose. This list is RECONCILED, so the card count is
     whatever the client's price list holds (the kit demos 3; a 5-package
     client gets 5). Grid leaves a trailing row of 1 or 2 stranded against a
     hole; flex-wrap + justify-content centres it. The inert <template> is
     display:none so it never takes a slot. */
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  align-items: stretch;
  gap: var(--rc-gap);
}
.rate-cards > .rate-card {
  flex: 0 1 calc((100% - 2 * var(--rc-gap)) / 3 - 0.5px);
  min-width: 260px;
}

.rate-card {
  position: relative;
  border: 1px solid var(--ink);
  padding: 1.2rem 1.4rem 1.3rem;
  display: flex;
  flex-direction: column;
  background: #fff;
}
.rate-card--dark { background: var(--brown); color: var(--cream); border-color: var(--brown); }
.rate-number {
  position: absolute;
  top: 0.4rem;
  right: 0.9rem;
  font-family: var(--serif);
  font-weight: 300;
  font-size: clamp(2.6rem, 4vw, 3.6rem);
  line-height: 1;
  color: rgba(20, 20, 20, 0.12);
}
.rate-card--dark .rate-number { color: rgba(255, 255, 255, 0.3); }
/* 3/2, tighter margins, and a vh cap: with 5-package reconciled content
   (9-row inclusion lists, 5-line descriptions) the 4/3 crop pushed the card
   to ~990px and a card never fit a laptop window. Text blocks are reconciler
   data and cannot shrink, so the figure and the spacing rhythm carry it. */
.rate-fig { overflow: hidden; margin: 1.1rem 0 0.9rem; }
.rate-fig img {
  width: 100%;
  aspect-ratio: 3 / 2;
  max-height: clamp(150px, 20vh, 200px);
  object-fit: cover;
}
/* The kit tuned crop focal points for its own demo photos via slug selectors
   (glow / moonlight). Those slugs do not exist in this build and the photos
   are the client's own, so the rules are removed rather than left dead. Add
   per-slug object-position here only if a specific card crops badly. */
@media (prefers-reduced-motion: no-preference) {
  .rate-card { transition: translate 0.35s ease, box-shadow 0.35s ease; }
  .rate-card:hover { translate: 0 -6px; box-shadow: 0 18px 40px rgba(0, 0, 0, 0.1); }
  .rate-fig img { transition: scale 0.6s ease; }
  .rate-card:hover .rate-fig img { scale: 1.05; }
}
/* padding-right reserves the corner the .rate-number watermark sits in (it
   reaches ~40px into this box at 1440 and ~27px below that). The kit's demo
   tags are all short enough to miss it by luck; real package tags are not, and
   between 901 and 1024, where the slider squeezes three cards into the row,
   even a 23-character tag ran under the numeral. Reserving the space makes a
   long tag WRAP instead, which the card already handles. */
.rate-tag {
  font-family: var(--label);
  font-size: 0.6875rem;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--blush);
  margin-bottom: 0.2rem;
  padding-right: 2.5rem;
}
.rate-card h3 {
  font-size: clamp(2rem, 3vw, 2.6rem);
  line-height: 1;
  margin-bottom: 0.5rem;
}
.rate-price {
  font-family: var(--label);
  font-size: 0.8125rem;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--rose);
  margin-bottom: 0.8rem;
}
.rate-card--dark .rate-price { color: var(--blush); }
.rate-blurb {
  font-family: 'Raleway', var(--body);
  font-size: 0.95rem;
  line-height: 1.5;
  margin-bottom: 0.8rem;
}
/* margin-bottom is AUTO, not a fixed 1.8rem, because this list is reconciled:
   its length is whatever that package's client_packages.inclusions holds (9
   rows on ELITE GLAM, 4 on SIGNATURE SOCIAL). Cards in the row are equal
   height, so the slack has to go somewhere. Sending it here pins the CTA to the
   foot of every card; when it sat on the button instead, the short cards opened
   a ~240px hole above it. The minimum gap now lives on .btn below. */
.rate-list {
  list-style: none;
  border-top: 1px solid rgba(20, 20, 20, 0.25);
  padding-top: 0.9rem;
  margin-bottom: auto;
  display: grid;
  gap: 0.35rem;
}
.rate-card--dark .rate-list { border-top-color: rgba(255, 255, 255, 0.35); }
.rate-list li {
  font-family: 'Raleway', var(--body);
  font-size: 0.875rem;
  line-height: 1.4;
  position: relative;
  padding-left: 1.1em;
}
.rate-list li::before {
  content: '+';
  position: absolute;
  left: 0;
  top: 0;
  font-family: var(--serif);
  font-weight: 300;
  color: var(--rose);
}
.rate-card--dark .rate-list li::before { color: var(--blush); }
/* The cross-link that used to sit between the list and the CTA was removed
   (owner, 2026-08-02), so the CTA is now the only thing below the bullets and
   this gap is the whole foot of the card. */
.rate-card .btn { margin-top: 1.4rem; align-self: start; }
/* A build can still put a cross-link back under the list (Midwest Selfie's
   Signature Booth card links to its own page). .text-link is ink, styled for
   light grounds, so on the dark card it vanished into the brown and sat flush
   on the last bullet. Same white the kit's other dark-ground links use
   (.oc-spread / .vr-cta / .gw-cta .text-link), and the list's own 0.9rem
   rhythm above it; align-self keeps its hover rule to the label's width. */
.rate-card .text-link { align-self: start; margin-top: 0.9rem; }
.rate-card--dark .text-link { color: #fff; }

/* ---------- Small screens ---------- */

@media (max-width: 800px) {
  /* Mobile type scale matching the home page's vw-based canvas */
  .rates-head h2 { font-size: 8.4vw; }
  .rates-head .script { font-size: 10.9vw; }
  .rate-cards { gap: 2rem; }
  .rate-cards > .rate-card { flex: 1 1 100%; }
  /* Leave the focal point CENTRED. The phone crop is far wider (1.79) than the
     sources (~1.26), so ~128px is lost off the top AND the bottom, and biasing
     the window upward to save the back row's hair was tried and reverted: on
     p15 and p09 it cut the FRONT subject's face at the mouth, which is the
     worse defect of the two. Centre keeps every face whole. */
  .rate-fig img { aspect-ratio: 240 / 134; }
}

/* ---------- 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) {
  .rate-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 overflow-x alone is not enough: a lone overflow-x forces overflow-y
       to compute to auto, and the hover-lift headroom (padding-top 22px /
       margin-top -22px) leaves ~26px of vertical overflow, so the rail became
       a 26px-deep vertical scroller that latched the wheel and froze PAGE
       scrolling over the whole section. hidden blocks user scrolling on both
       axes while scrollTo() in services.js keeps working. */
    overflow: hidden;
    padding-top: 22px; margin-top: -22px;
  }
  .rate-cards.is-slider > article {
    flex: 0 0 calc((100% - 2 * var(--rc-gap, 2.25rem)) / 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. Ported 2026-10-04 from
   design-02's pkg-rail block (itself from design-03, Charisma, owner call
   2026-09-22) onto this kit's .rate-cards / .rate-card list; the desktop rail
   above is untouched. Native scrolling only, no gesture code: the track
   scrolls 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. 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. Any card count from two up; keyed on the reconciler's own
   mark so a portal save that adds a package joins the track with no rebuild.
   900px, not this kit's 800px phone breakpoint, so it meets the desktop
   slider's 901px gate with no width where a 4+ list does neither. */
@media (max-width: 900px) {
  /* FULL BLEED: the section drops its side padding and the heading takes it
     back, so the track spans the screen with no negative margins. Descendant
     :has(), not child: services.js wraps a 4+ list in .svc-pkg-shell. */
  .rates:has(.rate-cards[data-bc-pkg-list="package"]) { padding-inline: 0; overflow-x: clip; }
  .rates:has(.rate-cards[data-bc-pkg-list="package"]) > .rates-head { padding-inline: clamp(1.25rem, 4vw, 3rem); }
  .rate-cards[data-bc-pkg-list="package"] {
    display: flex; flex-wrap: nowrap; justify-content: flex-start;
    /* Each card its own height (Charisma, owner 2026-09-22: equal heights
       "just leaves a ton of blank space"); desktop still stretches. */
    align-items: flex-start;
    gap: 10px; max-width: none; margin: 0;
    /* 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. 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 padding + card/2 lands on the
       track's centre at either end. */
    --pk-card: 84vw;
    padding: 0 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: a scroll container reports its whole
       content width to a flex/grid parent. width 0 + min-width 100%. */
    width: 0; min-width: 100%;
  }
  .rate-cards[data-bc-pkg-list="package"]::-webkit-scrollbar { display: none; }
  .rate-cards[data-bc-pkg-list="package"] > .rate-card { flex: 0 0 var(--pk-card); min-width: 0; scroll-snap-align: center; }
  /* THE NEIGHBOURS HAVE TO BE VISIBLE. Cards carry .reveal-item, which only
     turns on when the card intersects the viewport, and a card parked off to
     the side never does: the peek would be a card at opacity 0. In the track
     they are always shown; the heading above still reveals on scroll. */
  html.js .rate-cards[data-bc-pkg-list="package"] > .rate-card.reveal { opacity: 1; translate: none; }
  /* One package: nothing to peek at. :only-of-type, NOT :only-child, because
     the inert <template data-bc-pkg-item> is a sibling. */
  .rate-cards[data-bc-pkg-list="package"] > .rate-card:only-of-type { flex-basis: 100%; }
  .rate-cards[data-bc-pkg-list="package"]:has(> .rate-card:only-of-type) { padding-inline: clamp(1.25rem, 4vw, 3rem); }
}
/* The phone bar: back, a "2 / 3" counter read from the DOM, forward. Built and
   positioned by services.js; shown only while its track is on screen, and
   never over the open phone menu (the menu lives in the header's z-index 10
   layer, under this bar's 50). */
.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: #fff; 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; }
  body:has(.site-header.menu-open) .svc-pkg-mnav { opacity: 0; pointer-events: none; }
  .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(255, 255, 255, .45);
    font-size: 20px; line-height: 1; display: inline-flex; align-items: center; justify-content: center;
    -webkit-appearance: none; appearance: none;
  }
  .svc-pkg-mbtn:active { background: rgba(255, 255, 255, .14); }
  .svc-pkg-mcount { font-family: var(--label); font-weight: 400; font-size: 12px; letter-spacing: .2em; min-width: 52px; text-align: center; }
}
