/* ══════════════════════════════════════════════════════════════════════════
   /book-shoot v3 — the SITE's card anatomy, at portal scale.
   CS-PLAT-09 / book-v3, Dom 2026-08-23.

   WHAT THIS SHEET IS. Dom asked for capitalshots.ca/book, cloned: "a smaller
   version of what we have on the site with the toasts etc — identical but more
   compact, not crowded." So every measurement here is the LIVE SITE's own
   `.pk` / `.ala` card, taken from the served /book stylesheet and multiplied by
   ~0.7 — not a new visual language:

     site  →  here          site  →  here
     --pk-pad 20px → 14px   .pk__name  32px → 20px/600
     media  2.4/1  → 16/10  .pk__amt   29px → 21px
     .pk__item 14.5/600 → 14/600       flip 580ms → 250ms (portal's own)

   The flip MECHANIC is the portal's, not the site's: .ad-pcard/.ad-flip in
   agent-dash.css (250 ms, reduced-motion instant, `inert` on the hidden face).
   One motion vocabulary in this product, not two.

   WHY IT IS ITS OWN FILE. agent-dash.css owns `.bk-*` — the SMALL rate tile
   that the Dash's "Book a shoot" section renders through
   agent-book.js#rateTileHtml. That tile is still live on the Dash and is NOT
   this screen. Rewriting it in place would have changed a screen this lane does
   not own, so the booking screen's own anatomy lives here under `.bkv3`,
   exactly as cs-today.css was split out for the Today screen.

   COLOUR LAW (feedback_cs_backend_palette_red_black, 2026-08-22): --brand
   (#FF0016) on small elements and accents only; the flip card's BACK is black.
   White type and white icons on the red button, both themes.
   ══════════════════════════════════════════════════════════════════════════ */

/* The black face's palette lives on :root, NOT on .bkv3 — the upgrade popover
   is rendered into <body> (it has to escape the card's overflow and its 3D
   context), so a token defined on .bkv3 does not reach it and the panel comes
   out transparent. Measured on staging 2026-08-23. */
:root {
  --bkc-black: #0A0A0A;         /* Dom 2026-08-23: back of the flip card BLACK */
  --bkc-black-ink: #F4F4F4;
  --bkc-black-ink-2: rgba(244,244,244,.66);
  --bkc-black-line: rgba(244,244,244,.14);
}
.bkv3 { --bkc-pad: 14px; }      /* the site's 20px × 0.7 */

/* ── Page frame: main column + the sticky order rail ──────────────────────
   One column until there is honestly room for two. 1080 is where a 300px rail
   plus a 3-up card grid both fit without either being squeezed. */
.bkv3-cols { display: grid; gap: var(--sp-6); align-items: start; }
@media (min-width: 1080px) {
  .bkv3-cols { grid-template-columns: minmax(0, 1fr) 304px; gap: var(--sp-6); }
  .bkv3-rail { position: sticky; top: var(--sp-4); }
}
.bkv3-main { display: grid; gap: var(--sp-3); min-width: 0; }

/* On a narrow column the section hint ("Turn a card for the description and
   upgrades") squeezes into a 3-line stack beside its own heading. It drops to
   its own row instead — it is the only thing telling a touch user that the
   card turns, so hiding it is not an option. */
@media (max-width: 700px) {
  .bkv3 .ad-sec-h { flex-wrap: wrap; }
  .bkv3 .ad-sec-h .ad-sub { flex: 1 0 100%; }
}

/* ══ PACKAGE CARDS ════════════════════════════════════════════════════════ */

.bkp-grid {
  display: grid; gap: var(--sp-6);
  grid-template-columns: 1fr;
  align-items: stretch;                 /* every card is the tallest card */
}
@media (min-width: 620px) { .bkp-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (min-width: 980px) { .bkp-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); } }

.bkp { position: relative; min-width: 0; height: 100%; perspective: 1400px; }
.bkp-flip {
  position: relative; display: grid; height: 100%; min-height: 380px;
  transform-style: preserve-3d;
  transition: transform 250ms var(--ease);
}
.bkp.is-flipped .bkp-flip,
.bks.is-flipped .bkp-flip { transform: rotateY(180deg); }
@media (prefers-reduced-motion: reduce) { .bkp-flip { transition: none; } }

.bkp-face {
  grid-area: 1 / 1;
  display: flex; flex-direction: column; overflow: hidden;
  background: var(--bg-elevated); color: var(--ink);
  border: 1px solid var(--line); border-radius: var(--r-3);
  box-shadow: var(--shadow-1);
  -webkit-backface-visibility: hidden; backface-visibility: hidden;
  transition: border-color var(--t-fast) var(--ease), box-shadow 200ms var(--ease);
}
/* `backface-visibility` is a PAINT rule, not a hit-testing one — inside a
   preserve-3d stack Chrome still hit-tests the hidden face (measured on this
   portal's listing cards, 2026-08-22). The JS sets `inert`; this is the same
   guarantee for anything that does not honour it. */
.bkp .bkp-back, .bks .bkp-back { pointer-events: none; transform: rotateY(180deg); }
.bkp.is-flipped .bkp-back, .bks.is-flipped .bkp-back { pointer-events: auto; }
.bkp.is-flipped .bkp-front, .bks.is-flipped .bkp-front { pointer-events: none; }

.bkp-front:hover { border-color: var(--line-strong); }
.bkp.is-on .bkp-face { border-color: var(--brand); box-shadow: 0 0 0 1px var(--brand) inset, var(--shadow-1); }

/* ── the BLACK back (Dom 2026-08-23) ─────────────────────────────────────── */
.bkp-back {
  background: var(--bkc-black); color: var(--bkc-black-ink);
  border-color: rgba(244,244,244,.10);
}
.bkp.is-on .bkp-back { border-color: var(--brand); }
.bkp-back .bkp-rule { background: var(--bkc-black-line); }
.bkp-back .bkp-save { color: var(--bkc-black-ink-2); }
.bkp-back .bkp-save b { color: var(--bkc-black-ink); }
.bkp-back .bkp-was { color: rgba(244,244,244,.42); }

/* ── photo ────────────────────────────────────────────────────────────────
   16 : 10, the site's 2.4:1 band opened up because a portal card is narrower
   and a 2.4:1 strip on 300px is 125px of letterbox. */
.bkp-media { display: block; aspect-ratio: 16 / 10; overflow: hidden; background: var(--bg-sunken); flex: none; }
.bkp-media img { width: 100%; height: 100%; object-fit: cover; display: block; }

/* ── clicking the card turns it over (Dom: "clicking the card flips to a BLACK
   back"). The trigger is a STRETCHED, empty overlay button covering the upper
   area — not a wrapper. A wrapper would put a <ul> inside a <button> (invalid
   content model) and make the foot's Select a button inside a button. */
.bkp-top {
  position: relative; flex: 1 1 auto; min-height: 0;
  display: flex; flex-direction: column; align-items: stretch;
}
.bkp-turn {
  position: absolute; inset: 0; z-index: 2;
  margin: 0; padding: 0; border: 0; background: none; cursor: pointer;
  border-radius: var(--r-3) var(--r-3) 0 0;
}
.bkp-turn:focus-visible { outline: 2px solid var(--brand); outline-offset: -2px; }

.bkp-head {
  display: flex; align-items: flex-start; justify-content: space-between; gap: var(--sp-2);
  padding: var(--bkc-pad) var(--bkc-pad) 0;
}
.bkp-name { font-size: calc(20px * var(--text-scale, 1)); font-weight: 600; line-height: 1.15; letter-spacing: -.02em; color: inherit; }
.bkp-tag {
  flex: none; align-self: center;
  padding: 4px 7px 5px; border-radius: var(--r-1);
  background: var(--brand); color: var(--brand-ink);
  font: 700 calc(11px * var(--text-scale, 1))/1 var(--font-sans); letter-spacing: .01em; white-space: nowrap;
}

/* ── the inclusion list — EVERY line, never "+N more" (Dom 2026-08-23) ───── */
.bkp-list { list-style: none; display: grid; gap: 7px; margin: 0; padding: 11px var(--bkc-pad) 0; }
.bkp-item {
  display: flex; align-items: flex-start; gap: 8px;
  font-size: calc(14px * var(--text-scale, 1)); font-weight: 600; line-height: 1.3; letter-spacing: -.01em; color: inherit;
}
.bkp-item .bki { width: 14px; height: 14px; flex: none; margin-top: 1px; color: var(--brand); }
.bkp-back .bkp-item .bki { color: var(--brand); }

.bkp-fill { flex: 1 1 auto; min-height: var(--sp-3); }
.bkp-rule { height: 1px; background: var(--line); margin: 0; flex: none; }

/* ── price row ────────────────────────────────────────────────────────────
   "Save $135 vs à la carte · $585 $450" — the site's own row, one line. */
.bkp-meta {
  display: flex; align-items: baseline; justify-content: space-between; gap: var(--sp-2);
  flex-wrap: wrap; padding: 10px var(--bkc-pad);
}
.bkp-save { font-size: calc(12.5px * var(--text-scale, 1)); font-weight: 500; color: var(--ink-3); }
.bkp-save b { font-weight: 700; color: var(--ink-2); }
.bkp-amt {
  font-size: calc(21px * var(--text-scale, 1)); font-weight: 700; line-height: 1; letter-spacing: -.03em;
  color: inherit; font-variant-numeric: tabular-nums; white-space: nowrap;
}
.bkp-amt small { font-size: calc(11.5px * var(--text-scale, 1)); font-weight: 500; color: var(--ink-3); letter-spacing: 0; margin-left: 4px; }
.bkp-back .bkp-amt small { color: var(--bkc-black-ink-2); }
.bkp-was {
  font-size: calc(12.5px * var(--text-scale, 1)); font-weight: 500; color: var(--ink-4);
  text-decoration: line-through; margin-right: 6px;
}

/* ── foot: "Select Full →" ────────────────────────────────────────────────── */
.bkp-foot { display: flex; flex: none; }
.bkp-pick {
  flex: 1 1 auto; display: flex; align-items: center; justify-content: space-between; gap: var(--sp-2);
  min-height: 44px; padding: 0 var(--bkc-pad);
  margin: 0; border: 0; background: none; color: inherit; cursor: pointer;
  font: 600 calc(14px * var(--text-scale, 1))/1 var(--font-sans); letter-spacing: -.01em; text-align: left;
  border-radius: 0 0 var(--r-3) var(--r-3);
  transition: background var(--t-fast) var(--ease), color var(--t-fast) var(--ease);
}
.bkp-pick .bki { width: 16px; height: 16px; flex: none; transition: transform var(--t-fast) var(--ease); }
.bkp-pick:hover { background: color-mix(in srgb, var(--brand) 8%, transparent); color: var(--brand-deep); }
.bkp-back .bkp-pick:hover { background: rgba(244,244,244,.08); color: #FFFFFF; }
.bkp-pick:hover .bki { transform: translateX(3px); }
.bkp-pick:focus-visible { outline: 2px solid var(--brand); outline-offset: -3px; }
.bkp.is-on .bkp-pick { background: var(--brand); color: var(--brand-ink); }
.bkp.is-on .bkp-pick .bki { color: var(--brand-ink); transform: none; }
.bkp.is-on .bkp-pick:hover { background: var(--brand-deep); color: var(--brand-ink); }

/* ── back face: header, description, upgrade dropdowns ────────────────────── */
.bkp-back .bkp-head { padding-bottom: 0; }
.bkp-backx {
  flex: none; width: 26px; height: 26px; display: grid; place-items: center;
  border: 1px solid var(--bkc-black-line); border-radius: var(--r-1);
  background: none; color: var(--bkc-black-ink-2); cursor: pointer; padding: 0;
}
.bkp-backx:hover { color: var(--bkc-black-ink); border-color: rgba(244,244,244,.3); }
.bkp-backx:focus-visible { outline: 2px solid var(--brand); outline-offset: 2px; }
.bkp-backx .bki { width: 14px; height: 14px; }

.bkp-desc {
  margin: 9px 0 0; padding: 0 var(--bkc-pad);
  font-size: calc(13px * var(--text-scale, 1)); font-weight: 400; line-height: 1.55; color: var(--bkc-black-ink-2);
  text-wrap: pretty;
}
.bkp-cfg { display: grid; gap: 10px; padding: var(--sp-3) var(--bkc-pad) 0; }
.bkp-cfglab {
  display: block; margin-bottom: 4px;
  font: 600 calc(11px * var(--text-scale, 1))/1 var(--font-sans); letter-spacing: .06em; text-transform: uppercase;
  color: rgba(244,244,244,.5);
}
/* A fact, not a control — an inclusion that has nothing to choose renders as a
   row, never as a dropdown with one option (no dead controls). */
.bkp-fixed {
  display: flex; align-items: center; gap: 8px;
  min-height: 34px; padding: 0 10px;
  border: 1px dashed var(--bkc-black-line); border-radius: var(--r-2);
  font: 500 calc(12.5px * var(--text-scale, 1))/1.3 var(--font-sans); color: var(--bkc-black-ink-2);
}
.bkp-fixed .bki { width: 14px; height: 14px; flex: none; color: var(--brand); }

/* ══ POPOVER LISTBOX ══════════════════════════════════════════════════════
   Dom: "our popover listbox, not native". The panel is rendered into <body>,
   not into the card: a menu inside a rotateY(180deg) face with overflow:hidden
   is clipped by its own card and drawn behind its neighbours. Fixed position,
   measured off the trigger's rect. */
.bkl-btn {
  display: flex; align-items: center; justify-content: space-between; gap: var(--sp-2);
  width: 100%; min-height: 38px; padding: 0 10px;
  background: rgba(244,244,244,.06); color: var(--bkc-black-ink);
  border: 1px solid var(--bkc-black-line); border-radius: var(--r-2);
  font: 600 calc(13px * var(--text-scale, 1))/1.2 var(--font-sans); letter-spacing: -.01em; text-align: left; cursor: pointer;
  transition: background var(--t-fast) var(--ease), border-color var(--t-fast) var(--ease);
}
.bkl-btn:hover { background: rgba(244,244,244,.12); border-color: rgba(244,244,244,.26); }
.bkl-btn[aria-expanded="true"] { border-color: var(--brand); }
.bkl-btn:focus-visible { outline: 2px solid var(--brand); outline-offset: 2px; }
/* Dom 2026-08-30 "no double lines": when the listbox is OPEN the border is
   already the brand ring — the offset outline made a second, detached one. */
.bkl-btn[aria-expanded="true"]:focus-visible { outline: none; }
/* Dom 2026-08-30: the listbox caret is the SITE's select caret — butter
   #FFF083 (capitalshots.ca/book `.ala__sel`), and a size up so it reads. */
.bkl-btn .bki { width: 16px; height: 16px; flex: none; color: var(--accent-butter, #FFF083); transition: transform var(--t-fast) var(--ease); }
.bkl-btn[aria-expanded="true"] .bki { transform: rotate(180deg); }
.bkl-btn .v { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

.bkl-pop {
  position: fixed; z-index: 90; margin: 0; padding: 5px;
  max-height: 280px; overflow-y: auto;
  background: #0A0A0A; background: var(--bkc-black, #0A0A0A);
  color: #F4F4F4; color: var(--bkc-black-ink, #F4F4F4);
  border: 1px solid rgba(244,244,244,.18); border-radius: 10px; border-radius: var(--r-2);
  font-family: var(--font-sans);
  box-shadow: 0 18px 40px -14px rgba(0,0,0,.6);
}
.bkl-pop[hidden] { display: none; }
.bkl-opt {
  display: flex; align-items: center; justify-content: space-between; gap: var(--sp-3);
  width: 100%; min-height: 34px; padding: 6px 8px;
  border: 0; border-radius: var(--r-1); background: none; color: inherit; cursor: pointer;
  font: 500 calc(13px * var(--text-scale, 1))/1.3 var(--font-sans); text-align: left;
}
.bkl-opt .n { font-variant-numeric: tabular-nums; font-weight: 600; color: rgba(244,244,244,.72); white-space: nowrap; }
.bkl-opt:hover, .bkl-opt.is-cursor { background: rgba(244,244,244,.11); }
.bkl-opt[aria-selected="true"] { color: #FFFFFF; }
.bkl-opt[aria-selected="true"]::after {
  content: ""; flex: none; width: 6px; height: 6px; border-radius: 50%; background: var(--brand);
}
.bkl-opt:focus-visible { outline: 2px solid var(--brand); outline-offset: -2px; }

/* ══ SINGLE SERVICES — the same anatomy, smaller ═════════════════════════
   Dom 2026-08-29: "All these should be flip cards with option in the back —
   has to make sense", and "keep our animated thumbs and regular too."

   So `.bks` is now a SIZE VARIANT of the package card, not a second card: it
   reuses `.bkp-flip` / `.bkp-face` / `.bkp-front` / `.bkp-back` / `.bkp-turn` /
   `.bkp-backx` verbatim — one 250 ms rotateY, one BLACK back, one reduced-
   motion rule, one `inert` contract — and only overrides what a smaller card in
   a 4-up grid genuinely needs (radius, min-height, type scale). Same component
   on the Grapevine screen (views/agent-book-gv.js). */
.bks-grid { display: grid; gap: var(--sp-4); grid-template-columns: repeat(2, minmax(0, 1fr)); align-items: stretch; }
@media (min-width: 620px) { .bks-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
/* Dom 2026-08-30: 6-up squished text and cut prices — back to 4, prices never
   truncate (rule further down). */
@media (min-width: 980px) { .bks-grid { grid-template-columns: repeat(4, minmax(0, 1fr)); } }

/* The article is the 3D stage now — the background, the border and the shadow
   moved onto the two faces (`.bkp-face`), which is what makes the faces equal
   height: `.bkp-flip` is a 1-cell grid and both faces sit in grid-area 1/1. */
.bks {
  position: relative; min-width: 0; height: 100%;
  border-radius: var(--r-2);
  perspective: 1400px;
}
.bks .bkp-flip { min-height: 320px; }
/* The package card's 12px radius is too generous at this size — the site's own
   à-la-carte tile is the 10px one. */
.bks .bkp-face { border-radius: var(--r-2); }
.bks .bkp-turn { border-radius: var(--r-2) var(--r-2) 0 0; }
.bks.is-on .bkp-face { border-color: var(--brand); }
/* The selected ring paints ABOVE the media (the cover image used to sit on top
   of the inset shadow — Dom 2026-08-24 "photo is on top of the outline"). It
   stays on the ARTICLE, outside the preserve-3d stack, so it reads on whichever
   face is showing. */
.bks.is-on::after {
  content: ''; position: absolute; inset: 0; pointer-events: none; z-index: 3;
  border: 2px solid var(--brand); border-radius: inherit;
}
/* The upper area is the flip target — media + body, never the foot. */
.bks-top {
  position: relative; flex: 1 1 auto; min-height: 0;
  display: flex; flex-direction: column; align-items: stretch;
}
.bks-media { display: block; aspect-ratio: 16 / 10; overflow: hidden; background: var(--bg-sunken); flex: none; }
.bks-media img, .bks-media video { width: 100%; height: 100%; object-fit: cover; display: block; }
.bks-body { display: flex; flex-direction: column; gap: 5px; padding: 10px 11px 0; flex: 1 1 auto; }
.bks-name { font-size: calc(14.5px * var(--text-scale, 1)); font-weight: 600; line-height: 1.25; letter-spacing: -.015em; }
.bks-lines { list-style: none; display: grid; gap: 4px; margin: 2px 0 0; padding: 0; }
.bks-lines li {
  display: flex; align-items: flex-start; gap: 7px;
  font-size: calc(12.5px * var(--text-scale, 1)); font-weight: 500; line-height: 1.4; color: var(--ink-3);
}
.bks-lines li .bki { width: 13px; height: 13px; flex: none; margin-top: 2px; color: var(--brand); }

/* ── the BLACK back: head, full description, options ─────────────────────── */
.bks-bhead {
  display: flex; align-items: flex-start; justify-content: space-between; gap: var(--sp-2);
  padding: 10px 11px 0; flex: none;
}
.bks-bbody { flex: 1 1 auto; min-height: 0; overflow-y: auto; padding: 0 11px 10px; }
.bks-desc {
  margin: 7px 0 0;
  font-size: calc(12.5px * var(--text-scale, 1)); font-weight: 400; line-height: 1.5;
  color: var(--bkc-black-ink-2); text-wrap: pretty;
}
.bks-foot {
  display: flex; align-items: center; justify-content: space-between; gap: var(--sp-2);
  margin-top: 10px; border-top: 1px solid var(--line); flex: none;
}
.bkp-back .bks-foot { border-top-color: var(--bkc-black-line); }
.bks-p {
  padding-left: 11px; font-size: calc(14px * var(--text-scale, 1)); font-weight: 700; letter-spacing: -.02em;
  font-variant-numeric: tabular-nums; white-space: nowrap;
}
.bks-p small { font-size: calc(10.5px * var(--text-scale, 1)); font-weight: 500; color: var(--ink-3); letter-spacing: 0; margin-left: 3px; }
.bkp-back .bks-p small { color: var(--bkc-black-ink-2); }
.bks-add {
  display: flex; align-items: center; gap: 5px;
  min-height: 38px; padding: 0 11px; margin: 0;
  border: 0; background: none; color: var(--ink-2); cursor: pointer;
  font: 600 calc(13px * var(--text-scale, 1))/1 var(--font-sans); letter-spacing: -.01em;
  transition: background var(--t-fast) var(--ease), color var(--t-fast) var(--ease);
}
.bks-add .bki { width: 14px; height: 14px; }
.bks-add:hover { background: color-mix(in srgb, var(--brand) 8%, transparent); color: var(--brand-deep); }
.bks-add:focus-visible { outline: 2px solid var(--brand); outline-offset: -3px; }
.bks.is-on .bks-add { background: var(--brand); color: var(--brand-ink); }
.bks.is-on .bks-add .bki { color: var(--brand-ink); }
.bks.is-on .bks-add:hover { background: var(--brand-deep); }
/* the same control on the BLACK face */
.bkp-back .bks-add { color: var(--bkc-black-ink); border-radius: 0 0 var(--r-2) 0; }
.bkp-back .bks-add:hover { background: rgba(244,244,244,.08); color: #FFFFFF; }
.bks.is-on .bkp-back .bks-add { background: var(--brand); color: var(--brand-ink); }
.bks.is-on .bkp-back .bks-add:hover { background: var(--brand-deep); }

/* ══ SAMPLE STRIP — the site's "Photos" row ══════════════════════════════ */
.bkv3-strip-h { display: flex; align-items: center; gap: var(--sp-3); margin-bottom: var(--sp-3); }
.bkv3-title {
  display: inline-flex; align-items: center; gap: 8px;
  color: var(--ink);
  font: 600 calc(15px * var(--text-scale, 1))/1 var(--font-sans); letter-spacing: -.005em;
}
.bkv3-title .bki { width: 15px; height: 15px; color: var(--brand); }
/* `align-items: start` is load-bearing: a grid item defaults to align-self
   stretch, which SETS a height and defeats `aspect-ratio` — measured on
   staging 2026-08-23, the six 16:10 stills came out as portrait slivers. */
.bkv3-strip {
  display: grid; grid-template-columns: repeat(3, 1fr); gap: var(--sp-2);
  align-items: start;
}
@media (min-width: 620px) { .bkv3-strip { grid-template-columns: repeat(6, 1fr); } }
.bkv3-strip img {
  width: 100%; height: auto; aspect-ratio: 16 / 10; object-fit: cover; display: block;
  border-radius: var(--r-2); border: 1px solid var(--line); background: var(--bg-sunken);
}

/* ══ YOUR SHOOT — the order rail ═════════════════════════════════════════ */
.bkv3-rail .ad-sec-b { padding-top: var(--sp-1); }
.bkr-lines { list-style: none; margin: 0; padding: 0; display: grid; gap: 7px; }
.bkr-lines li { display: flex; justify-content: space-between; gap: var(--sp-3); font-size: calc(13.5px * var(--text-scale, 1)); }
.bkr-lines li > span:first-child { font-weight: 600; letter-spacing: -.01em; min-width: 0; }
.bkr-lines .n { font-weight: 500; font-variant-numeric: tabular-nums; color: var(--ink-2); white-space: nowrap; }
.bkr-lines li.is-sub { padding-left: 12px; }
.bkr-lines li.is-sub > span:first-child { font-weight: 400; color: var(--ink-3); }
.bkr-lines li.is-when > span:first-child { font-weight: 500; color: var(--ink-2); }
.bkr-empty { margin: 0; font-size: calc(13px * var(--text-scale, 1)); color: var(--ink-3); line-height: 1.5; }

.bkr-sums { margin: var(--sp-3) 0 0; padding-top: var(--sp-3); border-top: 1px solid var(--line); display: grid; gap: 6px; }
.bkr-row { display: flex; justify-content: space-between; gap: var(--sp-3); font-size: calc(13px * var(--text-scale, 1)); color: var(--ink-3); }
.bkr-row .n { font-variant-numeric: tabular-nums; color: var(--ink-2); }
/* Dom 2026-08-30: the pre-tax number is the one to read first */
.bkr-row.is-subtotal { color: var(--ink-2); }
.bkr-row.is-subtotal .n { font-size: calc(17px * var(--text-scale, 1)); font-weight: 650; color: var(--ink); }
.bkr-row.is-total {
  margin-top: 4px; padding-top: 8px; border-top: 1px solid var(--line);
  font-size: calc(14px * var(--text-scale, 1)); font-weight: 600; color: var(--ink);
}
.bkr-row.is-total .n { font-size: calc(19px * var(--text-scale, 1)); font-weight: 700; letter-spacing: -.03em; color: var(--ink); }
.bkr-fine { margin: var(--sp-2) 0 0; font-size: calc(12px * var(--text-scale, 1)); color: var(--ink-3); line-height: 1.5; }
.bkr-cta { margin-top: var(--sp-3); display: grid; gap: var(--sp-2); }
.bkr-cta .ad-btn { width: 100%; }
/* Dom 2026-08-23: white elements on the red buttons — text AND icon. */
.bkr-cta .ad-btn-primary, .bkr-cta .ad-btn-primary .bki { color: var(--brand-ink); }
.bkr-cta .ad-btn .bki { width: 15px; height: 15px; margin-left: 6px; }
.bkr-miss { margin: 0; font-size: calc(12px * var(--text-scale, 1)); color: var(--ink-3); line-height: 1.5; }

/* ══ shared icon glyph ═══════════════════════════════════════════════════ */
.bkv3 .bki {
  display: inline-block; vertical-align: middle;
  fill: none; stroke: currentColor; stroke-width: 1.7;
  stroke-linecap: round; stroke-linejoin: round;
}
.bkl-pop .bki { fill: none; stroke: currentColor; stroke-width: 1.7; stroke-linecap: round; stroke-linejoin: round; }


/* Per-photo quantity (Dom 2026-08-24): staging/twilight cards carry a count
   dropdown. It lives on the BLACK back now and is ALWAYS available there
   (Dom 2026-08-29) — on the front it only rendered once the card was already
   added, and since refresh() repaints in place it never actually appeared.
   House-styled select, 44px target, on the black face's palette. */
.bks-qtyrow {
  display: grid; gap: 6px;
  margin-top: var(--sp-3); padding-top: var(--sp-3);
  border-top: 1px solid var(--bkc-black-line);
  font: 500 calc(12.5px * var(--text-scale, 1))/1.2 var(--font-sans); color: var(--bkc-black-ink-2);
}
.bks-qtyrow select {
  width: 100%; min-height: 40px; padding: 0 10px;
  background: rgba(244,244,244,.06); color: var(--bkc-black-ink);
  border: 1px solid var(--bkc-black-line); border-radius: var(--r-2);
  font: 600 calc(13px * var(--text-scale, 1))/1 var(--font-sans);
}
.bks-qtyrow select option { background: var(--bkc-black); color: var(--bkc-black-ink); }
.bks-qtyrow select:focus-visible { outline: 2px solid var(--brand); outline-offset: 1px; }


/* ══════════════════════════════════════════════════════════════════════════
   GRAPEVINE — the same screen, the GV catalogue (views/agent-book-gv.js).
   Dom 2026-08-29: "GV get the same pricing as on their booking flow… replace
   the services with what we have on our GV booking site and leave whatever is
   left", and the flip cards "identical on both ends so we dont have
   discrepencies."

   So there is NO new card here. The GV screen draws `.bks` — the same component
   as /book-shoot's singles — and the only additions below are the two states
   the CS screen has no use for: a COVERED tile (no Add, because there is
   nothing to add) and the builder's-plan swap toggle on the Floor Plan back.
   The purple is the tenant skin doing its job through --brand (html.is-gv,
   tokens.css); not one colour is written down here.
   ══════════════════════════════════════════════════════════════════════════ */

.gv-lede {
  margin: 0 0 var(--sp-4);
  font-size: calc(13.5px * var(--text-scale, 1)); line-height: 1.55; color: var(--ink-2);
  text-wrap: pretty;
}

/* ── a COVERED tile: included, still worth turning over ─────────────────────
   No ring and no tinted border — a covered card is not a SELECTED card, and
   six brand-edged tiles in a row read as six things the agent just clicked.
   The badge carries the state, and the card keeps its ordinary hover. */
.bks.is-covered .bks-p { font-weight: 600; letter-spacing: -.01em; color: var(--ink-2); }
/* A covered/carried card's foot is the word alone — the corner pip is the
   at-a-glance state, and a second badge repeating it truncated the word at 375
   (measured 2026-08-29). Kept as a class for the agency "Included" pill. */
.bks.is-covered .bks-foot, .bks.is-package .bks-foot { min-height: 38px; align-items: center; }
/* the builder's-plan swap, showing on the front */
.bks.is-swapped .bks-p { color: var(--ink-3); }

/* ── DIRECT MANIPULATION on the card front (Dom 2026-08-29) ───────────────
   Dom: "instead of reinventing do what we already have on GV booking page",
   and on the floor-plan swap: "deselecting is easier than clicking on the flip
   card to select builder floor plan — a bit badly planned."

   So the GV card front is the control, exactly as the live GV tile is
   (gv-4.28.10.js l.1519-1534: the whole `.svc` is role=button and one tap
   toggles). Three pieces, all mirroring that tile:
     .bks-hit    the stretched toggle   ← the tile's own click handler
     .bks-x      the corner + / − / ✓   ← the tile's `<span class="x">` (l.1953)
     .bks-qtybar the inline − n + row   ← the tile's `.qty` (l.1971), shown
                                          only once the service is on (l.1732)
   The flip survives as `.bks-info`, an explicit small target, because our card
   carries the long description the GV tile prints inline. No control is ever
   reachable only by turning the card. */
.bks-hit {
  position: absolute; inset: 0; z-index: 2;
  margin: 0; padding: 0; border: 0; background: none; cursor: pointer;
  border-radius: var(--r-2) var(--r-2) 0 0;
}
.bks-hit:focus-visible { outline: 2px solid var(--brand); outline-offset: -2px; }

/* The corner pip. A span inside the hit area — never a button, which would be
   a button inside a button. The glyph is CSS content keyed off the state, the
   way the GV tile does it (l.1954-1955, l.1982). */
.bks-x {
  position: absolute; top: 8px; right: 8px; z-index: 3;
  width: 26px; height: 26px; border-radius: 50%;
  display: grid; place-items: center;
  font: 600 15px/1 var(--font-sans);
  background: rgba(10,10,10,.72); color: #FFFFFF;
  border: 1px solid rgba(255,255,255,.18);
  pointer-events: none;
  transition: background var(--t-fast) var(--ease), color var(--t-fast) var(--ease);
}
.bks-x[data-badge="add"]::before     { content: "+"; }
.bks-x[data-badge="on"]::before      { content: "\2212"; }   /* − */
.bks-x[data-badge="covered"]::before { content: "\2713"; font-size: 13px; }  /* ✓ */
.bks-x[data-badge="swap"]::before    { content: "\21BA"; font-size: 14px; }  /* ↺ take ours back */
.bks-x[data-badge="on"], .bks-x[data-badge="covered"] {
  background: var(--brand); color: var(--brand-ink); border-color: transparent;
}
.bks-x[data-badge="swap"] { background: var(--ink); color: var(--bg); border-color: transparent; }

/* The flip, demoted to an explicit affordance so the front can toggle.
   A 44px HIT BOX around a 26px circle — the GV tile's own arrangement for its
   corner control (l.1953-1954: a 44×44 `.x` whose `:before` is the 28px pill),
   and the shape that satisfies this portal's coarse-pointer touch law
   (main.css:8889, 44px minimum on every button) without a `.tap-exempt`
   escape hatch and without the button rendering as a 26×44 oval. */
.bks-info {
  position: absolute; top: 0; left: 0; z-index: 3;
  width: 44px; height: 44px; min-height: 44px; padding: 0;
  display: grid; place-items: center;
  border: 0; background: none; color: #FFFFFF; cursor: pointer;
}
.bks-info::before {
  content: ''; position: absolute; width: 26px; height: 26px; border-radius: 50%;
  background: rgba(10,10,10,.72); border: 1px solid rgba(255,255,255,.18);
  transition: background var(--t-fast) var(--ease);
}
.bks-info:hover::before { background: rgba(10,10,10,.92); }
.bks-info:focus-visible { outline: 2px solid var(--brand); outline-offset: -8px; border-radius: 50%; }
.bks-info .bki { position: relative; width: 14px; height: 14px; }

/* The inline quantity stepper — front, under the toggle's hit area so its own
   buttons are reachable, hidden until the service is on. */
.bks-qtybar {
  display: flex; align-items: center; justify-content: space-between; gap: var(--sp-2);
  padding: 8px 11px; flex: none;
  border-top: 1px solid var(--line);
}
.bks-qtybar[hidden] { display: none; }
.bks-qlab { font: 500 calc(12px * var(--text-scale, 1))/1.2 var(--font-sans); color: var(--ink-3); }
.bks-qctl { display: inline-flex; align-items: center; gap: 6px; }
/* 44px, so the coarse-pointer law (main.css:8889) lands on a CIRCLE rather
   than stretching a 30px button into a 30×44 oval. GV's own stepper is 40
   (l.1972); 44 is that shape at this product's touch minimum. */
.bks-qctl button {
  flex: none;   /* never shrink into an oval in a narrow card */
  width: 44px; height: 44px; min-height: 44px; padding: 0; border-radius: 50%;
  border: 1px solid var(--line-strong); background: var(--bg); color: var(--ink);
  font: 600 15px/1 var(--font-sans); cursor: pointer;
  transition: background var(--t-fast) var(--ease), border-color var(--t-fast) var(--ease);
}
.bks-qctl button:hover { background: var(--bg-hover); border-color: var(--brand); }
.bks-qctl button:focus-visible { outline: 2px solid var(--brand); outline-offset: 2px; }
.bks-qv {
  min-width: 16px; text-align: center;
  font: 700 calc(13.5px * var(--text-scale, 1))/1 var(--font-sans);
  font-variant-numeric: tabular-nums; color: var(--ink);
}

/* A narrow card's foot must never let the price and the control collide —
   measured at 375 on 2026-08-29.
   REVERSED 2026-08-30 (Dom: "shows $17 please never cut prices"). The money
   used to be what gave way: `overflow:hidden; text-overflow:ellipsis` turned
   "$175 + HST" into "$17…". A price is not a label — a clipped one is WRONG,
   not merely tight. So the number is now rigid and the FOOT is what gives way:
   it wraps, and under 460 it stacks outright (rule at the foot of this file). */
.bks .bks-p { min-width: 0; overflow: visible; text-overflow: clip; flex: none; }
.bks .bks-add { flex: none; }
.bks .bks-foot { flex-wrap: wrap; }

/* ── the anchor price on an add-on card ────────────────────────────────── */
.bks-p s { font-weight: 500; color: var(--ink-4); margin-right: 3px; }
.bkp-back .bks-p s { color: rgba(244,244,244,.42); }

/* ── the rail's covered-set summary ────────────────────────────────────── */
.gv-covered-line {
  display: flex; align-items: flex-start; gap: 7px;
  margin: var(--sp-3) 0 0; padding-top: var(--sp-3); border-top: 1px solid var(--line);
  font-size: calc(12px * var(--text-scale, 1)); line-height: 1.5; color: var(--ink-3);
}
.gv-covered-line .bki { width: 13px; height: 13px; flex: none; margin-top: 2px; color: var(--brand); }
.gv-covered-line b { color: var(--ink-2); font-weight: 600; }

/* "optional" beside a field label — the label row is already uppercase meta,
   so this is the same row at a lighter weight, not a second type style. */
.bkv3 .bk-f > span i { font-style: normal; font-weight: 400; color: var(--ink-4); }

/* The GV screen's polite live region — gv-4.28.10.js announce() (l.1488). A tap
   that only moves a corner pip still has to be audible. Off-screen, never
   display:none, or a screen reader stops announcing it. */
.gv-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;
}

/* At 375 a 2-up service card is ~127px wide, and a foot carrying "$225 $175
   + HST" beside an Add button cannot fit both — measured in the browser
   2026-08-29. The money takes its own row and the control goes full width,
   which is the ordinary mobile answer and keeps every price readable.
   Dom 2026-08-30: /book-shoot's own singles (#bk-singles) get the SAME answer.
   The note that used to sit here — "the /book-shoot singles are an approved
   screen this lane does not own" — is spent: Dom's punch list put that grid in
   this lane, and it is a 2-up at 375 with the identical collision. */
@media (max-width: 460px) {
  #bk-singles .bks-foot,
  #gv-included .bks-foot, #gv-addons .bks-foot, #gv-extras .bks-foot {
    flex-direction: column; align-items: stretch; gap: 0;
  }
  #bk-singles .bks-p,
  #gv-included .bks-p, #gv-addons .bks-p, #gv-extras .bks-p {
    padding: 8px 11px 0; overflow: visible; text-overflow: clip;
  }
  #bk-singles .bks-add,
  #gv-included .bks-add, #gv-addons .bks-add, #gv-extras .bks-add {
    justify-content: space-between; width: 100%;
  }
  #gv-included .bks-qtybar, #gv-addons .bks-qtybar, #gv-extras .bks-qtybar {
    flex-direction: column; align-items: stretch; gap: 6px;
  }
  #gv-addons .bks-qctl, #gv-extras .bks-qctl { justify-content: space-between; }
}


/* Dom 2026-08-30: "shows $17 please never cut prices" — a money figure never
   ellipsizes. The pill grows or the row wraps around it; the number is whole.
   The selector list is the classes agent-book.js ACTUALLY emits: `.bkp-amt`,
   `.bkp-was`, `.bks-p`. It previously named `.bkp-price` and `.bkp-amount`,
   neither of which this screen renders, so the rule guarded nothing and the
   real price line was still being ellipsized by the `.bks .bks-p` rule above. */
.bkp-amt, .bkp-was, .bks-p, .bkp-foot b {
  white-space: nowrap; overflow: visible; text-overflow: clip; flex: none;
}
/* The price row itself may wrap around the number; the number may not break. */
.bkp-meta { min-width: 0; }

/* At 4-up a single card is ~200px on a 900px main column. Long copy has to WRAP
   there, not squeeze the track or push the price out: a grid track sized
   `minmax(0, 1fr)` cannot be widened by its content, so an unbreakable string
   would otherwise overflow the card. Nothing here is a new type style — it is
   the wrapping behaviour the existing type needs at this width. */
.bks-name, .bks-lines li, .bks-desc, .bkp-name, .bkp-item {
  min-width: 0; overflow-wrap: anywhere; text-wrap: pretty;
}

/* ══ ADDRESS AUTOCOMPLETE ═════════════════════════════════════════════════
   Dom 2026-08-30: "address suggestions are different than in other our
   places... drop down?" The component (components/address-input.js) is styled
   by cs-shell.css on cockpit pages; this page never loads that sheet, so the
   list rendered as bare inline buttons stacked in the flow.

   ANATOMY = the live site's `.addr-sugg` (capitalshots.ca/book l.278-284),
   which is the Places-style panel every CS surface shows:
     · absolutely positioned, pinned to BOTH edges of the field, 6px below it
     · one panel, `overflow:hidden`, so the rows clip to its radius
     · rows are full-width buttons, left-aligned, generous padding
     · hover and the keyboard cursor are the SAME background
   Two-line rows are ours, not the site's — our endpoint returns Places'
   structured `main`/`secondary`, and showing the street on its own line above a
   muted city line is what the cockpit already does. Every colour here is a
   portal token: no site yellow, no site emerald, no literal fallbacks.

   `.bk-f` is already `position: relative` (agent-dash.css l.1049), so this
   needs no `:has()` to establish the containing block.

   THE CLIP WAS HALF THE COMPLAINT. `.ad-sec` is `overflow: hidden` so a section
   card clips to its own radius (agent-dash.css l.40-45), and the dropdown is a
   child of that card — so it was being guillotined at the card's bottom edge:
   three suggestions rendered, roughly one and a bit were visible. Measured in
   the browser 2026-08-30 (list 175px tall inside a 148px card).

   Only the ADDRESS section opts out, by its own class. It holds fields, a
   button and a note — nothing that needs clipping to the radius — so nothing
   else on this screen or any other changes. The alternative, rendering the
   panel into <body> the way `.bkl-pop` does, buys nothing here: that panel
   escapes a rotateY face, this one only has to leave a card. ── */
.bkv3 .bkv3-sec-addr { overflow: visible; }
.bk-addr-list {
  display: none; position: absolute; top: calc(100% + 6px); left: 0; right: 0; z-index: 60;
  max-height: 320px; overflow: hidden auto;
  background: var(--bg-elevated); color: var(--ink);
  border: 1px solid var(--line); border-radius: var(--r-2);
  box-shadow: var(--shadow-3);
}
.bk-addr-list.is-open { display: block; }
/* WHY `flex-wrap` AND NOT JUST `display:block`. main.css's coarse-pointer law
   forces `display:inline-flex; align-items:center; min-height:44px` onto every
   button, at a specificity no class selector here can reach
   (`body:not(:has(#app-nav.cs-sidebar)) :is(button,…)` — roughly 1-4-2). Its
   guard is the COCKPIT's sidebar, which /book-shoot does not render, so on this
   page the law applies and it laid the street and the city out SIDE BY SIDE —
   "2179 Erinbrook CrescentOttawa, ON, Canada". On the cockpit pages the sidebar
   suppresses the law, `display:block` survives, and the same component stacks
   properly. That is exactly Dom's "different than in other our places".

   Rather than fight with !important, this works with the law: main.css sets no
   `flex-wrap`, so `wrap` here wins uncontested, and two full-width children in
   a wrapping flex row stack. Both paths now stack — the flex one by wrapping,
   the block one by `display:block` — so the rows read the same on every page
   whether that law applies or not, and the 44px touch target is kept. */
.bk-addr-list button {
  display: block; width: 100%; margin: 0; padding: 10px 14px;
  flex-wrap: wrap;
  text-align: left; font: inherit; cursor: pointer;
  border: 0; border-bottom: 1px solid var(--line);
  background: transparent; color: var(--ink);
  transition: background var(--t-fast) var(--ease);
}
.bk-addr-list button:last-child { border-bottom: 0; }
.bk-addr-list button:hover, .bk-addr-list button.is-on { background: var(--bg-hover); }
.bk-addr-list button:focus-visible { outline: 2px solid var(--brand); outline-offset: -2px; }
/* The street. It is the line a person reads, so it never truncates to an
   ellipsis mid-number — it wraps. */
.bk-addr-list .csaddr-main {
  display: block; width: 100%; font-weight: 600; line-height: 1.3;
  font-size: calc(14px * var(--text-scale, 1)); letter-spacing: -.01em;
  overflow-wrap: anywhere;
}
/* City / province, quiet, under it. */
.bk-addr-list .csaddr-sec {
  display: block; width: 100%; margin-top: 2px; line-height: 1.35;
  font-size: calc(12.5px * var(--text-scale, 1)); color: var(--ink-3);
  overflow-wrap: anywhere;
}


/* ══════════════════════════════════════════════════════════════════════════
   DATE AND TIME — the site's date pager anatomy, on portal tokens.
   Dom 2026-08-30: "Cal looks different than on our CS site."

   THE COMPONENT IS NOT REPLACED. /book-shoot mounts `mountInlineCal` from
   components/cs-minical.js (agent-book.js l.1559) and that mount is used by
   NOTHING ELSE in the product, so `.csmc-inline` is a private scope: the field
   picker (`.csmc-pop`) and the Calendar page's panel (`.csmc-panel`) keep the
   approved skin in cs-minical.css untouched. No new library, no second grid.

   WHAT THE SITE ACTUALLY DOES (capitalshots.ca/book, `.pager` / `.pday`,
   l.601-624 + l.2081-2115) and what it becomes here:

     site                                        here
     ─────────────────────────────────────────── ───────────────────────────
     day cell is a filled ROUNDED TILE            same, --bg-sunken + --line
       (.pday, radius 8, background var(--ink),     hairline
        inset hairline) — NOT a bare numeral
     cell is a flex COLUMN: numeral + a small     same: .csmc-n over .csmc-dots
       sub-label under it (.pday__d/.pday__m)       (our open-day marker)
     7 FLUID columns, 5px gap, Monday-start       same, repeat(7,minmax(0,1fr))
     weekday header is its own row above          same, .csmc-dow
     SELECTED = FILLED accent tile, contrast ink  filled --brand, #FFF ink
     TODAY (unselected) = a RING, no fill         ring, no fill
     disabled/past = fill REMOVED + faded         same
     hover only on available days                 same
     month title LEFT, both arrows grouped RIGHT  same, via order/margin
     prev DISABLED at the current month           same (cs-minical.js paint())
     bounded block (.pager max-width 620)         the .bk-when column bounds it

   COLOUR (rewritten 2026-08-30): --brand IS the site's emerald now, and Dom
   ruled the select caret back onto the site's `#fff083` butter (--accent-butter,
   on .bkl-btn only, where it sits on the black back face). Every neutral is
   still the portal's own ladder. There is no pinned #FFFFFF left: type on a
   brand fill reads --brand-ink, which is near-black on emerald and white under
   the GV grape skin.

   TODAY stays RED, but as the RING rather than a filled disc: the fill is the
   grammar the site reserves for the day you picked, and red is the portal's
   meaning for "today". Anatomy from the site, colour from our tokens.
   ══════════════════════════════════════════════════════════════════════════ */

/* The calendar is no longer a fixed 244px object, so the column that holds it
   is no longer sized by one. agent-dash.css l.1094 belongs to another lane —
   this sheet loads after it and overrides only for this screen. */
@media (min-width: 720px) {
  .bkv3 .bk-when { grid-template-columns: minmax(0, 340px) minmax(0, 1fr); }
}
.bkv3 .csmc-inline { width: 100%; max-width: 100%; }

/* ── ‹ Month YYYY ›  title left, arrows grouped right ───────────────────── */
.csmc-inline .csmc-head { justify-content: flex-start; gap: 6px; margin-bottom: 10px; }
.csmc-inline .csmc-title {
  order: 0; margin-right: auto;
  font-size: calc(15px * var(--text-scale, 1)); font-weight: 700; letter-spacing: -.015em;
}
.csmc-inline .csmc-nav[data-step="-1"] { order: 1; }
.csmc-inline .csmc-nav[data-step="1"]  { order: 2; }
/* The site's chevrons are 34px. Ours stay 40: main.css enforces a 44px minimum
   on every button under a coarse pointer, and a 34px square would be stretched
   into a 34×44 oval on touch — the "yo-yo shape" this component exists to
   prevent. Square, hairline, no fill is the anatomy; 40 is our scale for it. */
.csmc-inline .csmc-nav { border-radius: var(--r-2); }
.csmc-inline .csmc-nav:disabled { opacity: .3; cursor: default; }
.csmc-inline .csmc-nav:disabled:hover { background: none; color: var(--ink-3); }

/* ── the grid: 7 fluid tracks, one 5px gutter in both directions ────────── */
.csmc-inline .csmc-dow,
.csmc-inline .csmc-row {
  grid-template-columns: repeat(7, minmax(0, 1fr));
  gap: 5px; justify-content: stretch;
}
.csmc-inline .csmc-grid { display: grid; gap: 5px; }
.csmc-inline .csmc-dow {
  margin-bottom: 6px;
  font-size: calc(10px * var(--text-scale, 1)); font-weight: 600;
}
/* The site's pager has no week band, and behind a row of filled tiles a band
   reads as a paint bug rather than as orientation. Off here only — the
   Calendar page's panel still bands the week it is showing. */
.csmc-inline .csmc-row.is-band { background: none; }

/* ── a day: the TILE ────────────────────────────────────────────────────── */
.csmc-inline .csmc-day {
  width: 100%; height: auto; min-height: 34px;
  justify-content: center; gap: 2px; padding: 4px 2px;
  border-radius: var(--r-2);
  background: var(--bg-sunken);
  box-shadow: inset 0 0 0 1px var(--line);
  transition: background var(--t-fast) var(--ease),
              color var(--t-fast) var(--ease),
              box-shadow var(--t-fast) var(--ease);
}
/* The numeral is plain type on the tile now — the 22px disc was the OLD cell's
   only shape, and inside a tile it reads as a box inside a box. */
.csmc-inline .csmc-n {
  width: auto; height: auto; border-radius: 0; background: none;
  font-size: calc(13px * var(--text-scale, 1)); font-weight: 600;
}
/* …so the base sheet's disc-hover must not paint a pill behind it.
   Hover is only offered to a device that HAS one: on touch a :hover state
   sticks to the last tile tapped, and a stuck highlight beside the real
   selection reads as two chosen days. The site guards its own the same way
   (`.pday:hover:not([disabled])` on a pointer device).

   The pill-neutraliser itself stays UNGUARDED: cs-minical.css paints it on
   `:hover` with no pointer guard of its own, and a tap can leave that state
   behind, so it has to be cancelled on every device. */
.csmc-inline .csmc-day:hover .csmc-n { background: none; }
@media (hover: hover) {
  .csmc-inline .csmc-day:not(.is-off):hover {
    background: var(--bg-hover);
    box-shadow: inset 0 0 0 1px var(--line-strong);
  }
}
.csmc-inline .csmc-day:focus-visible { border-radius: var(--r-2); }

/* TODAY — a ring, never a fill. The fill belongs to the day you picked.
   (The ring itself is re-stated after the muted-day block below, which would
   otherwise strip it — see the note there.) */
.csmc-inline .csmc-day.is-today .csmc-n,
.csmc-inline .csmc-day.is-today:hover .csmc-n { background: none; color: inherit; font-weight: 700; }

/* THE DAY YOU PICKED — the one filled tile in the grid. */
.csmc-inline .csmc-day.is-sel,
.csmc-inline .csmc-day.is-sel:hover {
  background: var(--brand); color: var(--brand-ink); box-shadow: none;
}
.csmc-inline .csmc-day.is-sel:hover { background: var(--brand-deep); }
.csmc-inline .csmc-day.is-sel .csmc-n {
  color: var(--brand-ink); font-weight: 700; background: none; box-shadow: none;
}
/* The open-day marker sits ON the red tile once that day is chosen, so it has
   to change ink or it disappears into it. The dot's colour is written by the
   JS as an inline style, which is the one case `!important` is the only lever. */
.csmc-inline .csmc-day.is-sel .csmc-dot { background: var(--brand-ink) !important; }

/* Not this month, and days we cannot sell: the tile itself goes away, which is
   the site's own treatment (`.pday[disabled]{background:transparent}`). Ours
   fades to .38 rather than the site's .28 — the numeral still has to be
   READABLE on our lighter ground, a muted day is not a hidden one.

   `:not(.is-sel)` is load-bearing. The grid renders trailing days of the next
   month, and an open one of those is pickable — so the day you chose can BE an
   out-of-month cell. Without the guard this reset (later in the file, same
   specificity) stripped the red fill straight back off it and left white
   numerals on nothing: the picked day rendered invisible. Measured in the
   browser 2026-08-30, viewing August with September 3 selected. */
.csmc-inline .csmc-day.is-out:not(.is-sel),
.csmc-inline .csmc-day.is-off:not(.is-sel),
.csmc-inline .csmc-day.is-off:not(.is-sel):hover {
  background: none; box-shadow: none;
}
.csmc-inline .csmc-day.is-off:not(.is-sel) { opacity: .38; cursor: default; }
.csmc-inline .csmc-day.is-today.is-off .csmc-n { background: none; color: inherit; }

/* TODAY'S RING, re-stated so the reset above cannot take it. The site keeps it
   on a disabled day too (`.pday[disabled]` clears the background, never the
   box-shadow) and that is right: "today" is ORIENTATION, not an offer. On a day
   with no open slot it simply fades with the rest of the cell. Equal
   specificity to the reset, so it has to sit after it. */
.csmc-inline .csmc-day.is-today:not(.is-sel) { box-shadow: inset 0 0 0 1px var(--brand); }

/* ── the summary line under the grid ("N days open in the next four weeks").
   Ours, not the site's, and it stays: it is the only thing on the screen that
   says how much room there is before you click a day. Set as the site sets its
   hints — quiet, left, under the block. ── */
.csmc-inline .csmc-foot {
  margin-top: 10px; padding-top: 10px; text-align: left;
  font-size: calc(12px * var(--text-scale, 1));
}


/* ══════════════════════════════════════════════════════════════════════════
   GRAPEVINE, SECOND PASS — the GV catalogue on the PACKAGE card.
   Dom 2026-08-30, on a screenshot of /book-shoot for a Grapevine agent:
   "looks cheaply designed now."

   WHAT CHANGED, AND WHAT DID NOT. The GV screen drew `.bks`, the SMALL card,
   four to a row: a $175 3D tour and a 45-photo kit were both announced on a
   ~200px chip. views/agent-book-gv.js now draws the `.bkp` PACKAGE anatomy —
   the same one /book-shoot's bundles use, class for class, in `.bkp-grid`
   (3-up at 980, 2-up at 620, single column under that).

   SO THERE IS NO NEW CARD HERE EITHER. Everything above this block is
   untouched: not one `.bkv3`, `.bkp*`, `.bks*` or `.bkl*` base rule was
   edited, and `#bk-singles` — the CS singles grid a sibling lane is working
   in — is not named once below. Every selector here is scoped to the three GV
   grids by id.

   WHAT IS ACTUALLY IN THIS BLOCK: the four places the GV-only front controls
   (.bks-hit / .bks-x / .bks-info / .bks-qtybar) need the bigger card's radius
   and padding, the selected ring the package card paints as an inset shadow
   (which the media covers), and the covered tile's word in the price slot.

   COLOUR: not one value. The purple is html.is-gv driving --brand (tokens.css);
   red never appears on a Grapevine surface and no grape is written down.
   ══════════════════════════════════════════════════════════════════════════ */

/* HEIGHT. The package card's 380px floor is sized for a CS bundle's four or
   five inclusion rows; a GV tile carries ONE line, so at 380 the covered cards
   came out with ~120px of empty band between the copy and the price row —
   measured in the browser 2026-08-30. 320 is this sheet's own number for a
   card of this content (`.bks .bkp-flip`), and it is a FLOOR, not a height:
   `.bkp-grid` still stretches every card in a row to the tallest, so an add-on
   with a quantity stepper keeps setting its row. */
#gv-included .bkp-flip,
#gv-addons .bkp-flip,
#gv-extras .bkp-flip { min-height: 320px; }

/* Animated service thumbs (SVC_VID) in the package media band. `.bkp-media img`
   is styled above; the site's own card has no video, ours does. */
#gv-included .bkp-media video,
#gv-addons .bkp-media video,
#gv-extras .bkp-media video { width: 100%; height: 100%; object-fit: cover; display: block; }

/* The stretched toggle takes the PACKAGE card's radius (--r-3), not the small
   card's. Same shape as `.bkp-turn`, which it replaces on a toggleable tile. */
#gv-included .bks-hit,
#gv-addons .bks-hit,
#gv-extras .bks-hit { border-radius: var(--r-3) var(--r-3) 0 0; }

/* THE SELECTED RING. `.bkp.is-on .bkp-face` paints it as an INSET shadow, and
   on a card whose first child is a full-bleed photo the media sits on top of it
   (Dom 2026-08-24, on the CS side: "photo is on top of the outline"). The small
   card solved this with an ::after on the article, outside the preserve-3d
   stack; the same answer, at the package card's radius. */
#gv-included .bkp.is-on .bkp-face,
#gv-addons .bkp.is-on .bkp-face,
#gv-extras .bkp.is-on .bkp-face { box-shadow: var(--shadow-1); }
#gv-included .bkp.is-on::after,
#gv-addons .bkp.is-on::after,
#gv-extras .bkp.is-on::after {
  content: ''; position: absolute; inset: 0; pointer-events: none; z-index: 3;
  border: 2px solid var(--brand); border-radius: var(--r-3);
}

/* A COVERED tile is not a SELECTED tile — it never gets the ring, and its price
   slot carries a WORD. At `.bkp-amt`'s 21px/700 "Included" shouts; this is the
   same slot, read as a state rather than as money. */
#gv-included .bkp.is-covered .bkp-amt {
  font-size: calc(15px * var(--text-scale, 1)); font-weight: 600;
  letter-spacing: -.01em; color: var(--ink-2);
}
#gv-included .bkp.is-covered .bkp-back .bkp-amt { color: var(--bkc-black-ink); }
#gv-included .bkp.is-swapped .bkp-amt { color: var(--ink-3); }

/* The inline − n + row sits between the price row and the action, so it takes
   the package card's gutter rather than the small card's 11px. */
#gv-addons .bks-qtybar,
#gv-extras .bks-qtybar { padding: 8px var(--bkc-pad); }

/* SAFETY NET, not a layout: a long description plus a dropdown on the black
   face must never be guillotined by `.bkp-face { overflow: hidden }`. The face
   scrolls only if it has to; at every measured length it does not. */
#gv-included .bkp-back,
#gv-addons .bkp-back,
#gv-extras .bkp-back { overflow-y: auto; }

/* At 375 a single-column card is the full width, so the price row has room —
   the 460px stack the small card needed does not apply to `.bkp-meta`, which
   is already a wrapping baseline row. Nothing to add. */
