/* ============================================================================
   WoBooks Composed Ecommerce Theme — production design system
   Recolor-safe: every color derives from runtime tokens (--primary, --surface…).
   Motion baseline: CSS scroll-driven .reveal, base opacity:1, guarded.
   ========================================================================== */

:root {
  /* Runtime overrides these — never hardcode hex inside component rules. */
  --primary: #2d2a26;
  --primary-dark: #1a1815;
  --primary-light: #4a463f;
  --secondary: #8a7d6b;
  --accent: #b8965a;
  --background: #ffffff;
  --surface: #f7f5f1;
  --text: #1f1d1a;
  --muted: #6f6a61;
  --border: #e4e0d8;
  --font-sans: 'Plus Jakarta Sans', system-ui, -apple-system, 'Segoe UI', sans-serif;
  --font-display: 'Cormorant Garamond', Georgia, 'Times New Roman', serif;
  --radius: 10px;

  /* Motion tokens — reference everywhere, never hardcode durations/eases. */
  --dur-micro: 140ms;
  --dur-ui: 240ms;
  --dur-reveal: 640ms;
  --dur-slow: 1100ms;
  --ease-standard: cubic-bezier(.4, 0, .2, 1);
  --ease-out: cubic-bezier(.22, 1, .36, 1);
  --ease-spring: cubic-bezier(.34, 1.56, .64, 1);

  --container: 1200px;
  --space-section: clamp(3.5rem, 7vw, 6.5rem);
}

*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }

html { scroll-behavior: smooth; -webkit-text-size-adjust: 100%; }

body {
  font-family: var(--font-sans);
  background: var(--background);
  color: var(--text);
  line-height: 1.65;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

img { max-width: 100%; display: block; }
img[src=""], img:not([src]) { display: none !important; }
a { color: inherit; text-decoration: none; }
ul, ol { list-style: none; }

h1, h2, h3, h4 {
  font-family: var(--font-display);
  font-weight: 500;
  line-height: 1.12;
  text-wrap: balance;
  color: var(--text);
}
h1 { font-size: clamp(2.5rem, 1.9rem + 3vw, 4.6rem); }
h2 { font-size: clamp(1.9rem, 1.5rem + 1.9vw, 3rem); }
h3 { font-size: clamp(1.2rem, 1.05rem + .7vw, 1.6rem); }
p { text-wrap: pretty; }

.container { max-width: var(--container); margin-inline: auto; padding-inline: clamp(1rem, 4vw, 2.5rem); }
.eyebrow {
  display: inline-block;
  font-family: var(--font-sans);
  font-size: .72rem;
  font-weight: 600;
  letter-spacing: .16em;
  text-transform: uppercase;
  color: var(--accent);
  margin-bottom: .9rem;
}
.section-head { max-width: 640px; margin-bottom: clamp(2rem, 4vw, 3.25rem); }
.section-head p { color: var(--muted); margin-top: .75rem; font-size: 1.05rem; }
.section-head--center { margin-inline: auto; text-align: center; }

/* ── Accessibility ──────────────────────────────────────────────────────── */
.skip-link {
  position: absolute; left: -9999px; top: 0; z-index: 999;
  background: var(--primary); color: var(--background);
  padding: .75rem 1.25rem; border-radius: 0 0 var(--radius) 0;
}
.skip-link:focus { left: 0; }
:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; border-radius: 3px; }

/* ── Buttons ────────────────────────────────────────────────────────────── */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: .5rem;
  font-family: var(--font-sans); font-weight: 600; font-size: .9rem;
  padding: .85rem 1.75rem; border-radius: var(--radius); border: 1.5px solid transparent;
  cursor: pointer; transition: background var(--dur-ui) var(--ease-standard),
    color var(--dur-ui) var(--ease-standard), border-color var(--dur-ui) var(--ease-standard),
    transform var(--dur-micro) var(--ease-standard);
}
.btn:active { transform: translateY(1px); }
.btn--primary { background: var(--primary); color: var(--background); }
.btn--primary:hover { background: var(--primary-dark); }
.btn--accent { background: var(--accent); color: var(--background); }
.btn--accent:hover { background: color-mix(in oklab, var(--accent) 82%, #000); }
.btn--outline { background: transparent; color: var(--text); border-color: var(--border); }
.btn--outline:hover { border-color: var(--primary); background: var(--surface); }
.btn--block { width: 100%; }

/* ── Header ─────────────────────────────────────────────────────────────── */
.header {
  position: sticky; top: 0; z-index: 100;
  background: color-mix(in oklab, var(--background) 88%, transparent);
  backdrop-filter: saturate(140%) blur(10px);
  border-bottom: 1px solid var(--border);
}
.header__nav { display: flex; align-items: center; justify-content: space-between; height: 72px; gap: 1.5rem; }
.header__brand { display: flex; align-items: center; gap: .6rem; }
.header__logo { height: 32px; width: auto; }
.header__brand-name { font-family: var(--font-display); font-size: 1.4rem; font-weight: 600; }
.header__links { display: flex; gap: clamp(1.25rem, 3vw, 2.5rem); }
.header__links a { font-size: .9rem; font-weight: 500; color: var(--muted); transition: color var(--dur-ui) var(--ease-standard); }
.header__links a:hover { color: var(--text); }
.header__actions { display: flex; align-items: center; gap: 1rem; }
.cart-icon-btn { position: relative; display: inline-flex; color: var(--text); }
.cart-badge {
  position: absolute; top: -8px; right: -10px; min-width: 18px; height: 18px;
  padding: 0 5px; border-radius: 9px; background: var(--accent); color: var(--background);
  font-size: .68rem; font-weight: 700; line-height: 18px; text-align: center;
}
.hamburger { display: none; flex-direction: column; gap: 4px; background: none; border: none; cursor: pointer; padding: 6px; }
.hamburger span { width: 22px; height: 2px; background: var(--text); transition: transform var(--dur-ui) var(--ease-standard); }
.nav-overlay { display: none; }

/* ── Hero ───────────────────────────────────────────────────────────────── */
.hero { position: relative; min-height: clamp(480px, 82vh, 820px); display: flex; align-items: flex-end; overflow: hidden; background: var(--surface); }
.hero__bg { position: absolute; inset: 0; }
.hero__bg img { width: 100%; height: 100%; object-fit: cover; }
.hero__overlay { position: absolute; inset: 0; background: linear-gradient(to top, color-mix(in oklab, var(--primary-dark) 88%, transparent) 0%, color-mix(in oklab, var(--primary-dark) 30%, transparent) 55%, transparent 100%); }
.hero__content { position: relative; z-index: 1; padding-block: clamp(2.5rem, 7vw, 5.5rem); max-width: 760px; }
.hero--has-image .hero__content, .hero--has-image .hero__content :is(h1, p, .eyebrow) { color: var(--background); }
.hero--has-image .eyebrow { color: var(--accent); }
/* An image hero paints its content with --background (the light half of the
   pair) because it sits on the dark overlay above. `.btn--outline` hard-sets
   `color: var(--text)` — a real declaration on the element, so it BEATS that
   inherited colour, and the secondary CTA rendered dark-on-dark: a visible
   bordered box with an invisible label, on the hero of every composed theme in
   this family. Seen 2026-08-16 on `recipe-ecommerce-sell-trust` ("Browse
   categories"), and the same two lines are in business / local-service /
   real-estate / restaurant, whose image heroes carry the same outline CTA.
   Written token-relative (never a literal colour) so it stays recolor-safe:
   the hero's foreground is --background here for the same reason the heading's
   is. */
.hero--has-image .hero__ctas .btn--outline {
  color: var(--background);
  border-color: color-mix(in oklab, var(--background) 55%, transparent);
}
.hero--has-image .hero__ctas .btn--outline:hover {
  color: var(--background);
  background: color-mix(in oklab, var(--background) 16%, transparent);
  border-color: var(--background);
}
.hero__title-prefix { display: block; font-style: italic; font-weight: 400; opacity: .9; }
.hero__subtitle { font-size: clamp(1rem, .95rem + .3vw, 1.2rem); max-width: 520px; margin-block: 1.25rem 2rem; opacity: .92; }
/* `hero.content` is declared `markdown` on the business contract and inherited
   by ecommerce / local-service / real-estate / restaurant, the Manager offers
   it as an editable control, and until 2026-08-28 no generic hero shape read
   it — an owner's intro paragraph was accepted and silently dropped (TFS-13,
   and the named upstream cause of the recipe-* seed-filled-dead-field bucket).
   The marker ships on an EMPTY element body on purpose: the converter then
   compiles `{!! theme_var('hero.content', '') !!}` with no baked fallback copy,
   which is why the `:empty` collapse below is load-bearing — an unset field
   must render byte-identically to a hero that never had one. Same idiom as
   `.cine-hero__body:empty` in the cinematic-stage variant. */
.hero__body { max-width: 56ch; margin-block: 0 2rem; opacity: .92; }
.hero__body:empty { display: none; }
.hero__body p + p { margin-top: 1rem; }
.hero__ctas { display: flex; flex-wrap: wrap; gap: 1rem; }

/* Hero variant: split (content + media, no overlay) */
.hero--split { min-height: auto; align-items: center; background: var(--background); padding-block: clamp(2.5rem, 6vw, 5rem); }
.hero__split { display: grid; grid-template-columns: 1fr 1fr; gap: clamp(1.5rem, 4vw, 3.5rem); align-items: center; }
.hero__split-content :is(h1, .hero__subtitle) { color: var(--text); }
.hero__split-media { border-radius: var(--radius); overflow: hidden; aspect-ratio: 4/5; background: var(--surface); }
.hero__split-media img { width: 100%; height: 100%; object-fit: cover; }

/* Hero variant: minimal (centered text, no image) */
.hero--minimal { min-height: auto; align-items: center; background: var(--surface); text-align: center; padding-block: clamp(4rem, 10vw, 8rem); }
.hero__minimal { position: relative; z-index: 1; max-width: 760px; margin-inline: auto; }
/* Decorative backdrop for the `minimal` shape. The minimal gene stays
   `imagery: none` in `_components/hero/component.json` — do NOT "fix" it. This
   is a low-opacity wash behind the copy, not a picture, so nothing about the
   genome's shape selection changes; it exists only so `hero.image`, a field the
   contract declares and the Manager accepts edits into, is no longer dropped on
   this shape. The <img> is inert: empty alt, aria-hidden wrapper, low fetch
   priority, lazy — it is deferred so it cannot steal bandwidth from the copy.
   KNOWN, MEASURED (2026-08-28): a full-bleed image is still an LCP candidate in
   Chrome even at .12 opacity, so on a tenant that sets `hero.image` the LCP
   element becomes this backdrop rather than the <h1>. Local medians showed no
   slowdown (1310ms with it, 1775ms with it blocked — the webfont gates the
   heading), but on a slow mobile link this photo would govern LCP. If that
   shows up in field data, serve a downscaled variant here rather than deleting
   the binding — the field must stay reachable.
   Gated on the WRAPPER, not just the <img>: the fleet-wide
   `img[src=""] { display: none }` rule hides the image but would leave the
   ::after gradient painting a wash over every minimal hero with no photo. Same
   wrapper-level `:has()` idiom as `.about__media` in `_components/about/style.css`.
   With the image unset the entire scrim is gone and the render is byte-identical
   to before this rule existed. */
.hero__scrim { position: absolute; inset: 0; z-index: 0; overflow: hidden; pointer-events: none; }
.hero__scrim img { width: 100%; height: 100%; object-fit: cover; opacity: .12; }
/* The veil is an ACCESSIBILITY control, not decoration. Measured 2026-08-28 on
   a live minimal hero: with a plain top-to-bottom fade the texture reached the
   copy column and dragged `.hero__subtitle` from 3.75:1 to 3.36:1 — a scrim
   must never move text contrast at all. The radial stop is opaque `--surface`
   out to 410px each side of centre — deliberately expressed against the 760px
   `.hero__minimal` column rather than a viewport percentage, because a
   percentage narrows with the viewport and re-exposed the copy to the texture
   at 390px (measured 3.51:1 there before this stop was pinned). Every
   character now sits on pure surface at every width, and the texture reads
   only in the margin beyond the column. Keep the opaque stop wider than
   `.hero__minimal` if you ever retune it. */
.hero__scrim::after { content: ""; position: absolute; inset: 0; background: radial-gradient(ellipse 760px 78% at 50% 46%, var(--surface) 0%, var(--surface) 54%, transparent 100%), linear-gradient(to bottom, transparent 0%, var(--surface) 100%); }
.hero__scrim:has(> img[src=""]), .hero__scrim:has(> img:not([src])) { display: none; }
.hero--minimal :is(h1) { color: var(--text); }
.hero--minimal .hero__subtitle { margin-inline: auto; color: var(--muted); }
/* Deliberately inherits `--text` rather than taking `--muted` like the subtitle
   above it: at 16px, `--muted` on `--surface` measures 3.44:1 — below the 4.5:1
   WCAG AA floor for body copy. This is the owner's own paragraph, the longest
   run of reading text in the hero, and it must be legible. Softening comes from
   the inherited `opacity: .92`, which keeps it ~10:1. */
.hero--minimal .hero__body { margin-inline: auto; }
.hero--minimal .hero__ctas { justify-content: center; }

/* ── Categories ─────────────────────────────────────────────────────────── */
.categories { padding-block: var(--space-section); }
.categories__grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(220px, 1fr)); gap: clamp(1rem, 2vw, 1.5rem); }
.category-card { position: relative; display: block; aspect-ratio: 4/5; border-radius: var(--radius); overflow: hidden; background: var(--surface); }
.category-card img { width: 100%; height: 100%; object-fit: cover; transition: transform var(--dur-reveal) var(--ease-out); }
.category-card:hover img { transform: scale(1.06); }
.category-card__label { position: absolute; inset: auto 0 0 0; padding: 1.5rem 1.25rem .9rem; color: #fff; font-family: var(--font-display); font-size: 1.3rem; background: linear-gradient(to top, rgba(0,0,0,.6), transparent); }

/* ── Products (carousel/grid) ───────────────────────────────────────────── */
.products { padding-block: var(--space-section); background: var(--surface); }
.products__head { display: flex; align-items: flex-end; justify-content: space-between; gap: 1rem; margin-bottom: clamp(1.5rem, 3vw, 2.5rem); flex-wrap: wrap; }
.product-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(250px, 1fr)); gap: clamp(1.25rem, 2.5vw, 2rem); }
.product-card { background: var(--background); border-radius: var(--radius); overflow: hidden; display: flex; flex-direction: column; }
.product-card__image-wrap { position: relative; display: block; aspect-ratio: 3/4; overflow: hidden; background: var(--surface); }
.product-card__image-wrap img { width: 100%; height: 100%; object-fit: cover; transition: transform var(--dur-reveal) var(--ease-out); }
.product-card__image-wrap:hover img { transform: scale(1.05); }
.product-card__quick-view {
  position: absolute; inset: auto .75rem .75rem auto; width: 38px; height: 38px;
  display: grid; place-items: center; border-radius: 50%; background: var(--background); color: var(--text);
  opacity: 0; transform: translateY(8px); transition: opacity var(--dur-ui) var(--ease-standard), transform var(--dur-ui) var(--ease-standard);
}
.product-card__image-wrap:hover .product-card__quick-view { opacity: 1; transform: translateY(0); }
.product-card__info { padding: 1rem 1.1rem 1.25rem; display: flex; flex-direction: column; gap: .4rem; flex: 1; }
.product-card__category { font-size: .7rem; font-weight: 600; letter-spacing: .12em; text-transform: uppercase; color: var(--muted); }
.product-card__title { font-family: var(--font-display); font-size: 1.2rem; font-weight: 500; }
.product-card__title a:hover { color: var(--accent); }
.product-card__price { display: flex; align-items: baseline; gap: .5rem; margin-top: auto; padding-top: .35rem; }
.product-card__price-current { font-weight: 600; font-size: 1rem; }
.product-card__price-original { font-size: .85rem; color: var(--muted); text-decoration: line-through; }
.product-card__add-btn { margin-top: .85rem; width: 100%; padding: .7rem 1rem; font-size: .8rem; letter-spacing: .04em; text-transform: uppercase; background: var(--primary); color: var(--background); border: none; border-radius: var(--radius); cursor: pointer; transition: background var(--dur-ui) var(--ease-standard); }
.product-card__add-btn:hover { background: var(--primary-dark); }
.product-card__badge { position: absolute; top: .75rem; left: .75rem; background: var(--accent); color: var(--background); font-size: .65rem; font-weight: 700; letter-spacing: .08em; text-transform: uppercase; padding: .25rem .55rem; border-radius: 5px; }

/* ── Testimonials ───────────────────────────────────────────────────────── */
.testimonials { padding-block: var(--space-section); }
.testimonials__grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); gap: clamp(1.25rem, 2.5vw, 2rem); }
.testimonial-card { background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius); padding: 2rem; }
.testimonial-card__quote { font-family: var(--font-display); font-size: 1.2rem; line-height: 1.5; margin-bottom: 1.5rem; }
.testimonial-card__author { display: flex; align-items: center; gap: .85rem; }
.testimonial-card__author img { width: 46px; height: 46px; border-radius: 50%; object-fit: cover; }
.testimonial-card__name { font-weight: 600; font-size: .95rem; }
.testimonial-card__role { font-size: .82rem; color: var(--muted); }

/* ── FAQs ───────────────────────────────────────────────────────────────── */
.faqs { padding-block: var(--space-section); background: var(--surface); }
.faqs__list { max-width: 780px; margin-inline: auto; }
.faq-item { border-bottom: 1px solid var(--border); }
.faq-item__q { display: flex; align-items: center; justify-content: space-between; gap: 1rem; width: 100%; padding: 1.35rem 0; background: none; border: none; cursor: pointer; text-align: left; font-family: var(--font-display); font-size: 1.15rem; color: var(--text); }
.faq-item__icon { flex: none; transition: transform var(--dur-ui) var(--ease-standard); }
.faq-item[open] .faq-item__icon { transform: rotate(45deg); }
.faq-item__a { padding-bottom: 1.35rem; color: var(--muted); max-width: 68ch; }

/* ── Policies ───────────────────────────────────────────────────────────── */
.policies { padding-block: var(--space-section); }
.policies__grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(260px, 1fr)); gap: clamp(1.25rem, 2.5vw, 2rem); }
.policy-card { padding: 1.75rem; border: 1px solid var(--border); border-radius: var(--radius); }
.policy-card h3 { margin-bottom: .6rem; }
.policy-card p { color: var(--muted); }

/* ── Contact ────────────────────────────────────────────────────────────── */
.contact { padding-block: var(--space-section); background: var(--surface); }
.contact__grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); gap: 1.5rem; max-width: 900px; }
.contact__item { display: flex; flex-direction: column; gap: .3rem; }
.contact__item span:first-child { font-size: .72rem; font-weight: 600; letter-spacing: .12em; text-transform: uppercase; color: var(--muted); }
.contact__item a, .contact__item p { font-size: 1.05rem; }

/* ── Breadcrumbs ────────────────────────────────────────────────────────── */
.breadcrumbs { padding-block: 1.25rem; }
.breadcrumbs ol { display: flex; flex-wrap: wrap; gap: .5rem; font-size: .85rem; color: var(--muted); }
.breadcrumbs li:not(:last-child)::after { content: '/'; margin-left: .5rem; opacity: .5; }
.breadcrumbs a:hover { color: var(--text); }

/* ── Product detail ─────────────────────────────────────────────────────── */
.product-detail { padding-block: clamp(2rem, 4vw, 3.5rem) var(--space-section); }
.product-detail__grid { display: grid; grid-template-columns: 1.1fr 1fr; gap: clamp(2rem, 5vw, 4rem); align-items: start; }
.product-gallery__main { aspect-ratio: 1; border-radius: var(--radius); overflow: hidden; background: var(--surface); }
.product-gallery__main img { width: 100%; height: 100%; object-fit: cover; }
.product-gallery__thumbs { display: flex; gap: .75rem; margin-top: .85rem; }
.product-gallery__thumbs button { width: 76px; height: 76px; border: 1px solid var(--border); border-radius: var(--radius, 8px); overflow: hidden; background: none; cursor: pointer; padding: 0; }
.product-info__category { font-size: .72rem; font-weight: 600; letter-spacing: .12em; text-transform: uppercase; color: var(--muted); }
.product-info h1 { margin-block: .5rem .75rem; }
.product-info__price { font-size: 1.6rem; font-weight: 600; margin-bottom: 1.25rem; }
.product-info__price-original { font-size: 1.05rem; color: var(--muted); text-decoration: line-through; margin-left: .6rem; }
.product-info__desc { color: var(--muted); margin-bottom: 1.75rem; }
.variant-selector { margin-bottom: 1.25rem; }
.variant-selector fieldset { border: none; }
.variant-selector__label { font-size: .8rem; font-weight: 600; letter-spacing: .06em; text-transform: uppercase; margin-bottom: .6rem; }
.variant-selector__options { display: flex; flex-wrap: wrap; gap: .5rem; }
.variant-chip { display: inline-flex; align-items: center; padding: .5rem .95rem; border: 1.5px solid var(--border); border-radius: var(--radius); cursor: pointer; font-size: .85rem; }
.variant-chip input { position: absolute; opacity: 0; }
.variant-chip--active, .variant-chip:has(input:checked) { border-color: var(--primary); background: var(--primary); color: var(--background); }
.product-info__actions { display: flex; gap: 1rem; margin-block: 1.5rem; }
.trust-signals { display: flex; flex-wrap: wrap; gap: 1.25rem; padding-top: 1.5rem; border-top: 1px solid var(--border); }
.trust-signals__item { display: flex; align-items: center; gap: .5rem; font-size: .85rem; color: var(--muted); }

/* ── Reviews ────────────────────────────────────────────────────────────── */
.reviews { padding-block: var(--space-section); background: var(--surface); }
.reviews-list { display: grid; gap: 1.25rem; max-width: 780px; margin-bottom: 2.5rem; }
.review-item { background: var(--background); border: 1px solid var(--border); border-radius: var(--radius); padding: 1.5rem; }
.review-author { font-weight: 600; }
.review-stars { color: var(--accent); margin-left: .5rem; }
.review-title { display: block; margin-block: .5rem .25rem; }
.review-body { color: var(--muted); }
.review-form-placeholder { max-width: 560px; display: grid; gap: .85rem; }
.review-form-placeholder input, .review-form-placeholder textarea, .form-input, .form-select {
  width: 100%; padding: .85rem 1rem; border: 1.5px solid var(--border); border-radius: var(--radius);
  font: inherit; background: var(--background); color: var(--text);
}
.form-input:focus, .form-select:focus, textarea:focus { border-color: var(--primary); outline: none; }

/* ── Cart ───────────────────────────────────────────────────────────────── */
.cart { padding-block: clamp(2rem, 4vw, 3.5rem) var(--space-section); }
.cart__grid { display: grid; grid-template-columns: 1.6fr 1fr; gap: clamp(2rem, 4vw, 3rem); align-items: start; }
.cart-item { display: grid; grid-template-columns: 100px 1fr auto auto auto; gap: 1.25rem; align-items: center; padding: 1.25rem 0; border-bottom: 1px solid var(--border); }
.cart-item__img-wrap { width: 100px; aspect-ratio: 1; border-radius: 8px; overflow: hidden; background: var(--surface); }
.cart-item__img-wrap img { width: 100%; height: 100%; object-fit: cover; }
.cart-item__title { font-family: var(--font-display); font-size: 1.1rem; display: block; }
.cart-item__price { font-weight: 600; }
.cart-item__original { color: var(--muted); text-decoration: line-through; font-size: .85rem; margin-right: .4rem; }
.cart-item__qty { display: inline-flex; align-items: center; gap: .5rem; border: 1px solid var(--border); border-radius: var(--radius); padding: .25rem .5rem; }
.qty-btn { width: 26px; height: 26px; border: none; background: none; cursor: pointer; font-size: 1.1rem; color: var(--text); }
.cart-item__remove { background: none; border: none; cursor: pointer; color: var(--muted); }
.cart-item__remove:hover { color: var(--text); }
.cart-summary { background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius); padding: 1.75rem; position: sticky; top: 96px; }
.cart-summary__row { display: flex; justify-content: space-between; padding: .5rem 0; }
.cart-summary__row--total { border-top: 1px solid var(--border); margin-top: .5rem; padding-top: 1rem; font-weight: 700; font-size: 1.15rem; }
.empty-state { text-align: center; padding: clamp(3rem, 8vw, 6rem) 1rem; max-width: 460px; margin-inline: auto; }
.empty-state__icon { width: 64px; height: 64px; color: var(--muted); margin-inline: auto; margin-bottom: 1.25rem; }
.empty-state h2 { margin-bottom: .75rem; }
.empty-state p { color: var(--muted); margin-bottom: 1.5rem; }

/* ── Checkout ───────────────────────────────────────────────────────────── */
.checkout { padding-block: clamp(2rem, 4vw, 3.5rem) var(--space-section); }
/* Order-blocked notice (e.g. oversell guard). Semantic status colours are fixed
   by design — an error must read as an error under any brand recolour. */
.checkout-notice { display: flex; flex-direction: column; gap: .25rem; padding: .9rem 1.15rem; margin-bottom: 1.75rem; border: 1px solid #eab8b3; border-left: 3px solid #c0392b; border-radius: var(--radius); background: #fcecea; color: #7d241c; }
.checkout-notice__title { font-weight: 700; }
.checkout-notice__text { color: #7d241c; }
.checkout-progress { margin-bottom: 2.5rem; }
.checkout-progress ol { display: flex; align-items: flex-start; max-width: 380px; }
.checkout-progress__step { flex: 1; display: flex; flex-direction: column; align-items: center; gap: 6px; position: relative; font-size: .8rem; color: var(--muted); }
.checkout-progress__step span { width: 26px; height: 26px; border-radius: 50%; display: grid; place-items: center; background: var(--surface); border: 1.5px solid var(--border); font-weight: 600; }
.checkout-progress__step:not(:last-child)::after { content: ''; position: absolute; top: 13px; left: 50%; width: 100%; height: 2px; background: var(--border); z-index: -1; }
.checkout-progress__step--completed span, .checkout-progress__step--active span { background: var(--primary); color: var(--background); border-color: var(--primary); }
.checkout-progress__step--active { color: var(--text); font-weight: 600; }
.checkout__grid { display: grid; grid-template-columns: 1.5fr 1fr; gap: clamp(2rem, 4vw, 3rem); align-items: start; }
.checkout__fieldset { border: none; margin-bottom: 2rem; }
.checkout__fieldset legend { font-family: var(--font-display); font-size: 1.3rem; margin-bottom: 1rem; }
.form-row { display: grid; grid-template-columns: 1fr 1fr; gap: 1rem; margin-bottom: 1rem; }
.form-group { margin-bottom: 1rem; }
.form-group label { display: block; font-size: .82rem; font-weight: 600; margin-bottom: .4rem; }
.method-option { display: flex; align-items: center; gap: .75rem; padding: 1rem; border: 1.5px solid var(--border); border-radius: var(--radius); margin-bottom: .75rem; cursor: pointer; }
.method-option:has(input:checked) { border-color: var(--primary); }
.checkout-summary-item { display: grid; grid-template-columns: 56px 1fr auto; gap: .85rem; align-items: center; padding: .75rem 0; border-bottom: 1px solid var(--border); }
.checkout-summary-item img { border-radius: 6px; object-fit: cover; }
.checkout-summary-item__title { font-weight: 500; font-size: .9rem; }
.checkout-summary-item__qty { font-size: .8rem; color: var(--muted); }

/* ── Footer ─────────────────────────────────────────────────────────────── */
.footer { background: var(--primary-dark); color: color-mix(in oklab, var(--background) 78%, var(--primary)); padding-block: clamp(3rem, 6vw, 4.5rem) 1.75rem; }
.footer__top { display: grid; grid-template-columns: 1.6fr 1fr 1fr 1.4fr; gap: clamp(1.5rem, 3vw, 2.5rem); padding-bottom: 2.5rem; border-bottom: 1px solid color-mix(in oklab, var(--background) 14%, transparent); }
.footer__brand-name { font-family: var(--font-display); font-size: 1.5rem; color: var(--background); display: block; margin-bottom: .6rem; }
.footer__brand p { font-size: .92rem; opacity: .85; max-width: 30ch; }
.footer__social { display: flex; gap: .65rem; margin-top: 1.1rem; }
.footer__social-link { width: 38px; height: 38px; display: grid; place-items: center; border-radius: var(--radius, 50%); border: 1px solid color-mix(in oklab, var(--background) 22%, transparent); color: var(--background); transition: background var(--dur-ui) var(--ease-standard); }
.footer__social-link:hover { background: var(--accent); border-color: var(--accent); }
.footer__links-col h4, .footer__newsletter h4 { color: var(--background); font-family: var(--font-sans); font-size: .8rem; letter-spacing: .12em; text-transform: uppercase; margin-bottom: 1rem; }
.footer__links-col ul { display: grid; gap: .6rem; }
.footer__links-col a { font-size: .92rem; opacity: .85; }
.footer__links-col a:hover { opacity: 1; color: var(--accent); }
.footer__newsletter p { font-size: .9rem; opacity: .85; margin-bottom: 1rem; }
.newsletter-form { display: flex; gap: .5rem; }
.newsletter-form .form-input { background: color-mix(in oklab, var(--background) 12%, transparent); border-color: color-mix(in oklab, var(--background) 22%, transparent); color: var(--background); }
.footer__bottom { display: flex; flex-wrap: wrap; justify-content: space-between; gap: .75rem; padding-top: 1.75rem; font-size: .82rem; opacity: .75; }

/* ── Motion: scroll-driven reveal (base visible, progressively enhanced) ── */
.reveal { opacity: 1; }
@supports (animation-timeline: view()) {
  @media (prefers-reduced-motion: no-preference) {
    .reveal {
      opacity: 0; transform: translateY(28px);
      animation: reveal-in linear both;
      animation-timeline: view();
      animation-range: entry 0% entry 38%;
    }
  }
}
@keyframes reveal-in { to { opacity: 1; transform: none; } }

/* ── Responsive ─────────────────────────────────────────────────────────── */
@media (max-width: 900px) {
  .product-detail__grid, .cart__grid, .checkout__grid, .hero__split { grid-template-columns: 1fr; }
  .hero__split-media { order: -1; }
  .footer__top { grid-template-columns: 1fr 1fr; }
  .cart-summary { position: static; }
}
@media (max-width: 720px) {
  .header__links { display: none; }
  .hamburger { display: flex; }
  .products__head { flex-direction: column; align-items: flex-start; }
  .form-row { grid-template-columns: 1fr; }
  .cart-item { grid-template-columns: 72px 1fr auto; grid-template-areas: 'img title remove' 'img qty total'; row-gap: .5rem; }
  .cart-item__img-wrap { grid-area: img; width: 72px; }
  .footer__top { grid-template-columns: 1fr; }
}

/* ---------------------------------------------------------------------------
   WB form baseline — assembled-form controls (2026-07-19).
   Harvested contact/booking/quote variants ship structural form markup
   (form-group / form-input / contact-form …) but relied on donor CSS that the
   composer never carries. Without this block their inputs render as raw
   browser defaults (verified live on an assembled karyana site). Token-driven
   so Style Presets retoken it like everything else.
--------------------------------------------------------------------------- */
.contact-form, .contact__form, .contact__form-card form, .booking-form, .quote-form, .reservation-form {
  display: flex; flex-direction: column; gap: 1rem;
}
.form-row { display: grid; gap: 1rem; }
.form-row--2col { grid-template-columns: 1fr 1fr; }
@media (max-width: 640px) { .form-row--2col { grid-template-columns: 1fr; } }
.form-group { display: flex; flex-direction: column; gap: .4rem; margin-bottom: 0; }
.form-label,
.form-group label { font-size: .82rem; font-weight: 600; color: var(--text); }
.form-input,
.form-textarea,
.form-group input, .form-group textarea, .form-group select,
.contact-form input, .contact-form textarea, .contact-form select,
.contact__form input, .contact__form textarea, .contact__form select {
  width: 100%;
  padding: .75rem 1rem;
  font: inherit;
  color: var(--text);
  background: var(--background);
  border: 1.5px solid var(--border);
  border-radius: var(--radius, 10px);
  transition: border-color var(--dur-ui, .18s) var(--ease-standard, ease);
}
.form-input:focus, .form-textarea:focus,
.form-group :is(input, textarea, select):focus,
.contact-form :is(input, textarea, select):focus,
.contact__form :is(input, textarea, select):focus {
  outline: none;
  border-color: var(--primary);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--primary) 18%, transparent);
}
.form-textarea,
.form-group textarea, .contact-form textarea, .contact__form textarea { min-height: 7.5rem; resize: vertical; }
.form-submit,
.contact-form button[type="submit"], .contact__form button[type="submit"] {
  align-self: flex-start;
  padding: .8rem 1.9rem;
  font: inherit; font-weight: 600;
  color: var(--background, #fff);
  background: var(--primary);
  border: none;
  border-radius: var(--radius, 10px);
  cursor: pointer;
  transition: background var(--dur-ui, .18s) var(--ease-standard, ease), transform var(--dur-ui, .18s) var(--ease-standard, ease);
}
.form-submit:hover,
.contact-form button[type="submit"]:hover, .contact__form button[type="submit"]:hover {
  background: var(--primary-dark, var(--primary));
  transform: translateY(-1px);
}
.form-honeypot { position: absolute !important; left: -9999px !important; width: 1px; height: 1px; overflow: hidden; }


/* ── section component: testimonials ── */
/* Section Component: testimonials — self-contained, token-only, recolor-safe.
   Relies on the shared primitive layer for .container / .section-head /
   .eyebrow / .reveal. Dormant until the L1 CSS collector. */
.testimonials { padding-block: var(--space-section); }
.testimonials__grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); gap: clamp(1.25rem, 2.5vw, 2rem); }
.testimonial-card { background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius); padding: 2rem; }
.testimonial-card__quote { font-family: var(--font-display); font-size: 1.2rem; line-height: 1.5; margin-bottom: 1.5rem; }
.testimonial-card__author { display: flex; align-items: center; gap: .85rem; }
.testimonial-card__author img { width: 46px; height: 46px; border-radius: 50%; object-fit: cover; }
/* Empty-image guard, component-scoped so it travels with an INJECTED section:
   the L2 renderer leaves src="" until the owner uploads a photo, and a visible
   <img src=""> is the browser's broken-image icon. */
.testimonial-card__author img[src=""], .testimonial-card__author img:not([src]) { display: none !important; }
.testimonial-card__name { font-weight: 600; font-size: .95rem; }
.testimonial-card__role { font-size: .82rem; color: var(--muted); }

/* ── section component: faqs ── */
/* Section Component: faqs — self-contained, token-only, recolor-safe.
   Relies on the shared primitive layer for .container / .section-head /
   .eyebrow / .reveal (present in every composed theme). Dormant until the
   L1 CSS collector wires it into the composed stylesheet. */
.faqs { padding-block: var(--space-section); background: var(--surface); }
.faqs__list { max-width: 780px; margin-inline: auto; }
.faq-item { border-bottom: 1px solid var(--border); }
.faq-item__q { display: flex; align-items: center; justify-content: space-between; gap: 1rem; width: 100%; padding: 1.35rem 0; background: none; border: none; cursor: pointer; text-align: left; font-family: var(--font-display); font-size: 1.15rem; color: var(--text); }
.faq-item__icon { flex: none; transition: transform var(--dur-ui) var(--ease-standard); }
.faq-item[open] .faq-item__icon { transform: rotate(45deg); }
.faq-item__a { padding-bottom: 1.35rem; color: var(--muted); max-width: 68ch; }

/* ── section component: contact ── */
/* Section Component: contact — self-contained, token-only, recolor-safe.
   Relies on the shared primitive layer for .container / .section-head /
   .eyebrow / .reveal. Dormant until the L1 CSS collector. */
.contact { padding-block: var(--space-section); background: var(--surface); }
.contact__grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); gap: 1.5rem; max-width: 900px; }
.contact__item { display: flex; flex-direction: column; gap: .3rem; }
.contact__item span:first-child { font-size: .72rem; font-weight: 600; letter-spacing: .12em; text-transform: uppercase; color: var(--muted); }
.contact__item a, .contact__item p { font-size: 1.05rem; }

/* ── list empty state (TFS8-2) ── */
.wb-list-empty { grid-column: 1 / -1; margin: 0; padding: var(--space-md, 1.5rem) 0; color: var(--muted); text-align: center; }

/* ── motion pack: bold (P2.1 — vibe-driven reveal) ───────────────────────
   Resting state is fully visible; the hidden `from` is gated behind @supports
   AND prefers-reduced-motion. transform/opacity only. */
@supports (animation-timeline: view()) {
  @media (prefers-reduced-motion: no-preference) {
    .reveal {
      animation: wb-reveal-bold .42s cubic-bezier(.05,.7,.1,1) both;
      animation-timeline: view();
      animation-range: entry 0% cover 35%;
    }
      .reveal:nth-child(2) { animation-range: entry 4% cover 39%; }
      .reveal:nth-child(3) { animation-range: entry 8% cover 43%; }
      .reveal:nth-child(4) { animation-range: entry 12% cover 47%; }
      .reveal:nth-child(5) { animation-range: entry 16% cover 51%; }
      .reveal:nth-child(6) { animation-range: entry 20% cover 55%; }

    @keyframes wb-reveal-bold {
      from { opacity: 0; transform: translateY(22px) scale(1.015); }
      to   { opacity: 1; transform: none; }
    }
  }
}

/* Reduced-motion + no-support safety net: content is always visible. */
@media (prefers-reduced-motion: reduce) {
  .reveal { animation: none; opacity: 1; transform: none; }
}
/* ── surface finish (P2.2) — hero-scoped, token-driven, pointer-transparent ── */
[data-section="hero"] { position: relative; isolation: isolate; }
[data-section="hero"]::after {
  content: ""; position: absolute; inset: 0; z-index: -1; pointer-events: none;
  background: linear-gradient(115deg,
    color-mix(in srgb, var(--primary, #2563eb) 14%, transparent) 0%,
    transparent 45%,
    color-mix(in srgb, var(--accent, var(--primary, #2563eb)) 12%, transparent) 100%);
}
/* ── imagery treatment (P2.3) — per-team token, editorial images only ────────
   Product, menu and logo images are intentionally excluded: their colour is
   information, not decoration. */
[data-section="hero"] img,
[data-section="about"] img {
  filter: var(--img-filter, none);
}

/* __wobooks-defensive__ — appended by HtmlZipThemeConverterV2.
   Hide images whose src resolves to empty (e.g. data-src-field bindings
   for Items / categories the owner hasn't uploaded a photo for yet).
   Without this rule, the browser shows the alt-text fallback —
   that's the bug behind the literal word 'image' showing in avatar
   slots and About images on the production Braise theme. */
img[src=""], img:not([src]) { display: none !important; }

/* Grid-collapse fix: [data-list] is the WoBooks repeater wrapper. When the
   grid/flex layout lives on the PARENT, the wrapper would otherwise become
   a single grid/flex item and collapse every [data-item] row into one cell.
   display:contents makes the wrapper layout-transparent so each row
   participates in the parent track. Mirrors TemplateSkeletonGenerator so
   converted themes match skeleton/AI-generated themes. (Convention: never
   put the grid/flex container ON the [data-list] element itself.) */
[data-list] { display: contents; }
