/* ==========================================================================
   Nørd Store — store.css
   Ported target: Jade/Pug templates on Express.

   Tokens: this sheet does NOT declare --bg / --bg-soft / --bg-deep / --ink /
   --ink-2 / --ink-3 / --rule / --accent. They come from the main site sheet.
   Every reference carries the site's own value as a var() fallback only so
   these files can be opened standalone during porting — remove the fallbacks
   once both stylesheets load together if you prefer.

   New tokens are prefixed --store-. New classes are prefixed .sn-store-.
   Breakpoints: 1100px, 680px, 600px. No others.
   ========================================================================== */

/* CRITICAL:start — inline this block above the fold
   (nav, page frame, type reset, catalogue grid skeleton) */

:root {
  --store-row-h: 360px;        /* catalogue uniform row height, desktop */
  /* Alias the main site's layout tokens rather than restating their values,
     so a change on site-2026.css carries over to the store. */
  --store-max: var(--maxw, 1480px);
  --store-pad: var(--pad-page, 32px);
  --store-gap: var(--gap-section, 96px);
  --store-hairline: 0.5px solid var(--rule, oklch(0.205 0.022 256 / 0.14));
  --store-nav-h: 72px;
}

.sn-store-body {
  margin: 0;
  background: var(--bg, oklch(0.985 0.002 250));
  color: var(--ink, oklch(0.205 0.022 256));
  font-family: "PT Sans", Helvetica, Arial, sans-serif;
  font-size: 16px;
  line-height: 1.55;
  -webkit-font-smoothing: antialiased;
}

.sn-store-page {
  max-width: var(--store-max);
  margin: 0 auto;
  padding: 0 var(--store-pad);
}

.sn-store-body a { color: inherit; text-decoration: none; }
.sn-store-body a:hover { color: var(--accent, oklch(0.56 0.205 25)); }

/* focus — visible on everything interactive, never removed */
.sn-store-body a:focus-visible,
.sn-store-body button:focus-visible,
.sn-store-body [tabindex]:focus-visible {
  outline: 2px solid var(--accent, oklch(0.56 0.205 25));
  outline-offset: 3px;
}

/* mono: every fact, label, number — reuses the site's mono treatment */
.sn-store-mono {
  font-family: "IBM Plex Mono", ui-monospace, monospace;
  font-size: 11px;
  font-weight: 400;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--ink-3, oklch(0.64 0.014 256));
  font-variant-numeric: tabular-nums;
}

/* nav — three-column grid, blurred, hairline bottom */
.sn-store-nav {
  position: sticky;
  top: 0;
  z-index: 20;
  background: color-mix(in oklab, var(--bg, oklch(0.985 0.002 250)) 86%, transparent);
  backdrop-filter: blur(10px) saturate(160%);
  -webkit-backdrop-filter: blur(10px) saturate(160%);
  border-bottom: var(--store-hairline);
}
.sn-store-nav__inner {
  max-width: var(--store-max);
  margin: 0 auto;
  padding: 0 var(--store-pad);
  min-height: var(--store-nav-h);
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  align-items: center;
  gap: 24px;
}
.sn-store-nav__mark { display: flex; align-items: center; gap: 12px; }
.sn-store-nav__mark img { display: block; width: 125px; height: 24px; }
.sn-store-nav__sub {
  border-left: var(--store-hairline);
  padding-left: 12px;
}
.sn-store-nav__links { display: flex; gap: 28px; }
.sn-store-nav__links a { color: var(--ink-2, oklch(0.43 0.018 256)); }
.sn-store-nav__links a[aria-current="page"] { color: var(--ink, oklch(0.205 0.022 256)); }
.sn-store-nav__cross { display: flex; justify-content: flex-end; }
.sn-store-nav__cross a {
  color: var(--ink-2, oklch(0.43 0.018 256));
  border-bottom: var(--store-hairline);
  padding-bottom: 2px;
}

/* catalogue grid skeleton — uniform row height, native aspect ratios */
.sn-store-grid {
  display: flex;
  flex-wrap: wrap;
  /* flex-start, not flex-end: a card is a fixed-height frame plus a
     variable-height meta block, so aligning bottoms shifts a card's image up
     the moment its title wraps to two lines — and the aligned meta hairlines
     are the whole point of the uniform row height. */
  align-items: flex-start;
  gap: 64px 40px;
  margin-top: 48px;
}
.sn-store-card {
  flex: 0 1 auto;
  display: block;
  /* A tall artwork at a uniform row height makes a narrow column; without a
     floor, the meta row below it wraps one word per line. */
  min-width: 260px;
  transition: transform .25s;
}
/* width: max-content so the frame is exactly as wide as the image it holds.
   Left to fill the card, a long title widens the card and the frame paints a
   grey slab out to the right of the artwork. */
.sn-store-card__frame { overflow: hidden; width: max-content; max-width: 100%; }
.sn-store-card__frame img {
  display: block;
  height: var(--store-row-h);
  width: auto;
  max-width: 100%;
  object-fit: contain;
  /* Placeholder fill lives on the image, not the frame, so it can never
     extend past the artwork's own edges. */
  background: var(--bg-soft, oklch(0.96 0.003 250));
  transition: transform .6s cubic-bezier(.2,.8,.2,1);
}
/* CRITICAL:end */

/* --------------------------------------------------------------------------
   Display type — reuses .sn-display from the main site (size/weight/tracking
   identical); kept here under a store name only so the store can ship alone.
   -------------------------------------------------------------------------- */
.sn-store-display {
  margin: 0;
  font-weight: 400;
  font-size: clamp(40px, 6vw, 88px);
  letter-spacing: -0.025em;
  line-height: 1.02;
  text-wrap: pretty;
}
.sn-store-display--sm { font-size: clamp(40px, 4.4vw, 64px); }
.sn-store-display em { font-style: normal; color: var(--accent, oklch(0.56 0.205 25)); }

.sn-store-rule { border: 0; border-top: var(--store-hairline); margin: 0; }

/* hero ---------------------------------------------------------------- */
.sn-store-hero { padding-top: 32px; }
.sn-store-hero img {
  display: block;
  width: 100%;
  height: clamp(320px, 44vw, 620px);
  object-fit: cover;
  background: var(--bg-soft, oklch(0.96 0.003 250));
}
.sn-store-hero__rule { margin-top: 16px; border-top: var(--store-hairline); }

/* filter + sort bar ---------------------------------------------------- */
.sn-store-controls {
  margin-top: 56px;
  border-top: var(--store-hairline);
  border-bottom: var(--store-hairline);
  padding: 14px 0;
  display: flex;
  flex-wrap: wrap;
  gap: 20px 40px;
  align-items: center;
  justify-content: space-between;
}
.sn-store-controls__set { display: flex; flex-wrap: wrap; gap: 20px; align-items: center; }
.sn-store-controls a { color: var(--ink-2, oklch(0.43 0.018 256)); }
.sn-store-controls a[aria-current="true"] {
  color: var(--ink, oklch(0.205 0.022 256));
  border-bottom: 0.5px solid var(--ink, oklch(0.205 0.022 256));
  padding-bottom: 3px;
}

/* artwork card --------------------------------------------------------- */
.sn-store-card:hover { transform: translateY(-3px); }
.sn-store-card:hover .sn-store-card__frame img { transform: scale(1.03); }
.sn-store-card__meta {
  margin-top: 14px;
  padding-top: 12px;
  border-top: var(--store-hairline);
  display: flex;
  flex-wrap: wrap;
  gap: 4px 16px;
  align-items: baseline;
  /* Takes the card's width without contributing to it: otherwise the card is
     sized by the longest title rather than by the artwork, and a wordy title
     stretches its column across the grid. */
  width: 0;
  min-width: 100%;
}
.sn-store-card__title {
  flex: 1 1 auto;
  /* Matches .sn-grid-client on the main site. The delivered 700 is a real
     bold against a design language that gets its emphasis from size. */
  font-size: 17px;
  font-weight: 500;
  letter-spacing: -0.005em;
  text-transform: none;
  color: var(--ink, oklch(0.205 0.022 256));
  font-family: "PT Sans", Helvetica, Arial, sans-serif;
}
.sn-store-card__price { color: var(--ink, oklch(0.205 0.022 256)); text-align: right; }
.sn-store-card--unavailable .sn-store-card__price { color: var(--ink-3, oklch(0.64 0.014 256)); }

.sn-store-count {
  margin-top: 80px;
  border-top: var(--store-hairline);
  padding-top: 14px;
  display: flex;
  flex-wrap: wrap;
  gap: 12px 24px;
  justify-content: space-between;
}

/* artwork detail ------------------------------------------------------- */
.sn-store-crumb { padding: 14px 0; border-bottom: var(--store-hairline); }
.sn-store-crumb a { color: var(--ink-2, oklch(0.43 0.018 256)); }

.sn-store-detail {
  display: grid;
  grid-template-columns: minmax(0, 1.15fr) minmax(0, 1fr);
  gap: 64px 80px;
  padding: 64px 0 var(--store-gap);
  align-items: start;
}
.sn-store-detail__figure { margin: 0; display: flex; flex-direction: column; gap: 14px; }
.sn-store-detail__figure img {
  display: block;
  /* Both axes capped, neither forced. width:100% with a max-height made the
     box taller than a tall painting's own shape, and object-fit painted the
     leftover as grey slabs down either side — the same defect the catalogue
     cards had. Letting the image size itself means there is no leftover. */
  width: auto;
  max-width: 100%;
  height: auto;
  max-height: 820px;
  background: var(--bg-soft, oklch(0.96 0.003 250));
}

.sn-store-detail__body { display: flex; flex-direction: column; max-width: 52ch; }
/* With every photograph stacked, the column beside them can run several
   screens long, and the price and the buy button would scroll away with the
   first image. Sticky only where there is room to sit: below 1100px the grid
   is one column and the body is above the photographs anyway. */
@media (min-width: 1101px) {
  .sn-store-detail__body {
    position: sticky;
    top: calc(var(--store-nav-h) + 24px);
  }
}
.sn-store-detail__title { margin-top: 16px; }

/* spec list ------------------------------------------------------------ */
.sn-store-spec { margin: 40px 0 0; border-top: var(--store-hairline); }
.sn-store-spec > div {
  display: grid;
  grid-template-columns: 120px 1fr;
  gap: 16px;
  padding: 12px 0;
  border-bottom: var(--store-hairline);
}
.sn-store-spec dt { color: var(--ink-3, oklch(0.64 0.014 256)); }
.sn-store-spec dd { margin: 0; color: var(--ink-2, oklch(0.43 0.018 256)); }

/* editorial paragraph — the store is the first consumer of the serif on this
   site: site-2026.css declares --font-serif at :21 and never uses it, and
   there is no .sn-serif class to reuse. */
.sn-store-note {
  margin: 36px 0 0;
  font-family: Newsreader, Georgia, "Times New Roman", serif;
  font-weight: 300;
  font-size: 21px;
  line-height: 1.55;
  color: var(--ink-2, oklch(0.43 0.018 256));
}
.sn-store-note--sm { font-size: 19px; }

/* price + CTA ---------------------------------------------------------- */
.sn-store-buy {
  margin-top: 44px;
  border-top: var(--store-hairline);
  padding-top: 24px;
  display: flex;
  flex-wrap: wrap;
  gap: 24px 32px;
  align-items: center;
  justify-content: space-between;
}
.sn-store-price { display: flex; flex-direction: column; gap: 6px; }
.sn-store-price__value {
  font-family: "IBM Plex Mono", ui-monospace, monospace;
  font-size: 22px;
  letter-spacing: .02em;
  font-variant-numeric: tabular-nums;
  color: var(--ink, oklch(0.205 0.022 256));
}
.sn-store-cta {
  display: inline-block;
  border: 0;
  cursor: pointer;
  background: var(--ink, oklch(0.205 0.022 256));
  color: var(--bg, oklch(0.985 0.002 250));
  padding: 14px 22px;
  border-radius: 999px;
  font-family: "IBM Plex Mono", ui-monospace, monospace;
  font-size: 11px;
  letter-spacing: .1em;
  text-transform: uppercase;
  transition: background .25s;
}
/* `.sn-store-body a { color: inherit }` is (0,1,1) and beats a bare
   `.sn-store-cta` at (0,1,0), so the anchor form of the CTA rendered dark
   ink on the dark ink pill — an invisible button. Match the anchor
   explicitly so both the <button> and <a> forms are legible. */
.sn-store-body a.sn-store-cta { color: var(--bg, oklch(0.985 0.002 250)); }
.sn-store-cta:hover,
.sn-store-body a.sn-store-cta:hover {
  background: var(--accent, oklch(0.56 0.205 25));
  color: var(--bg, oklch(0.985 0.002 250));
}
.sn-store-link {
  color: var(--ink-2, oklch(0.43 0.018 256));
  border-bottom: var(--store-hairline);
  padding-bottom: 3px;
  align-self: flex-start;
}

/* status: sold / reserved — text, never colour alone -------------------- */
.sn-store-status {
  margin-top: 36px;
  border-top: var(--store-hairline);
  border-bottom: var(--store-hairline);
  padding: 20px 0;
  display: flex;
  flex-direction: column;
  gap: 10px;
}
.sn-store-status__fact { color: var(--ink, oklch(0.205 0.022 256)); }
.sn-store-status__note { font-size: 17px; line-height: 1.6; color: var(--ink-2, oklch(0.43 0.018 256)); }
.sn-store-actions { margin-top: 40px; display: flex; flex-wrap: wrap; gap: 20px 28px; align-items: center; }

/* shipping / returns --------------------------------------------------- */
.sn-store-terms {
  margin-top: 40px;
  border-top: var(--store-hairline);
  padding-top: 20px;
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
  gap: 28px;
}
.sn-store-terms div { display: flex; flex-direction: column; gap: 8px; }
.sn-store-terms p { margin: 0; font-size: 15px; line-height: 1.6; color: var(--ink-2, oklch(0.43 0.018 256)); }

/* checkout ------------------------------------------------------------- */
.sn-store-checkout { max-width: 900px; margin: 0 auto; padding: var(--store-gap) var(--store-pad); }
.sn-store-order {
  margin-top: 56px;
  border-top: var(--store-hairline);
  padding-top: 24px;
  display: flex;
  flex-wrap: wrap;
  gap: 28px;
  align-items: flex-start;
}
.sn-store-order img { display: block; width: 160px; height: auto; background: var(--bg-soft, oklch(0.96 0.003 250)); }
.sn-store-order__body { flex: 1 1 260px; display: flex; flex-direction: column; gap: 8px; }
.sn-store-order__title { font-size: 24px; line-height: 1.2; }

.sn-store-totals { margin-top: 40px; }
.sn-store-totals > div {
  display: flex;
  justify-content: space-between;
  gap: 24px;
  padding: 12px 0;
  border-top: var(--store-hairline);
}
.sn-store-totals dt { color: var(--ink-3, oklch(0.64 0.014 256)); }
.sn-store-totals dd { margin: 0; color: var(--ink-2, oklch(0.43 0.018 256)); }
.sn-store-totals__sum { padding: 18px 0; border-bottom: var(--store-hairline); align-items: baseline; }
.sn-store-totals__sum dt { color: var(--ink, oklch(0.205 0.022 256)); }
.sn-store-totals__sum dd { font-size: 22px; color: var(--ink, oklch(0.205 0.022 256)); }

.sn-store-ship {
  margin-top: 36px;
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
  gap: 28px;
}
.sn-store-ship div { display: flex; flex-direction: column; gap: 8px; }
.sn-store-ship p { margin: 0; font-size: 15px; line-height: 1.6; color: var(--ink-2, oklch(0.43 0.018 256)); }
.sn-store-submit {
  margin-top: 48px;
  border-top: var(--store-hairline);
  padding-top: 28px;
  display: flex;
  flex-wrap: wrap;
  gap: 20px 28px;
  align-items: center;
}

/* cross-back band + footer --------------------------------------------- */
.sn-store-cross {
  border-top: var(--store-hairline);
  border-bottom: var(--store-hairline);
  padding: 28px 0;
  display: flex;
  flex-wrap: wrap;
  gap: 20px 32px;
  align-items: baseline;
  justify-content: space-between;
}
.sn-store-cross p {
  margin: 0;
  font-family: Newsreader, Georgia, serif;
  font-weight: 300;
  font-size: 24px;
  line-height: 1.4;
  color: var(--ink-2, oklch(0.43 0.018 256));
  max-width: 40ch;
}
.sn-store-cross a { border-bottom: 0.5px solid var(--ink, oklch(0.205 0.022 256)); padding-bottom: 3px; }

.sn-store-footer {
  margin-top: var(--store-gap);
  border-top: var(--store-hairline);
  background: var(--bg-soft, oklch(0.96 0.003 250));
}
.sn-store-footer__inner {
  max-width: var(--store-max);
  margin: 0 auto;
  padding: 64px var(--store-pad);
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
  gap: 48px 40px;
  align-items: start;
}
.sn-store-footer__mark { display: flex; flex-direction: column; gap: 18px; }
.sn-store-footer__mark img { display: block; width: 202px; height: 39px; }
.sn-store-footer__col { display: flex; flex-direction: column; gap: 10px; }
.sn-store-footer__col a { color: var(--ink-2, oklch(0.43 0.018 256)); }
.sn-store-footer__col > span { color: var(--ink-3, oklch(0.64 0.014 256)); }
.sn-store-footer__about { display: flex; flex-direction: column; gap: 14px; }
/* Newsletter signup. Light ground here, unlike the main site's ink footer,
   so it takes the store's own ink tokens rather than inverted ones. */
.sn-store-news {
  display: flex;
  flex-wrap: wrap;
  gap: 12px 16px;
  align-items: baseline;
}
.sn-store-news label {
  flex: 1 0 100%;
  color: var(--ink-3, oklch(0.64 0.014 256));
}
.sn-store-news input {
  flex: 1 1 160px;
  min-width: 0;
  font: inherit;
  text-transform: none;
  letter-spacing: normal;
  color: var(--ink, oklch(0.205 0.022 256));
  background: transparent;
  border: 0;
  border-bottom: var(--store-hairline);
  border-radius: 0;
  padding: 6px 0;
}
.sn-store-news input:focus {
  outline: none;
  border-bottom-color: var(--ink, oklch(0.205 0.022 256));
}
.sn-store-news__privacy {
  margin: 0;
  font-size: 11px;
  line-height: 1.5;
  text-transform: none;
  letter-spacing: normal;
  color: var(--ink-3, oklch(0.64 0.014 256));
}

/* visually hidden, still announced */
.sn-store-vh {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  border: 0;
  overflow: hidden;
  clip: rect(0 0 0 0);
  clip-path: inset(50%);
  white-space: nowrap;
}

.sn-store-skip {
  position: absolute;
  left: -9999px;
}
.sn-store-skip:focus {
  left: var(--store-pad);
  top: 8px;
  z-index: 40;
  background: var(--ink, oklch(0.205 0.022 256));
  color: var(--bg, oklch(0.985 0.002 250));
  padding: 10px 16px;
  border-radius: 999px;
}

/* --------------------------------------------------------------------------
   1100px — detail collapses to one column, catalogue rows get shorter
   -------------------------------------------------------------------------- */
@media (max-width: 1100px) {
  :root { --store-row-h: 280px; --store-gap: 72px; }
  .sn-store-detail { grid-template-columns: 1fr; gap: 48px; }
  .sn-store-detail__body { max-width: 60ch; }
  .sn-store-grid { gap: 48px 32px; }
}

/* --------------------------------------------------------------------------
   680px — nav stacks to two rows, spec list narrows
   -------------------------------------------------------------------------- */
@media (max-width: 680px) {
  :root { --store-row-h: 220px; --store-pad: 24px; --store-gap: 56px; }
  .sn-store-nav__inner {
    grid-template-columns: 1fr auto;
    padding-top: 14px;
    padding-bottom: 14px;
    gap: 12px 20px;
  }
  /* Back to one row. The second row existed to fit three things across a
     phone; with the cross-link gone there are two, and they sit either side
     of it. */
  .sn-store-nav__links { grid-column: 2; justify-self: end; gap: 20px; flex-wrap: wrap; }
  /* Hidden, not removed: it is a real link between two hosts and a crawler
     should keep finding it. On a phone it pushed the nav into a second row
     for a route the footer already offers. */
  .sn-store-nav__cross { display: none; }
  .sn-store-spec > div { grid-template-columns: 110px 1fr; gap: 12px; }
  .sn-store-display { font-size: clamp(34px, 9vw, 56px); }
}

/* --------------------------------------------------------------------------
   600px — single-column catalogue, full-width images
   -------------------------------------------------------------------------- */
@media (max-width: 600px) {
  :root { --store-pad: 20px; }
  .sn-store-grid { flex-direction: column; align-items: stretch; gap: 40px; }
  /* The frame is width:max-content on wide screens so it hugs the artwork.
     Left that way here, the img's width:100% resolves against the image's
     own intrinsic width — a 2000px painting made the whole page 2000px wide
     and every phone scrolled sideways. */
  .sn-store-card { min-width: 0; }
  .sn-store-card__frame { width: 100%; }
  /* Several photographs swipe sideways rather than stacking: four paintings
     down a phone is four screens of scrolling before the price. Snap so a
     swipe lands on a photograph rather than between two, and let the next
     one peek — a full-width slide gives no sign there is anything beside
     it. No script: a gallery that needs one can half-work. */
  .sn-store-detail__figure--scroll {
    flex-direction: row;
    flex-wrap: nowrap;
    overflow-x: auto;
    overscroll-behavior-x: contain;
    scroll-snap-type: x mandatory;
    -webkit-overflow-scrolling: touch;
    scrollbar-width: none;
  }
  .sn-store-detail__figure--scroll::-webkit-scrollbar { display: none; }
  /* Tops aligned, not centres: stretched slides centred each photograph on
     a common axis, so four works started at four different heights. */
  .sn-store-detail__figure--scroll {
    align-items: flex-start;
  }
  .sn-store-detail__figure--scroll > .sn-store-shot {
    flex: 0 0 86%;
    scroll-snap-align: center;
  }
  /* Sized by the photograph, capped on both axes. Forcing width:100% here
     put a tall work in a box wider than itself and object-fit painted the
     remainder grey — the same slabs removed from the stacked view. */
  .sn-store-detail__figure--scroll img {
    width: auto;
    max-width: 100%;
    max-height: 62vh;
    margin: 0 auto;
  }

  /* Capped so no single work is taller than the screen it is scanned on.
     The desktop grid gives every piece the same row height and lets width
     vary; this is that idea on a phone, where the axes swap. Width follows,
     so the shape is still the artwork's own. */
  .sn-store-card__frame img {
    width: auto;
    max-width: 100%;
    height: auto;
    max-height: 78vh;
  }
  .sn-store-card__meta { flex-wrap: wrap; gap: 6px 16px; }
  .sn-store-card__title { flex: 1 0 100%; order: -1; }
  .sn-store-card__price { text-align: left; }
  .sn-store-buy, .sn-store-cross { gap: 20px; }
  .sn-store-order img { width: 120px; }
  /* Edge to edge. The page is padded, so the hero pulls back out of that
     padding by exactly the same amount rather than assuming a width —
     100vw would overflow anywhere a scrollbar takes room. Nothing above it
     either: it sits straight under the nav. */
  .sn-store-hero {
    padding-top: 0;
    margin-left: calc(var(--store-pad) * -1);
    margin-right: calc(var(--store-pad) * -1);
  }
  /* Its own shape, not a 260px letterbox. cover on a narrow screen threw
     away the sides of a wide photograph — of the four works on that wall you
     saw the middle two. Capped so a portrait hero cannot eat the screen
     before the catalogue starts. */
  .sn-store-hero img { height: auto; max-height: 70vh; object-fit: contain; }
  /* The hairline sits on the image, not a stripe below it. */
  .sn-store-hero__rule { margin-top: 0; }
}

@media (prefers-reduced-motion: reduce) {
  .sn-store-card, .sn-store-card__frame img, .sn-store-cta { transition: none; }
  .sn-store-card:hover { transform: none; }
  .sn-store-card:hover .sn-store-card__frame img { transform: none; }
}

/* waitlist form — the same hairline field treatment as the contact page */
.sn-store-notify {
  display: flex;
  flex-wrap: wrap;
  gap: 12px 16px;
  align-items: baseline;
  margin-top: 16px;
}
.sn-store-notify label {
  flex: 1 0 100%;
}
.sn-store-notify input {
  flex: 1 1 200px;
  font: inherit;
  color: var(--ink, oklch(0.205 0.022 256));
  background: transparent;
  border: 0;
  border-bottom: var(--store-hairline);
  padding: 8px 0;
  border-radius: 0;
}
.sn-store-notify input:focus {
  outline: none;
  border-bottom-color: var(--ink, oklch(0.205 0.022 256));
}

/* ─────── quantity ─────── */
.sn-store-qty {
  display: flex;
  align-items: baseline;
  gap: 12px;
  margin-bottom: 16px;
}
.sn-store-qty select {
  font: inherit;
  color: var(--ink, oklch(0.205 0.022 256));
  background: transparent;
  border: 0;
  border-bottom: var(--store-hairline);
  border-radius: 0;
  padding: 6px 4px 6px 0;
}
.sn-store-qty select:focus {
  outline: none;
  border-bottom-color: var(--ink, oklch(0.205 0.022 256));
}

/* ─────── full-size viewer ─────── */
/* The button is a wrapper, not a control with a look of its own: the
   photograph is the affordance. */
.sn-store-shot {
  display: block;
  padding: 0;
  border: 0;
  background: none;
  cursor: zoom-in;
  width: 100%;
  text-align: left;
}
.sn-store-shot:focus-visible {
  outline: 2px solid var(--accent, oklch(0.56 0.205 25));
  outline-offset: 3px;
}

.sn-store-lb {
  border: 0;
  padding: 0;
  max-width: 100vw;
  max-height: 100vh;
  width: 100vw;
  height: 100vh;
  background: var(--bg, oklch(0.985 0.002 250));
  color: var(--ink, oklch(0.205 0.022 256));
  /* Centres the photograph and leaves real space around it. Filling the
     dialog with the image left nowhere to click to dismiss — the image was
     the whole surface. */
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: zoom-out;
}
.sn-store-lb:not([open]) { display: none; }
.sn-store-lb::backdrop {
  background: oklch(0.205 0.022 256 / 0.92);
}
.sn-store-lb__img {
  display: block;
  /* Fits whole: a zoom that crops is not a zoom. */
  max-width: calc(100vw - 96px);
  max-height: calc(100vh - 112px);
  width: auto;
  height: auto;
  object-fit: contain;
  cursor: default;
}
.sn-store-lb__close {
  position: absolute;
  top: 20px;
  right: 24px;
  z-index: 2;
  border: 0;
  background: none;
  color: var(--ink-2, oklch(0.43 0.018 256));
  cursor: pointer;
  padding: 8px;
}
.sn-store-lb__nav {
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
  z-index: 2;
  border: 0;
  background: none;
  color: var(--ink-2, oklch(0.43 0.018 256));
  /* Big enough to hit on a phone without aiming. */
  font-size: 40px;
  line-height: 1;
  padding: 16px 20px;
  cursor: pointer;
}
.sn-store-lb__nav--prev { left: 4px; }
.sn-store-lb__nav--next { right: 4px; }
.sn-store-lb__nav:hover,
.sn-store-lb__close:hover { color: var(--ink, oklch(0.205 0.022 256)); }
.sn-store-lb__count {
  position: absolute;
  bottom: 20px;
  left: 0;
  right: 0;
  margin: 0;
  text-align: center;
}
@media (max-width: 600px) {
  .sn-store-lb__img { max-width: calc(100vw - 32px); max-height: calc(100vh - 128px); }
  /* 44px is the floor for a target a thumb has to find without aiming; the
     glyph alone measured 39 wide. */
  .sn-store-lb__nav { font-size: 32px; padding: 12px 16px; min-width: 48px; }
}
