/*
 * Pyramid design tokens.
 *
 * These :root variables are the public contract every block reads from.
 * The runtime values come from applyTokens(theme) — see theme/applyTokens.ts.
 *
 * The defaults below are a fallback for the "clean-light" preset; in practice
 * applyTokens() injects the restaurant's actual SiteTheme onto data-theme,
 * which cascades over these.
 */

/* Global baseline: this file is bundled for published sites (see
 * packages/static generateSite) and imported in apps/web globals.css.
 * Keep border-box and mobile text behavior here so static output matches
 * the editor — do not add resets only in apps/web. */
*, *::before, *::after {
  box-sizing: border-box;
}
html {
  -webkit-text-size-adjust: 100%;
  text-size-adjust: 100%;
}

:root {
  /* ── Color tokens — Brand Tokens v2 canonical names ─────────────────
   *
   * Tier 3 semantic-role tokens. Block CSS reads these directly via
   * `var(--color-bg)`, `var(--color-fg)`, etc. The values shipped here
   * are the fallbacks that paint when no inline tokens are stamped on
   * the wrapping element (e.g. unauthenticated public chrome). The
   * authoritative values come from `applyTokens()` which inlines the
   * tenant's derived palette on `<html>` (published) or `.pe-device-screen`
   * + `.pyramid-theme` (editor canvas).
   *
   * Naming follows GitHub Primer / Radix Themes conventions: surfaces
   * ascend in elevation (bg → bgSubtle → bgEmphasis), text descends in
   * emphasis (fg → fgMuted → fgSubtle), borders ascend in visibility
   * (border → borderStrong), accent has an on-color + tinted variant.
   *
   * The MAPPING (which palette step backs each role) lives in
   * `packages/core/src/theme/semantic.ts` and is derived per mode
   * (light / dark) from the operator's brand color.
   */
  --color-bg: #ffffff;
  --color-bg-subtle: #f6f7f9;
  --color-bg-emphasis: #f6f7f9;
  --color-fg: #0b1220;
  --color-fg-muted: #4a5568;
  --color-fg-subtle: #4a5568;
  --color-border: rgba(11, 18, 32, 0.08);
  --color-border-strong: rgba(11, 18, 32, 0.16);
  --color-accent: #16a34a;
  --color-accent-fg: #ffffff;
  --color-accent-muted: #16a34a;

  /* ── Legacy aliases (back-compat) ───────────────────────────────────
   *
   * Block CSS migrated off these in Phase 3 of Brand Tokens v2. We keep
   * the alias chain alive ONLY for back-compat with:
   *   - operator-authored custom CSS that may reference `--ds-bg`
   *   - 3rd-party blocks that haven't migrated yet
   *   - in-flight tenant data with custom CSS strings storing `var(--ds-*)`
   *
   * Pure aliases — every value `var()`s into the canonical `--color-*`
   * chain so there's a single source of truth. Removing this block is
   * a breaking change for any external consumer; do it on a major version.
   */
  --ds-bg: var(--color-bg);
  --ds-bg-soft: var(--color-bg-emphasis);
  --ds-fg: var(--color-fg);
  --ds-fg-soft: var(--color-fg-muted);
  --ds-muted: var(--color-fg-muted);
  --ds-border: var(--color-border);
  --ds-accent: var(--color-accent);
  --ds-accent-fg: var(--color-accent-fg);
  --ds-color-primary: var(--color-accent);
  --ds-color-primary-fg: var(--color-accent-fg);
  --ds-color-secondary: var(--color-accent);
  --ds-color-surface: var(--color-bg);
  --ds-color-surface-elevated: var(--color-bg-emphasis);
  --ds-color-text: var(--color-fg);
  --ds-color-text-muted: var(--color-fg-muted);
  --ds-color-border: var(--color-border);

  /* ── Typography ───────────────────────────────────────────────────── */
  --ds-font-display: "Inter", ui-sans-serif, system-ui, sans-serif;
  --ds-font-body: "Inter", ui-sans-serif, system-ui, sans-serif;
  --ds-font-display-weight: 700;
  --ds-font-body-weight: 400;
  --ds-type-scale: 1.25;
  --ds-text-base: 16px;
  --ds-text-sm: calc(var(--ds-text-base) / var(--ds-type-scale));
  --ds-text-lg: calc(var(--ds-text-base) * var(--ds-type-scale));
  --ds-text-xl: calc(var(--ds-text-lg) * var(--ds-type-scale));
  --ds-text-2xl: calc(var(--ds-text-xl) * var(--ds-type-scale));
  --ds-text-3xl: calc(var(--ds-text-2xl) * var(--ds-type-scale));
  --ds-text-4xl: calc(var(--ds-text-3xl) * var(--ds-type-scale));

  /* ── Spacing scale (driven by SiteTheme.spacing) ──────────────────────
   * Use `cqi` (container query inline size) NOT `vw`. `.pyramid-theme`
   * declares `container-type: inline-size`, so `cqi` resolves to the
   * pyramid container's width — which is the BROWSER viewport on the
   * published site (same value as `vw` in that context) but the DEVICE
   * FRAME width during editor mobile/tablet preview. With `vw`, mobile
   * preview was sized to the user's 1920px monitor so containers
   * overflowed the 390px iPhone frame. `cqi` makes mobile preview
   * actually mobile.
   */
  --ds-section-y: clamp(64px, 8cqi, 128px);
  --ds-container: min(1240px, 92cqi);

  /* ── Radius scale ─────────────────────────────────────────────────── */
  --ds-radius-sm: 6px;
  --ds-radius: 14px;
  --ds-radius-lg: 22px;

  /* ── Shadows ──────────────────────────────────────────────────────── */
  --ds-shadow-1: 0 1px 2px rgba(0, 0, 0, 0.06), 0 4px 14px rgba(0, 0, 0, 0.04);
  --ds-shadow-2: 0 12px 40px rgba(0, 0, 0, 0.12);

  /* ── Motion ───────────────────────────────────────────────────────── */
  --ds-ease: cubic-bezier(0.22, 1, 0.36, 1);

  /* ── Z-stack (block-side scaffolding) ─────────────────────────────────
   * The editor chrome owns its own ladder via --pe-z-* in
   * packages/editor/src/styles.css. These --ds-z-* tokens are the
   * BLOCKS-side equivalent — used by sticky navs, full-screen overlays,
   * and any future block that needs to layer above content. Both
   * ladders are documented end-to-end in OPERATIONS.md "Z-stack chart".
   *
   * Local stacking inside a block (image behind text, gradient overlay)
   * uses negative integers directly — those don't need tokens because
   * they form a private context, not a global ladder. */
  --ds-z-sticky: 50;
  --ds-z-overlay: 200;
}

/* ── Spacing presets — applied via [data-spacing] ──────────────────── */
[data-spacing="compact"] {
  --ds-section-y: clamp(40px, 5cqi, 80px);
}
[data-spacing="normal"] {
  --ds-section-y: clamp(64px, 8cqi, 128px);
}
[data-spacing="spacious"] {
  --ds-section-y: clamp(96px, 12cqi, 192px);
}

/* ── Radius presets — applied via [data-radius] ───────────────────── */
[data-radius="sharp"] {
  --ds-radius-sm: 0px;
  --ds-radius: 2px;
  --ds-radius-lg: 4px;
}
[data-radius="soft"] {
  --ds-radius-sm: 6px;
  --ds-radius: 10px;
  --ds-radius-lg: 16px;
}
[data-radius="rounded"] {
  --ds-radius-sm: 10px;
  --ds-radius: 18px;
  --ds-radius-lg: 28px;
}
[data-radius="pill"] {
  --ds-radius-sm: 999px;
  --ds-radius: 999px;
  --ds-radius-lg: 999px;
}

/* ── Shadow presets — applied via [data-shadows] ──────────────────── */
[data-shadows="none"] {
  --ds-shadow-1: none;
  --ds-shadow-2: none;
}
[data-shadows="soft"] {
  --ds-shadow-1: 0 1px 2px rgba(0, 0, 0, 0.06), 0 4px 14px rgba(0, 0, 0, 0.04);
  --ds-shadow-2: 0 12px 40px rgba(0, 0, 0, 0.12);
}
[data-shadows="lifted"] {
  --ds-shadow-1: 0 2px 4px rgba(0, 0, 0, 0.08), 0 12px 30px rgba(0, 0, 0, 0.12);
  --ds-shadow-2: 0 30px 80px rgba(0, 0, 0, 0.25);
}

/* ── Preset overrides (kept for the legacy editorial / noir presets) ─
 *
 * These rules ONLY apply when an element carries `data-theme="..."` AND
 * has NO inline style override for the same property. The published
 * shell + editor canvas BOTH stamp inline tokens via applyTokens, so
 * inline always wins on the same element. These rules are the fallback
 * that paints when a preset is selected but the operator hasn't yet
 * triggered an applyTokens cycle (e.g. brand-new tenant first paint).
 */
[data-theme="editorial"] {
  --color-bg: #faf7f2;
  --color-bg-subtle: #f1ece4;
  --color-bg-emphasis: #f1ece4;
  --color-fg: #1a1410;
  --color-fg-muted: #524739;
  --color-fg-subtle: #524739;
  --color-accent: #b3431d;
  --color-border: rgba(26, 20, 16, 0.1);
  --color-border-strong: rgba(26, 20, 16, 0.2);
  --ds-font-display: "Fraunces", "Times New Roman", serif;
}

/* Noir 2027 — deep botanical dark with a vivid lime accent. The legacy
   selector `[data-theme="thc-premium-2027"]` is kept as an alias so any
   stored Restaurant.theme.preset value still resolves correctly until
   migration `20260420000004_rename_theme_preset` rewrites it. */
[data-theme="noir-2027"],
[data-theme="thc-premium-2027"] {
  --color-bg: #07120c;
  --color-bg-subtle: #0e1d14;
  --color-bg-emphasis: #0e1d14;
  --color-fg: #f5f1e6;
  --color-fg-muted: #b9c4ad;
  --color-fg-subtle: #b9c4ad;
  --color-accent: #c8ff4d;
  --color-accent-fg: #07120c;
  --color-border: rgba(245, 241, 230, 0.08);
  --color-border-strong: rgba(245, 241, 230, 0.16);
}

[data-theme="ocean-blue"] {
  --color-bg: #f8fafc;
  --color-bg-subtle: #f1f5f9;
  --color-bg-emphasis: #f1f5f9;
  --color-fg: #0f172a;
  --color-fg-muted: #64748b;
  --color-fg-subtle: #64748b;
  --color-accent: #0284c7;
  --color-accent-fg: #f8fafc;
  --color-border: rgba(15, 23, 42, 0.08);
  --color-border-strong: rgba(15, 23, 42, 0.16);
  --ds-font-display: "Plus Jakarta Sans", ui-sans-serif, system-ui, sans-serif;
}

[data-theme="sunrise-sand"] {
  --color-bg: #fffbeb;
  --color-bg-subtle: #fef3c7;
  --color-bg-emphasis: #fef3c7;
  --color-fg: #1c1917;
  --color-fg-muted: #78716c;
  --color-fg-subtle: #78716c;
  --color-accent: #ea580c;
  --color-accent-fg: #fffbeb;
  --color-border: rgba(28, 25, 23, 0.08);
  --color-border-strong: rgba(28, 25, 23, 0.18);
  --ds-font-display: "Fraunces", Georgia, "Times New Roman", serif;
}

[data-theme="midnight-ink"] {
  --color-bg: #020617;
  --color-bg-subtle: #0f172a;
  --color-bg-emphasis: #0f172a;
  --color-fg: #f8fafc;
  --color-fg-muted: #94a3b8;
  --color-fg-subtle: #94a3b8;
  --color-accent: #38bdf8;
  --color-accent-fg: #020617;
  --color-border: rgba(248, 250, 252, 0.1);
  --color-border-strong: rgba(248, 250, 252, 0.2);
  --ds-font-display: "DM Sans", ui-sans-serif, system-ui, sans-serif;
}

[data-theme="rose-quartz"] {
  --color-bg: #fff1f2;
  --color-bg-subtle: #ffe4e6;
  --color-bg-emphasis: #ffe4e6;
  --color-fg: #1f2937;
  --color-fg-muted: #6b7280;
  --color-fg-subtle: #6b7280;
  --color-accent: #e11d48;
  --color-accent-fg: #fff1f2;
  --color-border: rgba(31, 41, 55, 0.08);
  --color-border-strong: rgba(31, 41, 55, 0.18);
  --ds-font-display: "Manrope", ui-sans-serif, system-ui, sans-serif;
}

[data-theme="graphite-pro"] {
  --color-bg: #fafafa;
  --color-bg-subtle: #f4f4f5;
  --color-bg-emphasis: #f4f4f5;
  --color-fg: #18181b;
  --color-fg-muted: #71717a;
  --color-fg-subtle: #71717a;
  --color-accent: #3b82f6;
  --color-accent-fg: #fafafa;
  --color-border: rgba(24, 24, 27, 0.08);
  --color-border-strong: rgba(24, 24, 27, 0.18);
  --ds-font-display: "Geist", ui-sans-serif, system-ui, sans-serif;
}

[data-theme="citrus-pop"] {
  --color-bg: #fefce8;
  --color-bg-subtle: #fef9c3;
  --color-bg-emphasis: #fef9c3;
  --color-fg: #1c1917;
  --color-fg-muted: #78716c;
  --color-fg-subtle: #78716c;
  --color-accent: #ca8a04;
  --color-accent-fg: #1c1917;
  --color-border: rgba(28, 25, 23, 0.08);
  --color-border-strong: rgba(28, 25, 23, 0.18);
  --ds-font-display: "DM Sans", ui-sans-serif, system-ui, sans-serif;
}

[data-theme="forest-moss"] {
  --color-bg: #f0fdf4;
  --color-bg-subtle: #dcfce7;
  --color-bg-emphasis: #dcfce7;
  --color-fg: #052e16;
  --color-fg-muted: #3f6212;
  --color-fg-subtle: #3f6212;
  --color-accent: #15803d;
  --color-accent-fg: #f0fdf4;
  --color-border: rgba(5, 46, 22, 0.08);
  --color-border-strong: rgba(5, 46, 22, 0.18);
  --ds-font-display: "Plus Jakarta Sans", ui-sans-serif, system-ui, sans-serif;
}

[data-theme="lavender-dream"] {
  --color-bg: #faf5ff;
  --color-bg-subtle: #f3e8ff;
  --color-bg-emphasis: #f3e8ff;
  --color-fg: #1e1b4b;
  --color-fg-muted: #6b7280;
  --color-fg-subtle: #6b7280;
  --color-accent: #7c3aed;
  --color-accent-fg: #faf5ff;
  --color-border: rgba(30, 27, 75, 0.08);
  --color-border-strong: rgba(30, 27, 75, 0.18);
  --ds-font-display: "Manrope", ui-sans-serif, system-ui, sans-serif;
}

[data-theme="ion-cool"] {
  --color-bg: #f8fafc;
  --color-bg-subtle: #f1f5f9;
  --color-bg-emphasis: #f1f5f9;
  --color-fg: #0f172a;
  --color-fg-muted: #64748b;
  --color-fg-subtle: #64748b;
  --color-accent: #0ea5e9;
  --color-accent-fg: #f8fafc;
  --color-border: rgba(15, 23, 42, 0.08);
  --color-border-strong: rgba(15, 23, 42, 0.16);
  --ds-font-display: "Geist", ui-sans-serif, system-ui, sans-serif;
}

@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation-duration: 0.001ms !important;
    transition-duration: 0.001ms !important;
  }
}


/* Pyramid blocks - shared visual layer. Uses tokens from @pyramid/core/tokens.css */

/*
 * RESPONSIVE STRATEGY — read this before adding @media queries.
 *
 * Blocks render in TWO contexts with very different viewport semantics:
 *
 *   1. Published site: window viewport === content width. @media works.
 *   2. Editor canvas: the canvas is on a desktop screen but the user can
 *      preview at tablet (834) or mobile (390) widths via DeviceFrame.
 *      The browser viewport is STILL desktop, so @media (max-width: 720px)
 *      does NOT fire, and "mobile preview" looks identical to "desktop".
 *
 * Fix: declare a container on .pyramid-theme — the single wrapper that
 * exists in both contexts (editor ThemeProvider + static renderShell.ts).
 * Use `@container pyramid (max-width: ...)` everywhere instead of @media.
 * Container queries trigger off the pyramid-theme element's inline-size,
 * which equals the device width in editor preview AND equals the page
 * width in production. One rule, both worlds.
 *
 * Vertical sizing: raw `vh` tracks the *browser* window, so tablet/mobile
 * device previews were taller than the bezel. Prefer
 * `var(--pyramid-viewport-height, 100dvh)` (see renderShell + globals.css;
 * editor sets px on `.pe-device-scroll`) for viewport-height fractions.
 */
.pyramid-theme {
  background: var(--color-bg);
  color: var(--color-fg);
  font-family: var(--ds-font-body);
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
  container-type: inline-size;
  container-name: pyramid;

  /* Block-library scoped status / overlay tokens.
     Themes can override by defining the underlying --color-* token; if
     they don't, we fall back to neutral defaults that work on every
     theme (light + dark + neon-noir). Documented in CONVENTIONS §
     Theme tokens only — the var(--token, #hex) form is the audit's
     allowed way to declare a default colour value. */
  --pb-status-positive: var(--color-status-positive, #16a34a);
  --pb-status-negative: var(--color-status-negative, #dc2626);
  --pb-status-negative-fg: var(--color-status-negative-fg, #b91c1c);
  --pb-overlay-deep: var(--color-overlay-deep, #14171f);
  --pb-shadow-deep: var(--color-shadow-deep, #0f172a);

  /* Sticky-footer flex column: when the page content is shorter than the
     viewport, the slack space USED to paint var(--color-bg) (page colour)
     while the footer painted var(--color-bg-emphasis) — producing a visible
     "weird strip" of page bg directly below the footer. Switching to
     a flex column lets us push the LAST footer flush to the bottom via
     `margin-top: auto` (see :last-child rule below). The page chrome
     above (renderShell.ts) sets `body > .pyramid-theme { min-height:
     100dvh }` so this column actually has somewhere to push to.
     Container queries (container-type: inline-size) are unaffected by
     display: flex — they trigger off inline-size, not formatting model. */
  display: flex;
  flex-direction: column;

  /* Safety net: prevent any block from overflowing the container width.
     A single rogue 100vw / fixed-width / non-wrapping nowrap row was
     historically enough to push the WHOLE page off-canvas on mobile —
     and the published static site shows the same bug. `overflow: clip`
     contains the damage without introducing a useless scrollbar (which
     `overflow: hidden` does). Browser support: Chrome 90+, Safari 16+,
     Firefox 81+. */
  overflow-x: clip;
}
/* Push a trailing footer block to the viewport bottom so a short page
   never exposes the page bg below the footer. Targets `.pb-footer:last-child`
   specifically — if a tenant's last block is something else (e.g. a CTA
   strip), nothing pushes and the natural flow is preserved. */
.pyramid-theme > .pb-footer:last-child {
  margin-top: auto;
}

/* Subtle fixed “back to top” control (ThemeProvider + static runtime). */
.py-scroll-top {
  position: fixed;
  z-index: 50;
  right: max(0.75rem, env(safe-area-inset-right));
  bottom: max(0.75rem, env(safe-area-inset-bottom));
  width: 2.125rem;
  height: 2.125rem;
  display: grid;
  place-items: center;
  padding: 0;
  border: 1px solid color-mix(in oklab, var(--color-fg) 12%, transparent);
  border-radius: 9999px;
  background: color-mix(in oklab, var(--color-bg) 88%, var(--color-fg));
  color: color-mix(in oklab, var(--color-fg) 58%, transparent);
  box-shadow: 0 1px 2px color-mix(in oklab, var(--color-fg) 10%, transparent);
  cursor: pointer;
  opacity: 0;
  pointer-events: none;
  transform: translateY(0.375rem);
  transition:
    opacity 0.22s var(--ds-ease, ease),
    transform 0.22s var(--ds-ease, ease),
    background 0.15s ease,
    color 0.15s ease;
}
.py-scroll-top--visible {
  opacity: 0.62;
  pointer-events: auto;
  transform: translateY(0);
}
.py-scroll-top:hover {
  opacity: 0.9;
  color: color-mix(in oklab, var(--color-fg) 78%, transparent);
}
.py-scroll-top:focus-visible {
  outline: 2px solid color-mix(in oklab, var(--color-fg) 35%, transparent);
  outline-offset: 2px;
}
.py-scroll-top svg {
  width: 0.9375rem;
  height: 0.9375rem;
}

/* Universal media + long-word overflow guard. Applied at the
   .pyramid-theme scope (not the global :root) so editor chrome and
   admin pages aren't affected. Catches the entire class of "image
   wider than its column", "embedded YouTube iframe at fixed 560px",
   "non-breaking URL in body copy" bugs across every block — including
   blocks we haven't written yet. Per-block CSS can override when
   intentional (e.g. a marquee that genuinely needs to overflow). */
.pyramid-theme img,
.pyramid-theme video,
.pyramid-theme iframe,
.pyramid-theme svg {
  max-width: 100%;
  height: auto;
}
.pyramid-theme :is(h1, h2, h3, h4, h5, h6, p, span, a, li, blockquote, dt, dd) {
  overflow-wrap: anywhere;
}

/* tel:/mailto: from link fields — inherit surrounding color so the UA
   default blue does not break tenant branding. (Plain-text numbers on
   iOS are handled with format-detection in renderShell; explicit anchors
   still need this.) */
.pyramid-theme a[href^="tel:"],
.pyramid-theme a[href^="mailto:"] {
  color: currentColor;
  text-decoration: none;
  text-decoration-skip-ink: auto;
}
.pyramid-theme a[href^="tel:"]:where(:hover, :focus-visible),
.pyramid-theme a[href^="mailto:"]:where(:hover, :focus-visible) {
  color: var(--color-accent);
  text-decoration: underline;
  text-underline-offset: 0.2em;
}

.pyramid-section {
  padding-block: var(--ds-section-y);
  background: var(--color-bg);
  color: var(--color-fg);
}
.pyramid-section[data-tone="soft"] { background: var(--color-bg-emphasis); }
.pyramid-section[data-tone="inverse"] { background: var(--color-fg); color: var(--color-bg); }
.pyramid-section[data-pad="tight"] { padding-block: clamp(40px, 5cqi, 72px); }
.pyramid-section[data-pad="loose"] { padding-block: clamp(96px, 12cqi, 200px); }
.pyramid-section[data-pad="none"] { padding-block: 0; }
.pyramid-section--bleed { padding-inline: 0; }

.pyramid-section__container {
  width: var(--ds-container);
  margin-inline: auto;
}

/* Reveal animation */
.pyramid-reveal {
  opacity: 0;
  transform: translate3d(0, var(--reveal-y, 24px), 0);
  transition: opacity 700ms var(--ds-ease), transform 900ms var(--ds-ease);
  transition-delay: var(--reveal-delay, 0ms);
  will-change: opacity, transform;
}
.pyramid-reveal[data-revealed="true"] {
  opacity: 1;
  transform: translate3d(0, 0, 0);
}

/* Tilt */
.pyramid-tilt {
  position: relative;
  perspective: 1000px;
  transform-style: preserve-3d;
}
.pyramid-tilt__inner {
  transform: rotateX(var(--ty, 0deg)) rotateY(var(--tx, 0deg)) scale(var(--tz, 1));
  transition: transform 250ms var(--ds-ease);
  will-change: transform;
  transform-style: preserve-3d;
}
.pyramid-tilt__sheen {
  position: absolute;
  inset: 0;
  pointer-events: none;
  border-radius: inherit;
  background: radial-gradient(
    400px circle at var(--gx, 50%) var(--gy, 50%),
    rgba(255, 255, 255, 0.18),
    transparent 60%
  );
  mix-blend-mode: overlay;
  opacity: 0;
  transition: opacity 200ms var(--ds-ease);
}
.pyramid-tilt:hover .pyramid-tilt__sheen { opacity: 1; }

/* Image */
.pyramid-img {
  display: block;
  width: 100%;
  height: auto;
  object-fit: cover;
}
.pyramid-img--rounded { border-radius: var(--ds-radius); }

/* Token-driven placeholder rendered when an image src is empty.
   Block defaults ship empty src strings (CONVENTIONS.md "Asset path
   policy") so a fresh block drop never displays imagery the operator
   didn't choose. Pure CSS — no asset, never wrong for any vertical. */
.pyramid-img--placeholder {
  background:
    linear-gradient(
      135deg,
      var(--color-bg-emphasis, #f6f7f9) 0%,
      var(--color-border, rgba(11, 18, 32, 0.08)) 100%
    );
  position: relative;
  overflow: hidden;
  isolation: isolate;
}
.pyramid-img--placeholder::after {
  content: "";
  position: absolute;
  inset: 0;
  background-image:
    radial-gradient(
      circle at 30% 20%,
      color-mix(in oklab, var(--color-accent, #6b7280) 8%, transparent),
      transparent 50%
    ),
    radial-gradient(
      circle at 70% 80%,
      color-mix(in oklab, var(--color-accent, #6b7280) 6%, transparent),
      transparent 55%
    );
  pointer-events: none;
}

/* Field affordances (edit mode) */
.pyramid-field {
  outline: 1px dashed transparent;
  outline-offset: 4px;
  border-radius: 6px;
  transition: outline-color 120ms var(--ds-ease), background 120ms var(--ds-ease);
}
.pyramid-field:hover { outline-color: var(--color-accent); }
.pyramid-field:focus { outline: 2px solid var(--color-accent); }
.pyramid-field--text { cursor: text; }
.pyramid-field--image {
  position: relative;
  display: block;
  width: 100%;
  border: 0;
  background: transparent;
  padding: 0;
  cursor: pointer;
}
.pyramid-field--image:hover .pyramid-field__chip { opacity: 1; transform: translateY(0); }
.pyramid-field__chip {
  position: absolute;
  inset: auto 12px 12px auto;
  background: var(--color-accent);
  color: var(--color-accent-fg);
  font-size: 12px;
  font-weight: 600;
  padding: 6px 10px;
  border-radius: 999px;
  opacity: 0;
  transform: translateY(4px);
  transition: opacity 200ms, transform 200ms;
  pointer-events: none;
}
.pyramid-field--cta { cursor: pointer; }

/* Edit mode: `pyramid-field` applies a 6px radius; CTA is a pill. Win over the
   generic field rule so the dashed/focus affordance matches the button shape. */
button.pyramid-cta.pyramid-field--cta {
  border-radius: 999px;
}

/* CTA button base */
.pyramid-cta {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  padding: 14px 22px;
  border-radius: 999px;
  background: var(--color-accent);
  color: var(--color-accent-fg);
  font-weight: 600;
  border: 0;
  cursor: pointer;
  text-decoration: none;
  transition: transform 200ms var(--ds-ease), box-shadow 200ms var(--ds-ease), filter 200ms;
  box-shadow: var(--ds-shadow-1);
  max-width: 100%;
  /* Keep labels readable: don't let flex rows shrink the pill to zero or
     break mid-word (`overflow-wrap: anywhere` produced "Cont" / "act"). */
  min-width: min-content;
  flex-shrink: 0;
  overflow-wrap: break-word;
  word-break: normal;
}
.pyramid-cta:hover { transform: translateY(-2px); box-shadow: var(--ds-shadow-2); filter: brightness(1.05); }

/* CTA style variants — pair with `pyramidCtaStyleClass()` / `ctaButtonSchema.style`. */
.pyramid-cta--outline {
  background: transparent;
  color: var(--color-accent);
  border: 2px solid var(--color-accent);
  box-shadow: none;
}
.pyramid-cta--outline:hover {
  background: color-mix(in oklab, var(--color-accent) 12%, transparent);
  filter: none;
}
.pyramid-cta--ghost {
  background: transparent;
  color: var(--color-fg);
  border: 1px solid var(--color-border-strong);
  box-shadow: none;
}
.pyramid-cta--ghost:hover {
  background: color-mix(in srgb, var(--color-fg) 6%, transparent);
  border-color: color-mix(in srgb, var(--color-accent) 45%, var(--color-border-strong));
  filter: none;
}
.pyramid-cta--soft {
  background: color-mix(in oklab, var(--color-accent) 18%, var(--color-bg));
  color: var(--color-accent);
  border: 1px solid color-mix(in srgb, var(--color-accent) 28%, transparent);
  box-shadow: none;
}
.pyramid-cta--soft:hover {
  background: color-mix(in oklab, var(--color-accent) 28%, var(--color-bg));
  filter: none;
}
.pyramid-cta--contrast {
  background: var(--color-fg);
  color: var(--color-bg);
  border: 0;
  box-shadow: var(--ds-shadow-1);
}
.pyramid-cta--contrast:hover {
  filter: brightness(1.08);
}
.pyramid-cta--link {
  display: inline-flex;
  padding: 6px 4px;
  min-height: 0;
  background: transparent;
  color: var(--color-accent);
  border: 0;
  border-radius: 6px;
  box-shadow: none;
  font-weight: 600;
  text-decoration: underline;
  text-underline-offset: 0.2em;
}
.pyramid-cta--link:hover {
  transform: none;
  box-shadow: none;
  filter: none;
  background: color-mix(in oklab, var(--color-accent) 10%, transparent);
}

/* ---------- Hero ---------- */
.pb-hero {
  position: relative;
  min-height: clamp(560px, calc(0.88 * var(--pyramid-viewport-height, 100dvh)), 1080px);
  overflow: hidden;
  isolation: isolate;
  display: grid;
  align-items: end;
}
.pb-hero__media,
.pb-hero__media img {
  position: absolute; inset: 0;
  width: 100%; height: 100%;
  object-fit: cover;
  /* Portraits in a tall hero clip at the face — bias upward; JS parallax
     applies scale(1.08) on wide viewports only (see HeroParallax). */
  object-position: 50% 35%;
}
/* In edit mode, the image is wrapped in a button.pyramid-field--image so the
   operator can click to replace it. The wrapper inherits the absolute fill
   here so the hero looks the same as preview / published. Without this, the
   wrapper has no height (its only child is absolutely positioned), and the
   img collapses to 0 — making the hero appear empty in edit. */
.pb-hero__media .pyramid-field--image {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
}
/* Edit mode — image field fills the same shell as <img> in preview (tiles, lists, etc.). */
.pb-product__media > .pyramid-field--image,
.pb-service__media > .pyramid-field--image {
  display: block;
  width: 100%;
  height: 100%;
  min-height: 0;
}
.pb-feature__media .pyramid-field--image {
  display: block;
  width: 100%;
}
.pb-lookbook__item .pyramid-field--image {
  display: block;
  width: 100%;
  height: 100%;
}
.pb-blog__card .pyramid-field--image {
  display: block;
  width: 100%;
}
.pb-blog[data-variant="list"] .pb-blog__card .pyramid-field--image {
  height: 100%;
  min-height: 120px;
}
.pb-categories__tile .pyramid-field--image {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
}
/* Baseline: no extra scale here — HeroParallax applies translate + scale on
   wide viewports; double-scaling against nested editor scrollers looked broken. */
.pb-hero__media { z-index: -2; transform: translateZ(0); }
.pb-hero__veil {
  position: absolute; inset: 0; z-index: -1;
  background:
    radial-gradient(80% 60% at 30% 30%, rgba(0,0,0,0) 0%, rgba(0,0,0,0.55) 75%),
    linear-gradient(180deg, rgba(7,18,12,0) 30%, rgba(7,18,12,0.9) 100%);
  /* The veil is decoration only; it must NEVER intercept clicks
     (intercepting was making the "Add photo" affordance unclickable
     in fullbleed when the image was empty — the veil sat above the
     image button in stacking order). */
  pointer-events: none;
}
.pb-hero__inner {
  width: var(--ds-container);
  margin-inline: auto;
  padding-block: clamp(80px, 12cqi, 200px);
  color: var(--color-fg);
  display: grid;
  gap: 28px;
  max-width: 880px;
  /* Explicit stacking context so copy / CTAs always paint above the
     media + veil regardless of declaration order. Pairs with the
     z-index:-2 / -1 stack on .pb-hero__media / __veil. */
  position: relative;
  z-index: 1;
}
/* Empty-image affordance — fullbleed / centered.
   --------------------------------------------------
   In split, the image owns its own column and the default centered
   "Add photo" tile is correct. In fullbleed and centered the media
   sits BEHIND the copy; rendering the empty picker INSIDE .pb-hero__media
   (which has z-index:-2) stacks it under the headline + CTAs and the
   operator can't click it. Hero.block.tsx hoists the empty <Field> out
   into a sibling .pb-hero__image-pill div — that lives in the section's
   normal stacking context, so it can sit ABOVE .pb-hero__inner with a
   positive z-index. Visually, it's a small bottom-right pill so it
   never competes with the headline. */
.pb-hero__image-pill {
  position: absolute;
  inset: auto 16px 16px auto;
  z-index: 3;
  pointer-events: auto;
}
.pb-hero__image-pill .pyramid-field--image {
  position: static;
  width: auto;
  height: auto;
  display: inline-block;
}
.pb-hero__image-pill .pe-image-field__empty {
  width: auto;
  height: auto;
  aspect-ratio: auto;
  padding: 8px 14px;
  border-radius: 999px;
  background: color-mix(in oklab, var(--pb-overlay-deep) 86%, transparent);
  color: #fff;
  border: 1px solid rgba(255, 255, 255, 0.18);
  box-shadow: 0 10px 28px -8px rgba(0, 0, 0, 0.5);
  backdrop-filter: blur(14px) saturate(140%);
  -webkit-backdrop-filter: blur(14px) saturate(140%);
}
.pb-hero__image-pill .pe-image-field__empty-inner {
  flex-direction: row;
  align-items: center;
  gap: 8px;
}
.pb-hero__image-pill .pe-image-field__empty-icon svg {
  width: 16px;
  height: 16px;
}
.pb-hero__image-pill .pe-image-field__empty-title {
  font-size: 12px;
  font-weight: 600;
}
.pb-hero__image-pill .pe-image-field__empty-hint {
  display: none;
}
.pb-hero__eyebrow {
  display: inline-flex; align-items: center; gap: 10px;
  padding: 8px 14px; border-radius: 999px;
  background: rgba(245,241,230,0.08);
  border: 1px solid var(--color-border);
  font-size: 13px; letter-spacing: 0.08em; text-transform: uppercase;
  width: max-content;
}
.pb-hero__title {
  font-family: var(--ds-font-display);
  font-size: clamp(48px, 8cqi, 128px);
  line-height: 0.95;
  letter-spacing: -0.03em;
  margin: 0;
  font-weight: 700;
}
.pb-hero__title em { font-style: italic; color: var(--color-accent); font-weight: 500; }
.pb-hero__sub {
  font-size: clamp(16px, 1.5cqi, 22px);
  max-width: 60ch;
  color: var(--color-fg-muted);
  margin: 0;
}
.pb-hero__ctas { display: flex; gap: 14px; flex-wrap: wrap; row-gap: 10px; }
.pb-hero__ghost {
  display: inline-flex; align-items: center; gap: 10px;
  padding: 14px 22px; border-radius: 999px;
  background: transparent; color: var(--color-fg);
  border: 1px solid var(--color-border);
  text-decoration: none; font-weight: 600;
}
.pb-hero[data-variant="split"] {
  display: grid;
  grid-template-columns: 1fr 1fr;
  align-items: stretch;
}
.pb-hero[data-variant="split"] .pb-hero__media {
  position: relative;
  border-radius: var(--ds-radius-lg);
  overflow: hidden;
  margin: 24px;
}
.pb-hero[data-variant="split"] .pb-hero__veil { display: none; }

/* Centered: copy + CTAs centered horizontally over a full-bleed media
   layer. Slightly tighter overall so the centered axis reads cleanly. */
.pb-hero[data-variant="centered"] {
  align-items: center;
  text-align: center;
}
.pb-hero[data-variant="centered"] .pb-hero__inner {
  margin-inline: auto;
  align-items: center;
  justify-items: center;
  max-width: 760px;
}
.pb-hero[data-variant="centered"] .pb-hero__eyebrow,
.pb-hero[data-variant="centered"] .pb-hero__sub {
  margin-inline: auto;
}
.pb-hero[data-variant="centered"] .pb-hero__sub {
  text-wrap: balance;
}
.pb-hero[data-variant="centered"] .pb-hero__ctas {
  justify-content: center;
}

@container pyramid (max-width: 480px) {
  .pb-hero__ctas {
    flex-direction: column;
    align-items: stretch;
  }
  .pb-hero__ctas .pyramid-cta,
  .pb-hero__ctas .pb-hero__ghost {
    width: 100%;
    justify-content: center;
  }
}

/* Fullbleed is the natural default — no overrides needed beyond the
   base .pb-hero rules. We add an explicit empty selector so the
   variant data-attribute targets something for forward-compat. */
.pb-hero[data-variant="fullbleed"] { /* default look — base rules apply */ }

/* ---------- Nav ---------- */
.pb-nav-host {
  width: 100%;
}
.pb-nav-host[data-nav-position="sticky"] .pb-nav {
  position: sticky;
  top: 0;
}
.pb-nav-host[data-nav-position="fixed"] .pb-nav {
  position: fixed;
  left: 0;
  right: 0;
  top: 0;
  width: 100%;
}
/* Reserves space so fixed nav doesn’t cover the first section. The bar
   height varies by variant (minimal tightens block padding); 60px sits
   between minimal (~50px inner) and default (~58px inner) + 1px border. */
.pb-nav-host[data-nav-position="fixed"] .pb-nav__spacer {
  height: 60px;
  width: 100%;
  flex-shrink: 0;
}
.pb-nav[data-variant="minimal"] ~ .pb-nav__spacer,
.pb-nav-host:has(.pb-nav[data-variant="minimal"]) .pb-nav__spacer {
  height: 52px;
}
.pb-nav {
  z-index: var(--ds-z-sticky);
  backdrop-filter: saturate(140%) blur(18px);
  background: color-mix(in oklab, var(--color-bg) 75%, transparent);
  border-bottom: 1px solid var(--color-border);
}
.pb-nav__inner {
  width: var(--ds-container);
  margin-inline: auto;
  display: flex; align-items: center; justify-content: space-between;
  padding: 18px 0;
}
.pb-nav__brand { font-family: var(--ds-font-display); font-weight: 700; font-size: 22px; letter-spacing: -0.02em; }
.pb-nav__brand em { color: var(--color-accent); font-style: normal; }
/* Center cluster: link list + editor-only add control stay grouped so CTAs
   keep the same horizontal slot as preview (add isn’t an extra flex column). */
.pb-nav__mid {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 12px;
  flex: 1 1 auto;
  min-width: 0;
  overflow-x: auto;
  overflow-y: visible;
  scrollbar-width: thin;
}
.pb-nav__edit-add-link {
  flex-shrink: 0;
}
/* Desktop row: never shrink link items to zero width (that caused per-letter
   wrapping). Prefer horizontal scroll inside the cluster if someone packs
   many links before the hard editor cap. */
.pb-nav__links {
  display: flex;
  flex-wrap: nowrap;
  gap: 28px;
  list-style: none;
  padding: 0;
  margin: 0;
  min-width: 0;
}
.pb-nav__links li { flex-shrink: 0; }
.pb-nav__links a {
  color: var(--color-fg-muted);
  text-decoration: none;
  font-weight: 500;
  white-space: nowrap;
}
.pb-nav__links a:hover { color: var(--color-fg); }
/* Editor edit mode: obvious non-production chrome (preview / publish omit this). */
.pb-nav[data-pe-nav-edit="true"] {
  outline: 2px dashed color-mix(in oklab, var(--color-accent) 55%, var(--color-border));
  outline-offset: -2px;
}
.pb-nav__cta {
  display: flex;
  flex-wrap: wrap;
  gap: 10px 12px;
  align-items: center;
  justify-content: flex-end;
}
/* Ghost / outline second action — pairs with solid .pyramid-cta in the same cluster. */
.pb-nav__secondary-cta {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 10px 18px;
  border-radius: 999px;
  border: 1px solid var(--color-border-strong);
  font-weight: 600;
  font-size: 14px;
  text-decoration: none;
  color: var(--color-fg);
  white-space: nowrap;
  transition: border-color 180ms ease, background 180ms ease, color 180ms ease;
}
.pb-nav__secondary-cta:hover {
  border-color: var(--color-accent);
  color: var(--color-accent);
  background: color-mix(in oklab, var(--color-accent) 8%, transparent);
}
@media (prefers-reduced-motion: no-preference) {
  .pb-nav__secondary-cta {
    transition: border-color 180ms ease, background 180ms ease, color 180ms ease, transform 180ms ease;
  }
}

/* Hamburger toggle — hidden on wide layouts; the @container rule at
   1024px below switches it on and collapses the link list (tablet +
   phone — iPad frame is 834px wide, still too tight for a full row).
   Three-bar icon is built from spans so we don't need an SVG asset. */
.pb-nav__toggle {
  display: none;
  align-items: center;
  justify-content: center;
  width: 40px;
  height: 40px;
  border: 0;
  background: transparent;
  cursor: pointer;
  padding: 0;
  flex-direction: column;
  gap: 4px;
}
.pb-nav__toggle-bar {
  display: block;
  width: 22px;
  height: 2px;
  background: var(--color-fg);
  border-radius: 2px;
  transition: transform 180ms ease, opacity 180ms ease;
}
/* When the menu is open we morph the three bars into an X so the
   user gets affordance that this same control closes the menu. */
.pb-nav[data-open="true"] .pb-nav__toggle-bar:nth-child(1) {
  transform: translateY(6px) rotate(45deg);
}
.pb-nav[data-open="true"] .pb-nav__toggle-bar:nth-child(2) {
  opacity: 0;
}
.pb-nav[data-open="true"] .pb-nav__toggle-bar:nth-child(3) {
  transform: translateY(-6px) rotate(-45deg);
}

/* Minimal nav variant — drop the right-side CTA and tighten link
   weights so the bar reads as quiet wayfinding instead of a primary
   action surface. Used by editorial/blog sites that don't want a
   "buy now" pressure point on every page. */
.pb-nav[data-variant="minimal"] .pb-nav__cta { display: none; }
.pb-nav[data-variant="minimal"] .pb-nav__inner { padding-block: 14px; }
.pb-nav[data-variant="minimal"] .pb-nav__links { font-weight: 400; gap: 22px; }

/* Contrast — inverted dark bar. The default variant is frosted glass
   tied to --color-bg, which can be near-identical to --color-bg-emphasis
   on light themes (the previous "contrast" was a 1px tint difference at
   best). True contrast inverts to the foreground tone so the bar reads
   as a deliberate, premium fixture in any tenant theme. Tokens are
   color-mixed so accent-on-dark stays brand-safe. */
.pb-nav[data-variant="contrast"] {
  background: var(--color-fg);
  backdrop-filter: none;
  -webkit-backdrop-filter: none;
  border-bottom-color: color-mix(in oklab, var(--color-fg) 70%, var(--color-bg));
  border-bottom-width: 1px;
  color: var(--color-bg);
}
.pb-nav[data-variant="contrast"] .pb-nav__brand,
.pb-nav[data-variant="contrast"] .pb-nav__brand em {
  color: var(--color-bg);
}
.pb-nav[data-variant="contrast"] .pb-nav__links a {
  color: color-mix(in oklab, var(--color-bg) 78%, var(--color-fg));
}
.pb-nav[data-variant="contrast"] .pb-nav__links a:hover {
  color: var(--color-bg);
}
.pb-nav[data-variant="contrast"] .pb-nav__toggle-bar {
  background: var(--color-bg);
}
.pb-nav[data-variant="contrast"] .pb-nav__secondary-cta {
  color: var(--color-bg);
  border-color: color-mix(in oklab, var(--color-bg) 35%, transparent);
}
.pb-nav[data-variant="contrast"] .pb-nav__secondary-cta:hover {
  border-color: var(--color-accent);
  color: var(--color-accent);
  background: color-mix(in oklab, var(--color-accent) 18%, transparent);
}

/* ---------- Marquee ---------- */
.pb-marquee {
  overflow: hidden;
  border-block: 1px solid var(--color-border);
  background: var(--color-bg-emphasis);
  padding-block: 32px;
}
.pb-marquee__track {
  display: flex; gap: 64px;
  animation: pb-marquee 38s linear infinite;
  width: max-content;
}
.pb-marquee__item {
  font-family: var(--ds-font-display);
  font-size: clamp(22px, 3cqi, 40px);
  color: var(--color-fg-muted);
  white-space: nowrap;
  letter-spacing: -0.01em;
}
@keyframes pb-marquee { to { transform: translateX(-50%); } }
.pb-marquee--editing { overflow: visible; }
.pb-marquee__edit {
  display: flex;
  flex-wrap: wrap;
  gap: 18px 32px;
  align-items: center;
  justify-content: center;
  padding-inline: 24px;
}
.pb-marquee[data-variant="soft"] {
  border-block-color: color-mix(in oklab, var(--color-border) 55%, transparent);
  background: color-mix(in oklab, var(--color-bg-emphasis) 65%, transparent);
}

/* ---------- Product Grid ---------- */
.pb-products__head {
  display: flex; align-items: end; justify-content: space-between; gap: 20px; margin-bottom: 40px;
}
.pb-products__title {
  font-family: var(--ds-font-display);
  font-size: clamp(32px, 5cqi, 64px); margin: 0; letter-spacing: -0.02em; line-height: 1;
}
.pb-products__grid {
  display: grid; gap: 24px;
  grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));
}
.pb-products__grid[data-variant="dense"] {
  gap: 14px;
  grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
}
.pb-product {
  border-radius: var(--ds-radius-lg);
  background: var(--color-bg-emphasis);
  border: 1px solid var(--color-border);
  overflow: hidden;
  position: relative;
  transition: transform 300ms var(--ds-ease);
}
.pb-product__media {
  aspect-ratio: 4 / 5;
  /* Token-driven backdrop fills the space while the product photo
     loads (and stays visible behind transparent PNGs). Was hardcoded
     to noir-2027's #0e1d14, which leaked dispensary theming into every
     other theme — fixed in PR #19. */
  background: var(--color-bg-emphasis);
  position: relative;
}
.pb-product__media img { width: 100%; height: 100%; object-fit: cover; }
.pb-product__chips {
  position: absolute; top: 14px; left: 14px;
  display: flex; gap: 6px; flex-wrap: wrap;
}
.pb-product__chip {
  padding: 6px 10px;
  font-size: 11px; font-weight: 700; letter-spacing: 0.06em; text-transform: uppercase;
  background: rgba(0,0,0,0.55); color: #fff; border-radius: 999px;
  backdrop-filter: blur(6px);
}
.pb-product__chip--accent { background: var(--color-accent); color: var(--color-accent-fg); }
.pb-product__body { padding: 18px 18px 22px; display: grid; gap: 8px; }
.pb-product__name { font-size: 18px; font-weight: 600; margin: 0; }
.pb-product__strain { color: var(--color-fg-muted); font-size: 13px; margin: 0; text-transform: uppercase; letter-spacing: 0.08em; }
.pb-product__row { display: flex; align-items: center; justify-content: space-between; margin-top: 6px; }
.pb-product__price { font-size: 20px; font-weight: 700; }
.pb-product__add {
  width: 38px; height: 38px; border-radius: 50%;
  background: var(--color-accent); color: var(--color-accent-fg);
  border: 0; cursor: pointer; font-size: 22px; line-height: 1;
}

/* ---------- Feature Split ---------- */
.pb-feature {
  display: grid; gap: clamp(24px, 4cqi, 80px);
  grid-template-columns: 1fr 1fr; align-items: center;
}
.pb-feature[data-flip="true"] .pb-feature__media { order: 2; }
.pb-feature__media {
  width: 100%;
  max-width: min(480px, 100%);
  min-width: 0;
}
.pb-feature[data-variant="imageLeft"] .pb-feature__media { justify-self: start; }
.pb-feature[data-variant="imageRight"] .pb-feature__media { justify-self: end; }
.pb-feature[data-variant="stacked"] .pb-feature__media {
  justify-self: center;
  max-width: min(560px, 100%);
}
.pb-feature__media :is(img, picture) {
  display: block;
  width: 100%;
  border-radius: var(--ds-radius-lg);
}
.pb-feature__media img {
  height: auto;
  max-height: min(calc(0.5 * var(--pyramid-viewport-height, 100dvh)), 440px);
  object-fit: cover;
  aspect-ratio: 4 / 5;
}
.pb-feature[data-variant="imageLeft"] .pb-feature__media img {
  box-shadow: 14px 14px 0 color-mix(in srgb, var(--color-accent) 22%, transparent);
}
.pb-feature[data-variant="imageRight"] .pb-feature__media img {
  box-shadow: -14px 14px 0 color-mix(in srgb, var(--color-accent) 22%, transparent);
}
.pb-feature[data-variant="stacked"] .pb-feature__media img { box-shadow: none; }
.pb-feature__eyebrow {
  display: inline-block; padding: 6px 12px; border-radius: 999px;
  background: var(--color-bg-emphasis); border: 1px solid var(--color-border);
  font-size: 12px; letter-spacing: 0.08em; text-transform: uppercase; margin-bottom: 18px;
}
.pb-feature__title {
  font-family: var(--ds-font-display);
  font-size: clamp(28px, 4cqi, 56px); margin: 0 0 16px; line-height: 1.05; letter-spacing: -0.02em;
}
.pb-feature__body { color: var(--color-fg-muted); font-size: 17px; line-height: 1.6; max-width: 52ch; }
.pb-feature__list { margin-top: 24px; padding: 0; list-style: none; display: grid; gap: 12px; }
.pb-feature__list li { display: flex; gap: 10px; align-items: start; }
.pb-feature__list li::before { content: "—"; color: var(--color-accent); font-weight: 700; }

.pb-feature[data-variant="stacked"] {
  grid-template-columns: 1fr;
  gap: 28px;
}
.pb-feature[data-variant="stacked"] .pb-feature__media { order: 0; }

@container pyramid (max-width: 720px) {
  .pb-feature { grid-template-columns: 1fr; }
  .pb-feature[data-flip="true"] .pb-feature__media { order: 0; }
  .pb-feature__media,
  .pb-feature[data-variant="imageLeft"] .pb-feature__media,
  .pb-feature[data-variant="imageRight"] .pb-feature__media,
  .pb-feature[data-variant="stacked"] .pb-feature__media {
    justify-self: stretch;
    max-width: 100%;
  }
  .pb-feature__media img {
    max-height: min(calc(0.38 * var(--pyramid-viewport-height, 100dvh)), 340px);
    aspect-ratio: 16 / 10;
    box-shadow: none;
  }
}

/* ---------- Testimonials ---------- */
.pb-testimonials {
  display: grid; gap: 24px;
  grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
}
.pb-testimonial {
  padding: 28px;
  border-radius: var(--ds-radius-lg);
  background: var(--color-bg-emphasis);
  border: 1px solid var(--color-border);
  display: grid; gap: 18px;
}
.pb-testimonial__stars { color: var(--color-accent); letter-spacing: 4px; }
.pb-testimonial__stars--editable {
  display: inline-flex;
  gap: 2px;
  letter-spacing: 0;
  margin-bottom: 4px;
}
.pb-testimonial__star {
  background: transparent;
  border: 0;
  padding: 2px 1px;
  font: inherit;
  font-size: 18px;
  line-height: 1;
  color: color-mix(in srgb, var(--color-fg) 18%, transparent);
  cursor: pointer;
  transition: color 100ms ease, transform 100ms ease;
}
.pb-testimonial__star:hover { transform: scale(1.08); }
.pb-testimonial__star[data-active="true"] { color: var(--color-accent); }
.pb-testimonial__quote { font-size: 18px; line-height: 1.5; margin: 0; }
.pb-testimonial__who { display: flex; align-items: center; gap: 12px; }
.pb-testimonial__avatar { width: 40px; height: 40px; border-radius: 50%; object-fit: cover; }

.pb-testimonials[data-variant="plain"] .pb-testimonial {
  background: transparent;
  border: 0;
  padding: 20px 8px;
}
.pb-testimonials[data-variant="plain"] .pb-testimonial__quote {
  font-size: clamp(20px, 3cqi, 26px);
  font-style: italic;
}
.pb-testimonials[data-variant="compact"] {
  gap: 16px;
  grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
}
.pb-testimonials[data-variant="compact"] .pb-testimonial {
  padding: 18px 20px;
  gap: 12px;
}

/* ---------- Stats ---------- */
.pb-stats {
  display: grid; gap: 32px;
  grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
  text-align: center;
}
.pb-stat__num {
  font-family: var(--ds-font-display);
  font-size: clamp(48px, 7cqi, 96px); margin: 0; line-height: 1; color: var(--color-accent);
  letter-spacing: -0.04em;
}
.pb-stat__label { color: var(--color-fg-muted); margin-top: 8px; font-size: 14px; letter-spacing: 0.06em; text-transform: uppercase; }
/* Cards variant — each stat sits in its own elevated card so the row
   reads as a bento of facts instead of a single typographic surface.
   Useful when stats live above the fold in a spec page. */
.pb-stats[data-variant="cards"] > * {
  padding: 28px 24px;
  border-radius: var(--ds-radius-lg);
  background: color-mix(in oklab, var(--color-bg) 14%, transparent);
  border: 1px solid color-mix(in oklab, var(--color-bg) 22%, transparent);
}
/* Bare variant — drops the inverse tone (set in component) and uses
   foreground accent for numbers. Reads as quiet credibility chips
   inside a long content page rather than a hero band. */
.pb-stats[data-variant="bare"] {
  gap: 24px;
}
.pb-stats[data-variant="bare"] .pb-stat__num {
  color: var(--color-fg);
  font-size: clamp(40px, 5cqi, 64px);
}
.pb-stats[data-variant="bare"] .pb-stat__label {
  color: var(--color-fg-muted);
}

/* ---------- Lookbook ---------- */
.pb-lookbook {
  display: grid;
  gap: 14px;
  grid-template-columns: repeat(6, 1fr);
  grid-auto-rows: 200px;
}
.pb-lookbook__item { border-radius: var(--ds-radius); overflow: hidden; }
.pb-lookbook__item img { width: 100%; height: 100%; object-fit: cover; transition: transform 600ms var(--ds-ease); }
.pb-lookbook__item:hover img { transform: scale(1.06); }

.pb-lookbook[data-variant="bento"] .pb-lookbook__item:nth-child(1) { grid-column: span 4; grid-row: span 2; }
.pb-lookbook[data-variant="bento"] .pb-lookbook__item:nth-child(2) { grid-column: span 2; }
.pb-lookbook[data-variant="bento"] .pb-lookbook__item:nth-child(3) { grid-column: span 2; }
.pb-lookbook[data-variant="bento"] .pb-lookbook__item:nth-child(4) { grid-column: span 3; }
.pb-lookbook[data-variant="bento"] .pb-lookbook__item:nth-child(5) { grid-column: span 3; }
.pb-lookbook[data-variant="bento"] .pb-lookbook__item:nth-child(6) { grid-column: span 2; }
.pb-lookbook[data-variant="bento"] .pb-lookbook__item:nth-child(7) { grid-column: span 4; }

.pb-lookbook[data-variant="uniform"] {
  grid-template-columns: repeat(3, 1fr);
  grid-auto-rows: minmax(160px, 1fr);
}
.pb-lookbook[data-variant="uniform"] .pb-lookbook__item {
  grid-column: span 1 !important;
  grid-row: span 1 !important;
}

.pb-lookbook[data-variant="compact"] {
  gap: 8px;
  grid-auto-rows: 150px;
}
.pb-lookbook[data-variant="compact"] .pb-lookbook__item:nth-child(1) { grid-column: span 4; grid-row: span 2; }
.pb-lookbook[data-variant="compact"] .pb-lookbook__item:nth-child(2) { grid-column: span 2; }
.pb-lookbook[data-variant="compact"] .pb-lookbook__item:nth-child(3) { grid-column: span 2; }
.pb-lookbook[data-variant="compact"] .pb-lookbook__item:nth-child(4) { grid-column: span 3; }
.pb-lookbook[data-variant="compact"] .pb-lookbook__item:nth-child(5) { grid-column: span 3; }
.pb-lookbook[data-variant="compact"] .pb-lookbook__item:nth-child(6) { grid-column: span 2; }
.pb-lookbook[data-variant="compact"] .pb-lookbook__item:nth-child(7) { grid-column: span 4; }

@container pyramid (max-width: 720px) {
  .pb-lookbook { grid-template-columns: repeat(2, 1fr); grid-auto-rows: 180px; }
  .pb-lookbook__item { grid-column: span 1 !important; grid-row: span 1 !important; }
}

/* ---------- FAQ ---------- */
.pb-faq { max-width: 800px; margin: 0 auto; display: grid; gap: 12px; }
.pb-faq details {
  border-radius: var(--ds-radius);
  border: 1px solid var(--color-border);
  background: var(--color-bg-emphasis);
  padding: 18px 22px;
}
.pb-faq details[open] { background: color-mix(in oklab, var(--color-accent) 10%, var(--color-bg-emphasis)); }
.pb-faq summary {
  cursor: pointer; font-weight: 600; font-size: 17px; list-style: none;
  display: flex; align-items: center; justify-content: space-between;
}
.pb-faq summary::after { content: "+"; font-size: 22px; color: var(--color-accent); transition: transform 200ms; }
.pb-faq details[open] summary::after { transform: rotate(45deg); }
.pb-faq p { color: var(--color-fg-muted); margin: 12px 0 0; line-height: 1.6; }

.pb-faq[data-variant="spacious"] { gap: 20px; }
.pb-faq[data-variant="spacious"] details { padding: 24px 28px; }
.pb-faq[data-variant="compact"] { gap: 8px; }
.pb-faq[data-variant="compact"] details { padding: 14px 16px; }

/* ---------- CTA Banner ---------- */
.pb-cta {
  position: relative;
  border-radius: var(--ds-radius-lg);
  overflow: hidden;
  padding: clamp(48px, 8cqi, 120px);
  text-align: center;
  isolation: isolate;
  background:
    radial-gradient(60% 80% at 30% 20%, color-mix(in oklab, var(--color-accent) 25%, transparent), transparent 70%),
    linear-gradient(135deg, var(--color-bg-emphasis), var(--color-bg));
  border: 1px solid var(--color-border);
}
.pb-cta__copy { /* wrapper for text — lets split variant position it */ }
.pb-cta__action { /* wrapper for the CTA button */ }
.pb-cta__title {
  font-family: var(--ds-font-display);
  font-size: clamp(36px, 6cqi, 88px); margin: 0 0 16px; letter-spacing: -0.03em; line-height: 1;
}
.pb-cta__sub { color: var(--color-fg-muted); font-size: 18px; margin: 0 0 32px; }

/* Centered: default stacked layout — everything centered. */
.pb-cta[data-variant="centered"] { /* base rules already handle this */ }
.pb-cta[data-variant="centered"] .pb-cta__sub { margin-bottom: 32px; }

/* Split: two-column — copy on the left, button on the right. */
.pb-cta[data-variant="split"] {
  display: grid;
  grid-template-columns: 1fr auto;
  align-items: center;
  gap: clamp(24px, 4cqi, 64px);
  text-align: left;
}
.pb-cta[data-variant="split"] .pb-cta__sub { margin-bottom: 0; }
.pb-cta[data-variant="split"] .pb-cta__action {
  display: flex;
  align-items: center;
  justify-content: flex-end;
}

.pb-cta[data-variant="minimal"] {
  padding: clamp(28px, 5cqi, 64px);
  background: var(--color-bg-emphasis);
  border: 1px solid var(--color-border);
}
.pb-cta[data-variant="minimal"] .pb-cta__title {
  font-size: clamp(28px, 5cqi, 52px);
}
.pb-cta[data-variant="minimal"] .pb-cta__sub { margin-bottom: 24px; font-size: 16px; }

.pb-cta[data-variant="gradient"] {
  background:
    linear-gradient(
      145deg,
      color-mix(in oklab, var(--color-accent) 38%, var(--color-bg-emphasis)) 0%,
      var(--color-bg-emphasis) 48%,
      color-mix(in oklab, var(--color-accent) 14%, var(--color-bg)) 100%
    );
  border: 1px solid color-mix(in oklab, var(--color-accent) 35%, var(--color-border));
  box-shadow:
    0 24px 64px color-mix(in oklab, var(--color-accent) 12%, rgba(0, 0, 0, 0.35)),
    inset 0 1px 0 color-mix(in oklab, var(--color-fg) 8%, transparent);
}
.pb-cta[data-variant="gradient"] .pb-cta__title {
  text-shadow: 0 1px 24px color-mix(in oklab, var(--color-bg) 40%, transparent);
}

/* ---------- Footer ---------- */
.pb-footer {
  background: var(--color-bg-emphasis);
  border-top: 1px solid var(--color-border);
  padding-block: 64px 32px;
  padding-inline: clamp(20px, 5vw, 48px);
}
.pb-footer__inner {
  width: var(--ds-container); margin-inline: auto;
  display: grid; gap: 48px;
  grid-template-columns: 2fr repeat(3, 1fr);
}
.pb-footer__brand { font-family: var(--ds-font-display); font-size: 28px; letter-spacing: -0.02em; margin: 0 0 12px; }
.pb-footer__brand em { color: var(--color-accent); font-style: normal; }
.pb-footer__col h4 { margin: 0 0 16px; font-size: 13px; letter-spacing: 0.08em; text-transform: uppercase; color: var(--color-fg-muted); }
.pb-footer__col ul { list-style: none; padding: 0; margin: 0; display: grid; gap: 10px; }
.pb-footer__col a { color: var(--color-fg-muted); text-decoration: none; }
.pb-footer__bottom {
  width: var(--ds-container); margin: 48px auto 0;
  padding-top: 24px; border-top: 1px solid var(--color-border);
  display: flex; justify-content: space-between; color: var(--color-fg-muted); font-size: 13px;
}

.pb-footer[data-variant="compact"] {
  padding-block: 40px 24px;
}
.pb-footer[data-variant="compact"] .pb-footer__inner { gap: 28px; }
.pb-footer[data-variant="compact"] .pb-footer__brand { font-size: 22px; }
.pb-footer[data-variant="compact"] .pb-footer__bottom { margin-top: 32px; padding-top: 16px; }

.pb-footer[data-variant="split"] .pb-footer__inner {
  grid-template-columns: repeat(3, 1fr);
}
.pb-footer[data-variant="split"] .pb-footer__inner > :first-child {
  grid-column: 1 / -1;
}

@container pyramid (max-width: 720px) {
  .pb-footer {
    padding-inline: 16px;
    padding-block-end: max(32px, env(safe-area-inset-bottom, 0px));
  }
  .pb-footer__inner { grid-template-columns: 1fr 1fr; }
  .pb-footer[data-variant="split"] .pb-footer__inner { grid-template-columns: 1fr 1fr; }
}
@container pyramid (max-width: 480px) {
  .pb-footer__inner { grid-template-columns: 1fr; gap: 32px; }
  .pb-footer__bottom { flex-direction: column; gap: 8px; text-align: center; }
}

/* ---------- Age gate ----------
   Branches via visitorOverlayBranch + useEditMode():
     suppressed → .pb-agegate__suppressed
     editCompact → .pb-agegate__compact (in-flow rail; focus canvas uses editExpanded)
     editExpanded → .pb-agegate__preview + card
     visitor → .pb-agegate__overlay (preview/prod) */
.pb-agegate__compact {
  display: flex;
  align-items: center;
  gap: 14px;
  margin: 0 0 12px;
  padding: 12px 16px;
  border-radius: var(--ds-radius-lg);
  border: 1px solid var(--color-border);
  background: var(--color-bg-emphasis);
  box-shadow: 0 1px 0 color-mix(in srgb, var(--color-fg) 5%, transparent);
  max-width: min(100%, 400px);
}
.pb-agegate__compact-badge {
  flex-shrink: 0;
  width: 44px;
  height: 44px;
  border-radius: 999px;
  display: grid;
  place-items: center;
  font-size: 13px;
  font-weight: 800;
  letter-spacing: 0.02em;
  color: var(--color-accent-fg);
  background: var(--color-accent);
  border: 2px solid color-mix(in oklab, var(--color-accent) 75%, var(--color-border));
}
.pb-agegate__compact-copy {
  display: grid;
  gap: 2px;
  min-width: 0;
  text-align: left;
}
.pb-agegate__compact-title {
  font-size: 14px;
  font-weight: 600;
  color: var(--color-fg);
}
.pb-agegate__compact-hint {
  font-size: 12px;
  color: var(--color-fg-muted);
  line-height: 1.35;
}

.pb-agegate__preview {
  position: relative;
  padding: clamp(28px, 6cqi, 56px) 20px clamp(40px, 8cqi, 80px);
  background:
    radial-gradient(ellipse 80% 60% at 50% 0%, color-mix(in oklab, var(--color-accent) 18%, transparent), transparent 65%),
    linear-gradient(180deg, color-mix(in oklab, var(--color-bg) 92%, #0f172a) 0%, var(--color-bg-emphasis) 100%);
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 16px;
  border-block: 1px dashed color-mix(in oklab, var(--color-accent) 35%, var(--color-border));
}
.pb-agegate__preview-chrome {
  width: 100%;
  max-width: 520px;
  display: flex;
  flex-direction: column;
  gap: 6px;
  text-align: center;
}
.pb-agegate__preview-badge {
  display: inline-block;
  align-self: center;
  padding: 4px 10px;
  border-radius: 999px;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: color-mix(in oklab, var(--color-accent-fg) 90%, var(--color-fg));
  background: color-mix(in oklab, var(--color-accent) 22%, transparent);
  border: 1px solid color-mix(in oklab, var(--color-accent) 45%, var(--color-border));
}
.pb-agegate__preview-hint {
  margin: 0;
  font-size: 12px;
  line-height: 1.45;
  color: var(--color-fg-muted);
  max-width: 42ch;
  align-self: center;
}
.pb-agegate__preview .pb-agegate__card {
  width: 100%;
  max-width: 520px;
  border-radius: var(--ds-radius-lg);
  background: var(--color-bg);
  border: 1px solid var(--color-border);
  padding: 40px;
  text-align: center;
  box-shadow: var(--ds-shadow-2);
}
.pb-agegate__card--editor-float {
  box-shadow:
    0 24px 48px color-mix(in oklab, var(--pb-shadow-deep) 28%, transparent),
    0 0 0 1px color-mix(in oklab, var(--color-accent) 25%, var(--color-border));
}

.pb-agegate__suppressed {
  margin: 0 0 16px;
  padding: 12px 16px;
  border-radius: var(--ds-radius-md);
  border: 1px dashed color-mix(in oklab, var(--color-accent) 45%, var(--color-border));
  background: color-mix(in oklab, var(--color-bg-emphasis) 92%, var(--color-accent));
}
.pb-agegate__suppressed-inner {
  display: grid;
  gap: 8px;
  font-size: 13px;
  line-height: 1.4;
  color: var(--color-fg-muted);
}
.pb-agegate__suppressed-inner strong {
  color: var(--color-fg);
  font-size: 14px;
}
.pb-agegate__suppressed-meta strong {
  color: var(--color-fg);
}

.pb-agegate__overlay {
  position: fixed; inset: 0; z-index: var(--ds-z-overlay);
  background: color-mix(in oklab, var(--color-bg) 85%, black);
  backdrop-filter: blur(20px);
  display: grid; place-items: center; padding: 24px;
}
.pb-agegate__card {
  width: 100%; max-width: 520px;
  border-radius: var(--ds-radius-lg);
  background: var(--color-bg);
  border: 1px solid var(--color-border);
  padding: 40px;
  text-align: center;
  box-shadow: var(--ds-shadow-2);
}
.pb-agegate__card[data-variant="minimal"] {
  padding: 28px 22px;
  box-shadow: none;
}
.pb-agegate__card[data-variant="minimal"] .pb-agegate__title { font-size: 26px; }
.pb-agegate__card[data-variant="emphasis"] {
  border-width: 2px;
  border-color: var(--color-accent);
  box-shadow: 0 20px 50px color-mix(in oklab, var(--color-accent) 22%, transparent);
}
.pb-agegate__card[data-variant="emphasis"] .pb-agegate__title { font-size: 38px; }

.pb-agegate__title { font-family: var(--ds-font-display); font-size: 32px; margin: 0 0 12px; letter-spacing: -0.02em; }
.pb-agegate__row { display: flex; gap: 12px; justify-content: center; margin-top: 28px; }

/* ---------- Notice bar ---------- */
.pb-notice {
  background: var(--color-accent);
  color: var(--color-accent-fg);
  font-weight: 600;
  font-size: 13px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
}
.pb-notice__inner {
  width: var(--ds-container);
  margin-inline: auto;
  padding: 10px 0;
  display: flex; align-items: center; justify-content: center; gap: 16px; text-align: center;
  flex-wrap: wrap;
}
.pb-notice__text {
  white-space: normal;
  min-width: 0;
}
.pb-notice__inner .pyramid-cta {
  flex-shrink: 0;
  white-space: nowrap;
}
/* Notice CTA size (set from Edit button modal — notice bar only). */
.pb-notice[data-cta-size="compact"] .pyramid-cta:not(.pyramid-cta--link) {
  padding: 8px 14px;
  font-size: 12px;
}
.pb-notice[data-cta-size="default"] .pyramid-cta:not(.pyramid-cta--link) {
  padding: 10px 18px;
  font-size: 14px;
}
.pb-notice[data-cta-size="prominent"] .pyramid-cta:not(.pyramid-cta--link) {
  padding: 14px 22px;
  font-size: 15px;
}

.pb-notice[data-variant="quiet"] {
  background: var(--color-bg-emphasis);
  color: var(--color-fg-muted);
  border-block: 1px solid var(--color-border);
  text-transform: none;
  font-weight: 500;
  letter-spacing: 0.03em;
}
.pb-notice[data-variant="accent"] {
  background: color-mix(in oklab, var(--color-accent) 88%, black);
}

/* ---------- Categories ---------- */
.pb-categories {
  display: grid;
  gap: 16px;
  grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
}
.pb-categories__tile {
  position: relative;
  display: block;
  aspect-ratio: 4 / 5;
  border-radius: var(--ds-radius-lg);
  overflow: hidden;
  text-decoration: none;
  color: #fff;
  isolation: isolate;
  transition: transform 300ms var(--ds-ease);
  background: var(--color-bg-emphasis);
}
.pb-categories__tile:hover { transform: translateY(-6px); }
.pb-categories__tile img,
.pb-categories__tile .pyramid-img {
  position: absolute; inset: 0;
  width: 100%; height: 100%; object-fit: cover;
  transition: transform 600ms var(--ds-ease);
  z-index: -2;
  border-radius: 0 !important;
}
.pb-categories__tile:hover img { transform: scale(1.08); }
.pb-categories__tile::after {
  content: ""; position: absolute; inset: 0; z-index: -1;
  background: linear-gradient(180deg, rgba(0,0,0,0) 30%, rgba(0,0,0,0.85) 100%);
}
.pb-categories__label {
  position: absolute;
  bottom: 18px; left: 18px;
  font-family: var(--ds-font-display);
  font-size: 22px;
  font-weight: 700;
  letter-spacing: -0.01em;
}
/* Edit-mode tile chrome — replaces the wrapping <a> with a <div> so
   inline child Fields keep working, and surfaces an explicit "set href"
   pill at the top-right so the link target is still discoverable. */
.pb-categories__tile--editing { cursor: default; }
.pb-categories__tile--editing:hover { transform: none; }
.pb-categories__href-chip {
  position: absolute;
  top: 10px; right: 10px;
  z-index: 3;
  padding: 4px 10px;
  border-radius: 999px;
  background: rgba(0, 0, 0, 0.55);
  color: #fff;
  font-size: 11px;
  font-weight: 600;
  max-width: calc(100% - 20px);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
/* Icon-grid variant — compact 1:1 chips that read as a quick wayfinding
   row instead of full-bleed photo tiles. Lighter card surface so labels
   render in foreground tone (not on top of a darkened image). Used
   when the operator wants to highlight categories by glyph rather than
   hero imagery (e.g. a service menu with category icons). */
.pb-categories[data-variant="icons"] {
  grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));
  gap: 12px;
}
.pb-categories[data-variant="icons"] .pb-categories__tile {
  aspect-ratio: 1 / 1;
  background: var(--color-bg-emphasis);
  border: 1px solid var(--color-border);
  color: var(--color-fg);
  padding: 14px;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 10px;
}
.pb-categories[data-variant="icons"] .pb-categories__tile::after {
  display: none;
}
.pb-categories[data-variant="icons"] .pb-categories__tile img,
.pb-categories[data-variant="icons"] .pb-categories__tile .pyramid-img {
  position: relative;
  inset: auto;
  width: 56%;
  height: auto;
  aspect-ratio: 1 / 1;
  object-fit: contain;
  z-index: 0;
}
.pb-categories[data-variant="icons"] .pb-categories__tile .pyramid-field--image {
  position: relative;
  inset: auto;
  width: 56%;
  height: auto;
  aspect-ratio: 1 / 1;
}
.pb-categories[data-variant="icons"] .pb-categories__label {
  position: static;
  font-size: 14px;
  font-weight: 600;
  letter-spacing: -0.005em;
  text-align: center;
  color: var(--color-fg);
  font-family: var(--ds-font-body);
}
.pb-categories[data-variant="icons"] .pb-categories__tile:hover {
  border-color: var(--color-accent);
  transform: translateY(-3px);
}

/* ---------- Locations ---------- */
.pb-locations {
  display: grid; gap: 24px;
  grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
}
.pb-location {
  padding: 32px;
  border-radius: var(--ds-radius-lg);
  background: var(--color-bg);
  border: 1px solid var(--color-border);
  text-align: center;
}
.pb-location__city {
  font-family: var(--ds-font-display);
  font-size: 28px; margin: 0 0 16px; letter-spacing: -0.02em;
  color: var(--color-accent);
}
.pb-location__addr { color: var(--color-fg-muted); margin: 4px 0; }
.pb-location__phone { font-weight: 700; font-size: 18px; margin: 12px 0 4px; }
.pb-location__hours { color: var(--color-fg-muted); font-size: 14px; margin: 0; }
/* List variant — single column rows, left-aligned, divider lines.
   Better for >4 locations and dedicated "stores" pages where each
   row needs to read like a directory entry instead of a feature card. */
.pb-locations[data-variant="list"] {
  display: flex;
  flex-direction: column;
  gap: 0;
  border-top: 1px solid var(--color-border);
}
.pb-locations[data-variant="list"] .pb-location {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1.4fr) minmax(0, 1fr);
  gap: 24px;
  padding: 22px 0;
  border-radius: 0;
  border: 0;
  border-bottom: 1px solid var(--color-border);
  background: transparent;
  text-align: left;
  align-items: baseline;
}
.pb-locations[data-variant="list"] .pb-location__city {
  margin: 0;
  font-size: 22px;
}
.pb-locations[data-variant="list"] .pb-location__phone {
  margin: 0;
  font-size: 16px;
}
.pb-locations[data-variant="list"] .pb-location__hours {
  margin: 0;
}
.pb-locations[data-variant="list"] .pb-location__addr {
  margin: 0;
}
@container pyramid (max-width: 720px) {
  .pb-locations[data-variant="list"] .pb-location {
    grid-template-columns: 1fr;
    gap: 6px;
    padding: 18px 0;
  }
}

/* ---------- Service tiles ---------- */
.pb-services {
  display: grid; gap: 24px;
  grid-template-columns: repeat(auto-fit, minmax(380px, 1fr));
}
.pb-service {
  border-radius: var(--ds-radius-lg);
  overflow: hidden;
  background: var(--color-bg-emphasis);
  border: 1px solid var(--color-border);
  display: grid;
  grid-template-rows: auto 1fr;
}
.pb-service__media { aspect-ratio: 16 / 10; overflow: hidden; }
.pb-service__media img { width: 100%; height: 100%; object-fit: cover; }
.pb-service__body { padding: 32px; display: grid; gap: 16px; }
.pb-service__eyebrow {
  font-size: 12px; letter-spacing: 0.08em; text-transform: uppercase; color: var(--color-accent);
}
.pb-service__title {
  font-family: var(--ds-font-display);
  font-size: clamp(24px, 3cqi, 36px); margin: 0; line-height: 1.1; letter-spacing: -0.02em;
}
.pb-service__copy { color: var(--color-fg-muted); margin: 0; line-height: 1.6; }

.pb-services[data-variant="compact"] .pb-service__body { padding: 22px; }
.pb-services[data-variant="compact"] .pb-service__media { aspect-ratio: 16 / 9; }
.pb-services[data-variant="stacked"] {
  grid-template-columns: 1fr;
  max-width: 720px;
  margin-inline: auto;
}
.pb-services[data-variant="elevated"] .pb-service {
  border-color: color-mix(in oklab, var(--color-accent) 32%, var(--color-border));
  box-shadow:
    0 16px 36px color-mix(in oklab, var(--color-bg) 55%, rgba(0, 0, 0, 0.22)),
    0 0 0 1px color-mix(in oklab, var(--color-accent) 12%, transparent);
}
@media (prefers-reduced-motion: no-preference) {
  .pb-services[data-variant="elevated"] .pb-service {
    transition:
      transform 220ms cubic-bezier(0.25, 1, 0.5, 1),
      box-shadow 220ms ease,
      border-color 220ms ease;
  }
  .pb-services[data-variant="elevated"] .pb-service:hover {
    transform: translateY(-6px);
    box-shadow:
      0 22px 48px color-mix(in oklab, var(--color-accent) 18%, rgba(0, 0, 0, 0.28)),
      0 0 0 1px var(--color-accent);
    border-color: var(--color-accent);
  }
}

/* ---------- Benefits ---------- */
.pb-benefits {
  display: grid; gap: 32px;
  grid-template-columns: repeat(auto-fit, minmax(320px, 1fr));
}
.pb-benefit { padding: 0 8px; }
.pb-benefit__title {
  font-family: var(--ds-font-display);
  font-size: 28px; margin: 0 0 12px; letter-spacing: -0.02em;
  color: var(--color-accent);
}
.pb-benefit__body { color: var(--color-fg-muted); margin: 0; line-height: 1.6; max-width: 50ch; }

.pb-benefits[data-variant="cards"] .pb-benefit {
  padding: 24px 22px;
  border-radius: var(--ds-radius-lg);
  background: var(--color-bg-emphasis);
  border: 1px solid var(--color-border);
}
.pb-benefits[data-variant="tight"] {
  gap: 20px;
  grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
}

/* ---------- Trust strip ---------- */
.pb-truststrip__title {
  font-family: var(--ds-font-display);
  font-size: clamp(28px, 5cqi, 44px);
  letter-spacing: -0.02em;
  margin: 0 auto;
  max-width: 40ch;
  line-height: 1.15;
}
.pb-truststrip {
  list-style: none;
  margin: 0;
  padding: 16px 20px;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
  gap: 8px 4px;
  border-radius: var(--ds-radius-lg);
  background: var(--color-bg-emphasis);
  border: 1px solid var(--color-border);
}
.pb-truststrip[data-variant="quiet"] {
  background: color-mix(in oklab, var(--color-bg-emphasis) 60%, transparent);
}
.pb-truststrip__item {
  display: inline-flex;
  align-items: center;
  font-size: 13px;
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--color-fg-muted);
}
.pb-truststrip__item:not(:last-child)::after {
  content: "·";
  margin-left: 10px;
  color: var(--color-accent);
  font-weight: 700;
  opacity: 0.85;
}
.pb-truststrip__text { color: inherit; }

/* Marquee / ticker (duplicate row + translateX -50%, like pb-marquee) */
.pb-truststrip--marquee {
  overflow: hidden;
  list-style: none;
  margin: 0;
  padding: 0;
  border-radius: var(--ds-radius-lg);
  background: var(--color-bg-emphasis);
  border: 1px solid var(--color-border);
}
.pb-truststrip--marquee[data-variant="quiet"] {
  background: color-mix(in oklab, var(--color-bg-emphasis) 60%, transparent);
}
.pb-truststrip__viewport {
  overflow: hidden;
}
.pb-truststrip__track {
  display: flex;
  flex-wrap: nowrap;
  align-items: center;
  list-style: none;
  margin: 0;
  padding: 16px 20px;
  width: max-content;
  animation: pb-truststrip-marquee 42s linear infinite;
}
.pb-truststrip__track-item {
  display: inline-flex;
  align-items: center;
  flex-shrink: 0;
  font-size: 13px;
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--color-fg-muted);
  white-space: nowrap;
}
.pb-truststrip__track-sep {
  margin-inline: 10px;
  color: var(--color-accent);
  font-weight: 700;
  opacity: 0.85;
}
@keyframes pb-truststrip-marquee {
  to { transform: translateX(-50%); }
}
@media (prefers-reduced-motion: reduce) {
  .pb-truststrip__track {
    animation: none;
  }
}

/* ---------- Process steps ---------- */
.pb-process__title {
  font-family: var(--ds-font-display);
  font-size: clamp(32px, 6cqi, 52px);
  text-align: center;
  letter-spacing: -0.03em;
  margin: 0 0 48px;
  line-height: 1.1;
}
.pb-process {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: clamp(24px, 4cqi, 40px);
}
.pb-process[data-variant="horizontal"] {
  grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
}
.pb-process[data-variant="stacked"] {
  grid-template-columns: 1fr;
  max-width: 640px;
  margin-inline: auto;
}
.pb-process__step {
  margin: 0;
  padding: 0;
  /* Grid row stretch gives each li the same height; flex lets the card fill it */
  display: flex;
  flex-direction: column;
  min-height: 0;
}
.pb-process__step-inner {
  display: flex;
  gap: 20px;
  align-items: flex-start;
  flex: 1 1 auto;
  min-height: 0;
  padding: 24px 22px;
  border-radius: var(--ds-radius-lg);
  background: var(--color-bg-emphasis);
  border: 1px solid var(--color-border);
}
/* Editor: list-item wrapper defaults to align-items:flex-start — stretch so cards match row height */
.pb-process[data-variant="horizontal"] .pyramid-list-item--block {
  align-items: stretch;
  flex: 1 1 auto;
  min-height: 0;
  width: 100%;
}
.pb-process[data-variant="horizontal"] .pyramid-list-item--block .pyramid-list-item__remove {
  align-self: flex-start;
}
.pb-process__num {
  flex-shrink: 0;
  width: 44px;
  height: 44px;
  border-radius: 999px;
  display: flex;
  align-items: center;
  justify-content: center;
  font-family: var(--ds-font-display);
  font-weight: 700;
  font-size: 18px;
  background: color-mix(in oklab, var(--color-accent) 22%, var(--color-bg));
  color: var(--color-accent);
  border: 1px solid color-mix(in oklab, var(--color-accent) 45%, var(--color-border));
}
.pb-process__body { min-width: 0; }
.pb-process__step-title {
  font-family: var(--ds-font-display);
  font-size: 20px;
  margin: 0 0 10px;
  letter-spacing: -0.02em;
  line-height: 1.2;
}
.pb-process__step-body {
  margin: 0;
  color: var(--color-fg-muted);
  line-height: 1.6;
  font-size: 15px;
}

/* ---------- Brand strip ---------- */
.pb-brandstrip__head {
  display: grid; grid-template-columns: 1fr auto; gap: 24px; align-items: end; margin-bottom: 40px;
}
.pb-brandstrip__head > div { max-width: 60ch; }
.pb-brandstrip__grid {
  display: grid; gap: 12px;
  grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
}
.pb-brandstrip__chip {
  display: flex; align-items: center; justify-content: center;
  padding: 28px 16px;
  border-radius: var(--ds-radius);
  background: var(--color-bg-emphasis);
  border: 1px solid var(--color-border);
  font-family: var(--ds-font-display);
  font-size: 18px;
  letter-spacing: -0.01em;
  text-align: center;
  transition: border-color 200ms, transform 200ms;
}
.pb-brandstrip__chip:hover { border-color: var(--color-accent); transform: translateY(-2px); }
/* Marquee variant — published-only (editor stays in grid mode so chips
   remain click-editable). The track holds the brand list duplicated
   once and translates -50% to wrap seamlessly. */
.pb-brandstrip__marquee {
  overflow: hidden;
  mask-image: linear-gradient(90deg, transparent, #000 8%, #000 92%, transparent);
  -webkit-mask-image: linear-gradient(90deg, transparent, #000 8%, #000 92%, transparent);
}
.pb-brandstrip__marquee-track {
  display: flex;
  gap: 12px;
  width: max-content;
  animation: pb-brandstrip-marquee 36s linear infinite;
}
.pb-brandstrip__chip--marquee {
  flex-shrink: 0;
  min-width: 200px;
}
@keyframes pb-brandstrip-marquee {
  to { transform: translateX(-50%); }
}
@media (prefers-reduced-motion: reduce) {
  .pb-brandstrip__marquee-track { animation: none; }
}
@container pyramid (max-width: 720px) {
  .pb-brandstrip__head { grid-template-columns: 1fr; }
}

/* ---------- Blog cards ---------- */
.pb-blog {
  display: grid; gap: 24px;
  grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
}
.pb-blog__card {
  display: grid;
  grid-template-rows: auto 1fr;
  border-radius: var(--ds-radius-lg);
  overflow: hidden;
  background: var(--color-bg-emphasis);
  border: 1px solid var(--color-border);
  text-decoration: none;
  color: inherit;
  transition: transform 300ms var(--ds-ease), border-color 300ms;
}
.pb-blog__card:hover { transform: translateY(-4px); border-color: var(--color-accent); }
.pb-blog__card img { width: 100%; aspect-ratio: 16 / 10; object-fit: cover; }
.pb-blog__body { padding: 24px; display: grid; gap: 10px; }
.pb-blog__date { color: var(--color-fg-muted); font-size: 12px; letter-spacing: 0.08em; text-transform: uppercase; }
.pb-blog__title {
  font-family: var(--ds-font-display);
  font-size: 22px; margin: 0; line-height: 1.2; letter-spacing: -0.01em;
}
.pb-blog__excerpt { color: var(--color-fg-muted); margin: 0; line-height: 1.5; font-size: 14px; }
.pb-blog__more { color: var(--color-accent); font-weight: 600; font-size: 14px; margin-top: 4px; }

.pb-blog[data-variant="list"] {
  grid-template-columns: 1fr;
  gap: 16px;
}
.pb-blog[data-variant="list"] .pb-blog__card {
  grid-template-columns: minmax(100px, 180px) 1fr;
  grid-template-rows: minmax(0, 1fr);
}
.pb-blog[data-variant="list"] .pb-blog__card img {
  height: 100%;
  min-height: 120px;
}
.pb-blog[data-variant="compact"] {
  gap: 16px;
  grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
}
.pb-blog[data-variant="compact"] .pb-blog__body { padding: 18px; }

/* ---------- Newsletter ---------- */
.pb-newsletter {
  max-width: 640px;
  margin: 0 auto;
  text-align: center;
  padding: clamp(40px, 6cqi, 80px);
  border-radius: var(--ds-radius-lg);
  background:
    radial-gradient(60% 100% at 50% 0%, color-mix(in oklab, var(--color-accent) 18%, transparent), transparent 70%),
    var(--color-bg-emphasis);
  border: 1px solid var(--color-border);
}
.pb-newsletter__form {
  display: flex; gap: 10px; justify-content: center; margin-bottom: 16px; flex-wrap: wrap;
}
.pb-newsletter__input {
  flex: 1 1 280px;
  padding: 14px 18px;
  border-radius: 999px;
  border: 1px solid var(--color-border);
  background: var(--color-bg);
  color: var(--color-fg);
  font-size: 15px;
  font-family: inherit;
}
.pb-newsletter__input:focus { outline: 2px solid var(--color-accent); outline-offset: 2px; }
.pb-newsletter__consent { color: var(--color-fg-muted); font-size: 12px; margin: 12px 0 0; line-height: 1.5; }
.pb-newsletter__ok { color: var(--color-accent); font-size: 18px; font-weight: 600; margin: 0 0 16px; }
/* Card variant — same shape as the centered default but with a stronger
   surface (deeper background + larger radius + drop shadow) so the
   block reads as a "feature card" inside a longer page. Drops the
   accent radial wash; uses a clean themed mat instead. */
.pb-newsletter[data-variant="card"] {
  background: var(--color-bg);
  box-shadow:
    0 1px 0 color-mix(in oklab, var(--color-fg) 6%, transparent),
    0 24px 64px -16px color-mix(in oklab, var(--color-fg) 18%, transparent);
  border: 1px solid color-mix(in oklab, var(--color-border) 80%, transparent);
}
/* Inline bar variant — a single-line strip with copy on the left and
   the form on the right. Best at the bottom of long pages where a full
   card would feel like a second hero. */
.pb-newsletter[data-variant="inline"] {
  max-width: var(--ds-container);
  text-align: left;
  padding: clamp(24px, 4cqi, 40px);
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  gap: clamp(24px, 4cqi, 48px);
  align-items: center;
}
.pb-newsletter[data-variant="inline"] .pb-newsletter__form {
  margin-bottom: 0;
  justify-content: flex-start;
}
@container pyramid (max-width: 720px) {
  .pb-newsletter[data-variant="inline"] {
    grid-template-columns: 1fr;
    text-align: center;
  }
  .pb-newsletter[data-variant="inline"] .pb-newsletter__form {
    justify-content: center;
  }
}

/* ============================================================
   RESPONSIVE — container queries against .pyramid-theme
   ============================================================

   Three breakpoints across all 20 blocks:

     1024px  → tablet adjustments. Mostly nav crowding + grid density.
      720px  → primary mobile pivot. Single-column grids, smaller hero.
      480px  → tight phone. Tighter padding + typography compression.

   Container-relative `cqw` units are used for typography so headings
   scale with the device width inside the editor preview, not the actual
   browser viewport. That's the difference between "mobile preview looks
   like real mobile" and "mobile preview is a narrow desktop". */

/* ---------- 1024px (tablet) ---------- */
@container pyramid (max-width: 1024px) {
  /* Section gutters tighten. The published `--ds-container` already
     handles its own width, but section padding-block needs a hand. */
  .pyramid-section { padding-block: clamp(48px, 7cqw, 96px); }

  /* Nav — hamburger at ≤1024px pyramid width (includes iPad editor
     frame ~834px). A single horizontal row is too narrow for brand +
     many links + dual CTAs without ugly wrapping; 720px was too low
     and left tablet in the broken in-between state. */
  .pb-nav__inner {
    flex-direction: row;
    flex-wrap: wrap;
    gap: 0;
    padding: 14px 16px;
    align-items: center;
    justify-content: space-between;
  }
  .pb-nav__toggle { display: inline-flex; }
  .pb-nav__mid {
    flex-basis: 100%;
    flex-direction: column;
    align-items: stretch;
    gap: 0;
    font-size: 16px;
    max-height: 0;
    overflow: hidden;
    margin-top: 0;
    padding-top: 0;
    padding-bottom: 0;
    border-top: 1px solid transparent;
    transition:
      max-height 220ms ease,
      padding 220ms ease,
      margin-top 180ms ease,
      border-top-color 180ms ease;
  }
  .pb-nav__links {
    flex-direction: column;
    align-items: stretch;
    gap: 0;
    font-size: 16px;
    margin-top: 0;
    padding: 0;
    border: 0;
  }
  .pb-nav__edit-add-link { padding: 4px 4px 8px; }
  .pb-nav__links li { width: 100%; }
  .pb-nav__links a {
    display: block;
    padding: 12px 4px;
    font-size: 16px;
  }
  .pb-nav__cta {
    flex-basis: 100%;
    justify-content: stretch;
    margin-top: 0;
    max-height: 0;
    overflow: hidden;
    transition: max-height 220ms ease, margin-top 180ms ease;
  }
  .pb-nav__cta .pyramid-cta { width: 100%; }
  .pb-nav[data-open="true"] .pb-nav__mid {
    max-height: 560px;
    margin-top: 12px;
    padding-top: 8px;
    padding-bottom: 8px;
    border-top-color: var(--color-border);
  }
  .pb-nav[data-open="true"] .pb-nav__cta {
    max-height: 200px;
    margin-top: 12px;
    flex-direction: column;
    align-items: stretch;
  }
  .pb-nav[data-open="true"] .pb-nav__cta .pb-nav__secondary-cta {
    width: 100%;
    justify-content: center;
  }

  /* Service tiles: 2 columns is fine but make sure the minmax stops
     forcing horizontal scroll inside the iPad frame. */
  .pb-services { grid-template-columns: repeat(auto-fit, minmax(260px, 1fr)); }

  /* Split hero: side-by-side is cramped on tablet-width containers — stack
     with a bounded media height so the section does not read as triple-tall. */
  .pb-hero[data-variant="split"] {
    grid-template-columns: 1fr;
    min-height: clamp(460px, 82cqh, 880px);
  }
  .pb-hero[data-variant="split"] .pb-hero__media {
    position: relative;
    order: -1;
    margin: 16px 18px 0;
    height: auto;
    aspect-ratio: 16 / 10;
    max-height: min(calc(0.4 * var(--pyramid-viewport-height, 100dvh)), 380px);
  }
  .pb-hero[data-variant="split"] .pb-hero__veil { display: block; }
}

/* ---------- 720px (mobile pivot) ---------- */
@container pyramid (max-width: 720px) {
  /* Tighter section gutters and side padding. Most blocks size their
     inner container against `var(--ds-container)`; we override the
     section padding here so blocks breathe on phones without each one
     having to re-implement the rule. */
  .pyramid-section { padding-block: clamp(40px, 9cqw, 72px); padding-inline: 16px; }
  .pyramid-section--bleed { padding-inline: 0; }
  .pyramid-section__container,
  .pb-nav__inner,
  .pb-hero__inner,
  .pb-footer__inner,
  .pb-footer__bottom,
  .pb-notice__inner {
    width: 100%;
  }

  /* Hero — re-anchor type to container width so the title doesn't blow
     past the viewport on mobile. Original clamp used 8vw; cqw inside a
     390px container gives a sensible ~50–60px headline. */
  .pb-hero { min-height: clamp(420px, 90cqh, 720px); }
  .pb-hero__inner {
    padding-block: clamp(48px, 14cqw, 96px);
    padding-inline: 20px;
    max-width: 100%;
    gap: 18px;
  }
  .pb-hero__title { font-size: clamp(40px, 12cqw, 72px); }
  .pb-hero__sub   { font-size: clamp(15px, 4cqw, 18px); }
  .pb-hero__ctas  { gap: 10px; }
  .pb-hero__ctas .pyramid-cta,
  .pb-hero__ghost { padding: 12px 18px; font-size: 15px; }
  /* Split hero must collapse — no room for a 1fr 1fr at 390px. */
  .pb-hero[data-variant="split"] { grid-template-columns: 1fr; }
  .pb-hero[data-variant="split"] .pb-hero__media {
    margin: 16px 16px 0;
    height: auto;
    aspect-ratio: 4 / 3;
    min-height: 0;
  }
  .pb-hero[data-variant="split"] .pb-hero__veil { display: block; }

  /* Nav hamburger: see @container (max-width: 1024px) — applies to
     all phones and the tablet device frame, not only ≤720px. */

  /* Marquee — dial down the type, shorter gap. */
  .pb-marquee__track { gap: 36px; }
  .pb-marquee__item  { font-size: clamp(18px, 6cqw, 28px); }

  /* Product grid — single column with a tighter gap. */
  .pb-products__head { flex-direction: column; align-items: start; gap: 12px; margin-bottom: 24px; }
  .pb-products__title { font-size: clamp(28px, 8cqw, 44px); }
  .pb-products__grid { grid-template-columns: 1fr; gap: 16px; }
  .pb-product__media { aspect-ratio: 1 / 1; }

  /* Categories, blog, testimonials, brand chips, locations, benefits,
     services — all collapse to a single column. (Stats stays 2-col so
     the page doesn't read like a phonebook.) */
  .pb-categories,
  .pb-blog,
  .pb-testimonials,
  .pb-brandstrip__grid,
  .pb-locations,
  .pb-benefits,
  .pb-services { grid-template-columns: 1fr; gap: 16px; }
  .pb-process[data-variant="horizontal"] { grid-template-columns: 1fr; }
  .pb-truststrip { padding: 14px 16px; gap: 6px 2px; }
  .pb-truststrip__item { font-size: 11px; }
  .pb-stats     { grid-template-columns: repeat(2, 1fr); gap: 24px; }
  .pb-stat__num { font-size: clamp(36px, 12cqw, 56px); }
  .pb-categories__tile { aspect-ratio: 16 / 11; }
  .pb-categories__label { bottom: 14px; left: 14px; font-size: 18px; }
  .pb-service__body { padding: 22px; }
  .pb-service__media { aspect-ratio: 16 / 9; }
  .pb-location { padding: 22px; }
  .pb-blog__body { padding: 18px; }
  .pb-blog[data-variant="list"] .pb-blog__card {
    grid-template-columns: 1fr;
  }

  /* Feature split — already migrated above (single column) but re-state
     so flip-order behaves on mobile too. */
  .pb-feature { gap: 24px; }
  .pb-feature__media img { aspect-ratio: 4 / 3; }
  .pb-feature__title { font-size: clamp(26px, 8cqw, 40px); }
  .pb-feature__body  { font-size: 16px; }

  /* CTA banner — tighter padding; split collapses to single column. */
  .pb-cta { padding: clamp(32px, 9cqw, 64px); }
  .pb-cta__title { font-size: clamp(32px, 10cqw, 56px); }
  .pb-cta__sub   { font-size: 16px; }
  .pb-cta[data-variant="split"] {
    grid-template-columns: 1fr;
    text-align: center;
  }
  .pb-cta[data-variant="split"] .pb-cta__action { justify-content: center; }
  .pb-cta[data-variant="split"] .pb-cta__sub { margin-bottom: 24px; }

  /* FAQ — narrower inner padding. */
  .pb-faq details { padding: 14px 16px; }
  .pb-faq summary { font-size: 16px; }

  /* Newsletter — full-width inside the device, smaller padding. */
  .pb-newsletter { padding: 32px 20px; border-radius: var(--ds-radius); }
  .pb-newsletter__form { flex-direction: column; align-items: stretch; }
  .pb-newsletter__input { flex: 1 1 auto; }

  /* Notice bar — center, no horizontal scroll on long notices. */
  .pb-notice__inner { padding: 8px 14px; font-size: 12px; }

  /* Age gate (preview only — fixed overlay only fires in published mode) */
  .pb-agegate__card { padding: 28px 22px; }
  .pb-agegate__title { font-size: 26px; }

  /* Hours — head row of title + open/closed pill is already flex-wrap;
     collapse the optional grid layout to 1 column too so weekly rows
     stack instead of side-by-side on a 390px screen. */
  .pb-hours[data-layout="grid"] .pb-hours__list { grid-template-columns: 1fr; }
  .pb-hours__row { gap: 12px; }
  .pb-hours__day, .pb-hours__times { font-size: 15px; }

  /* Reservations form — heading shrinks; the inner form is already
     max-width: 640px. Tighten padding so the card doesn't dominate. */
  .pb-reservations { gap: 18px; }
  .pb-reservations__title { font-size: clamp(24px, 6cqi, 32px); }
  .pb-reservations__sub { font-size: 14px; }
  .pb-reservations__form { padding: 18px; }
  .pb-reservations__field { font-size: 13px; }

  /* Map block — caption + directions affordance shrink, iframe height
     drops further at 480px below. */
  .pb-map { border-radius: var(--ds-radius); }
  .pb-map__caption { padding: 8px 12px; font-size: 12px; }
}

/* ---------- 480px (tight phone) ---------- */
@container pyramid (max-width: 480px) {
  /* Footer collapse already handled above. Trim hero further so a 360px
     phone doesn't get squeezed. */
  .pb-hero { min-height: clamp(380px, 95cqh, 600px); }
  .pb-hero__title { font-size: clamp(36px, 13cqw, 56px); letter-spacing: -0.02em; }
  .pb-hero__inner { padding-inline: 16px; gap: 14px; }
  .pb-hero__eyebrow { font-size: 11px; padding: 6px 10px; }

  /* Section padding tighter. */
  .pyramid-section { padding-block: clamp(32px, 10cqw, 56px); padding-inline: 14px; }

  /* Stats: drop to a single 2-up row but with smaller numbers. */
  .pb-stat__num { font-size: clamp(32px, 13cqw, 48px); }

  /* Marquee runs faster at narrow widths so motion doesn't feel sluggish. */
  .pb-marquee__track { animation-duration: 22s; }
}

/* ---------- Map block ----------------------------------------------------
   `data-height` sets --map-h (viewport-relative via cqi) as a max band height.
   Frame shapes: wide 16∶9, cinematic 21∶9, square 1∶1, portrait 3∶4, strip bar,
   full bleed. Heights cap at --map-h except strip (fixed band).
   `data-composition` adds split / stacked copy beside or above the map.
   Directions sit inside `.pb-map__viewport` so they overlay the map, not
   the caption. */

.pb-map {
  /* cap height by preset; cqi tracks preview / published column width */
  --map-h: min(46cqi, calc(0.5 * var(--pyramid-viewport-height, 100dvh)), 400px);
  width: var(--ds-container);
  margin-inline: auto;
  border-radius: var(--ds-radius-lg);
  position: relative;
  background: linear-gradient(
    165deg,
    color-mix(in srgb, var(--color-bg) 40%, var(--color-bg-emphasis)) 0%,
    color-mix(in srgb, var(--color-bg-emphasis) 92%, var(--color-bg)) 100%
  );
  border: 1px solid color-mix(in srgb, var(--color-border) 85%, var(--color-fg));
  box-shadow:
    0 1px 0 color-mix(in srgb, var(--color-bg) 80%, transparent),
    0 1px 2px color-mix(in srgb, var(--color-fg) 6%, transparent),
    0 20px 50px color-mix(in srgb, var(--color-fg) 7%, transparent);
}
/* Soft glass — lighter lift, still reads as a designed object */
.pb-map[data-chrome="soft"] {
  background: linear-gradient(
    165deg,
    color-mix(in srgb, var(--color-bg) 52%, var(--color-bg-emphasis)) 0%,
    color-mix(in srgb, var(--color-bg-emphasis) 88%, var(--color-bg)) 100%
  );
  border: 1px solid color-mix(in srgb, var(--color-border) 72%, var(--color-fg));
  box-shadow:
    0 1px 0 color-mix(in srgb, var(--color-bg) 72%, transparent),
    0 28px 72px color-mix(in srgb, var(--color-fg) 8%, transparent);
}
.pb-map[data-chrome="soft"] .pb-map__frame {
  box-shadow:
    inset 0 1px 0 color-mix(in srgb, var(--color-fg) 7%, transparent),
    inset 0 0 0 1px color-mix(in srgb, var(--color-fg) 5%, transparent);
}
/* Minimal line — flat editorial frame */
.pb-map[data-chrome="outline"] {
  background: var(--color-bg);
  border: 1px solid color-mix(in srgb, var(--color-fg) 12%, var(--color-border));
  box-shadow: none;
}
.pb-map[data-chrome="outline"] .pb-map__frame {
  background: color-mix(in srgb, var(--color-bg-emphasis) 94%, var(--color-bg));
  box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--color-fg) 7%, transparent);
}
/* Dark “hero” card — strong frame, accent CTA reads as premium. */
.pb-map[data-chrome="spotlight"] {
  background: linear-gradient(
    155deg,
    color-mix(in oklab, var(--color-fg) 88%, var(--color-bg)) 0%,
    color-mix(in oklab, var(--color-fg) 94%, var(--color-accent)) 100%
  );
  color: color-mix(in oklab, var(--color-bg) 96%, var(--color-fg));
  border: 1px solid color-mix(in srgb, var(--color-bg) 22%, transparent);
  box-shadow:
    0 1px 0 color-mix(in srgb, var(--color-bg) 12%, transparent),
    0 28px 56px color-mix(in srgb, #000 38%, transparent);
}
.pb-map[data-chrome="spotlight"][data-layout="fullbleed"] {
  padding-inline: clamp(18px, 5cqi, 40px);
  padding-block: clamp(20px, 4cqi, 36px);
  box-sizing: border-box;
}
.pb-map[data-chrome="spotlight"] .pb-map__title {
  color: color-mix(in oklab, var(--color-bg) 98%, var(--color-fg));
}
.pb-map[data-chrome="spotlight"] .pb-map__body,
.pb-map[data-chrome="spotlight"] .pb-map__caption {
  color: color-mix(in oklab, var(--color-bg) 72%, var(--color-fg-muted));
}
.pb-map[data-chrome="spotlight"] .pb-map__location {
  color: color-mix(in oklab, var(--color-bg) 88%, var(--color-fg));
  border-top-color: color-mix(in srgb, var(--color-bg) 22%, transparent);
}
.pb-map[data-chrome="spotlight"] .pb-map__eyebrow {
  background: color-mix(in srgb, var(--color-bg) 14%, transparent);
  border-color: color-mix(in srgb, var(--color-bg) 28%, transparent);
  color: color-mix(in oklab, var(--color-bg) 78%, var(--color-fg-muted));
}
.pb-map[data-chrome="spotlight"] .pb-map__frame {
  /* Match the dark card — avoid a light `--color-bg-emphasis` mat behind the map */
  background: color-mix(in oklab, var(--color-fg) 76%, var(--color-accent) 24%);
  border-radius: 20px;
  box-shadow:
    0 20px 44px color-mix(in srgb, #000 32%, transparent),
    inset 0 0 0 1px color-mix(in srgb, var(--color-bg) 16%, transparent);
}
.pb-map[data-chrome="spotlight"] .pb-map__iframe,
.pb-map[data-chrome="spotlight"] .pb-map__leaflet {
  background: color-mix(in oklab, var(--color-fg) 82%, var(--color-bg));
}
.pb-map[data-layout="fullbleed"][data-chrome="spotlight"] .pb-map__frame {
  border-radius: 18px;
}
.pb-map[data-chrome="spotlight"] .pb-map__caption {
  border-top-color: color-mix(in srgb, var(--color-bg) 18%, transparent);
}
.pb-map[data-composition="stacked"] {
  display: grid;
  gap: clamp(20px, 4cqi, 32px);
  grid-template-columns: minmax(0, 1fr);
}
.pb-map[data-composition="splitStart"] {
  display: grid;
  gap: clamp(22px, 4.5cqi, 40px);
  grid-template-columns: minmax(0, 1fr) minmax(0, 1.12fr);
  grid-template-areas: "copy map";
  align-items: stretch;
}
.pb-map[data-composition="splitEnd"] {
  display: grid;
  gap: clamp(22px, 4.5cqi, 40px);
  grid-template-columns: minmax(0, 1.12fr) minmax(0, 1fr);
  grid-template-areas: "map copy";
  align-items: stretch;
}
/* Split layouts reserve a "copy" cell for `.pb-map__intro`. When every intro
   field is empty (common with Place-ID-only maps: no auto location line),
   MapIntro renders nothing — but the grid still allocated copy, which reads
   as a large empty spotlight/dark band. Collapse to map-only. */
.pb-map[data-composition="splitStart"]:not(:has(.pb-map__intro)),
.pb-map[data-composition="splitEnd"]:not(:has(.pb-map__intro)) {
  grid-template-columns: 1fr;
  grid-template-areas: "map";
}
.pb-map__intro {
  grid-area: copy;
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: 0;
  min-width: 0;
}
.pb-map[data-composition="stacked"] .pb-map__intro {
  text-align: center;
  align-items: center;
  max-width: 40rem;
  margin-inline: auto;
}
.pb-map__eyebrow {
  display: inline-block;
  padding: 6px 12px;
  border-radius: 999px;
  background: color-mix(in srgb, var(--color-bg) 70%, var(--color-bg-emphasis));
  border: 1px solid var(--color-border);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: var(--color-fg-muted);
  margin-bottom: 14px;
}
.pb-map__title {
  font-family: var(--ds-font-display);
  font-size: clamp(26px, 4.2cqi, 40px);
  font-weight: var(--ds-font-display-weight, 700);
  line-height: 1.08;
  letter-spacing: -0.02em;
  margin: 0 0 12px;
  color: var(--color-fg);
}
.pb-map__body {
  margin: 0;
  font-size: clamp(15px, 2.8cqi, 17px);
  line-height: 1.6;
  color: var(--color-fg-muted);
  max-width: 52ch;
}
.pb-map[data-composition="stacked"] .pb-map__body {
  max-width: 48ch;
}
.pb-map__location {
  margin: 16px 0 0;
  font-size: 14px;
  line-height: 1.5;
  font-weight: 500;
  color: var(--color-fg);
  padding-top: 14px;
  border-top: 1px solid color-mix(in srgb, var(--color-border) 80%, transparent);
}
.pb-map[data-composition="stacked"] .pb-map__location {
  text-align: center;
  max-width: 42ch;
}
.pb-map[data-layout="fullbleed"][data-composition="splitStart"] .pb-map__intro,
.pb-map[data-layout="fullbleed"][data-composition="splitEnd"] .pb-map__intro,
.pb-map[data-layout="fullbleed"][data-composition="stacked"] .pb-map__intro {
  padding-inline: clamp(16px, 4cqi, 28px);
}
.pb-map[data-height="compact"] {
  --map-h: min(36cqi, calc(0.4 * var(--pyramid-viewport-height, 100dvh)), 280px);
}
.pb-map[data-height="balanced"] {
  --map-h: min(46cqi, calc(0.5 * var(--pyramid-viewport-height, 100dvh)), 400px);
}
.pb-map[data-height="tall"] {
  --map-h: min(62cqi, calc(0.56 * var(--pyramid-viewport-height, 100dvh)), 520px);
}
.pb-map[data-layout="fullbleed"] {
  width: 100%;
  margin-inline: 0;
  border-radius: 0;
  border-inline: 0;
  box-shadow: none;
  background: var(--color-bg-emphasis);
}
.pb-map[data-layout="fullbleed"][data-chrome="spotlight"] {
  box-shadow: none;
  background: linear-gradient(
    155deg,
    color-mix(in oklab, var(--color-fg) 88%, var(--color-bg)) 0%,
    color-mix(in oklab, var(--color-fg) 94%, var(--color-accent)) 100%
  );
}
.pb-map[data-layout="fullbleed"][data-chrome="soft"] {
  box-shadow: none;
  background: linear-gradient(
    180deg,
    color-mix(in srgb, var(--color-bg) 38%, var(--color-bg-emphasis)) 0%,
    var(--color-bg-emphasis) 100%
  );
}
.pb-map[data-layout="fullbleed"][data-chrome="outline"] {
  box-shadow: none;
  background: var(--color-bg);
  border-inline: 0;
  border-block: 1px solid color-mix(in srgb, var(--color-fg) 10%, var(--color-border));
}
.pb-map__viewport {
  grid-area: map;
  position: relative;
  width: 100%;
  border-radius: inherit;
  overflow: hidden;
  min-width: 0;
  /* Stack frame + overlay controls; lets the map grow when the grid row is
     taller than the intrinsic 16∶9 box (split layouts used to leave a huge
     empty band under a short frame). */
  display: flex;
  flex-direction: column;
  min-height: 0;
}
.pb-map[data-layout="fullbleed"] .pb-map__viewport {
  border-radius: 0;
}
.pb-map[data-composition="embed"] .pb-map__viewport {
  grid-area: unset;
}
/* Side-by-side copy + map: stretch the map column to at least --map-h so the
   iframe/Leaflet fills the cell instead of sitting in a thin strip. */
.pb-map[data-composition="splitStart"] .pb-map__viewport,
.pb-map[data-composition="splitEnd"] .pb-map__viewport {
  min-height: var(--map-h);
  align-self: stretch;
}
.pb-map[data-composition="stacked"] .pb-map__viewport {
  min-height: var(--map-h);
}
.pb-map__frame {
  position: relative;
  overflow: hidden;
  border-radius: inherit;
  /* Map children fill this box via flex — avoids “absolute-only” collapse. */
  display: flex;
  flex-direction: column;
  flex: 0 1 auto;
  /* Tint toward page bg so the well isn’t a bright slab on dark / soft sections */
  background:
    linear-gradient(
      180deg,
      color-mix(in srgb, var(--color-bg) 24%, transparent) 0%,
      transparent 42%
    ),
    color-mix(in srgb, var(--color-bg) 42%, var(--color-bg-emphasis));
  box-shadow:
    inset 0 1px 0 color-mix(in srgb, var(--color-fg) 8%, transparent),
    inset 0 0 0 1px color-mix(in srgb, var(--color-fg) 5%, transparent);
  /* If --map-h fails to resolve, percentage heights on the iframe collapse
     to the UA default (~150px). Keep a floor so the map never “ribbon”s. */
  min-height: 200px;
}
/* Full width of the card; 16∶9 height from width, capped by height preset */
.pb-map[data-layout="wide"] .pb-map__frame {
  width: 100%;
  aspect-ratio: 16 / 9;
  max-height: var(--map-h);
  margin-inline: auto;
  /* Do not use min-height:0 here — it removed the floor and let the flex
     map strip collapse when aspect-ratio + absolute children misbehaved. */
  flex: 0 0 auto;
}
/* Ultrawide “cinema” band — same cap as banner, wider aspect */
.pb-map[data-layout="cinematic"] .pb-map__frame {
  width: 100%;
  aspect-ratio: 21 / 9;
  max-height: var(--map-h);
  margin-inline: auto;
  flex: 0 0 auto;
}
.pb-map[data-layout="square"] {
  max-width: min(100%, 560px);
  margin-inline: auto;
}
.pb-map[data-layout="square"] .pb-map__frame {
  width: min(100%, var(--map-h));
  height: var(--map-h);
  margin-inline: auto;
  flex: 0 0 auto;
}
.pb-map[data-layout="portrait"] {
  max-width: min(100%, 560px);
  margin-inline: auto;
}
.pb-map[data-layout="portrait"] .pb-map__frame {
  width: min(100%, calc(var(--map-h) * 0.82));
  aspect-ratio: 3 / 4;
  margin-inline: auto;
  flex: 0 0 auto;
  max-height: min(calc(var(--map-h) * 1.35), 720px);
}
/* Useful low bar: fixed vertical band, still readable on mobile */
.pb-map[data-layout="strip"] .pb-map__frame {
  width: 100%;
  height: clamp(152px, min(24cqi, calc(0.26 * var(--pyramid-viewport-height, 100dvh))), 228px);
  margin-inline: auto;
  flex: 0 0 auto;
}
.pb-map[data-layout="fullbleed"] .pb-map__frame {
  width: 100%;
  height: var(--map-h);
  border-radius: 0;
  flex: 0 0 auto;
}
/* After layout rules: split / stacked maps must fill the stretched viewport
   (grid row height from copy column) instead of a short 16∶9 box + empty well. */
.pb-map[data-composition="splitStart"] .pb-map__frame,
.pb-map[data-composition="splitEnd"] .pb-map__frame,
.pb-map[data-composition="stacked"] .pb-map__frame {
  flex: 1 1 auto;
  height: 100%;
  max-height: none;
  aspect-ratio: unset;
  min-height: min(200px, var(--map-h));
  width: 100%;
}
.pb-map[data-composition="splitStart"][data-layout="square"] .pb-map__frame,
.pb-map[data-composition="splitEnd"][data-layout="square"] .pb-map__frame,
.pb-map[data-composition="stacked"][data-layout="square"] .pb-map__frame {
  width: min(100%, var(--map-h));
  max-width: min(100%, 560px);
  margin-inline: auto;
}
.pb-map[data-composition="splitStart"][data-layout="portrait"] .pb-map__viewport,
.pb-map[data-composition="splitEnd"][data-layout="portrait"] .pb-map__viewport,
.pb-map[data-composition="stacked"][data-layout="portrait"] .pb-map__viewport {
  align-items: center;
}
.pb-map[data-composition="splitStart"][data-layout="portrait"] .pb-map__frame,
.pb-map[data-composition="splitEnd"][data-layout="portrait"] .pb-map__frame,
.pb-map[data-composition="stacked"][data-layout="portrait"] .pb-map__frame {
  width: min(100%, calc(var(--map-h) * 0.88));
  max-width: 400px;
  margin-inline: auto;
  aspect-ratio: 3 / 4;
  height: auto;
  max-height: min(100%, calc(var(--map-h) * 1.25));
  flex: 0 1 auto;
}
.pb-map__iframe {
  display: block;
  flex: 1 1 auto;
  min-height: 0;
  width: 100%;
  border: 0;
  /* Loading / letterbox color: stay on-theme (overridden for spotlight above) */
  background: color-mix(in srgb, var(--color-bg) 38%, var(--color-bg-emphasis));
}
/* Leaflet + OSM (no Google API key, coordinates only) — fills frame like the iframe. */
.pb-map__leaflet {
  flex: 1 1 auto;
  min-height: 180px;
  width: 100%;
  min-width: 0;
  border-radius: inherit;
  z-index: 0;
  background: color-mix(in srgb, var(--color-bg) 38%, var(--color-bg-emphasis));
}
.pb-map__leaflet.leaflet-container {
  font: inherit;
}
.pb-map__leaflet .leaflet-bar {
  border: 1px solid color-mix(in srgb, var(--color-fg) 12%, var(--color-border));
  border-radius: 10px;
  box-shadow: 0 4px 16px color-mix(in srgb, var(--color-fg) 8%, transparent);
}
.pb-map__leaflet .leaflet-bar a {
  color: var(--color-fg);
  background: color-mix(in srgb, var(--color-bg) 88%, transparent);
}
.pb-map__leaflet .leaflet-bar a:hover {
  background: color-mix(in srgb, var(--color-bg-emphasis) 90%, transparent);
}
.pb-map__leaflet .leaflet-popup-content-wrapper {
  border-radius: var(--ds-radius);
  box-shadow: 0 8px 28px color-mix(in srgb, var(--color-fg) 12%, transparent);
  border: 1px solid color-mix(in srgb, var(--color-border) 90%, transparent);
}
.pb-map__leaflet .leaflet-popup-content {
  font-size: 14px;
  line-height: 1.45;
  color: var(--color-fg);
  margin: 10px 12px;
}
.pb-map__leaflet a {
  color: var(--color-accent);
}
.pb-map__directions {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  position: absolute;
  /* Clamp inset to the available frame width so the overlay stays
     visually inside the iframe on narrow widths (mobile preview, strip
     layouts) instead of getting hard-cropped against the rounded
     corner. max() keeps a sensible min on desktop. */
  bottom: max(10px, min(3cqi, 16px));
  right: max(10px, min(3cqi, 16px));
  z-index: 2;
  padding: 10px 16px 10px 14px;
  font-size: 13px;
  font-weight: 600;
  letter-spacing: 0.01em;
  text-decoration: none;
  color: var(--color-fg);
  border-radius: 999px;
  background: color-mix(in oklab, var(--color-bg) 82%, transparent);
  border: 1px solid color-mix(in srgb, var(--color-fg) 9%, transparent);
  box-shadow:
    0 2px 8px color-mix(in srgb, var(--color-fg) 8%, transparent),
    0 12px 32px color-mix(in srgb, var(--color-fg) 10%, transparent);
  backdrop-filter: blur(14px) saturate(160%);
  -webkit-backdrop-filter: blur(14px) saturate(160%);
  transition: background 150ms ease, transform 150ms ease, border-color 150ms ease;
  /* On very narrow frames (strip layout / phone preview) shrink the
     button before it would crowd the frame edge. */
  max-width: calc(100% - 24px);
  white-space: nowrap;
}
.pb-map__directions-icon {
  display: flex;
  color: var(--color-accent);
  flex-shrink: 0;
}
.pb-map__directions:hover {
  background: color-mix(in oklab, var(--color-bg) 94%, transparent);
  border-color: color-mix(in srgb, var(--color-accent) 35%, var(--color-fg));
  transform: translateY(-1px);
}
.pb-map__directions--below {
  grid-column: 1 / -1;
  position: static;
  width: 100%;
  max-width: 420px;
  margin-inline: auto;
  margin-top: 4px;
  justify-content: center;
  padding: 14px 22px;
  font-size: 15px;
  background: var(--color-accent);
  color: var(--color-accent-fg);
  border: none;
  box-shadow: 0 12px 32px color-mix(in srgb, var(--color-accent) 42%, transparent);
}
.pb-map__directions--below .pb-map__directions-icon {
  color: inherit;
}
.pb-map__directions--below:hover {
  background: color-mix(in oklab, var(--color-accent) 92%, var(--color-fg));
  border: none;
  transform: translateY(-1px);
  filter: none;
}
.pb-map[data-chrome="spotlight"] .pb-map__directions--below {
  box-shadow: 0 16px 36px color-mix(in srgb, #000 35%, transparent);
}
.pb-map__caption {
  grid-column: 1 / -1;
  padding: 14px 18px 4px;
  margin: 0;
  font-size: 13px;
  line-height: 1.5;
  letter-spacing: 0.01em;
  color: var(--color-fg-muted);
  background: transparent;
  border-top: 1px solid color-mix(in srgb, var(--color-border) 65%, transparent);
  max-width: 62ch;
}
.pb-map[data-composition="stacked"] .pb-map__caption {
  margin-inline: auto;
  text-align: center;
  max-width: 48ch;
}
.pb-map[data-composition="embed"] .pb-map__caption {
  grid-column: auto;
  max-width: none;
}
.pb-map--empty {
  min-height: 240px;
  display: grid;
  place-items: center;
  text-align: center;
  padding: 40px 24px;
  overflow: hidden;
  /* Match the resolved-map heights so toggling between "no address yet"
     and "address set" doesn't make the section visibly jump. The bare
     `min-height: 240px` was a hangover from before --map-h existed; it
     left compact-vs-tall feeling identical in the empty state. */
}
.pb-map--empty[data-height="compact"] { min-height: 200px; }
.pb-map--empty[data-height="balanced"] { min-height: 280px; }
.pb-map--empty[data-height="tall"] { min-height: 360px; }
.pb-map--empty[data-layout="strip"] { min-height: 152px; padding-block: 24px; }
.pb-map--empty[data-layout="square"] {
  max-width: min(100%, 520px);
  aspect-ratio: 1 / 1;
  min-height: 0;
}
.pb-map--empty[data-layout="cinematic"] {
  aspect-ratio: 21 / 9;
  min-height: 0;
}
.pb-map--empty[data-layout="portrait"] {
  max-width: min(100%, 520px);
  margin-inline: auto;
  aspect-ratio: 3 / 4;
  min-height: 0;
}
.pb-map--empty[data-layout="fullbleed"] {
  border-radius: 0;
  border-inline: 0;
}
.pb-map__placeholder {
  position: absolute; inset: 0;
  background:
    linear-gradient(135deg, var(--color-bg-emphasis) 0%, var(--color-border) 100%);
  z-index: 0;
}
.pb-map__empty-msg {
  position: relative; z-index: 1;
  display: grid; gap: 8px;
  max-width: 420px;
}
.pb-map__empty-msg strong { font-size: 17px; color: var(--color-fg); }
.pb-map__empty-msg span { font-size: 14px; color: var(--color-fg-muted); }

@container pyramid (max-width: 720px) {
  .pb-map[data-composition="splitStart"],
  .pb-map[data-composition="splitEnd"] {
    grid-template-columns: 1fr;
    grid-template-areas:
      "copy"
      "map";
    gap: clamp(18px, 5cqi, 28px);
  }
  .pb-map[data-composition="splitStart"]:not(:has(.pb-map__intro)),
  .pb-map[data-composition="splitEnd"]:not(:has(.pb-map__intro)) {
    grid-template-areas: "map";
  }
  .pb-map[data-height="compact"] {
    --map-h: min(40cqi, calc(0.42 * var(--pyramid-viewport-height, 100dvh)), 240px);
  }
  .pb-map[data-height="balanced"] {
    --map-h: min(48cqi, calc(0.46 * var(--pyramid-viewport-height, 100dvh)), 320px);
  }
  .pb-map[data-height="tall"] {
    --map-h: min(54cqi, calc(0.52 * var(--pyramid-viewport-height, 100dvh)), 400px);
  }
  .pb-map[data-layout="strip"] .pb-map__frame {
    height: clamp(140px, calc(0.22 * var(--pyramid-viewport-height, 100dvh)), 200px);
  }
  .pb-map__directions {
    bottom: 10px;
    right: 10px;
    padding: 8px 12px;
    font-size: 12px;
  }
  .pb-map__title {
    font-size: clamp(24px, 7cqi, 34px);
  }
}

@media (prefers-reduced-motion: reduce) {
  .pb-map__directions {
    transition: none;
  }
  .pb-map__directions:hover {
    transform: none;
  }
  .pb-map__directions--below:hover {
    transform: none;
  }
}

/* ---------- Hours block -------------------------------------------------- */

.pb-hours {
  width: var(--ds-container);
  margin-inline: auto;
  display: grid;
  gap: 18px;
}
.pb-hours[data-layout="grid"] { gap: 14px; }
.pb-hours__head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 12px;
}
.pb-hours__title {
  font-family: var(--ds-font-display);
  font-size: clamp(24px, 3cqi, 36px);
  margin: 0;
}
.pb-hours__pill {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 6px 12px;
  border-radius: 999px;
  background: var(--color-bg-emphasis);
  border: 1px solid var(--color-border);
  font-size: 13px;
  font-weight: 600;
  color: var(--color-fg);
}
.pb-hours__dot {
  width: 8px; height: 8px; border-radius: 50%;
  background: var(--color-fg-muted);
}
.pb-hours__pill[data-tone="open"] .pb-hours__dot { background: var(--pb-status-positive); }
.pb-hours__pill[data-tone="closed"] .pb-hours__dot { background: var(--pb-status-negative); }

.pb-hours__list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: 0;
  border-top: 1px solid var(--color-border);
}
.pb-hours[data-layout="grid"] .pb-hours__list {
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 10px;
  border: 0;
}
@container pyramid (min-width: 900px) {
  .pb-hours[data-layout="grid"] .pb-hours__list {
    grid-template-columns: repeat(4, minmax(0, 1fr));
  }
}
.pb-hours__row {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 16px;
  padding: 12px 0;
  border-bottom: 1px solid var(--color-border);
}
.pb-hours[data-layout="grid"] .pb-hours__row {
  display: grid;
  gap: 4px;
  padding: 14px 16px;
  background: var(--color-bg-emphasis);
  border-radius: var(--ds-radius);
  border-bottom: 0;
}
.pb-hours__row[data-today="true"] {
  font-weight: 700;
  color: var(--color-fg);
}
.pb-hours__row[data-today="true"] .pb-hours__day::before {
  content: "Today · ";
  color: var(--color-fg-muted);
  font-weight: 500;
}
.pb-hours__row[data-closed="true"] .pb-hours__times {
  color: var(--color-fg-muted);
  font-style: italic;
}
.pb-hours__day { font-size: 15px; }
.pb-hours__times { font-size: 15px; color: var(--color-fg); font-variant-numeric: tabular-nums; }
.pb-hours__tz {
  font-size: 12px;
  color: var(--color-fg-muted);
  margin: 0;
}
.pb-hours--empty .pb-hours__empty-msg {
  color: var(--color-fg-muted);
  font-size: 15px;
}

@container pyramid (max-width: 480px) {
  .pb-hours__row { padding: 10px 0; }
  .pb-hours__day, .pb-hours__times { font-size: 14px; }
}
/* Card variant — wraps the hours block in an elevated surface so it
   reads as a contact card on a long page. Default + grid layouts both
   benefit from the same surface treatment. */
.pb-hours[data-variant="card"] {
  padding: clamp(20px, 4cqi, 32px);
  border-radius: var(--ds-radius-lg);
  background: var(--color-bg);
  border: 1px solid var(--color-border);
  box-shadow:
    0 1px 0 color-mix(in oklab, var(--color-fg) 4%, transparent),
    0 16px 48px -16px color-mix(in oklab, var(--color-fg) 14%, transparent);
}
/* Inline strip — collapses to a single horizontal row. Useful in a
   sidebar or as a slim band beside a Map/Contact block. */
.pb-hours[data-variant="inline"] .pb-hours__list {
  display: flex;
  flex-wrap: wrap;
  gap: 8px 18px;
}
.pb-hours[data-variant="inline"] .pb-hours__row {
  display: inline-flex;
  align-items: baseline;
  gap: 8px;
  padding: 4px 10px;
  border-radius: 999px;
  background: color-mix(in oklab, var(--color-bg-emphasis) 70%, var(--color-bg));
  border: 1px solid color-mix(in oklab, var(--color-border) 80%, transparent);
}
.pb-hours[data-variant="inline"] .pb-hours__row[data-today="true"] {
  background: color-mix(in oklab, var(--color-accent) 14%, var(--color-bg));
  border-color: color-mix(in oklab, var(--color-accent) 35%, var(--color-border));
}
.pb-hours[data-variant="inline"] .pb-hours__day {
  font-weight: 600;
}
.pb-hours[data-variant="inline"] .pb-hours__head {
  margin-bottom: 12px;
}

/* ---------- Reservations block ------------------------------------------ */

.pb-reservations {
  width: var(--ds-container);
  max-width: 640px;
  margin-inline: auto;
  display: grid;
  gap: 24px;
}
.pb-reservations[data-variant="tight"] { gap: 16px; }
.pb-reservations[data-variant="tight"] .pb-reservations__form { padding: 18px; }
.pb-reservations[data-variant="airy"] {
  gap: 32px;
  max-width: 680px;
}
.pb-reservations[data-variant="airy"] .pb-reservations__form { padding: 32px; }
.pb-reservations__head { display: grid; gap: 8px; text-align: center; }
.pb-reservations__title {
  font-family: var(--ds-font-display);
  font-size: clamp(28px, 4cqi, 40px);
  margin: 0;
}
.pb-reservations__sub {
  margin: 0;
  color: var(--color-fg-muted);
  font-size: 16px;
}

.pb-reservations__form {
  display: grid;
  gap: 14px;
  background: var(--color-bg-emphasis);
  padding: 24px;
  border-radius: var(--ds-radius-lg);
  border: 1px solid var(--color-border);
}
.pb-reservations__row {
  display: grid;
  gap: 14px;
}
.pb-reservations__row--2 { grid-template-columns: 1fr; }
@container pyramid (min-width: 600px) {
  .pb-reservations__row--2 { grid-template-columns: 1fr 1fr; }
}
.pb-reservations__field {
  display: grid;
  gap: 6px;
  font-size: 14px;
  color: var(--color-fg);
}
.pb-reservations__field span {
  font-weight: 600;
  font-size: 13px;
  letter-spacing: 0.02em;
}
.pb-reservations__optional {
  font-style: normal;
  font-weight: 400;
  color: var(--color-fg-muted);
  margin-left: 4px;
}
.pb-reservations__field input,
.pb-reservations__field select,
.pb-reservations__field textarea {
  font: inherit;
  padding: 10px 12px;
  border-radius: var(--ds-radius);
  border: 1px solid var(--color-border);
  background: var(--color-bg);
  color: var(--color-fg);
  width: 100%;
  box-sizing: border-box;
}
.pb-reservations__field textarea { resize: vertical; min-height: 80px; }
.pb-reservations__field input:focus,
.pb-reservations__field select:focus,
.pb-reservations__field textarea:focus {
  outline: 2px solid var(--color-accent);
  outline-offset: 2px;
}
.pb-reservations__actions { display: flex; justify-content: flex-end; padding-top: 4px; }
.pb-reservations__actions .pyramid-cta { min-width: 200px; }

.pb-reservations__success {
  display: grid;
  gap: 6px;
  text-align: center;
  padding: 32px 24px;
  background: var(--color-bg-emphasis);
  border-radius: var(--ds-radius-lg);
  border: 1px solid var(--color-border);
}
.pb-reservations__success strong { font-size: 18px; color: var(--color-fg); }
.pb-reservations__success span { color: var(--color-fg-muted); font-size: 14px; }

.pb-reservations__error {
  margin: 0;
  padding: 10px 14px;
  border-radius: var(--ds-radius);
  background: color-mix(in oklab, var(--pb-status-negative) 10%, var(--color-bg-emphasis));
  color: var(--pb-status-negative-fg);
  font-size: 14px;
}

.pb-reservations__missing {
  display: grid;
  gap: 6px;
  text-align: center;
  padding: 28px 24px;
  background: var(--color-bg-emphasis);
  border-radius: var(--ds-radius-lg);
  border: 1px dashed var(--color-border);
}
.pb-reservations__missing strong { font-size: 16px; color: var(--color-fg); }
.pb-reservations__missing span { color: var(--color-fg-muted); font-size: 13px; }
.pb-reservations__missing code {
  background: var(--color-bg);
  padding: 1px 6px;
  border-radius: 4px;
  font-size: 12px;
}

.pb-reservations__widget {
  width: 100%;
  min-height: 400px;
  background: var(--color-bg-emphasis);
  border-radius: var(--ds-radius-lg);
  border: 1px solid var(--color-border);
}

/*
 * Edit-mode form non-interactivity. We intentionally do NOT add
 * `disabled` to every input — disabled inputs are not in the tab order
 * AND have a heavy "greyed out" UA appearance that would diverge from
 * the published preview the operator is trying to evaluate. Instead we
 * suppress pointer events on the whole form region so clicks fall
 * through to the BlockHost selection handler, and rely on the form's
 * `tabIndex=-1` to keep keyboard users out. The form still LOOKS
 * identical to the published version — same colors, same layout.
 */
.pb-reservations__body[data-edit-noninteractive="true"] {
  pointer-events: none;
}
.pb-reservations__body[data-edit-noninteractive="true"] input,
.pb-reservations__body[data-edit-noninteractive="true"] select,
.pb-reservations__body[data-edit-noninteractive="true"] textarea,
.pb-reservations__body[data-edit-noninteractive="true"] button {
  cursor: default;
}

/* ----------------------------------------------------------------
   Reservations — operator status panel (edit mode only)
   ----------------------------------------------------------------
   Only renders when EditModeContext.mode === "edit". Shows which
   booking channel was resolved and whether the necessary credentials
   are wired in the business profile, so the operator never has to
   guess "is this thing actually working?". Preview / prod render the
   real customer widget instead.
   ---------------------------------------------------------------- */
.pb-reservations-status {
  display: grid;
  gap: 14px;
  padding: 22px;
  background: var(--color-bg-emphasis);
  border: 1px dashed var(--color-border);
  border-radius: var(--ds-radius-lg);
}
.pb-reservations-status__head {
  display: grid;
  gap: 4px;
}
.pb-reservations-status__title {
  font-weight: 600;
  font-size: 15px;
  color: var(--color-fg);
}
.pb-reservations-status__sub {
  font-size: 13px;
  color: var(--color-fg-muted);
  line-height: 1.4;
}
.pb-reservations-status__list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: 8px;
}
.pb-reservations-status__row {
  display: grid;
  grid-template-columns: 110px 1fr auto;
  align-items: center;
  gap: 10px;
  padding: 10px 12px;
  background: var(--color-bg);
  border: 1px solid var(--color-border);
  border-radius: var(--ds-radius);
  font-size: 13px;
  color: var(--color-fg-muted);
}
.pb-reservations-status__row[data-active="true"] {
  border-color: var(--color-fg);
  box-shadow: 0 0 0 1px var(--color-fg) inset;
}
.pb-reservations-status__channel {
  font-weight: 600;
  color: var(--color-fg);
}
.pb-reservations-status__detail {
  font-size: 12.5px;
  color: var(--color-fg-muted);
  word-break: break-all;
}
.pb-reservations-status__badge {
  font-size: 11px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  padding: 3px 8px;
  border-radius: 999px;
  background: rgba(0, 0, 0, 0.08);
  color: var(--color-fg-muted);
}
.pb-reservations-status__row[data-connected="true"] .pb-reservations-status__badge {
  background: oklch(0.6 0.18 152 / 0.18);
  color: oklch(0.4 0.18 152);
}
.pb-reservations-status__cta {
  justify-self: start;
  font-size: 13px;
  font-weight: 500;
  color: var(--color-fg);
  text-decoration: none;
  border-bottom: 1px solid currentColor;
  padding-bottom: 1px;
}
.pb-reservations-status__cta:hover {
  opacity: 0.8;
}
