/* OxiShop — commerce UI built entirely on zap's design tokens (var(--zap-*)),
   so the dark/light switch and theme swap restyle the whole store. */
* { box-sizing: border-box; }
body { margin: 0; }
a { color: inherit; text-decoration: none; }
h1, h2, h3 { margin: 0; }

.zap { min-height: 100vh; display: flex; flex-direction: column; }
main { width: 100%; max-width: 1320px; margin: 0 auto; padding: 22px 18px 60px; flex: 1; }
.muted { color: var(--zap-muted); }

/* ── header ───────────────────────────────────────────────────────────────── */
.nav { background: var(--zap-surface); border-bottom: 1px solid var(--zap-border); position: sticky; top: 0; z-index: 50; }
.nav__inner { max-width: 1320px; margin: 0 auto; display: flex; align-items: center; gap: 18px; padding: 12px 18px; }
.brand { font-size: 22px; font-weight: 800; white-space: nowrap; }
.nav__links { display: flex; align-items: center; gap: 18px; margin-left: auto; }
.nav__cart { font-weight: 600; display: inline-flex; align-items: center; gap: 4px; }
.badge { background: var(--zap-primary); color: var(--zap-primary-contrast); border-radius: 999px;
  font-size: 12px; font-weight: 700; min-width: 19px; height: 19px; padding: 0 5px;
  display: inline-flex; align-items: center; justify-content: center; }

.search { position: relative; flex: 1; max-width: 640px; display: flex; }
.search__input { flex: 1; font: inherit; padding: 10px 14px; border: 1px solid var(--zap-border);
  border-radius: var(--zap-radius-sm) 0 0 var(--zap-radius-sm); background: var(--zap-elevated); color: var(--zap-text); }
.search__input:focus { outline: none; border-color: var(--zap-primary); box-shadow: 0 0 0 3px var(--zap-primary-soft); }
.search__btn { display: inline-flex; align-items: center; justify-content: center;
  border: 1px solid var(--zap-primary); background: var(--zap-primary); color: var(--zap-primary-contrast);
  padding: 0 16px; border-radius: 0 var(--zap-radius-sm) var(--zap-radius-sm) 0; cursor: pointer; font-size: 16px; }
/* spinner while the suggestion fetch is in flight (emoji hidden via font-size) */
.search__btn.is-loading { font-size: 0; }
.search__btn.is-loading::after { content: ""; width: 16px; height: 16px; flex: none;
  border: 2px solid rgba(255,255,255,.35); border-top-color: #fff; border-radius: 50%;
  animation: searchspin .6s linear infinite; }
@keyframes searchspin { to { transform: rotate(360deg); } }
.suggest { position: absolute; top: calc(100% + 6px); left: 0; right: 0; z-index: 60; }
.suggest__box { background: var(--zap-surface); border: 1px solid var(--zap-border); border-radius: var(--zap-radius-sm);
  box-shadow: var(--zap-shadow); overflow: hidden; }
.suggest__row { display: flex; align-items: center; gap: 10px; padding: 9px 12px; }
.suggest__row:hover, .suggest__row.is-hi { background: var(--zap-primary-soft); }
.suggest__emoji { font-size: 18px; }
.suggest__t { flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* mega menu */
.catstrip { display: flex; align-items: center; gap: 4px; padding: 4px 18px; max-width: 1320px; margin: 0 auto;
  font-size: 14px; border-top: 1px solid var(--zap-border); flex-wrap: wrap; }
.dept { position: relative; }
.dept__link { display: inline-block; padding: 9px 12px; font-weight: 600; color: var(--zap-text); border-radius: 8px; white-space: nowrap; }
.dept__link:hover { background: var(--zap-primary-soft); color: var(--zap-primary); }
/* Super offers — pinned right, soft red pill with a periodic shine sweep */
.dept__sale { color: #dc2626; margin-left: auto; position: relative; overflow: hidden;
  background: rgba(220, 38, 38, .08); }
.dept__sale::after { content: ""; position: absolute; top: 0; bottom: 0; left: -75%; width: 50%;
  background: linear-gradient(105deg, transparent, rgba(255, 255, 255, .85) 50%, transparent);
  transform: skewX(-20deg); animation: saleshine 2.8s ease-in-out infinite; pointer-events: none; }
[data-theme="dark"] .dept__sale { color: #f87171; background: rgba(248, 113, 113, .12); }
[data-theme="dark"] .dept__sale::after { background: linear-gradient(105deg, transparent, rgba(255, 255, 255, .25) 50%, transparent); }
@keyframes saleshine { 0% { left: -75%; } 55%, 100% { left: 125%; } }
@media (prefers-reduced-motion: reduce) { .dept__sale::after { animation: none; } }
/* Frosted glass: the panel blurs and saturates whatever it covers, so it reads
   as a layer above the page rather than a card pasted onto it. The inset top
   highlight is the lit edge that sells the material. */
.megamenu { position: absolute; top: 100%; left: 0; min-width: 200px; z-index: 70;
  background: rgba(255, 255, 255, .60);
  -webkit-backdrop-filter: blur(20px) saturate(180%);
  backdrop-filter: blur(20px) saturate(180%);
  border: 1px solid rgba(255, 255, 255, .55); border-radius: var(--zap-radius-sm);
  box-shadow: 0 14px 36px rgba(15, 23, 42, .16), inset 0 1px 0 rgba(255, 255, 255, .70);
  padding: 6px; opacity: 0; visibility: hidden; transform: translateY(4px);
  transition: opacity .12s, transform .12s; }
[data-theme="dark"] .megamenu { background: rgba(24, 24, 27, .55);
  border-color: rgba(255, 255, 255, .10);
  box-shadow: 0 14px 36px rgba(0, 0, 0, .50), inset 0 1px 0 rgba(255, 255, 255, .07); }
/* Without backdrop-filter there is nothing to frost — fall back to the solid
   surface rather than a washed-out translucent panel over live text. */
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  .megamenu { background: var(--zap-surface); border-color: var(--zap-border);
    box-shadow: var(--zap-shadow); }
}
.dept:hover .megamenu { opacity: 1; visibility: visible; transform: translateY(0); }
.megamenu { display: flex; gap: 6px; }
.megamenu__links { display: flex; flex-direction: column; min-width: 168px; }
.megamenu a { display: block; padding: 8px 12px; border-radius: 7px; color: var(--zap-text); white-space: nowrap; }
.megamenu a:hover { background: var(--zap-primary-soft); color: var(--zap-primary); }

/* preview panel — a photo from the hovered category, or the department tile */
.megamenu__art {
  position: relative; width: 190px; flex: none; padding: 0 !important;
  border-radius: var(--zap-radius-sm); overflow: hidden;
  display: flex; align-items: center; justify-content: center; font-size: 54px;
}
.megamenu__art:hover { background: inherit; }
.megamenu__art img {
  position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover;
  transition: opacity .18s, transform .35s ease-out;
}
.megamenu__art:hover img { transform: scale(1.05); }
.megamenu__art.is-swapping img { opacity: 0; }
.megamenu__emoji { position: relative; filter: drop-shadow(0 2px 6px rgba(0, 0, 0, .25)); }
.megamenu__art:has(img) .megamenu__emoji { display: none; }
.megamenu__cap {
  position: absolute; left: 0; right: 0; bottom: 0; padding: 18px 12px 9px;
  font-size: 13px; font-weight: 700; color: #fff; white-space: nowrap;
  background: linear-gradient(transparent, rgba(0, 0, 0, .55));
}
/* a translucent rule reads as part of the glass; the solid token does not */
.megamenu__all { font-weight: 700; border-bottom: 1px solid rgba(15, 23, 42, .12);
  border-radius: 7px 7px 0 0; margin-bottom: 4px; }
[data-theme="dark"] .megamenu__all { border-bottom-color: rgba(255, 255, 255, .12); }
.chip--sale { color: #dc2626; border-color: #fecaca; }

/* color swatches + size buttons */
.swatches { display: flex; gap: 5px; }
.swatch { width: 15px; height: 15px; border-radius: 999px; border: 1px solid rgba(0,0,0,.15); display: inline-block; }
.swatch--lg { width: 30px; height: 30px; }
.swatch--pick { cursor: pointer; padding: 0; outline-offset: 2px; }
.swatch--pick.is-on { outline: 2px solid var(--zap-primary); }
.variant { margin: 14px 0; }
.variant__label { display: block; font-size: 13px; color: var(--zap-muted); margin-bottom: 8px; }
.swatchpick, .sizepick { display: flex; flex-wrap: wrap; gap: 8px; }
.size-b { display: inline-flex; align-items: center; justify-content: center; min-width: 42px; height: 38px; padding: 0 10px;
  border: 1px solid var(--zap-border); border-radius: 10px; font-weight: 600; font-size: 14px; background: var(--zap-surface); color: var(--zap-text); cursor: pointer; }
.size-b--pick:hover { border-color: var(--zap-primary); }
.size-b.is-on { border-color: var(--zap-primary); background: var(--zap-primary); color: var(--zap-primary-contrast); }
/* no-JS radio fallbacks: hide the input, style the sibling */
.swatch-r input, .size-r input { position: absolute; opacity: 0; pointer-events: none; }
.swatch-r input:checked + .swatch { outline: 2px solid var(--zap-primary); }
.size-r input:checked + .size-b { border-color: var(--zap-primary); background: var(--zap-primary); color: var(--zap-primary-contrast); }
.swatch-r, .size-r { display: inline-flex; cursor: pointer; }
/* stacked: qty stepper on top, full-width Add to cart below it */
.buyrow { display: flex; flex-direction: column; align-items: stretch; gap: 12px; margin-top: 18px; max-width: 320px; }
.qtybox-wrap { display: inline-flex; align-items: center; gap: 4px; border: 1px solid var(--zap-border); border-radius: 999px; padding: 4px; align-self: flex-start; }
.buyrow .zap-btn, .buyrow .btn { width: 100%; white-space: nowrap; display: inline-flex; align-items: center; justify-content: center; }

/* search results: filter sidebar + grid */
.results { display: grid; grid-template-columns: 248px 1fr; gap: 24px; align-items: start; }
.results__main { min-width: 0; }
/* In-flight refinement (search.js). The .16s delay means a swap that lands
   quickly — the common case — never dims at all; only a slow one shows it. */
.results { transition: opacity .1s ease .16s; }
.results.is-swapping { opacity: .55; pointer-events: none; }
.sidebar { position: sticky; top: 128px; display: flex; flex-direction: column; gap: 14px; }
.facets__title { font-weight: 700; margin-bottom: 8px; }

.facetnav { background: var(--zap-surface); border: 1px solid var(--zap-border); border-radius: var(--zap-radius); padding: 14px; }
.facetnav a { display: block; padding: 7px 9px; border-radius: 8px; color: var(--zap-muted); font-size: 14px; }
.facetnav a:hover { background: var(--zap-primary-soft); color: var(--zap-primary); }
.facetnav a.on { background: var(--zap-primary-soft); color: var(--zap-primary); font-weight: 600; }

.filters { background: var(--zap-surface); border: 1px solid var(--zap-border); border-radius: var(--zap-radius); padding: 6px 14px 14px; }
.filters__head { display: flex; align-items: center; justify-content: space-between; padding: 10px 0; border-bottom: 1px solid var(--zap-border); }
.filters__clear { color: var(--zap-primary); font-size: 13px; font-weight: 600; }
.filters__clear:hover { text-decoration: underline; }
.facet { border-bottom: 1px solid var(--zap-border); }
.facet:last-of-type { border-bottom: 0; }
.facet > summary { list-style: none; cursor: pointer; font-weight: 600; padding: 12px 0; display: flex; justify-content: space-between; align-items: center; }
.facet > summary::-webkit-details-marker { display: none; }
.facet > summary::after { content: "–"; color: var(--zap-muted); font-size: 18px; }
.facet:not([open]) > summary::after { content: "+"; }
.facet__body { padding-bottom: 12px; }
.facet__scroll { max-height: 230px; overflow-y: auto; }
.facet__opt { display: flex; align-items: center; gap: 9px; padding: 5px 4px; border-radius: 7px; cursor: pointer; font-size: 14px; }
.facet__opt:hover { background: var(--zap-primary-soft); }
.facet__opt input { accent-color: var(--zap-primary); width: 16px; height: 16px; flex: none; }
.facet__name { flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.facet__count { color: var(--zap-muted); font-size: 13px; }
.slider-wrap { padding: 14px 8px 4px; }
.price-vals { display: flex; justify-content: space-between; font-weight: 600; font-size: 13px; margin: 2px 2px 12px; color: var(--zap-muted); }
.price-facet { display: flex; align-items: center; gap: 8px; }
.price-in { width: 100%; min-width: 0; font: inherit; padding: 8px 9px; border: 1px solid var(--zap-border); border-radius: var(--zap-radius-sm); background: var(--zap-elevated); color: var(--zap-text); }
.btn--sm { padding: 8px 12px; font-size: 14px; flex: none; }

/* ── hero / chips ─────────────────────────────────────────────────────────── */
/* The art column is narrow and its contents sit at its left edge, because
   centring a 110px glyph inside a 340px column parked it against the card's
   right margin with a wide empty channel between it and the text. The blurb
   was doing the same thing from the other side: capped at 52ch it stopped
   less than three quarters of the way across a column half again as wide, so
   the two halves of the hero were held apart by their own settings rather
   than by any spacing. */
.hero { display: grid; grid-template-columns: 1.6fr .4fr; gap: 20px; align-items: center;
  background: var(--zap-surface); border: 1px solid var(--zap-border); border-radius: var(--zap-radius);
  padding: 48px 44px; box-shadow: var(--zap-shadow); margin-bottom: 22px; }
.hero h1 { font-size: 34px; line-height: 1.15; margin-bottom: 12px; }
/* The same red the sale pill and the danger button use, rather than a fresh
   hex — the page already has one red and a second one would read as a bug. */
.hero p { color: #dc2626; max-width: 76ch; margin: 0 0 28px; font-size: 19px; line-height: 1.6; }
.hero__art { font-size: 110px; text-align: left; }
.cats { display: flex; flex-wrap: wrap; gap: 10px; margin-bottom: 26px; }
.chip { background: var(--zap-surface); border: 1px solid var(--zap-border); border-radius: 999px; padding: 7px 15px; font-size: 14px; font-weight: 600; }
.chip:hover { border-color: var(--zap-primary); color: var(--zap-primary); }

/* space-between pushed a lone heading to the left and whatever followed it to
   the far right — which was the point while every row ended in a "See all".
   Without one, a subtitle would have been flung across the page. */
/* A row's heading has to win against the row underneath it. A 21px line eight
   pixels above a grid of colour photographs reads as a caption for the cards
   rather than as the start of a new display.
   
   Bigger, heavier, tighter, with the air above rather than below so the
   heading belongs to what follows — and a short accent bar to mark where it
   starts. A rule across the page was tried and was too much: it cut the page
   into slabs when all the heading needed was to be seen. */
.sec-head { display: flex; align-items: baseline; justify-content: space-between; gap: 10px;
  margin: 0 0 18px; padding-top: 14px; position: relative; }
.sec-head .sec-sub { margin-right: auto; }
.sec-head h2 { font-size: 26px; font-weight: 800; letter-spacing: -.02em; line-height: 1.15; }
.sec-head::before { content: ""; position: absolute; top: 0; left: 0; width: 44px; height: 3px;
  border-radius: 2px; background: var(--zap-primary); }

main > section + section { margin-top: 40px; }
.sec-more { display: flex; justify-content: center; margin-top: 22px; }
.sec-more .btn { padding: 11px 26px; }

/* ── promo carousel ───────────────────────────────────────────────────────── */
/* A scroll-snap track, not a transform strip: scrolling IS the carousel, so it
   works before promo.js loads and keeps native touch momentum on a phone. The
   arrows and dots the module injects only drive the same scroll. */
.promo { position: relative; margin-bottom: 26px; border-radius: var(--zap-radius); overflow: hidden; }
.promo:focus-visible { outline: 2px solid var(--zap-primary); outline-offset: 3px; }
.promo__track { display: flex; overflow-x: auto; scroll-snap-type: x mandatory;
  scrollbar-width: none; -ms-overflow-style: none; border-radius: var(--zap-radius); }
.promo__track::-webkit-scrollbar { display: none; }
/* background-size/position exist for the inlined 24px preview the template
   paints here: it has to fill the frame the same way object-fit: cover fills
   it with the real photo, or the picture would appear to shift as it loads. */
.promo__slide { position: relative; flex: 0 0 100%; scroll-snap-align: start;
  aspect-ratio: 1600 / 460; display: block; background: var(--zap-elevated);
  background-size: cover; background-position: center; }
.promo__img { width: 100%; height: 100%; object-fit: cover; display: block; }
/* The caption sits on the photo, so it carries its own gradient rather than
   trusting whatever happens to be in that corner of the image. */
.promo__cap { position: absolute; left: 0; right: 0; bottom: 0; padding: 52px 32px 22px;
  display: flex; flex-direction: column; align-items: flex-start; gap: 5px; color: #fff;
  background: linear-gradient(transparent, rgba(0, 0, 0, .68)); }
.promo__eyebrow { font-size: 12px; font-weight: 700; letter-spacing: .09em; text-transform: uppercase; opacity: .85; }
.promo__title { font-size: 27px; font-weight: 800; line-height: 1.15; text-shadow: 0 2px 12px rgba(0, 0, 0, .35); }
.promo__cta { margin-top: 7px; font-size: 14px; font-weight: 700; padding: 8px 15px; border-radius: 999px;
  background: var(--zap-primary); color: var(--zap-primary-contrast); }
.promo__slide:hover .promo__cta { filter: brightness(1.08); }

/* Glass, not a white pill: the photo reads through the control the same way it
   does through the mega menu. The tint is dark rather than light because the
   slides are not — a white scrim disappears under the sneakers frame, while a
   dark one keeps the white chevron legible on every photo in the deck. */
.promo__btn { position: absolute; top: 50%; transform: translateY(-50%); z-index: 2;
  width: 40px; height: 40px; border-radius: 999px; cursor: pointer;
  font-size: 22px; line-height: 1; display: flex; align-items: center; justify-content: center;
  color: #fff; text-shadow: 0 1px 6px rgba(0, 0, 0, .5);
  background: rgba(17, 24, 39, .30); border: 1px solid rgba(255, 255, 255, .38);
  -webkit-backdrop-filter: blur(10px) saturate(160%);
  backdrop-filter: blur(10px) saturate(160%);
  opacity: .85; transition: opacity .15s, background .15s; }
.promo:hover .promo__btn, .promo:focus-within .promo__btn { opacity: 1; }
.promo__btn:hover { background: rgba(17, 24, 39, .48); }
/* Nothing to frost without backdrop-filter — a dim scrim keeps the contrast. */
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  .promo__btn { background: rgba(0, 0, 0, .38); }
  .promo__btn:hover { background: rgba(0, 0, 0, .52); }
}
.promo__btn--prev { left: 14px; }
.promo__btn--next { right: 14px; }
/* Touch has swipe, and a control that only appears on hover never will there. */
@media (hover: none) { .promo__btn { display: none; } }

.promo__dots { position: absolute; left: 0; right: 0; bottom: 12px; z-index: 2;
  display: flex; justify-content: center; gap: 7px; }
.promo__dot { width: 7px; height: 7px; padding: 0; border: 0; border-radius: 999px; cursor: pointer;
  background: rgba(255, 255, 255, .55); transition: width .2s, background .2s; }
.promo__dot[aria-selected="true"] { width: 20px; background: #fff; }

@media (max-width: 700px) {
  .promo__slide { aspect-ratio: 3 / 2; }
  .promo__cap { padding: 46px 18px 26px; }
  .promo__title { font-size: 20px; }
}

/* ── image picker (custom file button + cropper) ──────────────────────────── */
/* The native input stays in the form — it carries the field name and the file
   the crop is written back into — so it is hidden rather than removed, and
   only once the island is there to replace it. */
.picker { display: flex; flex-wrap: wrap; align-items: center; gap: 10px; margin-top: 4px; }
.picker.is-enhanced .picker__input { position: absolute; width: 1px; height: 1px;
  opacity: 0; pointer-events: none; }
.picker__btn { flex: none; }
.picker__status { font-size: 13px; min-width: 0; overflow: hidden; text-overflow: ellipsis; }
.picker__status--ok { color: #16a34a; font-weight: 600; }
.picker__label { display: block; font-weight: 600; font-size: 13.5px; }
/* What is going to be uploaded. A product can carry several photos, so this is
   a row that wraps; the shape comes from the picture itself rather than a fixed
   ratio, since the same picker serves a square product photo and a wide slide. */
.picker__previews { display: flex; flex-wrap: wrap; gap: 8px; }
.picker__previews:not(:empty) { flex-basis: 100%; margin-top: 2px; }
.picker__preview { flex: none; height: 68px; width: auto; max-width: 260px; object-fit: cover;
  border-radius: 8px; border: 1px solid var(--zap-border); display: block; }
/* the cropper's stage inside the dialog — wide and short, like the slide */
.zap-modal .zap-crop__stage { min-height: 340px; }

/* the carousel row in the admin table — wide and short, like the slide */
.promo-thumb { width: 132px; height: 38px; object-fit: cover; border-radius: 7px;
  border: 1px solid var(--zap-border); display: block; }

/* ── brand row ────────────────────────────────────────────────────────────── */
/* The store's brands are names, not logos, so the type carries the tile: the
   wordmark centred and letterspaced, catalog depth underneath it. Sits above
   Featured, and stays quieter than the product cards below — same surface, no
   imagery — so it reads as a way into the catalog, not a competing row. */
.brandrow { display: grid; grid-template-columns: repeat(auto-fit, minmax(148px, 1fr));
  gap: 12px; margin-bottom: 26px; }
.brandtile { display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 4px;
  min-height: 84px; padding: 14px 12px; text-align: center;
  background: var(--zap-surface); border: 1px solid var(--zap-border); border-radius: var(--zap-radius);
  transition: border-color .15s, box-shadow .15s, transform .15s; }
.brandtile:hover { border-color: var(--zap-primary); box-shadow: var(--zap-shadow); transform: translateY(-2px); }
.brandtile__name { font-size: 17px; font-weight: 800; letter-spacing: .04em; }
.brandtile:hover .brandtile__name { color: var(--zap-primary); }
.brandtile__count { font-size: 12px; color: var(--zap-muted); }

/* ── product grid + card ──────────────────────────────────────────────────── */
.grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(215px, 1fr)); gap: 16px; }
.card { position: relative; background: var(--zap-surface); border: 1px solid var(--zap-border); border-radius: var(--zap-radius);
  overflow: hidden; display: flex; flex-direction: column; transition: box-shadow .15s, transform .15s; }
.card:hover { box-shadow: var(--zap-shadow); transform: translateY(-2px); }
.card__link { display: block; }
/* Square, like the file. The photo is stored 1:1 and the product page shows it
   1:1; the card was taking a 4:3 band out of the middle, which quietly cropped
   the top and bottom eighth off every product in a listing. */
.card__img { position: relative; aspect-ratio: 1; display: flex; align-items: center; justify-content: center; font-size: 64px; overflow: hidden; }
.card__img img, .pdp__img img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
/* The discount, as a corner rather than a pill.
   
   A 12px pill floating over a photograph is a label the eye files with the
   photograph. A triangle cut into the corner belongs to the card instead — it
   has an edge the image cannot dilute, and it takes the number with it.
   
   Three things this needs, and each one is a separate layer.
   
   The shape is a pseudo-element, not the box, because the number has to be
   rotated and rotating the box would rotate the cut with it. drop-shadow
   rather than box-shadow: box-shadow draws around the border box and would
   outline a square that is not there, while drop-shadow follows what is left
   after clipping.
   
   The gradient runs to the bottom-right corner — the half that gets clipped
   away — so its stops are compressed into the part that survives, or it
   arrives looking flat.
   
   And the number sits on the hypotenuse: centred on the triangle's centroid,
   which is a third of the way in on both axes, and turned -45° so it runs
   parallel to the cut edge. */
.card__off { position: absolute; top: 0; left: 0; width: 86px; height: 86px;
  border-radius: 0; background: none; padding: 0; pointer-events: none; }
.card__off::before { content: ""; position: absolute; inset: 0;
  clip-path: polygon(0 0, 100% 0, 0 100%);
  background: linear-gradient(135deg, #fb923c 0%, #f43f5e 26%, #b91c1c 52%);
  filter: drop-shadow(2px 2px 5px rgba(0, 0, 0, .38)); }
.card__off__n { position: absolute; left: 33%; top: 33%; white-space: nowrap;
  transform: translate(-50%, -50%) rotate(-45deg);
  font-size: 18px; font-weight: 800; letter-spacing: -.03em; line-height: 1;
  color: #fff; text-shadow: 0 1px 2px rgba(0, 0, 0, .3); }
.card__off--lg { width: 118px; height: 118px; }
.card__off--lg .card__off__n { font-size: 25px; }
.card__brand { color: var(--zap-muted); font-size: 12px; text-transform: uppercase; letter-spacing: .04em; padding: 12px 14px 0; }
.card__title { font-weight: 600; padding: 2px 14px 0; line-height: 1.3; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; min-height: 2.6em; }
.card__body { padding: 6px 14px 14px; display: flex; flex-direction: column; gap: 7px; margin-top: auto; }
.card__price { display: flex; align-items: baseline; gap: 8px; }
.price { font-size: 20px; font-weight: 800; }
.price--lg { font-size: 30px; }
.list { color: var(--zap-muted); text-decoration: line-through; font-size: 14px; }
.save { color: #16a34a; font-weight: 700; font-size: 14px; }
.prime { color: var(--zap-primary); font-size: 13px; font-weight: 600; }

.rating { font-size: 14px; display: inline-flex; gap: 6px; align-items: center; }
.rating__stars { color: #f59e0b; letter-spacing: 1px; }

/* ── buttons ──────────────────────────────────────────────────────────────── */
.btn { font: inherit; font-weight: 600; border: 1px solid var(--zap-border); background: var(--zap-elevated);
  color: var(--zap-text); border-radius: 999px; padding: 9px 16px; cursor: pointer; text-align: center; }
.btn:hover { border-color: var(--zap-primary); }
.btn--primary { background: var(--zap-primary); border-color: var(--zap-primary); color: var(--zap-primary-contrast); }
.btn--primary:hover { filter: brightness(1.07); }
.btn--add { background: var(--zap-primary); border-color: var(--zap-primary); color: var(--zap-primary-contrast); }
.btn--add:hover { filter: brightness(1.06); }

/* ── favorites (wishlist) ─────────────────────────────────────────────────── */
/* heart overlay on cards */
.fav-btn { position: absolute; top: 8px; right: 8px; z-index: 2; width: 34px; height: 34px;
  border: 0; border-radius: 999px; cursor: pointer; font-size: 18px; line-height: 1;
  background: rgba(255,255,255,.85); color: #c2c2c2; backdrop-filter: blur(3px);
  box-shadow: 0 1px 4px rgba(0,0,0,.12); transition: transform .1s, color .12s; }
.fav-btn:hover { transform: scale(1.12); color: #e0245e; }
.fav-btn.is-fav { color: #e0245e; }
[data-theme="dark"] .fav-btn { background: rgba(20,20,20,.6); }

/* header favorites link */
.nav__fav { position: relative; }
.nav__fav #fav-badge .badge { background: #e0245e; color: #fff; }

/* product-page favorite toggle */
.btn--favline { display: inline-flex; align-items: center; gap: 8px; margin-top: 12px; }
.btn--favline__icon { color: #c2c2c2; font-size: 18px; transition: color .12s; }
.btn--favline.is-fav .btn--favline__icon { color: #e0245e; }
.btn--favline__on { display: none; }
.btn--favline.is-fav .btn--favline__on { display: inline; }
.btn--favline.is-fav .btn--favline__off { display: none; }
.btn--favline.is-fav { border-color: #e0245e; color: #e0245e; }

/* ── auth / account ───────────────────────────────────────────────────────── */
.nav__auth { font-weight: 600; color: var(--zap-text); text-decoration: none; padding: 6px 4px; white-space: nowrap; }
.nav__auth:hover { color: var(--zap-primary); }

/* ── fixed header geometry (no flicker on refresh) ────────────────────────────
   The theme bar, auth label and badges are mounted/updated client-side after
   load. Reserve their final dimensions up front so hydration never shifts the
   header layout. */
#theme-bar { width: 176px; height: 38px; flex: none; }
#theme-bar .zap-sel { width: 130px; }
#theme-bar .zap-sel__trigger { width: 100%; }
#theme-bar .zap-sel__val { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
#auth-nav { display: inline-flex; align-items: center; width: 100px; height: 38px;
  overflow: hidden; text-overflow: ellipsis; }
#fav-badge, #cart-badge { display: inline-flex; align-items: center; justify-content: center;
  width: 26px; height: 18px; flex: none; }
#fav-badge .badge, #cart-badge .badge { margin: 0; }
.authwrap { max-width: 420px; margin: 40px auto; }
.auth-card { padding: 28px; }
.auth-card h1 { margin: 0 0 18px; font-size: 24px; }
.auth-card label { display: block; margin-bottom: 14px; font-weight: 600; font-size: 14px; }
.auth-card input { display: block; width: 100%; margin-top: 6px; padding: 10px 12px; font: inherit; font-weight: 400;
  border: 1px solid var(--zap-border); border-radius: var(--zap-radius-sm); background: var(--zap-bg); color: var(--zap-text); }
.auth-card input:focus { outline: none; border-color: var(--zap-primary); box-shadow: 0 0 0 3px var(--zap-primary-soft); }
.auth-err { background: #fee2e2; color: #991b1b; padding: 10px 12px; border-radius: var(--zap-radius-sm); margin: 0 0 14px; font-size: 14px; }
.hp-field { position: absolute !important; left: -9999px !important; width: 1px; height: 1px; overflow: hidden; }
.auth-alt { margin: 16px 0 0; text-align: center; color: var(--zap-muted); font-size: 14px; }
.auth-alt a { color: var(--zap-primary); font-weight: 600; }

.acct-head { display: flex; align-items: flex-start; justify-content: space-between; gap: 16px; margin-bottom: 8px; }
.acct-head h1 { margin: 0; }
.acct-orders { display: flex; flex-direction: column; gap: 10px; }
.acct-order { display: block; padding: 14px 16px; border: 1px solid var(--zap-border); border-radius: var(--zap-radius);
  background: var(--zap-surface); text-decoration: none; color: var(--zap-text); transition: border-color .12s, box-shadow .12s; }
.acct-order:hover { border-color: var(--zap-primary); box-shadow: var(--zap-shadow); }
.acct-order__top { display: flex; justify-content: space-between; margin-bottom: 4px; }
.acct-order__status { text-transform: capitalize; color: var(--zap-primary); font-weight: 600; font-size: 13px; }

/* ── customer reviews ─────────────────────────────────────────────────────── */
.reviews { margin-top: 28px; }
/* Reviews load after paint. The skeleton mirrors the loaded geometry exactly —
   a 16px summary line with 16px below it, then the 48px sign-in band — so
   replacing it shifts nothing. The whole section is reserved with min-height
   in case the swap lands a frame early. */
#reviews-app { min-height: 96px; }
.rev-skeleton__summary { height: 20px; width: 220px; margin: 0 0 16px; }
.rev-skeleton__band { height: 48px; border-radius: var(--zap-radius-sm); }
.skel { background: var(--zap-elevated); border-radius: 6px; position: relative; overflow: hidden; }
.skel::after { content: ""; position: absolute; inset: 0; transform: translateX(-100%);
  background: linear-gradient(90deg, transparent, rgba(148, 163, 184, .18), transparent);
  animation: skel-sweep 1.4s ease-in-out infinite; }
[data-theme="dark"] .skel::after {
  background: linear-gradient(90deg, transparent, rgba(255, 255, 255, .07), transparent); }
@keyframes skel-sweep { 100% { transform: translateX(100%); } }
@media (prefers-reduced-motion: reduce) { .skel::after { animation: none; } }

.rev-summary { font-size: 16px; margin: 0 0 16px; }
.rev-stars { color: #f59e0b; letter-spacing: 1px; }
.rev-stars--off { color: var(--zap-border); }
.rev-signin { padding: 14px 16px; background: var(--zap-elevated); border-radius: var(--zap-radius-sm); }
.rev-signin a { color: var(--zap-primary); font-weight: 600; }
.rev-form { background: var(--zap-surface); border: 1px solid var(--zap-border); border-radius: var(--zap-radius);
  padding: 16px; margin-bottom: 20px; }
.rev-form__stars { margin-bottom: 10px; }
.rev-star { background: none; border: 0; cursor: pointer; font-size: 26px; line-height: 1; padding: 0 3px;
  color: var(--zap-border); transition: color .1s, transform .1s; }
.rev-star:hover { transform: scale(1.15); }
.rev-star.is-on { color: #f59e0b; }
.rev-form__text { display: block; width: 100%; padding: 10px 12px; font: inherit; resize: vertical;
  border: 1px solid var(--zap-border); border-radius: var(--zap-radius-sm); background: var(--zap-bg);
  color: var(--zap-text); margin-bottom: 12px; }
.rev-form__text:focus { outline: none; border-color: var(--zap-primary); box-shadow: 0 0 0 3px var(--zap-primary-soft); }
.rev-form__row { display: flex; align-items: center; gap: 12px; }
.rev-list { display: flex; flex-direction: column; gap: 12px; }
.rev { background: var(--zap-surface); border: 1px solid var(--zap-border); border-radius: var(--zap-radius); padding: 14px 16px; }
.rev__head { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; margin-bottom: 6px; }
.rev-mine { background: var(--zap-primary-soft); color: var(--zap-primary); font-size: 12px; font-weight: 700;
  padding: 2px 8px; border-radius: 999px; }
.rev__at { font-size: 13px; margin-left: auto; }
.rev__text { margin: 0; white-space: pre-wrap; overflow-wrap: anywhere; }
.rev-pager { margin-top: 18px; }
.rev-pager button.pager__btn { font: inherit; cursor: pointer; }

/* favorites page empty state */
.fav-empty { text-align: center; padding: 64px 20px; }
.fav-empty__icon { font-size: 64px; color: var(--zap-border); line-height: 1; }
.fav-empty h2 { margin: 12px 0 6px; }
.fav-empty .btn { margin-top: 18px; }
.btn--lg { padding: 12px 22px; font-size: 16px; }
.btn--block { display: block; width: 100%; }

/* ── product detail page ──────────────────────────────────────────────────── */
.crumbs { font-size: 13px; color: var(--zap-muted); margin-bottom: 16px; }
.crumbs a:hover { color: var(--zap-primary); }
.pdp { display: grid; grid-template-columns: 1fr 1fr; gap: 32px; margin-bottom: 36px; }
.pdp__gallery { display: flex; flex-direction: column; gap: 10px; }
.pdp__img { position: relative; aspect-ratio: 1; border-radius: var(--zap-radius); display: flex; align-items: center; justify-content: center; font-size: 150px; overflow: hidden; }
.pdp__thumbs { display: flex; gap: 8px; flex-wrap: wrap; }
.pdp__thumb { width: 64px; height: 64px; padding: 0; border: 2px solid var(--zap-border); border-radius: 10px; overflow: hidden; cursor: pointer; background: var(--zap-surface); }
.pdp__thumb img { width: 100%; height: 100%; object-fit: cover; display: block; }
.pdp__thumb:hover { border-color: var(--zap-primary); }
.pdp__thumb.is-on { border-color: var(--zap-primary); box-shadow: 0 0 0 2px var(--zap-primary-soft); }

/* ── gallery: stage controls, hover zoom, lightbox ───────────────────────── */

.pdp__img.is-zoomable { cursor: zoom-in; }
.pdp__img img { transition: transform .18s ease-out; will-change: transform; }
.pdp__img.is-zooming img { transition: transform .08s linear; }
.pdp__img.is-zooming .pdp__zoomhint, .pdp__img.is-zooming .card__off { opacity: 0; }

.pdp__nav {
  position: absolute; top: 50%; transform: translateY(-50%); z-index: 3;
  width: 40px; height: 40px; border-radius: 50%; cursor: pointer;
  display: flex; align-items: center; justify-content: center;
  font-size: 26px; line-height: 1; padding-bottom: 3px;
  color: var(--zap-text); border: 1px solid rgba(255, 255, 255, .5);
  background: rgba(255, 255, 255, .65);
  -webkit-backdrop-filter: blur(10px) saturate(180%);
  backdrop-filter: blur(10px) saturate(180%);
  opacity: 0; transition: opacity .15s, background .15s;
}
.pdp__img:hover .pdp__nav, .pdp__nav:focus-visible { opacity: 1; }
.pdp__nav:hover { background: rgba(255, 255, 255, .9); }
.pdp__nav--prev { left: 10px; }
.pdp__nav--next { right: 10px; }
[data-theme="dark"] .pdp__nav { background: rgba(24, 24, 27, .6); border-color: rgba(255, 255, 255, .14); }
[data-theme="dark"] .pdp__nav:hover { background: rgba(24, 24, 27, .85); }

.pdp__count, .pdp__zoomhint {
  position: absolute; bottom: 10px; z-index: 3; pointer-events: none;
  padding: 3px 9px; border-radius: 999px; font-size: 12px; font-weight: 600;
  color: #fff; background: rgba(0, 0, 0, .45); transition: opacity .15s;
}
.pdp__count { left: 10px; }
.pdp__zoomhint { right: 10px; font-size: 14px; padding: 3px 8px; }

/* lightbox */
.lb { position: fixed; inset: 0; z-index: 200; display: flex; flex-direction: column;
  background: rgba(9, 9, 11, .93); -webkit-backdrop-filter: blur(6px); backdrop-filter: blur(6px);
  animation: lb-in .16s ease-out; }
@keyframes lb-in { from { opacity: 0; } }
.lb__bar { display: flex; align-items: center; justify-content: flex-end; gap: 8px; padding: 12px 16px; }
.lb__count { margin-right: auto; color: rgba(255, 255, 255, .7); font-size: 13px; font-weight: 600; }
.lb__btn { width: 36px; height: 36px; border-radius: 50%; cursor: pointer; font-size: 18px; line-height: 1;
  color: #fff; background: rgba(255, 255, 255, .12); border: 0; transition: background .15s; }
.lb__btn:hover { background: rgba(255, 255, 255, .24); }
.lb__stage { flex: 1; display: flex; align-items: center; justify-content: center; overflow: hidden; padding: 0 16px; }
.lb__img { max-width: 100%; max-height: 100%; object-fit: contain; cursor: grab;
  transition: transform .12s ease-out; touch-action: none; user-select: none; }
.lb__img:active { cursor: grabbing; }
.lb__nav { position: absolute; top: 50%; transform: translateY(-50%); width: 48px; height: 48px;
  border-radius: 50%; cursor: pointer; font-size: 30px; line-height: 1; padding-bottom: 4px;
  color: #fff; background: rgba(255, 255, 255, .12); border: 0; transition: background .15s; }
.lb__nav:hover { background: rgba(255, 255, 255, .26); }
.lb__nav--prev { left: 16px; }
.lb__nav--next { right: 16px; }
.lb__strip { display: flex; gap: 8px; justify-content: center; flex-wrap: wrap; padding: 14px 16px 20px; }
.lb__thumb { width: 56px; height: 56px; padding: 0; border-radius: 8px; overflow: hidden; cursor: pointer;
  border: 2px solid transparent; opacity: .55; background: none; transition: opacity .15s, border-color .15s; }
.lb__thumb img { width: 100%; height: 100%; object-fit: cover; display: block; }
.lb__thumb:hover { opacity: .85; }
.lb__thumb.is-on { opacity: 1; border-color: #fff; }

@media (prefers-reduced-motion: reduce) {
  .pdp__img img, .lb__img, .lb { transition: none; animation: none; }
}
@media (max-width: 640px) {
  .pdp__nav { opacity: 1; }
  .lb__nav { width: 40px; height: 40px; font-size: 24px; }
}

/* admin gallery manager */
.gallery-mgr { margin-top: 16px; }
.gallery-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(140px, 1fr)); gap: 12px; }
.gallery-item { position: relative; aspect-ratio: 1; border-radius: var(--zap-radius-sm); overflow: hidden; border: 1px solid var(--zap-border); }
.gallery-item.is-primary { border-color: var(--zap-primary); box-shadow: 0 0 0 2px var(--zap-primary-soft); }
.gallery-item img { width: 100%; height: 100%; object-fit: cover; display: block; }
.gallery-badge { position: absolute; top: 6px; left: 6px; background: var(--zap-primary); color: var(--zap-primary-contrast); font-size: 11px; font-weight: 700; padding: 2px 7px; border-radius: 999px; }
.gallery-actions { position: absolute; bottom: 6px; right: 6px; display: flex; gap: 4px; }
.gallery-actions .btn { background: rgba(0,0,0,.55); border: 0; color: #fff; backdrop-filter: blur(2px); }
.gallery-actions .btn--danger:hover { background: #dc2626; color: #fff; }
.gallery-actions .btn:hover { background: rgba(0,0,0,.8); }
/* admin photo field */
.photo-field { display: flex; gap: 16px; align-items: flex-start; }
.photo-field__preview { width: 110px; height: 110px; object-fit: cover; border-radius: 12px; border: 1px solid var(--zap-border); flex: none; }
.photo-field__none { width: 110px !important; height: 110px !important; font-size: 48px !important; flex: none; }
.photo-field__ctl { display: flex; flex-direction: column; gap: 10px; font-size: 13.5px; }
.photo-field__ctl input[type="file"] { font: inherit; }
.pdp__info h1 { font-size: 27px; margin: 6px 0 10px; }
.pdp__blurb { color: var(--zap-muted); margin: 12px 0; }
.pdp__price { display: flex; align-items: baseline; gap: 10px; margin: 14px 0 6px; }
.stock { font-weight: 600; color: #16a34a; }
.stock--low { color: #d97706; }
.pdp__desc { margin-top: 22px; border-top: 1px solid var(--zap-border); padding-top: 18px; }
.pdp__desc p { color: var(--zap-text); line-height: 1.6; }
.tags { list-style: none; padding: 0; display: flex; flex-wrap: wrap; gap: 8px; margin-top: 12px; }
.tags li { background: var(--zap-elevated); border: 1px solid var(--zap-border); border-radius: 999px; padding: 4px 11px; font-size: 13px; color: var(--zap-muted); }

/* colors, sizes and the buy row each on their own line */
.buybox { display: flex; flex-direction: column; align-items: flex-start; gap: 4px; margin: 18px 0; }
.buybox .variant { margin: 8px 0; }
.qtybox { display: inline-flex; align-items: center; gap: 4px; border: 1px solid var(--zap-border); border-radius: 999px; padding: 4px; }
.qtybox__b { width: 32px; height: 32px; border-radius: 999px; border: 0; background: var(--zap-elevated); color: var(--zap-text); font-size: 18px; cursor: pointer; }
.qtybox__b:hover { background: var(--zap-primary-soft); }
.qtybox__n { min-width: 28px; text-align: center; font-weight: 700; }
.qtybox__in { width: 56px; font: inherit; text-align: center; border: 1px solid var(--zap-border); border-radius: var(--zap-radius-sm); padding: 6px; background: var(--zap-elevated); color: var(--zap-text); }

/* ── cart ─────────────────────────────────────────────────────────────────── */
.cartwrap, .checkout { display: grid; grid-template-columns: 1fr 320px; gap: 24px; align-items: start; }
.cartlist { display: flex; flex-direction: column; gap: 14px; }
.cartline { display: grid; grid-template-columns: 84px 1fr auto; gap: 14px; align-items: center;
  background: var(--zap-surface); border: 1px solid var(--zap-border); border-radius: var(--zap-radius); padding: 14px; }
.cartline__img { width: 84px; height: 84px; border-radius: var(--zap-radius-sm); display: flex; align-items: center; justify-content: center; font-size: 40px; overflow: hidden; }
.cartline__img img, .drawerline__img img { width: 100%; height: 100%; object-fit: cover; }
.cartline__title { font-weight: 600; }
.cartline__ctl { display: flex; align-items: center; gap: 10px; margin-top: 8px; }
.cartline__price { font-weight: 800; font-size: 18px; }
.inlineform { display: inline; }
.linkbtn { background: none; border: 0; color: var(--zap-primary); cursor: pointer; font: inherit; padding: 0; }
.linkbtn:hover { text-decoration: underline; }

.summary { background: var(--zap-surface); border: 1px solid var(--zap-border); border-radius: var(--zap-radius); padding: 18px; box-shadow: var(--zap-shadow); position: sticky; top: 92px; }
.summary__row { display: flex; justify-content: space-between; margin: 8px 0; }
.summary__line { display: flex; align-items: center; justify-content: space-between; gap: 10px; font-size: 14px; margin: 6px 0; color: var(--zap-muted); }
/* Checkout lines carry a thumbnail; the confirmation page's don't (order items
   are read back from SQL and hold no image), so both shapes must lay out. */
.summary__thumb { flex: 0 0 40px; width: 40px; height: 40px; border-radius: var(--zap-radius-sm); display: flex; align-items: center; justify-content: center; font-size: 20px; overflow: hidden; }
.summary__thumb img { width: 100%; height: 100%; object-fit: cover; }
.summary__desc { flex: 1; min-width: 0; }
.summary__amt { flex: none; white-space: nowrap; }
.summary__total { font-size: 19px; border-top: 1px solid var(--zap-border); padding-top: 12px; margin-top: 12px; }
.summary hr { border: 0; border-top: 1px solid var(--zap-border); margin: 12px 0; }

/* ── checkout / confirm ───────────────────────────────────────────────────── */
.card-box { background: var(--zap-surface); border: 1px solid var(--zap-border); border-radius: var(--zap-radius); padding: 24px; box-shadow: var(--zap-shadow); }
.checkout__form h3 { margin: 18px 0 10px; }
.checkout__form h3:first-child { margin-top: 0; }
.checkout__form label { display: block; margin-bottom: 12px; font-weight: 600; font-size: 14px; }
.checkout__form input, .checkout__form textarea, .checkout__form select { width: 100%; font: inherit; margin-top: 5px; padding: 10px 12px;
  border: 1px solid var(--zap-border); border-radius: var(--zap-radius-sm); background: var(--zap-elevated); color: var(--zap-text); font-weight: 400; }
.checkout__form input:focus, .checkout__form textarea:focus, .checkout__form select:focus { outline: none; border-color: var(--zap-primary); box-shadow: 0 0 0 3px var(--zap-primary-soft); }

.confirm { max-width: 620px; margin: 0 auto; text-align: center; }
.confirm__check { width: 64px; height: 64px; border-radius: 999px; background: #16a34a; color: #fff; font-size: 34px;
  display: flex; align-items: center; justify-content: center; margin: 0 auto 16px; }
.confirm h1 { margin-bottom: 8px; }
.confirm__ship { text-align: left; background: var(--zap-elevated); border-radius: var(--zap-radius-sm); padding: 14px; margin: 18px 0; }
.confirm .summary { box-shadow: none; text-align: left; margin: 18px 0; position: static; }

/* ── cart drawer ──────────────────────────────────────────────────────────── */
.drawerbody { display: flex; flex-direction: column; }
.drawerline { display: grid; grid-template-columns: 60px 1fr auto; gap: 14px; align-items: center;
  padding: 16px 0; border-bottom: 1px solid var(--zap-border); }
.drawerline:first-child { padding-top: 4px; }
.drawerline:last-child { border-bottom: 0; }
.drawerline__img { width: 60px; height: 60px; border-radius: 12px; display: flex; align-items: center; justify-content: center; font-size: 30px; flex: none; overflow: hidden; }
.drawerline__main { min-width: 0; display: flex; flex-direction: column; gap: 6px; }
.drawerline__title { font-weight: 600; font-size: 14px; line-height: 1.3; color: var(--zap-text);
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
.drawerline__title:hover { color: var(--zap-primary); }
.drawerline__sub { color: var(--zap-muted); font-size: 12.5px; }
.drawerline__actions { display: flex; align-items: center; gap: 14px; margin-top: 2px; }
.drawerline__price { font-weight: 800; font-size: 15px; white-space: nowrap; align-self: center; }

.stepper { display: inline-flex; align-items: center; border: 1px solid var(--zap-border); border-radius: 999px; }
.stepper__b { width: 30px; height: 30px; border: 0; background: transparent; color: var(--zap-text);
  font-size: 17px; line-height: 1; cursor: pointer; border-radius: 999px; }
.stepper__b:hover { background: var(--zap-primary-soft); color: var(--zap-primary); }
.stepper__n { min-width: 30px; text-align: center; font-weight: 700; font-size: 14px; }

/* footer: full-width block (override theme's right-aligned flex foot) */
.zap-drawer__foot { display: block; padding: 16px 18px; }
.drawerfoot { display: flex; flex-direction: column; gap: 12px; }
.drawerfoot .summary__total { margin: 0; padding: 0; border: 0; font-size: 18px; }
.drawer__viewcart { display: block; text-align: center; }
.zap-drawer__foot .btn--primary,
.zap-drawer__foot .zap-btn { width: 100%; }

/* pagination */
.pager { display: flex; flex-wrap: wrap; align-items: center; justify-content: center; gap: 6px; margin: 28px 0 6px; }
.pager__page, .pager__btn { display: inline-flex; align-items: center; justify-content: center; min-width: 38px; height: 38px; padding: 0 12px;
  border: 1px solid var(--zap-border); border-radius: 10px; font-weight: 600; font-size: 14px; color: var(--zap-text); background: var(--zap-surface); }
.pager__page:hover, .pager__btn:hover { border-color: var(--zap-primary); color: var(--zap-primary); }
.pager__page.is-current { background: var(--zap-primary); border-color: var(--zap-primary); color: var(--zap-primary-contrast); }
.pager__btn.is-disabled { color: var(--zap-muted); opacity: .5; pointer-events: none; }
.pager__gap { padding: 0 4px; color: var(--zap-muted); }
.pager__info { text-align: center; font-size: 13px; margin: 4px 0 0; }

.empty { text-align: center; color: var(--zap-muted); padding: 60px 0; font-size: 17px; }
.empty a { color: var(--zap-primary); font-weight: 600; }
.sortbar select { font: inherit; padding: 7px 10px; border-radius: var(--zap-radius-sm); border: 1px solid var(--zap-border); background: var(--zap-elevated); color: var(--zap-text); margin-left: 6px; }

/* ── footer ───────────────────────────────────────────────────────────────── */
/* ── footer ───────────────────────────────────────────────────────────────── */
/* Columns share the page's 1320px measure so they line up with the grid above
   rather than floating in their own width. The link columns are auto-fit, so
   the row folds to two and then one without a breakpoint per step. */
.foot { border-top: 1px solid var(--zap-border); background: var(--zap-surface); font-size: 14px; }
.foot__cols { max-width: 1320px; margin: 0 auto; padding: 34px 18px 26px;
  display: grid; grid-template-columns: 1.6fr repeat(4, 1fr); gap: 26px; }
.foot__col h3 { font-size: 13px; text-transform: uppercase; letter-spacing: .06em;
  color: var(--zap-muted); margin-bottom: 11px; }
.foot__col nav { display: flex; flex-direction: column; gap: 8px; }
.foot__col nav a { color: var(--zap-text); width: fit-content; }
.foot__col nav a:hover { color: var(--zap-primary); text-decoration: underline; }
.foot__brand { font-size: 19px; font-weight: 800; margin-bottom: 8px; }
.foot__col--brand p { margin: 0; max-width: 34ch; line-height: 1.5; }
.foot__quick { display: flex; gap: 10px; margin-top: 14px; font-size: 17px; }
.foot__quick a { width: 34px; height: 34px; border-radius: 999px; display: inline-flex;
  align-items: center; justify-content: center; border: 1px solid var(--zap-border); }
.foot__quick a:hover { border-color: var(--zap-primary); background: var(--zap-primary-soft); }

.foot__pay { max-width: 1320px; margin: 0 auto; padding: 0 18px 22px;
  display: flex; align-items: center; flex-wrap: wrap; gap: 8px; }
.foot__paylabel { font-size: 13px; text-transform: uppercase; letter-spacing: .06em;
  color: var(--zap-muted); margin-right: 4px; }
/* Masked, not <img>: an SVG in an <img> keeps its own black fill and would
   vanish against the dark theme's surface. As a mask the glyph is painted with
   background-color, so it follows the palette like any other footer text.
   A mask also clips any border or background to the glyph itself, which is
   why these are bare marks in a row rather than chips in frames. */
.paymark { width: 36px; height: 28px; display: inline-block; opacity: .8;
  background-color: var(--zap-muted);
  -webkit-mask-repeat: no-repeat; mask-repeat: no-repeat;
  -webkit-mask-position: center; mask-position: center;
  -webkit-mask-size: contain; mask-size: contain;
  transition: background-color .15s, opacity .15s; }
.foot__pay .paymark:hover { background-color: var(--zap-text); opacity: 1; }
.paymark--visa { -webkit-mask-image: url("/static/app/pay/visa.svg"); mask-image: url("/static/app/pay/visa.svg"); }
.paymark--mc { -webkit-mask-image: url("/static/app/pay/mastercard.svg"); mask-image: url("/static/app/pay/mastercard.svg"); }
.paymark--amex { -webkit-mask-image: url("/static/app/pay/americanexpress.svg"); mask-image: url("/static/app/pay/americanexpress.svg"); }
.paymark--paypal { -webkit-mask-image: url("/static/app/pay/paypal.svg"); mask-image: url("/static/app/pay/paypal.svg"); }
.paymark--applepay { -webkit-mask-image: url("/static/app/pay/applepay.svg"); mask-image: url("/static/app/pay/applepay.svg"); }
.paymark--stripe { -webkit-mask-image: url("/static/app/pay/stripe.svg"); mask-image: url("/static/app/pay/stripe.svg"); }
.foot__paynote { font-size: 13px; margin-left: 6px; }

.foot__bar { border-top: 1px solid var(--zap-border); text-align: center; padding: 16px 18px; }
.foot .muted { margin-top: 4px; }

@media (max-width: 900px) {
  .foot__cols { grid-template-columns: repeat(2, 1fr); }
  .foot__col--brand { grid-column: 1 / -1; }
}
@media (max-width: 520px) {
  .foot__cols { grid-template-columns: 1fr; gap: 22px; }
}

/* ── information pages ────────────────────────────────────────────────────── */
.info { max-width: 74ch; margin: 8px auto 0; }
.info h1 { font-size: 30px; line-height: 1.15; }
.info__lede { color: var(--zap-muted); font-size: 17px; line-height: 1.55; margin: 12px 0 0; }
.info__sec { margin-top: 34px; scroll-margin-top: 128px; }
.info__sec h2 { font-size: 19px; margin-bottom: 10px; }
.info__sec p { line-height: 1.65; margin: 0 0 12px; }
/* separate + zero spacing, not collapse: a collapsed border is clipped away by
   the rounded overflow, which leaves the table with no right-hand edge. */
.info__table { width: 100%; border-collapse: separate; border-spacing: 0; margin-top: 14px;
  border: 1px solid var(--zap-border); border-radius: var(--zap-radius); overflow: hidden; }
.info__table th { text-align: left; font-size: 12.5px; text-transform: uppercase; letter-spacing: .04em;
  color: var(--zap-muted); padding: 11px 12px; border-bottom: 1px solid var(--zap-border); }
.info__table td { padding: 11px 12px; border-bottom: 1px solid var(--zap-border); font-size: 14px; }
.info__table tbody tr:last-child td { border-bottom: 0; }
.theme-bar { display: flex; align-items: center; gap: 8px; }
.theme-bar .zap-sel { min-width: 130px; }
.iconbtn { width: 38px; height: 38px; border-radius: 999px; border: 1px solid var(--zap-border);
  background: var(--zap-elevated); cursor: pointer; font-size: 17px; line-height: 1;
  display: inline-flex; align-items: center; justify-content: center; padding: 0; }
.iconbtn:hover { border-color: var(--zap-primary); background: var(--zap-primary-soft); }
.zap-sel__opt { white-space: nowrap; }
/* Let the dropdown grow to fit the longest label (e.g. "macOS Aqua") instead of
   being pinned to the trigger width — kills the horizontal scrollbar. */
.zap-sel__panel { right: auto; min-width: 100%; width: max-content; max-width: 280px; overflow-x: hidden; }

/* ── admin module ─────────────────────────────────────────────────────────── */
.admin { display: grid; grid-template-columns: 220px 1fr; min-height: 100vh; }
.admin__nav { background: var(--zap-surface); border-right: 1px solid var(--zap-border);
  padding: 18px 14px; display: flex; flex-direction: column; gap: 18px; position: sticky; top: 0; height: 100vh; }
.admin__brand { font-weight: 800; font-size: 18px; }
.admin__brand span { color: var(--zap-primary); font-weight: 600; }
.admin__nav nav { display: flex; flex-direction: column; gap: 4px; }
.admin__nav nav a { padding: 9px 12px; border-radius: 9px; font-weight: 600; color: var(--zap-muted); }
.admin__nav nav a:hover { background: var(--zap-primary-soft); color: var(--zap-primary); }
.admin__nav nav a.on { background: var(--zap-primary); color: var(--zap-primary-contrast); }
.admin__navfoot { margin-top: auto; display: flex; flex-direction: column; gap: 8px; font-size: 14px; color: var(--zap-muted); }
.admin__main { padding: 26px 30px 60px; min-width: 0; max-width: 1320px; }
.admin__head { display: flex; align-items: center; justify-content: space-between; gap: 16px; margin: 18px 0 16px; flex-wrap: wrap; }
.admin__head h1 { font-size: 24px; } .admin__head h2 { font-size: 18px; }
.admin__actions { display: flex; gap: 10px; align-items: center; }
.admin-search { display: flex; gap: 6px; }
.admin-search input { font: inherit; padding: 8px 11px; border: 1px solid var(--zap-border);
  border-radius: var(--zap-radius-sm); background: var(--zap-elevated); color: var(--zap-text); min-width: 240px; }

.stats { display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: 12px; margin-bottom: 26px; }
.stat { background: var(--zap-surface); border: 1px solid var(--zap-border); border-radius: var(--zap-radius); padding: 16px; }
.stat__n { font-size: 24px; font-weight: 800; }
.stat__l { color: var(--zap-muted); font-size: 13px; margin-top: 2px; }
.stat--warn .stat__n { color: #d97706; }

.atable { width: 100%; border-collapse: collapse; background: var(--zap-surface);
  border: 1px solid var(--zap-border); border-radius: var(--zap-radius); overflow: hidden; }
.atable th { text-align: left; font-size: 12.5px; text-transform: uppercase; letter-spacing: .04em;
  color: var(--zap-muted); padding: 11px 12px; border-bottom: 1px solid var(--zap-border); }
.atable td { padding: 11px 12px; border-bottom: 1px solid var(--zap-border); vertical-align: middle; font-size: 14px; }
.atable tbody tr:last-child td { border-bottom: 0; }
.atable tbody tr:hover { background: var(--zap-elevated); }
.atable .num { text-align: right; white-space: nowrap; }
.atable .warn { color: #d97706; font-weight: 700; }
.atable--plain { border: 0; } .atable--plain td { padding: 7px 0; }
.atable--tight th, .atable--tight td { padding: 7px 10px; font-size: 13px; }

.shipmethods { display: flex; flex-direction: column; gap: 8px; margin: 12px 0 18px; }
.shipmethod { display: flex; align-items: center; gap: 10px; padding: 11px 13px; cursor: pointer;
  border: 1px solid var(--zap-border); border-radius: var(--zap-radius-sm); background: var(--zap-surface); }
.shipmethod:has(input:checked) { border-color: var(--zap-primary); box-shadow: 0 0 0 3px var(--zap-primary-soft); }
/* The form sizes inputs to the full width of their field. A radio is not a
   field: left at 100% it claimed the whole row and pushed the name, the
   estimate and the price onto a line of their own. */
.shipmethod input { width: 17px; height: 17px; padding: 0; margin: 0; flex: none;
  accent-color: var(--zap-primary); }
.shipmethod__name { font-weight: 600; }
.shipmethod__days { font-size: 13px; }
.shipmethod__cost { margin-left: auto; font-weight: 700; white-space: nowrap; }
.tracking { font-size: 13px; background: var(--zap-elevated); padding: 2px 7px; border-radius: 6px; }
.tracking--link { color: var(--zap-primary); font-weight: 600; }
.tracking--link:hover { text-decoration: underline; }
.carrier-new { margin-top: 18px; }

.newcolor { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; margin: 10px 0 4px; }
.newcolor__label { font-weight: 600; font-size: 13.5px; }
.newcolor__name { width: 150px; }
.newcolor__hex { width: 46px; height: 32px; padding: 2px; }
.newcolor__note { font-size: 12.5px; }
/* the form-wide block rule would stack these; this row is deliberately inline */
.aform .newcolor > input { display: inline-block; margin-top: 0; }

/* ── admin: visitors ──────────────────────────────────────────────────────── */
.vis__note { margin: -6px 0 16px; font-size: 13px; max-width: 70ch; }
.vis__cards { display: grid; grid-template-columns: 1fr 1fr; gap: 16px; margin-bottom: 18px; }
.vis__card { background: var(--zap-surface); border: 1px solid var(--zap-border); border-radius: var(--zap-radius); padding: 14px 16px; }
.vis__card h3 { font-size: 14px; margin-bottom: 8px; }
.vis__card .atable { border: 0; }
.vis__ip { font-size: 13px; background: var(--zap-elevated); padding: 2px 7px; border-radius: 6px; }
/* The per-visitor product list hangs under its row, so it must not pick up the
   row hover or the cell padding that separates the summary columns. */
.vis__detail td { padding: 0 12px 10px; border-bottom: 1px solid var(--zap-border); }
.vis__detail summary { cursor: pointer; font-size: 13px; color: var(--zap-muted); padding: 4px 0; }
.vis__pages { list-style: none; margin: 6px 0 4px; display: flex; flex-direction: column; gap: 5px; }
.vis__pages li { display: flex; align-items: baseline; gap: 8px; flex-wrap: wrap; font-size: 13px; }
.vis__count { font-weight: 700; }
.vis__url { font-size: 12px; color: var(--zap-muted); background: var(--zap-elevated); padding: 1px 6px; border-radius: 5px; }

.vis__filters { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; margin-bottom: 16px; }
.vis__filters input { padding: 7px 10px; border: 1px solid var(--zap-border); border-radius: var(--zap-radius-sm);
  background: var(--zap-surface); color: var(--zap-text); font-size: 13px; }
.vis__windows { display: flex; gap: 6px; margin-right: 4px; }

/* live feed status + a fade on whatever just moved */
.vis__live { display: inline-flex; align-items: center; gap: 7px; font-size: 12.5px; color: var(--zap-muted);
  background: var(--zap-surface); border: 1px solid var(--zap-border); border-radius: 999px; padding: 4px 12px; }
.vis__dot { width: 8px; height: 8px; border-radius: 50%; background: var(--zap-muted); flex: none; }
.vis__live[data-state="live"] .vis__dot { background: #16a34a; animation: vis-pulse 2s ease-in-out infinite; }
.vis__live[data-state="retry"] .vis__dot { background: #d97706; }
.vis__live[data-state="expired"] .vis__dot { background: #dc2626; }
@keyframes vis-pulse { 0%, 100% { opacity: 1; } 50% { opacity: .35; } }
tr.is-new > td { animation: vis-flash 2.5s ease-out; }
@keyframes vis-flash { from { background: var(--zap-primary-soft); } to { background: transparent; } }
@media (prefers-reduced-motion: reduce) {
  .vis__live[data-state="live"] .vis__dot { animation: none; }
  tr.is-new > td { animation: none; }
}
@media (max-width: 900px) { .vis__cards { grid-template-columns: 1fr; } }
.athumb { width: 38px; height: 38px; border-radius: 9px; display: inline-flex; align-items: center; justify-content: center; font-size: 19px; }
.alink { font-weight: 600; } .alink:hover { color: var(--zap-primary); }
.rowactions { display: flex; gap: 6px; align-items: center; white-space: nowrap; }
.btn--xs { padding: 5px 10px; font-size: 13px; border-radius: 8px; }
.btn--danger { color: #dc2626; border-color: #fca5a5; background: transparent; }
.btn--danger:hover { background: #dc2626; border-color: #dc2626; color: #fff; }
.flash { background: #16a34a14; border: 1px solid #16a34a55; color: #15803d;
  border-radius: var(--zap-radius-sm); padding: 10px 14px; font-weight: 600; }
.status { display: inline-block; padding: 3px 10px; border-radius: 999px; font-size: 12.5px; font-weight: 700; text-transform: capitalize; }
.status--placed    { background: #f59e0b22; color: #b45309; }
.status--shipped   { background: #3b82f622; color: #1d4ed8; }
.status--delivered { background: #16a34a22; color: #15803d; }
.status--cancelled { background: #dc262622; color: #b91c1c; }

.aform label { display: block; font-weight: 600; font-size: 13.5px; margin-bottom: 0; }
/* A control is inline-level by default, so it flows after its label's text and
   only drops to its own line if there is whitespace to break at. The big forms
   happen to have a newline there; the row-menu forms do not, and their 100%-wide
   inputs shot out of the popover. Make the control its own block and the markup
   stops mattering. Checkboxes and radios stay inline — they sit beside a label. */
.aform label > input:not([type="checkbox"]):not([type="radio"]),
.aform label > textarea,
.aform label > select { display: block; }
.aform input, .aform select, .aform textarea { width: 100%; font: inherit; font-weight: 400; margin-top: 5px;
  padding: 9px 11px; border: 1px solid var(--zap-border); border-radius: var(--zap-radius-sm);
  background: var(--zap-elevated); color: var(--zap-text); }
.aform input:focus, .aform select:focus, .aform textarea:focus { outline: none; border-color: var(--zap-primary); box-shadow: 0 0 0 3px var(--zap-primary-soft); }
.aform__grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 14px; }
.aform__grid .span2 { grid-column: span 2; }
.aform__check { display: flex; align-items: center; gap: 8px; align-self: end; padding-bottom: 9px; }
.aform__check input { width: 17px; height: 17px; margin: 0; accent-color: var(--zap-primary); }
.aform__section { font-weight: 700; margin: 22px 0 10px; padding-top: 16px; border-top: 1px solid var(--zap-border); }
/* A divider above the first thing in a card divides it from nothing, and
   leaves a stripe of empty space at the top of the box. */
.aform__section:first-child { margin-top: 0; padding-top: 0; border-top: 0; }
.aform__full { margin-bottom: 12px; }
.aform__note { font-size: 13px; margin: 8px 0 0; }
/* Bottom-aligned, because this row mixes bare buttons with labelled fields:
   stretching a button to the height of a label-plus-input turns it into an
   oval floating beside the box it belongs to. */
.aform__actions { display: flex; gap: 10px; margin-top: 22px; align-items: flex-end; }
.colorpick { display: grid; grid-template-columns: repeat(auto-fill, minmax(130px, 1fr)); gap: 6px; }
.colorpick__opt { display: flex; align-items: center; gap: 8px; font-weight: 500; font-size: 13.5px;
  padding: 6px 8px; border-radius: 8px; cursor: pointer; }
.colorpick__opt:hover { background: var(--zap-primary-soft); }
.colorpick__opt input { width: 15px; height: 15px; margin: 0; accent-color: var(--zap-primary); }
.admin-err { background: #dc262614; border: 1px solid #dc262655; color: #b91c1c;
  border-radius: var(--zap-radius-sm); padding: 10px 14px; margin-bottom: 14px; font-size: 14px; }
.order-grid { display: grid; grid-template-columns: 1.1fr .9fr; gap: 18px; align-items: start; }
.order-delete { margin-top: 18px; border-top: 1px solid var(--zap-border); padding-top: 14px; text-align: right; }

/* zap-enhanced admin bits */
.confirm-actions { display: flex; gap: 10px; justify-content: flex-end; }
.confirm-msg { margin: 0; }
.zapsel-host { margin-top: 5px; }
.zapsel-host .zap-sel { min-width: 0; }
.disc-prev { color: #16a34a; font-weight: 700; font-size: 12.5px; }
.admin__navfoot .theme-bar { flex-direction: column; align-items: stretch; gap: 8px; margin-bottom: 6px; }
.admin__navfoot .theme-bar .zap-sel { min-width: 0; }
/* #theme-bar is sized for the storefront header, where the bar is one row.
   Stacked in the sidebar it needs two, and the fixed 38px let the mode toggle
   spill over the links underneath. */
.admin__navfoot #theme-bar { width: auto; height: auto; }

/* featured star toggle + filter chips in products list */
.starbtn { background: none; border: 0; cursor: pointer; font-size: 20px; line-height: 1; padding: 2px 4px;
  color: var(--zap-border); transition: color .12s, transform .1s; }
.starbtn:hover { color: #f59e0b; transform: scale(1.15); }
.starbtn.is-on { color: #f59e0b; }
.admin__actions .chip { padding: 7px 13px; font-size: 13.5px; }
.admin__actions .chip--on { background: var(--zap-primary); border-color: var(--zap-primary); color: var(--zap-primary-contrast); }

/* categories admin */
.deptcard { margin-bottom: 16px; padding: 16px 18px; }
.deptcard__head { display: flex; align-items: center; gap: 12px; }
.deptcard__title { display: flex; flex-direction: column; gap: 2px; flex: 1; min-width: 0; }
.deptcard .facet > summary { font-size: 14px; padding: 10px 0; }
.catform { display: flex; gap: 8px; align-items: center; padding-bottom: 10px; flex-wrap: wrap; }
.catform input { width: auto; flex: 1; min-width: 140px; margin: 0; }
.catform__emoji { max-width: 70px; flex: 0 1 70px !important; }
.catform__grad { flex: 2 !important; }
.catstbl { margin: 8px 0; }
.catstbl th { padding: 8px 8px 8px 0; }
.catstbl td { padding: 9px 8px 9px 0; }
.catstbl__types { max-width: 320px; }
/* A row menu is absolutely positioned inside a table cell, and .atable carries
   overflow:hidden for its rounded corners — which clipped the panel at the
   table's edge, so opening Edit on the last row showed a sliver of a panel
   apparently stuck under the row. A table that hosts row menus gives up the
   clipping; .atable--plain has no border or radius to lose anyway. */
.catstbl, .atable:has(.rowmenu) { overflow: visible; }
.rowmenu { position: relative; display: inline-block; }
.rowmenu > summary { list-style: none; display: inline-flex; cursor: pointer; }
.rowmenu > summary::-webkit-details-marker { display: none; }
.rowmenu[open] > .rowmenu__form { position: absolute; right: 0; top: calc(100% + 6px); z-index: 40;
  background: var(--zap-surface); border: 1px solid var(--zap-border); border-radius: var(--zap-radius-sm);
  box-shadow: var(--zap-shadow); padding: 14px; width: 320px; }
/* Opens downward by default; admin.js adds is-up on the rows near the bottom
   of the page, where the panel would otherwise hang below the fold. */
.rowmenu.is-up[open] > .rowmenu__form { top: auto; bottom: calc(100% + 6px); }
.rowmenu__form label { margin-bottom: 10px; }
.rowmenu__form textarea, .rowmenu__form input, .rowmenu__form select { font-size: 13.5px; }

.admin-login { min-height: 100vh; display: flex; align-items: center; justify-content: center; padding: 20px; }
.admin-login__card { width: 360px; display: flex; flex-direction: column; gap: 14px; }
.admin-login__card h1 { font-size: 22px; text-align: center; }
.admin-login__card label { font-weight: 600; font-size: 14px; }
.admin-login__card input { width: 100%; font: inherit; margin-top: 6px; padding: 10px 12px;
  border: 1px solid var(--zap-border); border-radius: var(--zap-radius-sm); background: var(--zap-elevated); color: var(--zap-text); }
.admin-login__hint { text-align: center; font-size: 12.5px; margin: 0; }

@media (max-width: 900px) {
  .admin { grid-template-columns: 1fr; }
  .admin__nav { position: static; height: auto; flex-direction: row; align-items: center; }
  .admin__nav nav { flex-direction: row; }
  .admin__navfoot { margin: 0 0 0 auto; flex-direction: row; }
  .aform__grid { grid-template-columns: 1fr; } .aform__grid .span2 { grid-column: auto; }
  .order-grid { grid-template-columns: 1fr; }
}

/* ── responsive ───────────────────────────────────────────────────────────── */
/* The facet drawer is a disclosure only on small screens: on desktop the
   summary is hidden and the body always shows, so the column looks unchanged. */
.sidebar__toggle { display: none; }
.sidebar__drawer > .sidebar__body { display: flex; flex-direction: column; gap: 14px; }

@media (max-width: 860px) {
  .hero { grid-template-columns: 1fr; padding: 36px 28px; } .hero__art { display: none; }
  .hero h1 { font-size: 28px; }
  /* The desktop blurb grew to sit closer to the art; there is no art here, and
     a phone column has no room to spend on the extra size. */
  .hero p { font-size: 17px; }
  .pdp { grid-template-columns: 1fr; }
  .cartwrap, .checkout { grid-template-columns: 1fr; }
  .results { grid-template-columns: 1fr; }
  .facets { position: static; }
  .summary { position: static; }
  .nav__inner { flex-wrap: wrap; } .search { order: 3; flex-basis: 100%; max-width: none; }
  .catstrip { overflow-x: auto; flex-wrap: nowrap; scrollbar-width: none; }
  .catstrip::-webkit-scrollbar { display: none; }

  /* The megamenu cannot open inside the horizontally scrolling strip — an
     absolutely positioned child never escapes an overflow container, so it
     was clipped into the strip's bottom edge. Anchor it to the sticky header
     instead (.dept goes static) and open it on tap as a full-width sheet;
     store.js toggles .is-open, hover alone no longer opens it here. */
  .dept { position: static; }
  .megamenu { left: 10px; right: 10px; top: 100%; }
  .dept:hover .megamenu { opacity: 0; visibility: hidden; transform: translateY(4px); }
  .dept.is-open .megamenu { opacity: 1; visibility: visible; transform: translateY(0); }
  .megamenu__links { flex: 1; min-width: 0; max-height: 55vh; overflow-y: auto; }
  .megamenu a { white-space: normal; }
  .megamenu__art { width: 38%; min-height: 150px; }

  /* one tappable row instead of a full-height filter column */
  .sidebar { position: static; }
  .sidebar__toggle {
    display: flex; align-items: center; justify-content: space-between; gap: 10px;
    list-style: none; cursor: pointer; font-weight: 600;
    padding: 12px 14px; border-radius: var(--zap-radius);
    background: var(--zap-surface); border: 1px solid var(--zap-border);
  }
  .sidebar__toggle::-webkit-details-marker { display: none; }
  .sidebar__toggle::after { content: "▾"; color: var(--zap-muted); transition: transform .15s; }
  .sidebar__drawer[open] > .sidebar__toggle::after { transform: rotate(180deg); }
  .sidebar__drawer[open] > .sidebar__toggle { margin-bottom: 12px; }
  .sidebar__badge {
    margin-left: auto; margin-right: 4px; font-size: 11px; font-weight: 700;
    text-transform: uppercase; letter-spacing: .04em;
    padding: 2px 7px; border-radius: 999px;
    color: var(--zap-primary); background: var(--zap-primary-soft);
  }
  /* the facet lists are already scrollable; keep them short so the page is not
     one long list of checkboxes */
  .facet__scroll { max-height: 168px; }
  .sec-head { flex-wrap: wrap; gap: 10px; }
}

@media (max-width: 520px) {
  .grid { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 10px; }
  .pdp__thumb { width: 54px; height: 54px; }
}

/* footer perf line — full text color (black in light mode), not muted */
.foot__perf { font-size: 12.5px; margin-top: 4px; font-variant-numeric: tabular-nums; font-weight: 700;
  color: var(--zap-text); }

/* The textarea stays as the form field the editor writes into; it is only
   hidden once the island is there to replace it. */
.aform textarea.is-enhanced { position: absolute; width: 1px; height: 1px; opacity: 0; pointer-events: none; }

/* the description, as the editor shaped it */
.pdp__copy { line-height: 1.65; }
.pdp__copy p { margin: 0 0 12px; }
.pdp__copy h3 { font-size: 18px; margin: 18px 0 8px; }
.pdp__copy h4 { font-size: 16px; margin: 14px 0 6px; }
.pdp__copy ul, .pdp__copy ol { margin: 0 0 12px; padding-left: 22px; }
.pdp__copy li { margin: 3px 0; }
.pdp__copy blockquote { margin: 0 0 12px; padding-left: 14px; border-left: 3px solid var(--zap-border); color: var(--zap-muted); }
.pdp__copy a { color: var(--zap-primary); text-decoration: underline; }

/* ── stock by colour and size ─────────────────────────────────────────────── */
.vgrid-wrap { overflow-x: auto; margin-top: 10px; }
/* As wide as its contents, not as wide as the form: stretched to 100% a
   two-column grid put the colour name at one end of the row and its one input
   at the other, with a stretch of nothing between them. The wrapper scrolls
   when a product has enough sizes to need it. */
.vgrid { border-collapse: separate; border-spacing: 0; width: auto;
  border: 1px solid var(--zap-border); border-radius: var(--zap-radius); overflow: hidden; }
.vgrid th, .vgrid td { padding: 7px 9px; border-bottom: 1px solid var(--zap-border); }
.vgrid tbody tr:last-child th, .vgrid tbody tr:last-child td { border-bottom: 0; }
.vgrid thead th { font-size: 12.5px; text-transform: uppercase; letter-spacing: .04em;
  color: var(--zap-muted); text-align: center; background: var(--zap-elevated); }
/* A table cell, not a flex box. display:flex takes the <th> out of the table's
   row layout, so it stopped sharing a height with the <td> beside it and their
   bottom borders landed at different heights — the row line looked broken in
   two. The swatch sits inline instead. */
.vgrid__row { font-size: 14px; font-weight: 600; white-space: nowrap;
  text-align: left; padding-right: 18px; }
.vgrid__row .swatch { margin-right: 7px; vertical-align: middle; }
.vgrid td { text-align: center; }
/* .aform input sets width:100% and outranks a lone class, so the cell width
   has to be said from inside the form too. */
.vgrid__in, .aform .vgrid__in { width: 74px; font: inherit; padding: 6px 8px; text-align: right;
  border: 1px solid var(--zap-border); border-radius: var(--zap-radius-sm);
  background: var(--zap-elevated); color: var(--zap-text); }
.vgrid__in:focus { outline: none; border-color: var(--zap-primary); box-shadow: 0 0 0 3px var(--zap-primary-soft); }

/* a size with nothing left in the chosen colour: still clickable, so the
   shopper can see what it would cost them to want it */
.size-b.is-out { opacity: .45; text-decoration: line-through; }
.pdp__left { display: block; margin: 10px 0 -2px; font-size: 14px; font-weight: 600; color: #16a34a; }
.pdp__left--out { color: #dc2626; }

/* the checkout that could not be filled, said on the cart it came back to */
.cart-soldout { margin-bottom: 16px; }

/* ── order page: line thumbnails, cancellation ───────────────────────────── */
/* The picture sits inside the existing line rather than adding a column: the
   summary is a two-part row (what, how much) and that reads correctly whether
   or not a product still has a photo. */
.summary__line--pic { align-items: center; }
.oline { display: flex; align-items: center; gap: 10px; min-width: 0; }
.oline__pic { width: 44px; height: 44px; flex: 0 0 44px; border-radius: 8px;
  border: 1px solid var(--zap-border); object-fit: cover; display: block; background: var(--zap-elevated); }
.oline__pic--none { display: flex; align-items: center; justify-content: center; font-size: 20px; }
.oline__txt { min-width: 0; }
.invoice-line { margin: 14px 0 0; }
.confirm__acts { display: flex; flex-wrap: wrap; gap: 10px; align-items: center; justify-content: center; margin-top: 18px; }

/* The counterpart to .auth-err — a page that can only tell you when something
   went wrong reads as a page where nothing ever goes right. */
.auth-ok { background: #dcfce7; color: #166534; padding: 10px 12px; border-radius: var(--zap-radius-sm); margin: 0 0 14px; font-size: 14px; }
.resell { display: grid; gap: 6px; margin: 2px 0 4px; }
.resell__opt { display: flex; align-items: center; gap: 8px; font-size: 14px; font-weight: 600; }
/* .aform sizes every input to the full width of its field, which is right for
   a text box and absurd for a radio — it became a stretched control on a line
   of its own, with its label stranded underneath. Every inline control in
   these forms resets it the same way. */
.resell__opt input { width: 15px; height: 15px; margin: 0; flex: 0 0 auto; accent-color: var(--zap-primary); }

.doclist { list-style: none; margin: 0 0 4px; padding: 0; display: grid; gap: 6px; }
.doclist li { display: flex; align-items: baseline; gap: 8px; font-size: 14px; }
.doclist__kind { color: var(--zap-muted); font-size: 13px; min-width: 108px; }

/* ── checkout: phone with its dialling code, and the town line ───────────── */
/* One control made of two: the select carries the flag and the code, the input
   carries the number. They share a border so they read as a single field. */
.phonefield { display: flex; gap: 8px; margin-top: 5px; }
/* Scoped to .checkout__form on purpose: the form's own `input, select { width:
   100% }` is one element-selector more specific than a bare class, so an
   unscoped rule here loses and the dialling-code select eats the whole row —
   leaving the number box a sliver at the edge. The wrapper also carries the
   gap under the label, so the controls must not add a second one. */
.checkout__form .phonefield__cc, .checkout__form .phonefield__num { margin-top: 0; }
.checkout__form .phonefield__cc { flex: 0 0 auto; width: auto; min-width: 108px; }
.checkout__form .phonefield__num { flex: 1 1 auto; width: auto; min-width: 0; }
/* The shipping form in two columns. Fields that belong together sit together;
   the address itself spans both because a street line is not a short answer. */
.cogrid { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: 0 14px; }
.cogrid > .span2 { grid-column: 1 / -1; }
@media (max-width: 620px) { .cogrid { grid-template-columns: 1fr; } }

/* The select the address island lays over a text input. It has to look like
   the input it replaces, or the row it sits in stops lining up. */
.checkout__form .addr__sel { width: 100%; font: inherit; margin-top: 5px; padding: 10px 12px;
  border: 1px solid var(--zap-border); border-radius: var(--zap-radius-sm);
  background: var(--zap-elevated); color: var(--zap-text); }
.checkout__form .addr__sel:focus { outline: none; border-color: var(--zap-primary);
  box-shadow: 0 0 0 3px var(--zap-primary-soft); }

/* The zap Select replaces the native control, so the phone row's sizing has to
   move onto its host — the hidden <select> no longer occupies any space. */
.phonefield .zapsel-host { flex: 0 0 auto; min-width: 128px; margin-top: 0; }
.phonefield .zapsel-host .zap-sel { min-width: 128px; }
.checkout__form .zapsel-host { margin-top: 5px; }

/* Payment methods: the same row as the shipping options, with room for the
   sentence each one needs — "free shipping does not apply" is not a footnote,
   it is the thing that changes the total. */
.paymethods { display: flex; flex-direction: column; gap: 8px; margin: 12px 0 16px; }
/* Scoped to the form: `.checkout__form label { display: block }` is one element
   selector more specific than a bare class, so an unscoped rule here loses and
   the radio ends up on a line above its own label. The shipping rows escape it
   only by accident — their contents are inline, so block flow happens to put
   them side by side. */
.checkout__form .paymethod { display: flex; align-items: flex-start; gap: 10px; }
.paymethod { padding: 11px 13px; cursor: pointer;
  border: 1px solid var(--zap-border); border-radius: var(--zap-radius-sm); background: var(--zap-surface); }
.paymethod:has(input:checked) { border-color: var(--zap-primary); box-shadow: 0 0 0 3px var(--zap-primary-soft); }
.paymethod input { width: 17px; height: 17px; padding: 0; margin: 2px 0 0; flex: none;
  accent-color: var(--zap-primary); }
.paymethod__body { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.paymethod__name { font-weight: 600; }
.paymethod__hint { font-size: 13px; font-weight: 400; }

.paynote { margin: 14px 0 0; padding: 10px 12px; font-size: 14px;
  background: var(--zap-elevated); border-radius: var(--zap-radius-sm); }

/* `hidden` is a UA default of display:none, and any rule that sets display
   beats it — .checkout__form label { display: block } did, so hiding the card
   field left it on screen. Say it where the label rule can be overridden. */
.checkout__form label[hidden] { display: none; }

/* The required marker. aria-hidden in the markup because a screen reader
   already announces the control as required from the `required` attribute —
   reading "star" as well would be noise, not information. */
.req { color: #dc2626; font-weight: 700; }
.reqnote { font-size: 13px; margin: 0 0 14px; }

.formerr { background: #fee2e2; color: #991b1b; padding: 10px 12px; border-radius: var(--zap-radius-sm);
  margin: 0 0 16px; font-size: 14px; line-height: 1.6; }

/* A row's subtitle sits with its heading, not under it: the heading line is
   already a flex row with "See all" pushed to the end. */
.sec-sub { font-size: 14px; margin-left: 4px; align-self: center; }

/* A branch in the admin nav: a heading, and its children hanging off a guide
   line so it is clear where the group ends. It was a heading with indented
   entries under it, which made everything below the group look like part of
   it. */
.nav__branch { margin: 12px 0 2px; }
.nav__group { font-size: 11.5px; font-weight: 700; letter-spacing: .08em; text-transform: uppercase;
  color: var(--zap-muted); margin: 0 0 2px; padding: 4px 10px; cursor: pointer;
  display: flex; align-items: center; gap: 6px; border-radius: 8px; list-style: none; }
.nav__group:hover { background: var(--zap-primary-soft); color: var(--zap-text); }
/* The default triangle sits outside the padding and points the wrong way for a
   sidebar; drawn as a caret that turns instead. */
.nav__group::-webkit-details-marker { display: none; }
.nav__group::before { content: "\25B8"; font-size: 10px; transition: transform .12s; }
.nav__branch[open] > .nav__group::before { transform: rotate(90deg); }
.nav__kids { margin-left: 17px; padding-left: 11px; border-left: 1px solid var(--zap-border);
  display: flex; flex-direction: column; }
/* The tick joining a child to the line. Drawn rather than bordered so it stops
   at the text instead of running the width of the row. */
.admin__side .nav__kids .nav__sub { position: relative; }
.admin__side .nav__kids .nav__sub::before { content: ""; position: absolute;
  left: -11px; top: 50%; width: 7px; height: 1px; background: var(--zap-border); }

/* ── home page sections (admin) ──────────────────────────────────────────── */
.searchbar { display: flex; gap: 10px; align-items: center; }
.searchbar input { flex: 1 1 auto; font: inherit; padding: 9px 11px;
  border: 1px solid var(--zap-border); border-radius: var(--zap-radius-sm);
  background: var(--zap-elevated); color: var(--zap-text); }
.pickgrid { display: grid; gap: 8px; }
.pick { display: flex; align-items: center; gap: 12px; padding: 8px;
  border: 1px solid var(--zap-border); border-radius: var(--zap-radius-sm); }
.pick__pic { width: 44px; height: 44px; flex: 0 0 44px; display: flex; align-items: center;
  justify-content: center; font-size: 20px; border-radius: 8px; overflow: hidden;
  background: var(--zap-elevated); border: 1px solid var(--zap-border); }
.pick__pic img { width: 100%; height: 100%; object-fit: cover; display: block; }
.pick__txt { display: flex; flex-direction: column; gap: 1px; min-width: 0; flex: 1 1 auto; }
.pick__title { font-weight: 600; font-size: 14px; }

.sortlist { list-style: none; margin: 0 0 4px; padding: 0; display: grid; gap: 8px; }
.sortrow { display: flex; align-items: center; gap: 12px; padding: 8px;
  border: 1px solid var(--zap-border); border-radius: var(--zap-radius-sm);
  background: var(--zap-surface); }
.sortrow__grip { color: var(--zap-muted); font-size: 18px; line-height: 1; }
.is-sortable .sortrow { cursor: grab; }
.is-sortable .sortrow__pos { display: none; }
.sortrow.is-dragging { opacity: .45; }
.numin { width: 76px; }
.rowform { display: flex; align-items: center; gap: 8px; }
.rowcheck { display: flex; align-items: center; gap: 5px; font-size: 13px; white-space: nowrap; }
.rowcheck input { width: 15px; height: 15px; margin: 0; accent-color: var(--zap-primary); }
.removebox { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 14px; }

/* ── arranging the home page: the storefront's own cards ─────────────────── */
/* The list is the storefront grid, so the arrangement is looked at rather than
   read. The bar above each card is the part you grab — the card underneath is
   a card, and its links are switched off while sorting. */
.sortcard { position: relative; display: flex; flex-direction: column; gap: 6px; }
.sortcard__bar { display: flex; align-items: center; justify-content: space-between; gap: 8px; }
.sortcard__grip { font-size: 12px; color: var(--zap-muted); cursor: grab; letter-spacing: .04em; }
.is-sortable .sortcard { cursor: grab; }
.is-sortable .sortcard__pos { display: none; }
/* The card being carried, and the space it would fall into. Without the
   placeholder the grid reflows silently and there is nothing to aim at. */
.sortcard.is-dragging { opacity: .35; outline: 2px dashed var(--zap-primary); outline-offset: 2px; }
.is-sortable .sortcard { transition: transform .12s ease; }
.sortcard .card { height: 100%; }

/* A section on the admin home page: its controls, then the row as the
   storefront draws it. */
.secblock { margin-bottom: 18px; }
.secblock--off { opacity: .62; }
.secblock__head { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between;
  gap: 10px; margin-bottom: 14px; }
.secblock__title { display: flex; align-items: baseline; gap: 8px; font-size: 16px; }
.secblock__tag { font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: .06em;
  color: var(--zap-muted); border: 1px solid var(--zap-border); border-radius: 999px; padding: 1px 7px; }
.secblock__acts { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; }
/* Denser than the storefront's: this is a preview inside a page that also has
   a sidebar, and the point is the order, not the detail. */
.secblock__grid { grid-template-columns: repeat(auto-fill, minmax(178px, 1fr)); gap: 12px; }

/* The section block's own controls: a header of fields, a bar of actions, and
   a remove button that sits with the drag handle rather than on the card. */
.secblock__head { display: flex; flex-wrap: wrap; align-items: flex-end; gap: 10px; margin-bottom: 12px; }
.secblock__f { display: flex; flex-direction: column; gap: 3px; font-size: 12.5px; font-weight: 600;
  color: var(--zap-muted); }
.secblock__f input { font: inherit; font-weight: 400; color: var(--zap-text); padding: 7px 9px;
  border: 1px solid var(--zap-border); border-radius: var(--zap-radius-sm); background: var(--zap-elevated); }
.secblock__f--title { flex: 1 1 180px; }
.secblock__f--title input { font-size: 15px; font-weight: 700; }
.secblock__f--num input { width: 78px; }
.secblock__f--check { margin-bottom: 7px; }
.secblock__bar { display: flex; flex-wrap: wrap; align-items: center; gap: 10px; margin-bottom: 12px;
  padding-top: 10px; border-top: 1px solid var(--zap-border); }
/* `hidden` is display:none from the UA sheet and any display rule beats it —
   this one did, so the island's replacement sat beside the form it replaced. */
.secsearch { display: flex; gap: 6px; flex: 1 1 260px; }
.secsearch[hidden] { display: none; }
.secsearch input { flex: 1 1 auto; font: inherit; padding: 7px 9px; min-width: 0;
  border: 1px solid var(--zap-border); border-radius: var(--zap-radius-sm);
  background: var(--zap-elevated); color: var(--zap-text); }
.secfound { display: grid; gap: 6px; margin-bottom: 14px; }
.hiddenform { display: none; }
.cardrm { border: 1px solid var(--zap-border); background: var(--zap-surface); color: #dc2626;
  border-radius: 6px; width: 22px; height: 22px; line-height: 1; cursor: pointer; font-size: 12px; }
.cardrm:hover { background: #fee2e2; border-color: #fca5a5; }

/* The preview borrows the storefront's card, and the "add to cart" button comes
   with it. In the admin it is dead — the cart island is not mounted here — and
   it is not what this page is for. Hidden rather than a second card template,
   which would be two things to keep in step. */
.secblock .btn--add { display: none; }
/* The space the button left belongs to the card, not to a gap under it. */
.secblock .card__body { padding-bottom: 12px; }

.savehint { font-size: 12.5px; }
.savehint::before { content: "\2022 "; }

.sec-emoji { font-size: .95em; }
.secblock__f--emoji input { width: 68px; text-align: center; font-size: 16px; }

/* One emoji wide. A field sized for a sentence invites a sentence. */
.emojif input, .secblock__f--emoji input { width: 72px; text-align: center; font-size: 18px; }
.emojif { max-width: 120px; }

/* The move arrows, pinned to the top-right of the section they move. */
.secblock { position: relative; }
.secmove { position: absolute; top: 14px; right: 14px; display: flex; gap: 4px; }
.secmove .btn { min-width: 30px; padding-left: 8px; padding-right: 8px; }

.addsearch { flex: 1 1 260px; min-width: 0; }
.addsearch .zap-sel { width: 100%; }
