/* ============================================================
   Storefront design system
   Palette: espresso ink, parchment, antique brass, oxblood, sage
   Display: Fraunces · Body: Archivo · Utility: IBM Plex Mono
   ============================================================ */

:root {
  --color-ink: #000000;
  --color-footer-header: #151d3c;
  --color-background: #f6e4c8;
  --color-ink-soft: #d29a7d;
  --color-parchment: #c09f63;
  --color-parchment-dim: #e2d9c8;
  --color-brass: #d6bc8b;
  --color-brass-dark: #a9832f;
  --color-oxblood: #6b2737;
  --color-sage: #5c6b4f;
  --color-white: #fffdf9;
  --font-display: 'Fraunces', serif;
  --font-body: 'Archivo', sans-serif;
  --font-mono: 'IBM Plex Mono', monospace;
  --radius: 2px;
  --max-width: 1200px;
}

* { box-sizing: border-box; }
html {
  scroll-behavior: smooth;
  /* Hide the browser's own page scrollbar (the bulky grey bar that sat on
     the right edge, cutting across the header). The page still scrolls
     fine with the wheel/trackpad/touch/keyboard — this only hides the
     visible track+thumb rendered on top of it. */
  scrollbar-width: none;
  -ms-overflow-style: none;
}
html::-webkit-scrollbar { display: none; width: 0; height: 0; }
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  * { animation-duration: 0.01ms !important; animation-iteration-count: 1 !important; transition-duration: 0.01ms !important; }
}

body {
  margin: 0;
  font-family: var(--font-body);
  background: var(--color-background);
  color: var(--color-parchment);
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
  overflow-x: hidden;
}

h1, h2, h3 { font-family: var(--font-display); font-weight: 500; line-height: 1.1; margin: 0 0 0.5em; }
h1 { font-size: clamp(2rem, 4vw, 3rem); }
h2 { font-size: clamp(1.4rem, 2.5vw, 1.9rem); margin-top: 2.5rem; }
p { margin: 0 0 1em; }
a { color: inherit; }
img { max-width: 100%; display: block; }

.eyebrow {
  font-family: var(--font-mono);
  text-transform: uppercase;
  letter-spacing: 0.12em;
  font-size: 0.72rem;
  color: var(--color-oxblood);
  margin: 0 0 0.6em;
}

a:focus-visible, button:focus-visible, input:focus-visible, select:focus-visible, textarea:focus-visible {
  outline: 2px solid var(--color-brass);
  outline-offset: 2px;
}

/* ---- Buttons ---- */
.btn {
  display: inline-block;
  font-family: var(--font-body);
  font-weight: 600;
  font-size: 0.95rem;
  padding: 0.85em 1.6em;
  border-radius: var(--radius);
  border: 1px solid transparent;
  cursor: pointer;
  text-decoration: none;
  transition: transform 0.15s ease, background 0.15s ease;
}
.btn:hover { transform: translateY(-1px); }
.btn--brass { background: var(--color-brass); color: var(--color-ink); }
.btn--brass:hover { background: var(--color-brass-dark); }
.btn--outline { background: transparent; border-color: var(--color-ink); color: var(--color-ink); }
.btn--ghost { background: transparent; border-color: currentColor; }
.btn--small { padding: 0.5em 1.1em; font-size: 0.85rem; }
.btn--full { width: 100%; text-align: center; }
.btn[disabled] { opacity: 0.5; cursor: not-allowed; transform: none; }

.link-button { background: none; border: none; padding: 0; font: inherit; color: var(--color-oxblood); text-decoration: underline; cursor: pointer; }
.link-button--danger { color: #a3372c; }

/* ---- Header ---- */
.site-header {
  position: relative;
  z-index: 20;
  border-bottom: 1px solid rgba(28, 20, 16, 0.1);
  background: var(--color-footer-header);
}
.site-header__inner {
  max-width: var(--max-width);
  margin: 0 auto;
  padding: 1.1rem 1.5rem;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1.5rem;
}
.wordmark {
  font-family: var(--font-display);
  font-size: 1.5rem;
  text-decoration: none;
  color: inherit;
  letter-spacing: 0.01em;
}
.main-nav { display: flex; gap: 1.75rem; }
.main-nav a { text-decoration: none; font-size: 0.92rem; font-weight: 500; }
.header-actions { display: flex; align-items: center; gap: 1rem; }
.icon-link { position: relative; display: inline-flex; color: inherit; }
.cart-badge {
  position: absolute; top: -8px; right: -10px;
  background: var(--color-oxblood); color: var(--color-white);
  font-family: var(--font-mono); font-size: 0.65rem;
  border-radius: 999px; min-width: 16px; height: 16px;
  display: flex; align-items: center; justify-content: center; padding: 0 4px;
}

/* ---- Header: categories flyout button ---- */
.menu-toggle {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 38px;
  height: 38px;
  padding: 0;
  border: 1px solid rgba(237, 230, 217, 0.25);
  border-radius: var(--radius);
  background: transparent;
  color: inherit;
  cursor: pointer;
  flex: 0 0 auto;
  transition: background 0.15s ease, border-color 0.15s ease;
}
.menu-toggle:hover { background: rgba(237, 230, 217, 0.08); border-color: rgba(237, 230, 217, 0.4); }

/* ---- Header: search ---- */
.header-search {
  display: flex;
  align-items: center;
  border: 1px solid rgba(237, 230, 217, 0.25);
  border-radius: var(--radius);
  overflow: hidden;
  background: rgba(255, 253, 249, 0.04);
}
.header-search__input {
  border: none;
  background: transparent;
  color: inherit;
  font-family: var(--font-body);
  font-size: 0.85rem;
  padding: 0.55em 0.8em;
  width: 160px;
  max-width: 40vw;
}
.header-search__input::placeholder { color: currentColor; opacity: 0.55; }
.header-search__input:focus { outline: none; }
.header-search__submit {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border: none;
  background: transparent;
  color: inherit;
  cursor: pointer;
  padding: 0 0.7em;
  height: 36px;
}
.header-search__submit:hover { color: var(--color-brass); }

/* ---- Categories sidenav (flyout panel + overlay) ---- */
.sidenav-overlay {
  position: fixed;
  inset: 0;
  background: rgba(0, 0, 0, 0.45);
  z-index: 29;
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.2s ease;
}
.sidenav-overlay:not([hidden]) { opacity: 1; pointer-events: auto; }
.sidenav-overlay[hidden] { display: block; }

.sidenav {
  position: fixed;
  top: 0;
  left: 0;
  bottom: 0;
  width: min(320px, 85vw);
  background: var(--color-footer-header);
  color: var(--color-parchment);
  z-index: 30;
  overflow-y: auto;
  padding: 1.5rem;
  transform: translateX(-100%);
  transition: transform 0.25s ease;
  box-shadow: 2px 0 24px rgba(0, 0, 0, 0.25);
  /* Stays scrollable, just without the visible track+thumb. */
  scrollbar-width: none;
  -ms-overflow-style: none;
}
.sidenav::-webkit-scrollbar { display: none; width: 0; height: 0; }
.sidenav.is-open { transform: translateX(0); }

.sidenav__header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 1rem;
  padding-bottom: 0.75rem;
  border-bottom: 1px solid rgba(237, 230, 217, 0.15);
}
.sidenav__title {
  font-family: var(--font-display);
  font-size: 1.1rem;
  margin: 0;
  color: var(--color-white);
}
.sidenav__close {
  background: none;
  border: none;
  color: inherit;
  font-size: 1.4rem;
  line-height: 1;
  cursor: pointer;
  padding: 0.2em 0.4em;
}
.sidenav__close:hover { color: var(--color-brass); }

.sidenav__link {
  display: block;
  text-decoration: none;
  color: inherit;
  font-size: 0.92rem;
  padding: 0.5em 0;
}
.sidenav__link--all {
  font-weight: 600;
  color: var(--color-white);
  margin-bottom: 0.5rem;
  padding-bottom: 0.75rem;
  border-bottom: 1px solid rgba(237, 230, 217, 0.15);
}
.sidenav__list { list-style: none; margin: 0; padding: 0; }
.sidenav__item { margin: 0; }
.sidenav__item--parent > .sidenav__link { font-weight: 600; color: var(--color-white); margin-top: 0.4rem; }
.sidenav__item .sidenav__list { padding-left: 1rem; }
.sidenav__item .sidenav__list .sidenav__link { font-size: 0.86rem; opacity: 0.85; padding: 0.35em 0; }
.sidenav__item .sidenav__list .sidenav__link:hover { opacity: 1; color: var(--color-brass); }

body.is-home .site-header {
  position: absolute;
  top: 0; left: 0; right: 0;
  border-bottom-color: transparent;
  color: var(--color-parchment);
}

/* ---- Hero / 3D scroll stage ---- */
.hero { position: relative; height: 300vh; }
.hero__sticky {
  position: sticky;
  top: 0;
  height: 100vh;
  overflow: hidden;
  background: radial-gradient(ellipse at 50% 30%, #2a1f18 0%, var(--color-ink) 70%);
}
#bag-canvas { position: absolute; inset: 0; width: 100%; height: 100%; transition: opacity 0.4s ease; }
.hero__copy {
  position: relative;
  z-index: 5;
  height: 100%;
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  text-align: center;
  color: var(--color-parchment);
  padding: 0 1.5rem;
  pointer-events: none;
}
.hero__copy .eyebrow { color: var(--color-brass); }
.hero__copy h1 { font-size: clamp(2.4rem, 6vw, 4.2rem); color: var(--color-white); }
.hero__sub { max-width: 30em; opacity: 0.85; }
.hero__copy .btn { pointer-events: auto; }
#reveal-overlay {
  position: absolute; inset: 0;
  background: var(--color-parchment);
  opacity: 0;
  z-index: 4;
  pointer-events: none;
}

/* ---- Product grid / cards ---- */
.shop-preview, .store-layout, .page-header, .cart-page, .checkout-page, .account-page,
.legal-page, .contact-page, .order-confirm, .auth-page, .product-detail {
  max-width: var(--max-width);
  margin: 0 auto;
  padding: 3rem 1.5rem;
}
.shop-preview { text-align: center; }
.shop-preview h2 { margin-bottom: 2rem; }

.home-intro { border-top: 1px solid var(--color-parchment-dim); }
.home-intro__inner { max-width: var(--max-width); margin: 0 auto; padding: 3.5rem 1.5rem; text-align: center; }
.home-intro__inner h2 { max-width: 30em; margin-left: auto; margin-right: auto; }
.home-intro__inner > p { max-width: 42em; margin-left: auto; margin-right: auto; }
.home-intro__categories { list-style: none; display: flex; flex-wrap: wrap; justify-content: center; gap: 0.6rem; padding: 0; margin: 1.5rem 0 0; }
.home-intro__categories a { display: inline-block; text-decoration: none; border: 1px solid var(--color-ink-soft); border-radius: 999px; padding: 0.5em 1.1em; font-size: 0.88rem; }
.home-intro__categories a:hover { background: var(--color-ink); color: var(--color-parchment); border-color: var(--color-ink); }

.breadcrumb-nav { max-width: var(--max-width); margin: 1.2rem auto 0; padding: 0 1.5rem; font-size: 0.82rem; color: var(--color-ink-soft); }
.breadcrumb-nav a { text-decoration: none; color: var(--color-ink-soft); }
.breadcrumb-nav a:hover { color: var(--color-ink); text-decoration: underline; }
.breadcrumb-nav span[aria-current] { color: var(--color-ink); font-weight: 600; }

.product-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
  gap: 1.75rem;
  text-align: left;
  margin-top: 1.5rem;
}
.product-card {
  text-decoration: none;
  color: inherit;
  display: flex;
  flex-direction: column;
  max-width: 100%;
  height: 100%;
  min-height: 0;
  /* .tag--out ("Sold out") positions against this, not against
     .product-card__image — see that tag's comment below for why. */
  position: relative;
}
.product-card__image {
  position: relative;
  aspect-ratio: 4 / 5;
  /* flex-shrink (but NOT flex-grow — see below) lets this box give up
     height to the name/price lines below it whenever the card sits inside
     a fixed-height container (e.g. a page-builder cell) that's too short
     for a full 4:5 image + two lines of text — the picture scales itself
     down to fit rather than the card overflowing its box. */
  /* grow:0 is deliberate: this used to be "1 1 auto", which let the image
     box stretch to fill any leftover height in its row (e.g. a neighboring
     card with a 2-line name making the whole grid row taller). With
     object-fit:contain that leftover height showed up as a big empty gap
     above/below a picture that no longer matched the box's stretched size.
     grow:0 keeps the box at its natural 4:5-of-the-card's-width size —
     any leftover row height now becomes blank space below the card's
     name/price instead of stretching the picture's own box. */
  flex: 0 1 auto;
  min-height: 0;
  width: 100%;
  max-width: 100%;
  /* Was a solid parchment-dim fill — with object-fit:contain (below) any
     part of this box the picture doesn't cover reads as a visible gray/tan
     letterboxing bar. Transparent lets the page's own background show
     through instead, so a picture that doesn't fill its 4:5 box just blends
     in rather than looking like a stray gray band. */
  background: transparent;
  overflow: hidden;
  margin-bottom: 0.75rem;
  /* Picks up --pb-radius from an ancestor page-builder item (see
     App\BlockRenderer::renderBlock() and admin-page-builder.js's
     radiusClipStyle()) so a product picture placed via the page builder can
     be rounded to match its block's own "Corner rounding" setting, instead
     of only the block's padded outer edge ever looking rounded. Outside the
     page builder --pb-radius is unset, so this is 0 everywhere else. */
  border-radius: var(--pb-radius, 0);
}
/* object-fit: contain (not cover) so the whole picture always scales down
   to fit its box rather than being cropped — "make the pictures % smaller
   until they fit" rather than cutting parts of them off. */
/* border-radius lives on the img itself too, not just the box above — a
   contain-fit picture with any letterboxing wouldn't visibly look rounded
   from the box's rounding alone, since the box's corners can sit well
   outside the picture's own edges. */
.product-card__image img { display: block; width: 100%; height: 100%; max-width: 100%; max-height: 100%; object-fit: contain; transition: transform 0.4s ease; border-radius: var(--pb-radius, 0); }
.product-card:hover .product-card__image img { transform: scale(1.04); }
.product-card__placeholder { width: 100%; height: 100%; background: linear-gradient(135deg, #d8cdb8, #c7b998); }
.product-card__placeholder--large { aspect-ratio: 4/5; }
.product-card__name {
  font-weight: 600;
  margin: 0 0 0.2rem;
  flex: 0 0 auto;
  overflow: hidden;
  text-overflow: ellipsis;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
}
.product-card__price { font-family: var(--font-mono); font-size: 0.9rem; color: var(--color-oxblood); margin: 0; flex: 0 0 auto; }
.product-card__shipping-note { font-family: var(--font-body); font-size: 0.72rem; color: var(--color-ink-soft); margin: 0.15em 0 0; flex: 0 0 auto; }
.tag { display: inline-block; font-family: var(--font-mono); font-size: 0.7rem; text-transform: uppercase; letter-spacing: 0.06em; background: var(--color-ink); color: var(--color-parchment); padding: 0.25em 0.6em; border-radius: 999px; }
/* Positioned against .product-card (position:relative, above), not against
   .product-card__image — that box clips to its own "Picture rounding"
   corner, which cut this tag off whenever a picture was rounded, since the
   tag sits right where the rounded corner clips into. The image is always
   the card's first item, so the top-left corner still lines up visually. */
.tag--out { position: absolute; top: 0.6rem; left: 0.6rem; z-index: 1; background: var(--color-oxblood); color: var(--color-white); }
.center-cta { text-align: center; margin-top: 2.5rem; }

/* ---- Store layout (filters + results) ---- */
.page-header { padding-bottom: 1rem; }
.store-layout__inner { display: grid; grid-template-columns: 220px 1fr; gap: 2.5rem; }
.store-filters, .store-results { min-width: 0; }
.store-filters__heading { font-family: var(--font-mono); text-transform: uppercase; font-size: 0.75rem; letter-spacing: 0.08em; color: var(--color-ink-soft); margin: 1.5rem 0 0.5rem; }
.store-filters__list { list-style: none; padding: 0; margin: 0; display: flex; flex-direction: column; gap: 0.4rem; }
.store-filters__list a { text-decoration: none; font-size: 0.92rem; }
.store-filters__list a.is-active { font-weight: 700; color: var(--color-oxblood); }
.search-form { display: flex; gap: 0.4rem; }
.search-form input { flex: 1; padding: 0.55em 0.7em; border: 1px solid var(--color-ink-soft); border-radius: var(--radius); background: var(--color-white); }
.search-form button { border: 1px solid var(--color-ink); background: var(--color-ink); color: var(--color-parchment); padding: 0 0.9em; border-radius: var(--radius); cursor: pointer; }
.empty-state { color: var(--color-ink-soft); padding: 2rem 0; }
.pagination { display: flex; gap: 0.5rem; margin-top: 2rem; }
.pagination a { text-decoration: none; padding: 0.4em 0.8em; border: 1px solid var(--color-ink-soft); border-radius: var(--radius); }
.pagination a.is-active { background: var(--color-ink); color: var(--color-parchment); border-color: var(--color-ink); }

/* ---- Product detail ---- */
.product-detail__inner { display: grid; grid-template-columns: 1.1fr 1fr; gap: 3rem; }
.product-detail__gallery, .product-detail__info { min-width: 0; overflow-wrap: break-word; }
.thumb-row { display: flex; gap: 0.6rem; margin-top: 0.6rem; }
.thumb { border: 1px solid var(--color-ink-soft); background: none; padding: 0; width: 64px; height: 64px; cursor: pointer; overflow: hidden; }
.thumb img { width: 100%; height: 100%; object-fit: cover; }
.product-detail__price { font-family: var(--font-mono); font-size: 1.4rem; color: var(--color-oxblood); }
.product-detail__compare { text-decoration: line-through; color: var(--color-ink-soft); font-size: 1rem; margin-left: 0.5em; }
.product-detail__tax-note { display: block; font-family: var(--font-body); font-size: 0.78rem; color: var(--color-ink-soft); margin-top: 0.2em; }
.product-detail__shipping-note { display: block; font-family: var(--font-body); font-size: 0.78rem; color: var(--color-ink-soft); margin-top: 0.2em; }

.option-group { margin: 1.1rem 0; }
.option-group__label { font-size: 0.85rem; font-weight: 600; margin-bottom: 0.5rem; display: block; }
.option-group__hint { font-size: 0.8rem; color: var(--color-ink-soft); margin: 0.4rem 0 0; }
#gift-card-amount { font: inherit; font-size: 1.1rem; padding: 0.55em 0.7em; border: 1px solid var(--color-ink-soft); border-radius: var(--radius); width: 160px; max-width: 100%; }
.package-swatches { display: flex; flex-wrap: wrap; gap: 0.6rem; }
.package-swatch {
  width: 56px; height: 56px; padding: 0; border-radius: var(--radius);
  border: 2px solid transparent; background: var(--color-parchment-dim);
  cursor: pointer; overflow: hidden; position: relative;
}
.package-swatch img { width: 100%; height: 100%; object-fit: cover; }
.package-swatch__initial { display: flex; align-items: center; justify-content: center; height: 100%; font-weight: 700; }
.package-swatch.is-selected { border-color: var(--color-oxblood); }
.package-swatch:hover { border-color: var(--color-ink-soft); }
.package-swatch.is-soldout { opacity: 0.4; filter: grayscale(1); cursor: not-allowed; }
.package-swatch.is-soldout::after {
  content: ''; position: absolute; inset: 0;
  background: linear-gradient(to top right, transparent calc(50% - 1px), var(--color-ink) 50%, transparent calc(50% + 1px));
}
.option-group__selected-name { font-size: 0.85rem; color: var(--color-ink-soft); margin: 0.5rem 0 0; }
#size-select { padding: 0.6em 0.8em; border: 1px solid var(--color-ink-soft); border-radius: var(--radius); background: var(--color-white); min-width: 160px; }

#add-to-cart-form { display: flex; align-items: center; gap: 0.8rem; margin: 1.2rem 0 0.4rem; }
#add-to-cart-form input[type=number] { width: 70px; padding: 0.6em; border: 1px solid var(--color-ink-soft); border-radius: var(--radius); }
.stock-note { font-size: 0.85rem; color: var(--color-sage); }
.form-message { font-size: 0.85rem; min-height: 1.2em; }
.form-message.is-error { color: #a3372c; }
.form-message.is-success { color: var(--color-sage); }

/* ---- Forms (shared) ---- */
.form-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 1rem; margin-top: 1rem; }
.form-grid label, .auth-form label { display: flex; flex-direction: column; gap: 0.35rem; font-size: 0.85rem; font-weight: 600; }
.form-grid input, .form-grid select, .form-grid textarea,
.auth-form input, .auth-form textarea {
  font: inherit; padding: 0.65em 0.8em; border: 1px solid var(--color-ink-soft); border-radius: var(--radius); background: var(--color-white);
}
.span-2 { grid-column: span 2; }
@media (max-width: 640px) { .form-grid { grid-template-columns: 1fr; } .span-2 { grid-column: span 1; } }
.inline-form { display: flex; gap: 0.6rem; align-items: center; }

/* ---- Auth pages ---- */
.auth-page__inner { max-width: 420px; margin: 0 auto; }
.auth-form { display: flex; flex-direction: column; gap: 1rem; margin-top: 1.5rem; }
.auth-switch { margin-top: 1rem; font-size: 0.9rem; }
/* Overrides the shared column-stacked .auth-form label above — this one's a
   checkbox + its own text sitting side by side, not a field with a label
   above it. */
.auth-form__agree, .checkout-agree {
  flex-direction: row !important;
  align-items: flex-start;
  gap: 0.6rem !important;
  font-size: 0.85rem;
  font-weight: 400 !important;
}
.auth-form__agree input, .checkout-agree input { margin-top: 0.2em; flex: none; }

/* ---- Cart ---- */
.cart-table { display: flex; flex-direction: column; gap: 1.2rem; }
.cart-row { display: grid; grid-template-columns: 80px 1fr 90px 100px 30px; gap: 1rem; align-items: center; border-bottom: 1px solid var(--color-parchment-dim); padding-bottom: 1.2rem; }
.cart-row__image { width: 80px; height: 80px; overflow: hidden; background: var(--color-parchment-dim); }
.cart-row__image img { width: 100%; height: 100%; object-fit: cover; }
.cart-row__name { font-weight: 600; text-decoration: none; }
.cart-row__price { font-family: var(--font-mono); font-size: 0.85rem; color: var(--color-ink-soft); margin: 0.2em 0 0; }
.cart-row__variant { font-size: 0.8rem; color: var(--color-ink-soft); margin: 0.1em 0; }
.cart-row__warning { color: var(--color-oxblood); font-size: 0.8rem; margin: 0.2em 0; }
.qty-input { width: 100%; padding: 0.5em; border: 1px solid var(--color-ink-soft); border-radius: var(--radius); }
.cart-row__total { font-family: var(--font-mono); font-weight: 600; }
.cart-row__remove { background: none; border: none; font-size: 1.4rem; cursor: pointer; color: var(--color-ink-soft); }
.cart-summary { margin-top: 2rem; max-width: 360px; margin-left: auto; }
.cart-summary__row { display: flex; justify-content: space-between; padding: 0.4rem 0; }
.cart-summary__row--total { font-weight: 700; font-size: 1.1rem; border-top: 2px solid var(--color-ink); margin-top: 0.4rem; padding-top: 0.8rem; }
.cart-summary .btn { margin-top: 1rem; }

/* ---- Checkout ---- */
.checkout-page__inner { display: grid; grid-template-columns: 1.3fr 1fr; gap: 3rem; align-items: start; }
.checkout-address, .checkout-summary { min-width: 0; overflow-wrap: break-word; }
.address-list { display: flex; flex-direction: column; gap: 0.7rem; margin: 1rem 0; }
.address-option { display: flex; gap: 0.6rem; padding: 0.9rem; border: 1px solid var(--color-ink-soft); border-radius: var(--radius); font-size: 0.9rem; cursor: pointer; }
.address-option--static { justify-content: space-between; align-items: center; cursor: default; }
.is-hidden { display: none !important; }
.checkout-summary { background: var(--color-white); border: 1px solid var(--color-parchment-dim); padding: 1.5rem; border-radius: var(--radius); position: sticky; top: 1.5rem; }
.checkout-summary__row { display: flex; flex-wrap: wrap; justify-content: space-between; gap: 0.3rem 0.8rem; padding: 0.35rem 0; font-size: 0.92rem; }
.checkout-summary__row--total { font-weight: 700; font-size: 1.1rem; border-top: 2px solid var(--color-ink); margin-top: 0.4rem; padding-top: 0.8rem; }
.checkout-discount-row { color: var(--color-sage); }
.checkout-coupon { border-top: 1px solid var(--color-parchment-dim); border-bottom: 1px solid var(--color-parchment-dim); margin: 0.6rem 0; padding: 0.8rem 0; }
.checkout-coupon__row { display: flex; gap: 0.5rem; }
.checkout-coupon__row input { flex: 1; min-width: 0; padding: 0.55em 0.7em; border: 1px solid var(--color-ink-soft); border-radius: var(--radius); background: var(--color-white); font-size: 0.88rem; }
.checkout-coupon__applied { display: flex; justify-content: space-between; align-items: center; gap: 0.6rem; font-size: 0.9rem; }
.checkout-coupon .form-message { margin: 0.4rem 0 0; font-size: 0.82rem; }
.checkout-item-info { display: flex; align-items: center; flex-wrap: wrap; gap: 0.4rem; min-width: 0; }
.checkout-qty-input { width: 56px; padding: 0.3em; border: 1px solid var(--color-ink-soft); border-radius: var(--radius); }

/* ---- Notices / flash ---- */
.notice { padding: 0.9rem 1.2rem; border-radius: var(--radius); font-size: 0.9rem; margin: 1rem 0; }
.notice--warn { background: #f6e4c8; color: #6b4a1a; border: 1px solid #e0b878; }
.notice--success { background: #e3ebdc; color: #3d4a34; border: 1px solid #b9caac; }
.gift-card-codes { list-style: none; padding: 0; margin: 0.5rem 0; display: flex; flex-direction: column; gap: 0.3rem; }
.gift-card-codes code { font-size: 0.95rem; background: rgba(0,0,0,0.06); padding: 0.15em 0.5em; border-radius: 4px; }
.flash { max-width: var(--max-width); margin: 0 auto; padding: 0 1.5rem; }
.flash__inner { padding: 0.8rem 1.1rem; border-radius: var(--radius); margin-top: 1rem; font-size: 0.9rem; }
.flash--success .flash__inner { background: #e3ebdc; color: #3d4a34; border: 1px solid #b9caac; }
.flash--error .flash__inner { background: #f5dcd7; color: #7a2c20; border: 1px solid #e2a99c; }

/* ---- Account ---- */
.order-list { display: flex; flex-direction: column; gap: 0.6rem; margin: 1rem 0 2rem; }
.order-list__row { display: grid; grid-template-columns: 1fr auto auto auto; gap: 1.2rem; align-items: center; padding: 0.8rem 0; border-bottom: 1px solid var(--color-parchment-dim); }
.order-search { width: 100%; max-width: 340px; padding: 0.6em 0.8em; border: 1px solid var(--color-ink-soft); border-radius: var(--radius); background: var(--color-white); margin: 1rem 0 0.5rem; }
.muted { color: var(--color-ink-soft); font-size: 0.85rem; }
.add-address-details { margin-top: 1rem; }
.add-address-details summary { cursor: pointer; font-weight: 600; }

/* ---- Legal / contact ---- */
.legal-page__inner { max-width: 760px; }
.legal-page__inner h2 { margin-top: 2rem; font-size: 1.15rem; }
.contact-page__inner { display: grid; grid-template-columns: 1fr 1.2fr; gap: 3rem; }
.contact-info p { margin-bottom: 0.5rem; }

/* These pages are usually short (a page-header plus a page or two of
   plain text/a small form) — the standard section padding-bottom below,
   combined with the footer's own margin-top further down, was designed
   for longer/denser page types and left a large empty gap of parchment
   above the footer here. Trim both, scoped to just these page types, so
   the footer sits closer to wherever the content actually ends. */
.legal-page, .contact-page { padding-bottom: 1.5rem; }
main:has(> .legal-page) + .site-footer,
main:has(> .contact-page) + .site-footer {
  margin-top: 2rem;
}

/* ---- Footer ---- */
.site-footer { background: var(--color-footer-header); color: var(--color-parchment); margin-top: 4rem; }
.site-footer__inner { max-width: var(--max-width); margin: 0 auto; padding: 3rem 1.5rem 2rem; display: grid; grid-template-columns: 1.3fr repeat(3, 1fr); gap: 2rem; }
.footer-note { font-size: 0.85rem; opacity: 0.7; }
.footer-heading { font-family: var(--font-mono); font-size: 0.72rem; text-transform: uppercase; letter-spacing: 0.08em; opacity: 0.6; margin-bottom: 0.8rem; }
.footer-col a { display: block; text-decoration: none; font-size: 0.88rem; opacity: 0.85; margin-bottom: 0.5rem; }
.site-footer__legal { border-top: 1px solid rgba(237, 230, 217, 0.15); padding: 1.2rem 1.5rem; font-size: 0.75rem; opacity: 0.6; max-width: var(--max-width); margin: 0 auto; }
.site-footer__legal p { margin: 0.2rem 0; }

/* ---- Responsive ---- */
@media (max-width: 900px) {
  .main-nav { display: none; }
  .store-layout__inner, .product-detail__inner, .checkout-page__inner, .contact-page__inner { grid-template-columns: 1fr; }
  .cart-row {
    grid-template-columns: 60px 1fr;
    grid-template-areas: "img details" "img qty" "img total" "img remove";
  }
  .cart-row__image { grid-area: img; width: 60px; height: 60px; align-self: start; }
  .cart-row__details { grid-area: details; }
  .cart-row__qty { grid-area: qty; }
  .cart-row__total { grid-area: total; }
  .cart-row__remove { grid-area: remove; justify-self: start; }
  .site-footer__inner { grid-template-columns: 1fr 1fr; }
  .checkout-summary { position: static; top: auto; }
}

@media (max-width: 480px) {
  .checkout-summary__row.cart-item-row { flex-direction: column; align-items: flex-start; }
  .checkout-summary__row.cart-item-row .cart-row__total { align-self: flex-end; }
}

/* ---- Header logo image (Header & Footer admin) ---- */
.wordmark__logo { display: block; height: 32px; width: auto; }

/* ---- Page Builder: renders blocks saved in the admin Page Builder ---- */
.pb-grid {
  max-width: var(--max-width);
  margin: 0 auto;
  /* Named as custom properties (not just plain padding) so a block's "Bleed
     to top/bottom edge" option (.pb-item--bleed-top/-bottom below) can
     cancel out exactly whatever this padding currently is, including the
     legal/contact-page override just below, without hardcoding the number
     twice and risking the two drifting apart. */
  --pb-pad-top: 3rem;
  --pb-pad-bottom: 3rem;
  --pb-pad-x: 1.5rem;
  padding: var(--pb-pad-top) var(--pb-pad-x) var(--pb-pad-bottom);
  display: grid;
  /* 50 columns — must match App\BlockRenderer::GRID_COLUMNS (CSS can't read
     the PHP constant, so keep these in sync by hand if it ever changes). */
  grid-template-columns: repeat(50, 1fr);
  /* 5px per row — must match App\BlockRenderer::ROW_HEIGHT_PX (CSS can't
     read the PHP constant, so keep these in sync by hand if it ever changes). */
  grid-auto-rows: minmax(5px, auto);
  /* No forced gap between blocks — place them touching or leave empty
     columns/rows for your own spacing, now that the grid is fine enough
     (50 columns) to do that precisely. */
  gap: 0;
}
.pb-item { min-width: 0; overflow: auto; }
.pb-item--panel, .pb-item--html { border-radius: var(--radius); padding: 1.25rem; }

/* ---- Page Builder: "Full bleed" — breaks a block out of .pb-grid's
   centered max-width column to span the entire browser width, edge to
   edge. Classic full-bleed trick: works because .pb-item is a direct child
   of .pb-grid (the centered container), so `left: 50%` here resolves
   against .pb-grid's own width, and shifting back by half the *viewport*
   width (-50vw) lands the block's edges exactly at the browser window's
   edges regardless of how narrow .pb-grid's max-width actually is.
   App\BlockRenderer forces this block's own corner rounding and per-side
   spacing (margin) off whenever bleed is on — see its renderBlock()
   comment — since a rounded corner or side margin would visibly fight
   (and, being inline styles, override) the negative margins below. */
.pb-item--bleed {
  width: 100vw;
  max-width: 100vw;
  position: relative;
  left: 50%;
  right: 50%;
  margin-left: -50vw;
  margin-right: -50vw;
}

/* ---- Page Builder: "Bleed to top/bottom edge" — cancels .pb-grid's own
   top/bottom padding (see --pb-pad-top/--pb-pad-bottom above) so a block
   that's actually the first/last one on the page touches whatever's right
   above/below the page content, with nothing in between. Only meaningful on
   the true first/last block — used on any other block it'll just overlap
   its neighbor, same as any other page-builder setting used somewhere it
   doesn't make sense. The custom properties are inherited down from
   .pb-grid, so these automatically match whatever that padding currently
   is (including the legal/contact-page override) without hardcoding it
   again here. */
.pb-item--bleed-top { margin-top: calc(-1 * var(--pb-pad-top, 3rem)); }
.pb-item--bleed-bottom { margin-bottom: calc(-1 * var(--pb-pad-bottom, 3rem)); }
/* The footer's own top margin is a separate gap, on the footer's side, not
   .pb-grid's — cancel that too whenever any block on the page bled to the
   bottom edge, so it actually reaches the footer with zero gap instead of
   stopping short by that margin. :has() here matches regardless of how
   deep the block sits inside <main> (e.g. under the legal/contact wrapper),
   same idiom as the legal/contact footer-spacing rule above. */
main:has(.pb-item--bleed-bottom) + .site-footer { margin-top: 0; }
.pb-heading { margin: 0 0 0.4em; }
.pb-text { line-height: 1.6; }
.pb-text p:last-child { margin-bottom: 0; }
.pb-image { height: 100%; }
/* var(--pb-radius, ...) picks up the block's own "Picture rounding" setting
   (see App\BlockRenderer::renderBlock() / admin-page-builder.js) — falls
   back to the design system's default 2px so a plain unrounded image block
   looks the same as it always has. */
.pb-image img { width: 100%; height: 100%; display: block; border-radius: var(--pb-radius, var(--radius)); }
.pb-image a { display: block; height: 100%; }
.pb-button { display: flex; align-items: center; height: 100%; }
.pb-button .btn { max-width: 100%; overflow-wrap: break-word; }
.pb-panel { display: flex; flex-direction: column; justify-content: center; height: 100%; }

/* ---- Page Builder: picture button (a photo with an optional caption
   button overlaid on it) — was previously unstyled. ---- */
.pb-picture-btn { position: relative; height: 100%; display: flex; overflow: hidden; }
.pb-picture-btn img { width: 100%; height: 100%; display: block; object-fit: cover; border-radius: var(--pb-radius, 0); }
.pb-picture-btn .btn { position: absolute; left: 50%; transform: translateX(-50%); }
.pb-picture-btn--top .btn { top: 1rem; }
.pb-picture-btn--center .btn { top: 50%; transform: translate(-50%, -50%); }
.pb-picture-btn--bottom .btn { bottom: 1rem; }

/* ---- Page Builder: Slides (image/product/category carousel) — was
   previously unstyled, so every slide rendered stacked and visible at once
   instead of one at a time.

   Base rules below are the no-JS fallback (and what the admin editor's
   static preview uses, since it never runs main.js's carousel behavior):
   only the .is-active slide is shown, filling the box on its own. Once
   main.js's initSlides() runs on the real site, it adds the .pb-slides--js
   class, which switches every slide to sit side by side in a row so the
   track's own transform can slide between them — that's what lets a
   visitor drag/swipe the slider by hand instead of only using the
   prev/next buttons, and what the resize/drag handlers below animate. ---- */
.pb-slides { position: relative; height: 100%; overflow: hidden; touch-action: pan-y; --pb-slides-per-view: 1; --pb-slides-gap: 0px; --pb-slides-radius: 0px; }
.pb-slides__track { position: relative; height: 100%; display: flex; gap: var(--pb-slides-gap); }
/* position:relative so each slide's own .pb-slides__caption (position:
   absolute) anchors to THAT slide, not — for want of any other positioned
   ancestor — to .pb-slides itself. Without this every slide's caption
   landed in the exact same spot on the whole component regardless of which
   slide it belonged to, all stacked on top of each other, which is what
   made it look like only the first slide ever had any text.

   flex-basis/width use var(--pb-slides-per-view, 1) — the "Slides shown at
   once" admin setting (App\BlockRenderer::renderSlides() sets it inline per
   block) — so N slides sit side by side instead of always exactly one. The
   width formula subtracts however much of the row var(--pb-slides-gap)
   (the "Space between slides" setting) is eating up between them, so N
   slides + their gaps still add up to exactly 100% instead of overflowing
   past the block's own edge. */
.pb-slides__slide {
  position: relative;
  display: none;
  height: 100%;
  flex: 0 0 calc((100% - (var(--pb-slides-per-view, 1) - 1) * var(--pb-slides-gap)) / var(--pb-slides-per-view, 1));
  width: calc((100% - (var(--pb-slides-per-view, 1) - 1) * var(--pb-slides-gap)) / var(--pb-slides-per-view, 1));
  min-width: 0;
  /* "Item corner rounding" — rounds the whole slide (image + caption
     together), not just the picture — see App\BlockRenderer::renderSlides()'s
     comment on why this is separate from the shared "Picture rounding"
     field. Harmless at the default 0px even when slides touch (no Gap set),
     since there's nothing here to visibly clip. */
  border-radius: var(--pb-slides-radius);
  overflow: hidden;
}
.pb-slides__slide.is-active { display: block; }
.pb-slides--js .pb-slides__track {
  transition: transform 0.35s ease;
  cursor: grab;
  touch-action: pan-y;
}
.pb-slides--js .pb-slides__track:active { cursor: grabbing; }
/* Once JS attaches, every slide becomes a visible flex item (not just the
   first N marked .is-active) — main.js's initSlides() drags/animates the
   whole strip via `transform: translateX()`, same per-view width as above. */
.pb-slides--js .pb-slides__slide { display: block; }
.pb-slides__slide > a, .pb-slides__slide > img { display: block; width: 100%; height: 100%; }
.pb-slides__slide img {
  width: 100%; height: 100%; object-fit: cover; display: block;
  /* Independent "Picture rounding" setting — see .pb-image img above. */
  border-radius: var(--pb-radius, 0);
  -webkit-user-drag: none;
  user-select: none;
}
.pb-slides__caption {
  position: absolute; left: 0; right: 0; bottom: 0;
  padding: 1.5rem 1.5rem 1.1rem;
  background: linear-gradient(to top, rgba(0, 0, 0, 0.6), transparent);
  color: var(--color-white);
  font-family: var(--font-display);
  font-size: clamp(1rem, 2vw, 1.4rem);
}
.pb-slides__prev, .pb-slides__next {
  position: absolute; top: 50%; transform: translateY(-50%);
  width: 36px; height: 36px; border-radius: 50%; border: none;
  background: rgba(0, 0, 0, 0.35); color: var(--color-white);
  display: flex; align-items: center; justify-content: center;
  cursor: pointer; font-size: 1rem; z-index: 2;
}
.pb-slides__prev:hover, .pb-slides__next:hover { background: rgba(0, 0, 0, 0.55); }
.pb-slides__prev { left: 0.75rem; }
.pb-slides__next { right: 0.75rem; }
.pb-slides__dots {
  /* Sized to fit its dots (not left:0;right:0 spanning the full width) so
     the gaps between dots don't sit in an invisible full-width strip that
     would otherwise swallow clicks meant for the slide/link underneath. */
  position: absolute; left: 50%; bottom: 0.7rem; transform: translateX(-50%);
  display: flex; justify-content: center; gap: 0.4rem; z-index: 2;
}
.pb-slides__dot {
  width: 8px; height: 8px; padding: 0; border-radius: 50%; border: none;
  background: rgba(255, 255, 255, 0.55); cursor: pointer;
}
.pb-slides__dot.is-active { background: var(--color-white); }
/* Single-product feature block: let the card's own image shrink to whatever
   room its block is given (via the flex rules on .product-card / .product-
   card__image above) instead of overflowing or stretching the row. */
.pb-item--product { padding: 0.5rem; }
.pb-item--product .product-card__name { font-size: 0.95rem; }
.pb-item--product .product-card__price { font-size: 0.85rem; }
/* Here (unlike the plain store grid above) the picture's box shape isn't a
   side effect of a shared grid row — the admin deliberately resized this
   block to whatever shape they want. Forcing the fixed 4:5 portrait ratio
   in here fought that: a wide/short block still got a tall/narrow picture
   area wedged inside it, showing as a big gap on whichever sides the
   picture didn't reach. It also broke "Picture rounding": a differently-
   *shaped* box gets a differently-shaped round corner (e.g. "Completely
   round" on a wide box is a stadium/pill, but on a 4:5 portrait box it's a
   narrower pill standing upright) — clipping the block *and* an
   internally-mismatched picture box each their own way at once produced a
   lens/eye shape instead of one clean round edge. Letting the picture fill
   the block's own shape exactly (still via object-fit:contain, so nothing
   crops) keeps the two roundings — outer block and inner picture — on
   matching proportions, so "Completely round" on both actually reads as
   one consistent oval instead of two overlapping ones. */
.pb-item--product .product-card__image { aspect-ratio: auto; flex: 1 1 auto; margin-bottom: 0; }
.pb-item--product .product-card { gap: 0.4rem; }
.legal-page--builder .pb-grid, .contact-page--builder .pb-grid { --pb-pad-top: 3.5rem; }

/* ---- Page Builder: Categories (a small grid of category cards) — was
   previously unstyled. ---- */
.pb-categories {
  height: 100%;
  overflow: auto;
  display: grid;
  grid-template-columns: repeat(var(--pb-cat-cols, 3), 1fr);
  gap: 1.25rem;
}
.pb-categories__card { text-decoration: none; color: inherit; display: flex; flex-direction: column; }
.pb-categories__image {
  position: relative;
  aspect-ratio: 1 / 1;
  width: 100%;
  overflow: hidden;
  background: var(--color-parchment-dim);
  margin-bottom: 0.6rem;
  border-radius: var(--pb-radius, 0);
}
.pb-categories__image img { display: block; width: 100%; height: 100%; object-fit: cover; transition: transform 0.4s ease; border-radius: var(--pb-radius, 0); }
.pb-categories__card:hover .pb-categories__image img { transform: scale(1.04); }
.pb-categories__placeholder { width: 100%; height: 100%; background: linear-gradient(135deg, #d8cdb8, #c7b998); }
.pb-categories__name { font-weight: 600; text-align: center; margin: 0; font-size: 0.92rem; }
@media (max-width: 700px) {
  body:not(.pb-editor) .pb-categories { grid-template-columns: repeat(2, 1fr); }
}

/* "Perfect circle" picture rounding — a distinct choice from "Completely
   round": border-radius alone only makes an oval/pill out of whatever
   shape the picture's own box already is (a portrait product photo, a wide
   slide, a category thumbnail that isn't square, ...), never an actual
   circle unless that box happens to already be square. Forcing a 1:1
   aspect-ratio here, plus cropping to fill (object-fit:cover — a circular
   thumbnail with visible letterboxed corners defeats the point), gives a
   true circle regardless of the picture's natural shape. See the
   $circleClass comment in App\BlockRenderer::renderBlock() and
   radiusCircleClass() in admin-page-builder.js for where this class comes
   from. */
/* flex-shrink stays on (0 1 auto, not 0 0 auto) — a square sized off the
   block's full WIDTH can be taller than the block's actual HEIGHT (e.g. a
   short, wide block), and without shrink the circle just overflowed past
   its own block instead of scaling itself down to fit. */
/* Flex-shrink under aspect-ratio isn't pixel-perfect — the browser can
   still leave the square a couple of px taller than the block actually
   has room for. .pb-item's own default (overflow:auto, for text blocks
   that genuinely need to scroll) turned that couple-px mismatch into a
   visible scrollbar sitting right across the middle of the circle in the
   admin editor (GridStack gives the block a fixed pixel height there, so
   the mismatch shows; the live site's CSS-grid row grows to fit instead,
   which is why it only ever showed up in the editor). A picture is never
   meant to scroll, so clip the couple of px instead of scrolling it. */
.pb-radius-circle { overflow: hidden; }
.pb-radius-circle .product-card__image { aspect-ratio: 1 / 1; flex: 0 1 auto; min-height: 0; }
.pb-radius-circle .product-card__image img,
.pb-radius-circle .pb-image img,
.pb-radius-circle .pb-picture-btn img,
.pb-radius-circle .pb-slides__slide img,
.pb-radius-circle .pb-categories__image img {
  object-fit: cover;
}
.pb-radius-circle .pb-image img,
.pb-radius-circle .pb-picture-btn img,
.pb-radius-circle .pb-slides__slide img,
.pb-radius-circle .pb-categories__image {
  aspect-ratio: 1 / 1;
}

/* ---- Page Builder: layers (a lower layer in normal flow, higher layers
   stacked exactly on top of it — e.g. a background image/color behind a
   layer of text) ---- */
.pb-stack { position: relative; }
.pb-layer { position: absolute; inset: 0; pointer-events: none; }
.pb-layer .pb-item { pointer-events: auto; }

/* Real phones only — never inside the admin Page Builder's preview iframe
   (body.pb-editor), which can legitimately render narrower than 700px just
   from being squeezed into the admin layout's middle column, not because
   anyone's actually on a small screen. Without this guard, editing the page
   on a normal desktop could silently flatten layers back into stacked-below
   flow and crop/reflow the grid, purely because of how much room the admin
   sidebar and inspector panel happened to leave. */
@media (max-width: 700px) {
  body:not(.pb-editor) .pb-grid { grid-template-columns: repeat(6, 1fr); }
  body:not(.pb-editor) .pb-item { grid-column: 1 / -1 !important; grid-row: auto !important; height: auto !important; }
  body:not(.pb-editor) .pb-layer { position: static; }
  body:not(.pb-editor) .pb-stack .pb-grid[style] { height: auto !important; }
}
