/* XkroX Business Profile / Storefront — the reusable storefront
   presentation layer (XkroX Product UX, Stage UX1, 2026-09-08).
   Storefront Generation Stage S1 (2026-09-08) — CORRECTION ROUND: rebuilt
   from an onboarding-preview-card treatment into a real generated
   commerce website. See docs/xkrox_storefront_generation_s1_report.md.

   Consumed by the merchant onboarding split workbench's LEFT pane today;
   architected to become the SAME renderer a real public /business/{slug}
   route uses later — no onboarding-only shortcuts, no admin controls
   baked into the public-mode markup.

   Theme: driven entirely by the existing --pv-* custom properties
   (_ocPresentationVars() in onboarding/render.js). This file never
   hardcodes a brand color — only STRUCTURE, TYPOGRAPHY, and SPACING, so
   the same markup looks right under any presentation config. The
   no-config DEFAULT is now light/warm-editorial (render.js's own
   comment), never a black slab. */

.bp-root, .bp-detail {
  --bp-bg: var(--pv-bg, #fbf9f5);
  --bp-text: var(--pv-text, #17160f);
  --bp-muted: var(--pv-muted, #6f6a5c);
  --bp-card: var(--pv-card, #f2efe7);
  --bp-border: var(--pv-border, #e6e1d3);
  --bp-accent: var(--pv-accent, #17160f);
  --bp-radius: var(--pv-radius, 2px);
  --bp-serif: 'Fraunces', Georgia, 'Times New Roman', serif;
  --bp-sans: var(--pv-font, Inter, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif);
}

.bp-root {
  /* Storefront S2 §2 — page-background IMAGE mode. --pv-bg-image is
     `none` unless the merchant has actually chosen a real photo AND
     'photo-tint' — layering a contrast-safe scrim (--pv-bg-scrim, light
     or dark depending on appearance) UNDER it in the same declaration so
     foreground text always stays readable, no extra overlay element
     needed. Falls back to the flat --bp-bg exactly as before when unset. */
  background-color: var(--bp-bg);
  background-image: linear-gradient(var(--pv-bg-scrim, transparent), var(--pv-bg-scrim, transparent)), var(--pv-bg-image, none);
  background-size: cover;
  background-position: center;
  background-repeat: no-repeat;
  background-attachment: fixed;
  color: var(--bp-text);
  font-family: var(--bp-sans);
  min-height: 100%;
  width: 100%;
  box-sizing: border-box;
  position: relative;
}
.bp-root, .bp-root * { box-sizing: border-box; }
.bp-root a { text-decoration: none; color: inherit; }

/* ── Header — real commerce navigation ──────────────────────────────── */
.bp-header {
  display: flex; align-items: center; gap: clamp(16px, 3vw, 40px);
  padding: 20px clamp(20px, 4vw, 56px);
  border-bottom: 1px solid var(--bp-border);
  position: sticky; top: 0; background: var(--bp-bg); z-index: 4;
}
.bp-header-id { display: flex; align-items: center; gap: 10px; flex: none; }
.bp-logo {
  width: 30px; height: 30px; border-radius: 999px; flex: none;
  display: flex; align-items: center; justify-content: center;
  background: var(--bp-accent); color: var(--bp-bg);
  font-family: var(--bp-serif); font-size: 13px; font-weight: 600;
  overflow: hidden;
}
.bp-logo img { width: 100%; height: 100%; object-fit: cover; }
.bp-header-name {
  font-family: var(--bp-serif); font-size: 17px; font-weight: 500;
  letter-spacing: -.005em; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.bp-hnav { display: flex; align-items: center; gap: clamp(14px, 2.4vw, 28px); flex: 1 1 auto; min-width: 0; overflow-x: auto; scrollbar-width: none; }
.bp-hnav::-webkit-scrollbar { display: none; }
.bp-hnav-link {
  font-size: 13px; color: var(--bp-muted); white-space: nowrap; padding: 4px 0;
  border-bottom: 1.5px solid transparent;
}
.bp-hnav-link:hover, .bp-hnav-link[aria-current="true"] { color: var(--bp-text); }
.bp-header-actions { display: flex; align-items: center; gap: 16px; flex: none; margin-left: auto; }
.bp-ask {
  border: none; background: none; color: var(--bp-muted); font-size: 12.5px;
  cursor: pointer; padding: 0; white-space: nowrap;
}
.bp-ask:hover { color: var(--bp-text); }
.bp-cart {
  position: relative; display: inline-flex; align-items: center; color: var(--bp-text);
  background: none; border: none; padding: 4px; margin: 0; cursor: pointer; font: inherit;
}
.bp-cart[data-empty="true"] { color: var(--bp-muted); }
.bp-cart-count {
  position: absolute; top: -7px; right: -9px; min-width: 15px; height: 15px; padding: 0 3px;
  border-radius: 999px; background: var(--bp-accent); color: var(--bp-bg);
  font-size: 9.5px; font-weight: 600; display: flex; align-items: center; justify-content: center;
}
.bp-pill {
  display: inline-flex; align-items: center; gap: 6px;
  border: 1px solid var(--bp-border); border-radius: 999px;
  padding: 7px 14px; font-size: 12px; color: var(--bp-text);
  background: transparent; cursor: default; white-space: nowrap;
}

/* ── Promotion strip (system state — real, persisted, bounded) ──────── */
.bp-promo {
  display: flex; align-items: center; justify-content: center; gap: 18px;
  padding: 13px clamp(20px, 4vw, 56px); text-align: center; flex-wrap: wrap;
  border-bottom: 1px solid var(--bp-border);
}
.bp-promo-default { background: var(--bp-card); color: var(--bp-text); }
.bp-promo-bold { background: var(--bp-accent); color: var(--bp-bg); }
.bp-promo-quiet { background: transparent; color: var(--bp-muted); }
.bp-promo-text { font-size: 13px; letter-spacing: .01em; }
.bp-promo-text strong { font-weight: 600; margin-right: 8px; }
.bp-promo-cta { font-size: 12.5px; text-decoration: underline; text-underline-offset: 3px; white-space: nowrap; }

/* ── Hero — editorial, typography-led (no fabricated imagery) ───────── */
.bp-hero {
  padding: clamp(56px, 10vw, 128px) clamp(20px, 4vw, 56px) clamp(48px, 7vw, 80px);
  border-bottom: 1px solid var(--bp-border);
  max-width: 780px;
}
.bp-hero-eyebrow {
  font-size: 11px; letter-spacing: .16em; text-transform: uppercase;
  color: var(--bp-muted); margin: 0 0 20px;
}
.bp-hero-name {
  font-family: var(--bp-serif); font-weight: 440; font-style: normal;
  font-size: clamp(42px, 6.6vw, 76px); line-height: .98; letter-spacing: -.015em;
  margin: 0 0 22px;
}
.bp-hero-tagline { font-size: 17px; color: var(--bp-text); opacity: .78; margin: 0 0 30px; max-width: 46ch; line-height: 1.55; }
.bp-hero-cta {
  display: inline-flex; align-items: center; gap: 8px;
  border-bottom: 1.5px solid var(--bp-accent); padding-bottom: 3px;
  font-size: 13.5px; letter-spacing: .04em; text-transform: uppercase; font-weight: 500;
}
.bp-hero-cta::after { content: '→'; }
/* Checkpoint C §16 — a real, authoritative merchant photo as hero
   background (never a full "wallpaper the whole site" treatment — just
   this one section, per §19's "template system decides placements"). */
.bp-hero-photo {
  max-width: none; background-size: cover; background-position: center;
  color: #fff; border-bottom: none;
}
.bp-hero-photo .bp-hero-eyebrow { color: rgba(255,255,255,.75); }
.bp-hero-photo .bp-hero-tagline { color: #fff; opacity: .92; }
.bp-hero-photo .bp-hero-cta { border-bottom-color: #fff; }
.bp-hero-photo-cta {
  display: inline-block; margin-top: 18px; background: rgba(255,255,255,.14);
  border: 1px solid rgba(255,255,255,.5); color: #fff; border-radius: 999px;
  padding: 9px 18px; font-size: 12.5px; cursor: pointer;
}
.bp-hero-photo-cta:hover { background: rgba(255,255,255,.24); }
.bp-hero:not(.bp-hero-photo) .bp-hero-photo-cta {
  border: 1px solid var(--bp-border); color: var(--bp-muted); background: none; border-radius: 999px; padding: 9px 18px; font-size: 12.5px; cursor: pointer;
}
.bp-hero:not(.bp-hero-photo) .bp-hero-photo-cta:hover { color: var(--bp-text); border-color: var(--bp-text); }

/* ── Category nav ───────────────────────────────────────────────────── */
.bp-nav {
  display: flex; gap: 22px; overflow-x: auto; -ms-overflow-style: none; scrollbar-width: none;
  margin-bottom: 26px; border-bottom: 1px solid var(--bp-border); padding-bottom: 2px;
}
.bp-nav::-webkit-scrollbar { display: none; }
.bp-nav-item {
  flex: none; font-size: 13px; color: var(--bp-muted); background: none; border: none;
  padding: 6px 0 12px; cursor: pointer; border-bottom: 2px solid transparent; white-space: nowrap;
}
.bp-nav-item.active { color: var(--bp-text); border-bottom-color: var(--bp-accent); }
.bp-nav-item:hover { color: var(--bp-text); }

/* ── Sections (shared shell) ────────────────────────────────────────── */
.bp-section { padding: clamp(40px, 6vw, 72px) clamp(20px, 4vw, 56px); border-bottom: 1px solid var(--bp-border); }
.bp-root > .bp-section:last-of-type { border-bottom: none; }
.bp-section-head { display: flex; align-items: baseline; justify-content: space-between; margin-bottom: 26px; gap: 12px; }
.bp-section-title {
  font-family: var(--bp-serif); font-size: clamp(22px, 2.6vw, 30px); font-weight: 460;
  letter-spacing: -.005em; margin: 0;
}
.bp-section-count { font-size: 12.5px; color: var(--bp-muted); }
.bp-section-head-right { display: flex; align-items: center; gap: 12px; }

/* ── Manage sections (Storefront S2 §25/§27) ────────────────────────── */
.bp-manage-sections-wrap { position: relative; display: inline-block; }
.bp-manage-sections-btn {
  font-size: 12px; color: var(--bp-muted); background: none; border: 1px solid var(--bp-border);
  border-radius: 999px; padding: 5px 12px; cursor: pointer;
}
.bp-manage-sections-btn:hover { color: var(--bp-text); border-color: var(--bp-text); }
.bp-mansec-pop {
  position: absolute; top: calc(100% + 8px); right: 0; z-index: 60; width: 260px;
  background: var(--bp-card); border: 1px solid var(--bp-border); border-radius: var(--bp-radius);
  box-shadow: 0 12px 32px rgba(0,0,0,.16); padding: 14px;
}
.bp-mansec-title { font-size: 12px; font-weight: 600; color: var(--bp-text); margin-bottom: 10px; }
.bp-mansec-row { display: flex; align-items: center; gap: 6px; margin-bottom: 8px; }
.bp-mansec-input {
  flex: 1; min-width: 0; font-size: 13px; padding: 6px 8px; border-radius: 6px;
  border: 1px solid var(--bp-border); background: var(--bp-bg); color: var(--bp-text);
}
.bp-mansec-move {
  width: 24px; height: 24px; border-radius: 6px; border: 1px solid var(--bp-border);
  background: var(--bp-card); color: var(--bp-text); cursor: pointer; padding: 0;
}
.bp-mansec-move:disabled { opacity: .35; cursor: default; }
.bp-mansec-remove {
  width: 24px; height: 24px; border-radius: 6px; border: 1px solid var(--bp-border);
  background: var(--bp-card); color: #b3261e; cursor: pointer; padding: 0; flex-shrink: 0;
}
.bp-mansec-remove:hover { background: #b3261e; color: #fff; }
.bp-mansec-row-pending { opacity: .7; }
.bp-mansec-pending-name { flex: 1; font-size: 12.5px; color: var(--bp-muted); }
.bp-mansec-pending-name em { font-style: normal; opacity: .75; }
.bp-mansec-add { display: flex; gap: 6px; margin: 10px 0 4px; }
.bp-mansec-title-secondary { margin-top: 16px; padding-top: 12px; border-top: 1px solid var(--bp-border); }
.bp-mansec-check { display: flex; align-items: center; gap: 8px; flex: 1; font-size: 13px; color: var(--bp-text); cursor: pointer; }
.bp-mansec-check input[disabled] { opacity: .5; cursor: default; }
.bp-mansec-hint { font-size: 11px; color: var(--bp-muted); margin-top: 8px; line-height: 1.4; }

/* ── Empty catalog state — designed, never a bare box (§7-E/§32) ────── */
.bp-empty {
  display: flex; flex-direction: column; align-items: center; text-align: center; gap: 14px;
  padding: 56px 24px; border: 1px solid var(--bp-border); border-radius: var(--bp-radius);
  background: var(--bp-card);
}
.bp-empty-mark {
  width: 52px; height: 52px; border-radius: 999px; display: flex; align-items: center; justify-content: center;
  font-family: var(--bp-serif); font-size: 20px; color: var(--bp-muted); border: 1px solid var(--bp-border);
}
.bp-empty span:not(.bp-empty-mark) { font-size: 14.5px; color: var(--bp-muted); }
.bp-empty-cta {
  margin-top: 6px; display: inline-flex; align-items: center; gap: 6px;
  border: 1px solid var(--bp-accent); border-radius: 999px; padding: 10px 20px;
  font-size: 13px; color: var(--bp-text); background: none; cursor: pointer;
}
.bp-empty-cta:hover { background: var(--bp-accent); color: var(--bp-bg); }

/* ── Product / service grid + cards — designed, never database rows ── */
/* Final Compact Premium Onboarding round (2026-09-20), Part 13 —
   tightened the gap's upper bound (32px -> 24px) for a denser, more
   deliberate grid on wide screens; the missing-image placeholder
   (.bp-ph below) already preserves the SAME `aspect-ratio: 4/5` box a
   real photo gets, so a missing image was never actually a source of
   extra whitespace here — confirmed, not blindly assumed, by reading
   .bp-card-media's own aspect-ratio rule below. Storefront layout
   itself (auto-fill 3-up on desktop) is intentionally NOT redesigned. */
.bp-grid {
  display: grid; gap: clamp(14px, 1.8vw, 24px);
  grid-template-columns: repeat(auto-fill, minmax(190px, 1fr));
}
.bp-card {
  cursor: pointer; text-align: left; background: none; border: none; padding: 0;
  font: inherit; color: inherit; display: flex; flex-direction: column;
}
.bp-card-media {
  aspect-ratio: 4 / 5; border-radius: var(--bp-radius); overflow: hidden;
  background: var(--bp-card);
  display: flex; align-items: center; justify-content: center; position: relative;
  margin-bottom: 14px; transition: opacity .15s ease;
}
.bp-card:hover .bp-card-media { opacity: .85; }
.bp-card-media img { width: 100%; height: 100%; object-fit: cover; display: block; }
/* a designed neutral field when no authoritative image exists — a soft
   diagonal tone shift + a quiet typographic mark, never a fake photo. */
.bp-card-media.bp-ph {
  background: linear-gradient(155deg, var(--bp-card) 0%, var(--bp-card) 55%, var(--bp-border) 150%);
}
.bp-ph-mark {
  font-family: var(--bp-serif); font-size: 34px; color: var(--bp-muted); opacity: .45;
}
.bp-card-attn {
  position: absolute; top: 10px; right: 10px; width: 8px; height: 8px; border-radius: 999px;
  background: #b5473f; box-shadow: 0 0 0 3px var(--bp-bg);
}
.bp-card-name { font-size: 13.5px; font-weight: 450; line-height: 1.35; margin: 0 0 4px; }
.bp-card-desc {
  font-size: 12.5px; line-height: 1.4; color: var(--bp-muted); margin: 0 0 4px;
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
}
.bp-card-price { font-size: 13px; color: var(--bp-muted); margin: 0; font-variant-numeric: tabular-nums; }

/* XKROX R5 §5 — real per-item generation states, never a bare dead
   placeholder tile while a real batch is running. Status text uses
   --bp-text (the same full-contrast ink as ordinary body copy), never
   --bp-muted, per the explicit "no ultra-light low-contrast text"
   requirement. */
.bp-card-media.bp-ph-generating { background: var(--bp-card); }
.bp-card-loader {
  width: 22px; height: 22px; border-radius: 999px;
  border: 2.5px solid var(--bp-border); border-top-color: var(--bp-text);
  animation: bp-spin .8s linear infinite; margin-bottom: 8px;
}
@keyframes bp-spin { to { transform: rotate(360deg); } }
.bp-ph-status { font-size: 12px; color: var(--bp-text); font-weight: 500; }
.bp-card-media.bp-ph-generating { flex-direction: column; }
.bp-card-media.bp-ph-failed { flex-direction: column; gap: 8px; }
.bp-ph-retry {
  font: inherit; font-size: 12px; font-weight: 600; color: var(--bp-text);
  background: var(--bp-bg); border: 1px solid var(--bp-border); border-radius: 999px;
  padding: 4px 12px; cursor: pointer;
}
.bp-ph-retry:hover { background: var(--bp-border); }

/* ── Editorial / brand section ──────────────────────────────────────── */
.bp-editorial { max-width: 640px; }
.bp-about-text { font-size: 15.5px; line-height: 1.75; color: var(--bp-text); opacity: .85; margin: 0; white-space: pre-wrap; }
.bp-editorial-empty { display: flex; align-items: center; gap: 18px; flex-wrap: wrap; }
.bp-empty-prompt { font-size: 14.5px; color: var(--bp-muted); margin: 0; }

/* ── Gallery ────────────────────────────────────────────────────────── */
.bp-gallery { display: grid; gap: 12px; grid-template-columns: repeat(auto-fill, minmax(160px, 1fr)); }
.bp-gallery img { width: 100%; aspect-ratio: 1; object-fit: cover; border-radius: var(--bp-radius); }

/* ── Footer — known facts only, never "Not added yet" (§7-G) ────────── */
.bp-footer {
  padding: 32px clamp(20px, 4vw, 56px) 44px; display: flex; align-items: baseline;
  justify-content: space-between; gap: 16px; flex-wrap: wrap;
}
.bp-footer-name { font-family: var(--bp-serif); font-size: 15px; color: var(--bp-text); }
.bp-footer-facts { display: flex; gap: 18px; flex-wrap: wrap; font-size: 12.5px; color: var(--bp-muted); }

/* ── Edit-mode affordances (merchant preview only) ──────────────────── */
.bp-editaffordance {
  display: none; border: 1px solid var(--bp-border); background: none; color: var(--bp-muted);
  font-size: 12.5px; border-radius: 999px; padding: 7px 14px; cursor: pointer; white-space: nowrap;
}
.bp-editaffordance:hover { color: var(--bp-text); border-color: var(--bp-text); }
.bp-ask { border: none; padding: 0; }
.bp-root[data-mode="preview"] .bp-editaffordance { display: inline-flex; }

/* ── Customize popover (§1-6/§36 — explicit labels, real color swatches +
   custom picker, merchant preview only) ─────────────────────────────── */
.bp-customize-wrap { position: relative; }
.bp-customize-pop {
  position: absolute; top: calc(100% + 8px); right: 0; z-index: 20;
  background: var(--bp-bg, #fff); border: 1px solid var(--bp-border); border-radius: 10px;
  padding: 14px; width: 240px; max-height: 70vh; overflow-y: auto;
  box-shadow: 0 12px 32px -10px rgba(20,18,10,.28);
}
.bp-customize-group-label { font-size: 11px; text-transform: uppercase; letter-spacing: .08em; color: var(--bp-muted); margin: 14px 0 8px; }
.bp-customize-group-label:first-child { margin-top: 0; }
.bp-customize-row { display: flex; flex-wrap: wrap; gap: 8px; }
.bp-customize-swatch-btn {
  border: 1px solid var(--bp-border); background: none; color: var(--bp-text);
  border-radius: 999px; padding: 6px 12px; font-size: 12px; cursor: pointer;
}
.bp-customize-swatch-btn:hover { border-color: var(--bp-text); }
.bp-customize-swatches { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; }
.bp-customize-swatch {
  width: 26px; height: 26px; border-radius: 999px; border: 1px solid rgba(0,0,0,.14); cursor: pointer; padding: 0;
}
.bp-customize-swatch:hover { box-shadow: 0 0 0 2px var(--bp-bg, #fff), 0 0 0 3px var(--bp-border); }
.bp-customize-custom {
  width: 26px; height: 26px; border-radius: 999px; border: 1px dashed var(--bp-border);
  display: flex; align-items: center; justify-content: center; cursor: pointer; overflow: hidden;
  background: repeating-conic-gradient(from 0deg, #eee 0deg 90deg, #fff 90deg 180deg) 0 0 / 8px 8px;
}
.bp-customize-custom input[type="color"] {
  width: 34px; height: 34px; border: none; padding: 0; cursor: pointer; background: none;
}

/* ── Product detail overlay ─────────────────────────────────────────── */
/* D2 §10-14 — a deliberate ecommerce-style detail composition, not an
   "overlay accident": a contained, viewport-conscious two-column layout
   (media ~55-60%, info ~40-45%) instead of an unconstrained full-bleed
   4:5 image that could grow arbitrarily tall on a wide screen. Still an
   absolutely-positioned surface within .bp-root (a real routed page —
   /consumer/{slug}/explore/item/{id} — is a larger, riskier change than
   this same-day round's own scope allows; the caller (explore.js) resets
   and restores its own scroll container's scrollTop so "Back" returns to
   the exact previous Explore position, same contract either way). */
/* Final Correction R3 §8-10 — REPLACED, not tweaked: a real centered
   quick-view modal. `.bp-detail` is the fixed, full-viewport backdrop
   (never scroll-container-relative — see product_detail.js's own
   updated comment); `.bp-detail-panel` is the actual bounded,
   independently-scrolling modal card. This is deliberately the ONE
   shared implementation for onboarding preview AND consumer Explore —
   no second detail renderer. */
.bp-detail {
  position: fixed; inset: 0; z-index: 100; overflow-y: auto;
  background: rgba(18, 16, 10, .58);
  display: flex; align-items: center; justify-content: center;
  padding: clamp(16px, 4vw, 48px);
  animation: bpDetailBackdropIn .16s ease both;
  /* Identity + Discovery Correction R4 §35 — the actual rendering
     container's width, not the viewport's, decides side-by-side vs.
     stacked. In merchant split-workbench mode this same .bp-detail is
     CONTAINED to #obCanvas's own left-pane box (canvas.css's
     transform: translateZ(0) on #obCanvas — see its own comment, §32-37)
     which is meaningfully narrower than the full viewport a plain
     @media query would measure; in Consumer Explore (full-viewport,
     public mode) the container genuinely IS the viewport. One container
     query below correctly adapts to whichever is actually true, instead
     of two mode-specific breakpoints. */
  container-type: inline-size;
}
@keyframes bpDetailBackdropIn { from { opacity: 0; } to { opacity: 1; } }
.bp-detail-panel {
  position: relative; width: 100%; max-width: 1220px; max-height: 88vh;
  overflow-y: auto; background: var(--bp-bg); color: var(--bp-text);
  border-radius: 18px; box-shadow: 0 24px 70px -12px rgba(0, 0, 0, .45);
  animation: bpDetailPanelIn .18s cubic-bezier(.2,.8,.3,1) both;
}
@keyframes bpDetailPanelIn { from { opacity: 0; transform: translateY(10px) scale(.98); } to { opacity: 1; transform: none; } }
@media (prefers-reduced-motion: reduce) {
  .bp-detail, .bp-detail-panel { animation: none; }
}
.bp-detail-close {
  position: absolute; top: 14px; right: 14px; z-index: 2;
  width: 36px; height: 36px; border-radius: 50%;
  background: var(--bp-card); border: 1px solid var(--bp-border);
  color: var(--bp-text); font-size: 20px; line-height: 1; cursor: pointer;
  display: flex; align-items: center; justify-content: center;
}
.bp-detail-close:hover { background: var(--bp-accent); color: var(--bp-bg); border-color: var(--bp-accent); }
.bp-detail-body {
  display: grid; gap: clamp(20px, 3vw, 40px); padding: clamp(20px, 3.5vw, 40px);
  grid-template-columns: minmax(0, 1.35fr) minmax(260px, 1fr);
  align-items: start;
}
/* R4 §35 — a narrow rendering container (a real desktop viewport with a
   split-workbench left pane, not necessarily a phone) stacks image above
   info rather than cramping a two-column grid into too little width. */
@container (max-width: 640px) {
  .bp-detail-body { grid-template-columns: 1fr; }
}
.bp-detail-media-col { display: flex; gap: 12px; min-width: 0; }
.bp-detail-media {
  border-radius: calc(var(--bp-radius) * 0.7 + 4px); overflow: hidden; background: var(--bp-card);
  display: flex; align-items: center; justify-content: center;
  aspect-ratio: 1/1; max-height: min(58vh, 560px); width: 100%; flex: 1; min-width: 0;
}
.bp-detail-media img { width: 100%; height: 100%; object-fit: contain; }
.bp-detail-media .bp-ph { font-family: var(--bp-serif); font-size: 56px; color: var(--bp-muted); opacity: .45; }
.bp-detail-info { padding-top: 6px; }
.bp-detail-name { font-family: var(--bp-serif); font-size: clamp(22px, 2.4vw, 30px); font-weight: 460; margin: 0 0 8px; line-height: 1.2; }
.bp-detail-price { font-size: 17px; color: var(--bp-muted); margin: 0 0 18px; }
.bp-detail-desc { font-size: 14px; line-height: 1.65; color: var(--bp-text); opacity: .82; margin: 0 0 22px; max-width: 46ch; }
.bp-qty { display: inline-flex; align-items: center; gap: 14px; border: 1px solid var(--bp-border); border-radius: 999px; padding: 6px 8px; margin-bottom: 18px; }
.bp-qty button { width: 28px; height: 28px; border-radius: 999px; border: none; background: none; color: var(--bp-text); font-size: 16px; cursor: pointer; }
.bp-qty button:hover { background: var(--bp-card); }
.bp-qty span { min-width: 18px; text-align: center; font-size: 14px; }
.bp-addcart {
  display: block; width: 100%; max-width: 320px; border: none; border-radius: 2px;
  background: var(--bp-accent); color: var(--bp-bg); padding: 15px 20px; font-size: 13.5px;
  letter-spacing: .03em; text-transform: uppercase; font-weight: 500; cursor: pointer;
}
.bp-addcart:hover { opacity: .88; }
/* Storefront S2 §29/§30/§31 — a booking/request CTA reads the same as
   Add to cart structurally (same size/weight) but is never literally
   the cart action; §31's "+ Add price" preview affordance is a quiet
   text link, never styled like real price information. */
.bp-book-btn { background: var(--bp-text); }
.bp-detail-price-cta {
  display: inline-block; border: none; background: none; padding: 0; margin: 0 0 22px;
  font-size: 13px; color: var(--bp-muted); cursor: pointer; text-decoration: underline; text-underline-offset: 2px;
}
.bp-detail-price-cta:hover { color: var(--bp-text); }
.bp-preview-note { font-size: 12px; color: var(--bp-muted); margin-top: 12px; }
.bp-preview-note-confirm { color: var(--bp-text); font-weight: 500; margin-top: 16px; }

/* ── Product detail gallery (Checkpoint C §12) ──────────────────────── */
/* D2 §11/§13 — a vertical rail beside the primary image on desktop
   (order: -1 puts it visually before .bp-detail-media within the flex
   row, matching the ASCII mockup: thumb column | primary image). */
.bp-detail-thumbs {
  display: flex; flex-direction: column; gap: 8px; flex: none; order: -1;
  max-height: min(68vh, 620px); overflow-y: auto; padding: 1px;
}
.bp-detail-thumb {
  width: 52px; height: 52px; border-radius: var(--bp-radius); overflow: hidden;
  border: 1.5px solid transparent; padding: 0; cursor: pointer; background: var(--bp-card);
}
.bp-detail-thumb img { width: 100%; height: 100%; object-fit: cover; display: block; }
.bp-detail-thumb.active { border-color: var(--bp-accent); }

/* ── Item image management (Storefront S2 §16/§17) — merchant-preview-
   only controls attached directly to the gallery, so a merchant never
   needs a separate legacy catalog-edit page for a single photo. ────────── */
.bp-detail-thumb-wrap { position: relative; display: inline-block; }
.bp-thumb-manage {
  position: absolute; top: -6px; right: -6px; display: flex; gap: 2px;
}
.bp-thumb-mini {
  width: 18px; height: 18px; border-radius: 50%; border: 1px solid var(--bp-border);
  background: var(--bp-card); color: var(--bp-text); font-size: 11px; line-height: 1;
  cursor: pointer; padding: 0; display: flex; align-items: center; justify-content: center;
  box-shadow: 0 1px 3px rgba(0,0,0,.18);
}
.bp-thumb-mini:hover { background: var(--bp-accent); color: #fff; }
.bp-thumb-remove { color: #b3261e; }
.bp-thumb-remove:hover { background: #b3261e; color: #fff; }
.bp-detail-thumb.bp-thumb-add {
  display: flex; align-items: center; justify-content: center; font-size: 20px;
  color: var(--bp-muted); border: 1.5px dashed var(--bp-border); background: transparent;
}
.bp-detail-thumb.bp-thumb-add:hover { color: var(--bp-text); border-color: var(--bp-text); }

/* ── Cart drawer (Checkpoint C §10) — a real, wired preview cart, always
   viewport-fixed so it renders correctly regardless of #obCanvas's own
   internal scroll position. ─────────────────────────────────────────── */
.bp-cart-overlay {
  position: fixed; inset: 0; background: rgba(20, 18, 10, .32);
  display: flex; justify-content: flex-end; z-index: 950;
  animation: bpFade .16s ease both;
}
@keyframes bpFade { from { opacity: 0; } to { opacity: 1; } }
.bp-cart-drawer {
  width: min(400px, 100vw); height: 100%; background: var(--bp-bg, #fbf9f5);
  color: var(--bp-text, #17160f); display: flex; flex-direction: column;
  padding: 22px clamp(18px, 3vw, 28px); box-shadow: -8px 0 32px -8px rgba(20, 18, 10, .25);
  font-family: var(--bp-sans, inherit);
}
.bp-cart-head { display: flex; align-items: center; justify-content: space-between; margin-bottom: 18px; }
.bp-cart-head h2 { font-family: var(--bp-serif, serif); font-size: 20px; font-weight: 500; margin: 0; }
.bp-cart-close { background: none; border: none; font-size: 22px; line-height: 1; cursor: pointer; color: var(--bp-muted, #6f6a5c); padding: 4px; }
.bp-cart-close:hover { color: var(--bp-text, #17160f); }
.bp-cart-lines { flex: 1; overflow-y: auto; display: flex; flex-direction: column; gap: 14px; }
.bp-cart-line { display: flex; align-items: flex-start; justify-content: space-between; gap: 10px; padding-bottom: 14px; border-bottom: 1px solid var(--bp-border, #e6e1d3); }
.bp-cart-line-name { font-size: 14px; font-weight: 500; }
.bp-cart-line-meta { font-size: 12.5px; color: var(--bp-muted, #6f6a5c); margin-top: 3px; }
.bp-cart-line-remove { background: none; border: none; color: var(--bp-muted, #6f6a5c); font-size: 12px; cursor: pointer; padding: 0; white-space: nowrap; }
.bp-cart-line-remove:hover { color: var(--bp-text, #17160f); }
.bp-cart-subtotal { display: flex; justify-content: space-between; font-size: 14.5px; font-weight: 500; padding-top: 16px; margin-top: 4px; border-top: 1px solid var(--bp-border, #e6e1d3); }
.bp-cart-empty { flex: 1; display: flex; align-items: center; justify-content: center; text-align: center; color: var(--bp-muted, #6f6a5c); font-size: 13.5px; padding: 30px 0; }

@media (max-width: 720px) {
  .bp-hnav { display: none; }
  /* mobile: the modal becomes a full-screen sheet, not a small floating
     card (a ~1220px-max card would look lost on a phone). */
  .bp-detail { padding: 0; }
  .bp-detail-panel { max-width: 100%; max-height: 100%; height: 100%; border-radius: 0; }
  .bp-detail-body { grid-template-columns: 1fr; padding-left: 16px; padding-right: 16px; }
  .bp-detail-media { max-height: 48vh; aspect-ratio: 4/3; }
  /* D2 §13 — mobile: horizontal/swipe gallery below the image, not a
     vertical rail (which would compete with the image for width on a
     narrow screen). */
  .bp-detail-media-col { flex-direction: column; }
  .bp-detail-thumbs {
    flex-direction: row; order: 1; max-height: none; overflow-x: auto; overflow-y: hidden;
    -webkit-overflow-scrolling: touch;
  }
  .bp-detail-thumb, .bp-detail-thumb-wrap { flex: none; }
  .bp-grid { grid-template-columns: repeat(2, 1fr); gap: 14px; }
  .bp-hero { padding-top: 44px; }
  .bp-cart-drawer { width: 100vw; }
}
