/* Colors are split by ROLE, not by name, so dark mode is a token swap rather
   than a rewrite. --forest is a green *surface* (buttons, header, sell band);
   --accent is green *text* on a light surface. They're the same value in light
   mode and deliberately different in dark, where green text has to lift off a
   dark background instead of sitting on cream. */
:root {
  color-scheme: light dark;

  --page: #FFFFFF;        /* page + card surface */
  --band: #F7F4EB;        /* alternating section band */
  --forest: #0F3C1F;      /* green surface: primary button, header, sell */
  --forest-dark: #0A2814;
  --forest-light: #1B5230;
  --accent: #0F3C1F;      /* green text/border on a light surface */
  --on-dark: #FFFFFF;     /* text sitting on a green surface */
  --text-dark: #16281C;
  --text-muted: #4A5750;
  --border: #DCD6C4;
  --field: #FFFFFF;    /* form input surface */

  --cream: #F7F4EB;       /* kept: referenced by the Shopify theme CSS */
  --cream-white: #FFFFFF;

  --font-display: 'Oswald', sans-serif;
  --font-body: 'Inter', sans-serif;
}

/* Dark mode follows the phone's own setting — including iOS's sunset schedule,
   so "dark after dark" comes free without us guessing at a cutoff hour.
   Guarded with :not([data-theme="light"]) so the manual toggle can win. */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --page: #0D1B12;
    --band: #12261A;
    --forest: #1E5C36;    /* lifted, or a primary button vanishes into the page */
    --forest-dark: #0A2814;
    --forest-light: #2A6E45;
    --accent: #7FBF95;    /* green text has to be light here, not dark */
    --on-dark: #FFFFFF;
    --text-dark: #E7EDE8;
    --text-muted: #A0B0A6;
    --border: #27402F;
    --field: #162C1E;
  }
}

/* Explicit choice from the toggle beats the OS setting in both directions. */
:root[data-theme="dark"] {
  --page: #0D1B12;
  --band: #12261A;
  --forest: #1E5C36;
  --forest-dark: #0A2814;
  --forest-light: #2A6E45;
  --accent: #7FBF95;
  --on-dark: #FFFFFF;
  --text-dark: #E7EDE8;
  --text-muted: #A0B0A6;
  --border: #27402F;
  --field: #162C1E;
}

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

html { scroll-behavior: smooth; }

/* The header is sticky, so an anchor jump lands with the section heading hidden
   behind it. Offset every linkable section by roughly the header's height. */
section[id] { scroll-margin-top: 86px; }

body {
  font-family: var(--font-body);
  color: var(--text-dark);
  background: var(--page);
  line-height: 1.6;
}

.container {
  max-width: 1140px;
  margin: 0 auto;
  padding: 0 24px;
}

h1, h2, h3 {
  font-family: var(--font-display);
  text-transform: uppercase;
  letter-spacing: 0.02em;
  color: var(--accent);
}

a { color: inherit; text-decoration: none; }

.section-title {
  font-size: 2rem;
  text-align: center;
  margin-bottom: 8px;
}

.section-sub {
  text-align: center;
  color: var(--text-muted);
  max-width: 560px;
  margin: 0 auto 40px;
}

/* Buttons */
.btn {
  display: inline-block;
  padding: 14px 32px;
  font-family: var(--font-display);
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  border-radius: 4px;
  border: 2px solid transparent;
  cursor: pointer;
  transition: all 0.2s ease;
  font-size: 0.9rem;
}

.btn-primary {
  background: var(--forest);
  color: var(--on-dark);
}
.btn-primary:hover { background: var(--forest-dark); }

.btn-outline {
  background: transparent;
  border-color: var(--accent);
  color: var(--accent);
}
.btn-outline:hover { background: var(--forest); color: var(--on-dark); }

.btn-small { padding: 10px 20px; font-size: 0.8rem; }

/* Header */
.site-header {
  position: sticky;
  top: 0;
  background: var(--page);
  border-bottom: 1px solid var(--border);
  z-index: 100;
}

.header-inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding-top: 10px;
  padding-bottom: 10px;
}

.brand-logo { height: 52px; display: block; }

.main-nav {
  display: flex;
  gap: 32px;
}

.main-nav a {
  font-family: var(--font-display);
  font-weight: 500;
  text-transform: uppercase;
  font-size: 0.85rem;
  letter-spacing: 0.04em;
  color: var(--accent);
}
.main-nav a:hover { color: var(--forest-light); }

.nav-toggle {
  display: none;
  flex-direction: column;
  justify-content: center;
  gap: 5px;
  background: none;
  border: none;
  cursor: pointer;
  padding: 8px;
}
.nav-toggle span {
  width: 24px;
  height: 2px;
  background: var(--forest);
}

/* Hero */
.hero {
  background: var(--band);
  text-align: center;
  padding: 72px 0 88px;
  border-bottom: 1px solid var(--border);
}

.hero-logo {
  width: 180px;
  margin-bottom: 8px;
}

.hero h1 {
  font-size: 2.75rem;
  margin-bottom: 12px;
}

.hero-tagline {
  font-family: var(--font-display);
  font-size: 1.1rem;
  color: var(--accent);
  text-transform: uppercase;
  letter-spacing: 0.05em;
  margin-bottom: 32px;
}

.hero-buttons {
  display: flex;
  gap: 16px;
  justify-content: center;
  flex-wrap: wrap;
}

/* Categories */
.categories { padding: 80px 0; }

.category-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 32px;
  margin-top: 40px;
}

.category-card {
  text-align: center;
  padding: 32px 20px;
  border: 1px solid var(--border);
  border-radius: 8px;
  background: var(--band);
}

.category-icon { font-size: 2.5rem; margin-bottom: 12px; }

.category-card h3 { font-size: 1.15rem; margin-bottom: 8px; }

.category-card p { color: var(--text-muted); font-size: 0.92rem; }

/* Shop */
.shop { padding: 80px 0; background: var(--band); }

.product-grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 24px;
}

.product-card {
  background: var(--page);
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 20px;
  text-align: center;
}

.product-image-wrap {
  position: relative;
  margin-bottom: 16px;
}

/* Card photos vary slightly in aspect ratio, and a graded slab shot is never
   worth cropping. A fixed-ratio box plus object-fit: contain gives every card
   an identical footprint in the grid while showing the whole card. */
.product-image {
  width: 100%;
  aspect-ratio: 3 / 4;
  height: auto;
  object-fit: contain;
  border-radius: 6px;
  display: block;
  background: var(--band);
}

/* Recently sold — kept on the page briefly as social proof */
.product-card--sold .product-image {
  filter: grayscale(0.75);
  opacity: 0.55;
}

.sold-badge {
  position: absolute;
  top: 10px;
  left: 10px;
  background: var(--forest);
  color: var(--on-dark);
  font-family: var(--font-display);
  font-size: 0.75rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  padding: 5px 12px;
  border-radius: 3px;
}

.btn-sold {
  background: transparent;
  border-color: var(--border);
  color: var(--text-muted);
  cursor: default;
}

/* Coming Soon — cards not yet listed, offers only */
.coming-soon-section {
  padding: 80px 0;
  background: var(--page);
  border-top: 1px solid var(--border);
}

/* Personal Collection: a card away at PSA. Driven by an "At PSA" tag on the
   Shopify product, so it goes on and comes off without touching this file. */
.pc-note {
  margin: 2px 0 0;
  font-size: 0.78rem;
  font-style: italic;
  color: var(--text-muted);
}
.pc-note::before {
  content: "\2022\00a0";
  font-style: normal;
}

.soon-badge {
  position: absolute;
  top: 10px;
  left: 10px;
  background: var(--page);
  color: var(--accent);
  border: 1px solid var(--accent);
  font-family: var(--font-display);
  font-size: 0.7rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  padding: 5px 12px;
  border-radius: 3px;
}

.product-card--sold h3,
.product-card--sold .product-price {
  opacity: 0.6;
}

.product-card h3 {
  font-family: var(--font-body);
  text-transform: none;
  font-size: 0.9rem;
  font-weight: 600;
  color: var(--text-dark);
  margin-bottom: 8px;
  letter-spacing: normal;
  min-height: 2.7em;
}

/* No price on these, so give the title the extra line instead.
   Must sit after .product-card h3 — same specificity, later wins. */
.product-card--soon h3 { min-height: 3.4em; margin-bottom: 16px; }

.product-price {
  font-family: var(--font-display);
  font-size: 1.2rem;
  color: var(--accent);
  margin-bottom: 16px;
  display: flex;
  align-items: baseline;
  flex-wrap: wrap;
  gap: 8px;
}

/* The eBay list price, struck through. The point of the whole discount is that
   the shopper can SEE the site is cheaper, so this has to sit next to the price
   they pay rather than surface only at checkout. */
.product-price__was {
  font-family: var(--font-body);
  font-size: 0.85rem;
  font-weight: 400;
  color: var(--text-muted);
  text-decoration: line-through;
}

/* Green pill, white text. Both tokens are redefined per theme, so this stays
   legible in dark mode without a second rule. */
.product-price__off {
  font-family: var(--font-body);
  font-size: 0.7rem;
  font-weight: 700;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--on-dark);
  background: var(--forest);
  border-radius: 999px;
  padding: 2px 8px;
  white-space: nowrap;
}

.product-card--sold .product-price__was,
.product-card--sold .product-price__off {
  opacity: 0.6;
}

.product-actions {
  display: flex;
  gap: 10px;
  justify-content: center;
  flex-wrap: wrap;
}

.share-btn {
  cursor: pointer;
  min-width: 90px;
}

.grid-status {
  grid-column: 1 / -1;
  text-align: center;
  color: var(--text-muted);
}

.shop-cta { text-align: center; margin-top: 40px; }

.shop-note {
  max-width: 620px;
  margin: 32px auto 0;
  padding-top: 24px;
  border-top: 1px solid var(--border);
  text-align: center;
  font-size: 0.88rem;
  color: var(--text-muted);
  line-height: 1.7;
}

.shop-note strong { color: var(--text-dark); }

.shop-note a {
  color: var(--accent);
  text-decoration: underline;
}

/* Sell to us */
.sell { padding: 80px 0; background: var(--forest); color: var(--on-dark); }

.sell-inner {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 48px;
  align-items: center;
}

.sell-text h2 { color: var(--on-dark); text-align: left; margin-bottom: 16px; }
.sell-text p { margin-bottom: 16px; color: #D9E4DC; }
.sell-list {
  margin: 0 0 20px 0;
  padding-left: 20px;
  color: #D9E4DC;
}
.sell-list li { margin-bottom: 6px; }
.sell-text .btn-primary { background: var(--page); color: var(--accent); }
.sell-text .btn-primary:hover { background: var(--band); }

.sell-image {
  width: 100%;
  border-radius: 8px;
  box-shadow: 0 12px 32px rgba(0,0,0,0.3);
}

/* Contact */
.contact { padding: 80px 0; }

.contact-grid {
  display: grid;
  grid-template-columns: 1.3fr 1fr;
  gap: 56px;
  margin-top: 40px;
}

.contact-form { display: flex; flex-direction: column; }

.contact-form label {
  font-family: var(--font-display);
  font-size: 0.8rem;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--accent);
  margin-top: 16px;
  margin-bottom: 6px;
}

.contact-form input,
.contact-form textarea {
  background: var(--field);
  color: var(--text-dark);
  border: 1px solid var(--border);
  border-radius: 4px;
  padding: 12px 14px;
  font-family: var(--font-body);
  font-size: 0.95rem;
  resize: vertical;
}
.contact-form input:focus,
.contact-form textarea:focus {
  outline: none;
  border-color: var(--accent);
}

.contact-form input::placeholder,
.contact-form textarea::placeholder { color: var(--text-muted); }

.contact-form button { margin-top: 24px; align-self: flex-start; }

.form-status { margin-top: 12px; font-size: 0.9rem; color: var(--accent); }

.contact-info p { margin-bottom: 8px; color: var(--text-muted); }
.contact-info a:hover { color: var(--accent); }

.social-links {
  display: flex;
  gap: 16px;
  margin-top: 20px;
}
.social-links a { color: var(--accent); }
.social-links a:hover { color: var(--forest-light); }

/* Legal / policy pages */
.legal { padding: 64px 0 80px; }

.legal-inner {
  max-width: 760px;
}

.legal h1 {
  font-size: 2rem;
  margin-bottom: 8px;
}

.legal-updated {
  color: var(--text-muted);
  font-size: 0.9rem;
  margin-bottom: 32px;
}

.legal h2 {
  font-size: 1.15rem;
  margin-top: 36px;
  margin-bottom: 12px;
}

.legal p { margin-bottom: 16px; }

.legal ul {
  margin: 0 0 16px 0;
  padding-left: 22px;
}

.legal li { margin-bottom: 8px; }

.legal a {
  color: var(--accent);
  text-decoration: underline;
}
.legal a:hover { color: var(--forest-light); }

/* Footer */
.site-footer {
  background: var(--forest-dark);
  color: #B8C6BC;
  padding: 32px 0;
}

.footer-inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 16px;
}

.footer-logo { height: 36px; filter: brightness(0) invert(1); opacity: 0.9; }

.footer-inner p { font-size: 0.85rem; }

.footer-links {
  display: flex;
  gap: 24px;
}

.footer-links a {
  font-family: var(--font-display);
  text-transform: uppercase;
  font-size: 0.8rem;
  letter-spacing: 0.04em;
  color: #B8C6BC;
}
.footer-links a:hover { color: var(--on-dark); }

/* Responsive */
@media (max-width: 860px) {
  .main-nav { display: none; }
  .nav-toggle { display: flex; }
  .main-nav.open {
    display: flex;
    flex-direction: column;
    position: absolute;
    top: 100%;
    left: 0;
    right: 0;
    background: var(--page);
    border-bottom: 1px solid var(--border);
    padding: 16px 24px;
    gap: 16px;
  }
  .category-grid { grid-template-columns: 1fr; }
  .product-grid { grid-template-columns: repeat(2, 1fr); }
  .sell-inner { grid-template-columns: 1fr; }
  .sell-image { order: -1; }
  .contact-grid { grid-template-columns: 1fr; }
  .hero h1 { font-size: 2.1rem; }
  .footer-inner { justify-content: center; text-align: center; }
}

@media (max-width: 480px) {
  .product-grid { grid-template-columns: 1fr; }
}

/* Inventory search page */
.inventory { padding: 56px 0 80px; }

.search-wrap {
  position: relative;
  max-width: 620px;
  margin: 0 auto 20px;
}

.search-input {
  width: 100%;
  padding: 16px 44px 16px 18px;
  font-family: var(--font-body);
  font-size: 1rem;
  border: 2px solid var(--border);
  border-radius: 6px;
  background: var(--field);
  color: var(--text-dark);
}
.search-input::placeholder { color: var(--text-muted); }
.search-input:focus { outline: none; border-color: var(--accent); }
.search-input:disabled { opacity: 0.6; }

.search-clear {
  position: absolute;
  right: 10px;
  top: 50%;
  transform: translateY(-50%);
  background: none;
  border: none;
  font-size: 1.6rem;
  line-height: 1;
  color: var(--text-muted);
  cursor: pointer;
  padding: 0 6px;
}
.search-clear:hover { color: var(--accent); }

.quick-filters {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  justify-content: center;
  margin-bottom: 20px;
}

.chip {
  font-family: var(--font-display);
  font-size: 0.78rem;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  padding: 7px 14px;
  border: 1px solid var(--border);
  border-radius: 999px;
  background: var(--page);
  color: var(--accent);
  cursor: pointer;
  transition: all 0.15s ease;
}
.chip:hover { border-color: var(--accent); }
.chip--on { background: var(--forest); color: var(--on-dark); border-color: var(--accent); }

.inv-count {
  text-align: center;
  color: var(--text-muted);
  font-size: 0.88rem;
  margin-bottom: 24px;
}

.main-nav a.is-current { color: var(--forest-light); text-decoration: underline; }

.load-more-wrap { text-align: center; margin-top: 32px; }

/* Local pickup band */
.local-band {
  background: var(--forest);
  color: var(--on-dark);
  padding: 28px 0;
}

.local-inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 28px;
  flex-wrap: wrap;
}

.local-text { flex: 1 1 460px; }

.local-text h2 {
  color: var(--on-dark);
  font-size: 1.4rem;
  margin-bottom: 6px;
  text-align: left;
}

.local-text p {
  color: #D9E4DC;
  font-size: 0.94rem;
  max-width: 620px;
}

.btn-local {
  background: var(--page);
  color: var(--accent);
  white-space: nowrap;
}
.btn-local:hover { background: var(--band); }

@media (max-width: 700px) {
  .local-inner { justify-content: center; text-align: center; }
  .local-text h2 { text-align: center; }
}

.local-note { font-size: 0.9rem; color: var(--accent); font-weight: 500; }

.inv-bar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  flex-wrap: wrap;
  margin-bottom: 24px;
}

.inv-bar .inv-count { margin-bottom: 0; }

.sort-label {
  font-family: var(--font-display);
  font-size: 0.78rem;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--text-muted);
  display: flex;
  align-items: center;
  gap: 8px;
}

.sort-select {
  font-family: var(--font-body);
  font-size: 0.88rem;
  padding: 8px 10px;
  border: 1px solid var(--border);
  border-radius: 4px;
  background: var(--field);
  color: var(--text-dark);
  cursor: pointer;
}
.sort-select:focus { outline: none; border-color: var(--accent); }

/* Photo viewer */
.photo-btn {
  display: block;
  width: 100%;
  padding: 0;
  border: none;
  background: none;
  cursor: zoom-in;
  position: relative;
}

.photo-count {
  position: absolute;
  bottom: 8px;
  right: 8px;
  background: rgba(15, 60, 31, 0.85);
  color: var(--on-dark);
  font-family: var(--font-display);
  font-size: 0.68rem;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  padding: 3px 8px;
  border-radius: 3px;
}

.lightbox {
  position: fixed;
  inset: 0;
  z-index: 200;
  background: rgba(10, 40, 20, 0.94);
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  padding: 20px;
}
.lightbox[hidden] { display: none; }

.lb-stage {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 14px;
  max-width: 900px;
  max-height: 100%;
}

.lb-stage img {
  max-width: 100%;
  max-height: 74vh;
  object-fit: contain;
  border-radius: 6px;
  background: var(--band);
}

.lb-stage figcaption {
  display: flex;
  align-items: center;
  gap: 16px;
  flex-wrap: wrap;
  justify-content: center;
  color: var(--on-dark);
  font-size: 0.92rem;
  text-align: center;
}

.lb-counter {
  font-family: var(--font-display);
  letter-spacing: 0.06em;
  color: #B8C6BC;
}

.lb-nav, .lb-close {
  background: rgba(255,255,255,0.12);
  border: none;
  color: var(--on-dark);
  cursor: pointer;
  border-radius: 50%;
  line-height: 1;
  transition: background 0.15s ease;
}
.lb-nav:hover, .lb-close:hover { background: rgba(255,255,255,0.25); }

.lb-nav {
  width: 52px;
  height: 52px;
  font-size: 2rem;
  flex-shrink: 0;
}

.lb-close {
  position: absolute;
  top: 16px;
  right: 20px;
  width: 42px;
  height: 42px;
  font-size: 1.6rem;
}

@media (max-width: 640px) {
  .lb-nav { width: 42px; height: 42px; font-size: 1.6rem; }
  .lb-stage img { max-height: 62vh; }
}

/* The wordmark is a single dark green with a transparent interior, so on a dark
   page it flattens into an outline. Same fix the footer already uses on its
   forest band: knock it to white. */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .brand-logo,
  :root:not([data-theme="light"]) .hero-logo {
    filter: brightness(0) invert(1);
    opacity: 0.92;
  }
}
:root[data-theme="dark"] .brand-logo,
:root[data-theme="dark"] .hero-logo {
  filter: brightness(0) invert(1);
  opacity: 0.92;
}

/* --- Motion -----------------------------------------------------------------
   Four small things, all tied to something the page is actually doing: cards
   respond to a cursor, images catch light the way a refractor does, and the
   grid settles in rather than snapping. Everything here is switched off wholesale
   for prefers-reduced-motion at the bottom of this block. */

/* A card is a link target, so it should react to a cursor. */
.product-card {
  transition: transform 0.22s ease, box-shadow 0.22s ease, border-color 0.22s ease;
  will-change: transform;
}

.product-card:hover {
  transform: translateY(-4px);
  border-color: var(--forest);
  box-shadow: 0 10px 24px -12px rgba(15, 60, 31, 0.45);
}

/* Sold cards are history, not offers — they shouldn't invite a click. */
.product-card--sold:hover {
  transform: none;
  border-color: var(--border);
  box-shadow: none;
}

/* Hovering a card turns it over, the way you would in your hands. The back is
   the product's second Shopify image — HeyStack uploads front then back, so it
   is reliably the right one. Cards without a second image just don't flip;
   .has-back is only set when there is something to turn to. */
/* Perspective goes in the transform itself rather than on an ancestor. The
   perspective property only reaches an element's DIRECT children, and there is
   a wrapper in between — a button on the inventory page, a link on the home
   page. Putting it here means the flip does not depend on that structure. */
.card-flip {
  display: block;
  position: relative;
  transform-style: preserve-3d;
  transform: perspective(1100px) rotateY(0deg);
  transition: transform 0.65s cubic-bezier(0.2, 0.7, 0.3, 1);
}

/* Hover is a mouse idea. Gating it means a phone — where a tap counts as a
   hover and focus lands on the link — cannot get stuck showing the back. */
@media (hover: hover) {
  .has-back:hover .card-flip,
  .has-back:focus-within .card-flip {
    transform: perspective(1100px) rotateY(180deg);
  }
}

/* On touch the tap does the turning instead, set from main.js. Same transform,
   so the card turns identically on a phone and on a desk. */
.has-back.is-flipped .card-flip {
  transform: perspective(1100px) rotateY(180deg);
}

/* Nothing on a phone says a card has a back to see, so a small corner mark
   says it. It goes once the card is turned — by then you know. */
@media (hover: none) {
  .product-image-wrap.has-back::after {
    content: "⤾";
    position: absolute;
    right: 8px;
    bottom: 8px;
    z-index: 2;
    width: 26px;
    height: 26px;
    display: grid;
    place-items: center;
    border-radius: 50%;
    font-size: 0.95rem;
    line-height: 1;
    color: #fff;
    background: rgba(15, 60, 31, 0.55);
    pointer-events: none;
    transition: opacity 0.25s ease;
  }

  .product-image-wrap.has-back.is-flipped::after { opacity: 0; }
}

.card-face {
  display: block;
  width: 100%;
  backface-visibility: hidden;
  -webkit-backface-visibility: hidden;
  border-radius: 6px;
}

/* The back is stacked on the front and pre-rotated, so the halves meet edge-on
   halfway through the turn. */
.card-face--back {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: contain;
  background: var(--band);
  transform: rotateY(180deg);
}

/* Both of these have to stay readable through the turn, so they sit outside the
   flipping element rather than on a face. */
.sold-badge { z-index: 3; }

/* The grid settles in instead of snapping. Short, and only the first dozen are
   staggered — past that the delay would read as the page being slow. */
@keyframes dtp-rise {
  from { opacity: 0; transform: translateY(10px); }
  to   { opacity: 1; transform: none; }
}

.product-card {
  animation: dtp-rise 0.4s ease both;
}

.product-card:nth-child(1)  { animation-delay: 0.00s; }
.product-card:nth-child(2)  { animation-delay: 0.04s; }
.product-card:nth-child(3)  { animation-delay: 0.08s; }
.product-card:nth-child(4)  { animation-delay: 0.12s; }
.product-card:nth-child(5)  { animation-delay: 0.16s; }
.product-card:nth-child(6)  { animation-delay: 0.20s; }
.product-card:nth-child(7)  { animation-delay: 0.24s; }
.product-card:nth-child(8)  { animation-delay: 0.28s; }
.product-card:nth-child(9)  { animation-delay: 0.32s; }
.product-card:nth-child(10) { animation-delay: 0.36s; }
.product-card:nth-child(11) { animation-delay: 0.40s; }
.product-card:nth-child(12) { animation-delay: 0.44s; }

/* Buttons already transition; give the filter chips the same courtesy. */
.chip { transition: background 0.15s ease, color 0.15s ease, border-color 0.15s ease; }

/* Someone who has asked their OS for less motion gets none of it. The layout is
   identical either way — only the movement goes. */
@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.001ms !important;
    scroll-behavior: auto !important;
  }

  .product-card:hover { transform: none; }
  .has-back:hover .card-flip,
  .has-back:focus-within .card-flip { transform: perspective(1100px) rotateY(0deg); }
}

/* --- Loading placeholders ---------------------------------------------------
   The grid used to sit empty behind the words "Loading inventory" while 151
   products came down the wire, which reads as broken rather than busy. These
   are card-shaped so the layout does not jump when the real ones land.
   render() replaces the whole grid, so they need no cleanup. */
.skeleton-card {
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 20px;
}

.sk-img,
.sk-line {
  border-radius: 6px;
  background: linear-gradient(90deg, var(--band) 25%, var(--border) 50%, var(--band) 75%);
  background-size: 200% 100%;
  animation: sk-sweep 1.4s ease-in-out infinite;
}

.sk-img { aspect-ratio: 3 / 4; margin-bottom: 16px; }
.sk-line { height: 13px; margin: 0 auto 9px; width: 85%; }
.sk-line--short { width: 45%; }

@keyframes sk-sweep {
  from { background-position: 200% 0; }
  to   { background-position: -200% 0; }
}

/* --- Lightbox ---------------------------------------------------------------
   It used to appear instantly, which is jarring at full-screen size. */
.lightbox {
  animation: lb-in 0.2s ease both;
}

.lightbox .lb-stage {
  animation: lb-rise 0.26s cubic-bezier(0.2, 0.7, 0.3, 1) both;
}

@keyframes lb-in   { from { opacity: 0; } to { opacity: 1; } }
@keyframes lb-rise { from { opacity: 0; transform: scale(0.96); } to { opacity: 1; transform: none; } }

/* --- Section reveal ---------------------------------------------------------
   Homepage sections settle in as they come into view. Added by js/main.js only
   once IntersectionObserver is confirmed available, so without JS every section
   is simply visible — never hidden with no way back. */
.reveal {
  opacity: 0;
  transform: translateY(18px);
  transition: opacity 0.55s ease, transform 0.55s cubic-bezier(0.2, 0.7, 0.3, 1);
}

.reveal.is-in { opacity: 1; transform: none; }

@media (prefers-reduced-motion: reduce) {
  .sk-img, .sk-line { animation: none; }
  .reveal { opacity: 1; transform: none; transition: none; }
}

/* Static intro on the inventory page. It is there for people arriving cold from
   a search as much as for the crawler — the card grid means nothing without
   knowing whose shop it is. */
.inv-intro {
  max-width: 68ch;
  margin: 14px auto 0;
  font-size: 0.92rem;
  line-height: 1.6;
  color: var(--text-muted);
  text-align: center;
}

.inv-intro a { color: var(--accent); text-decoration: underline; }

/* --- Sell-to-us form --------------------------------------------------------
   This replaced a mailto button. A card buyer is worth a few dollars of margin;
   someone handing over a collection is worth hundreds, so this is the one path
   on the site that justifies the friction of a real form. */
.sell-form { margin-top: 18px; }

/* This form sits on the forest band, so its labels take the on-dark colour.
   They were inheriting the light-surface value and rendering near-black on
   dark green. */
.sell-form label {
  display: block;
  margin-bottom: 12px;
  font-family: var(--font-display);
  font-size: 0.82rem;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--on-dark);
}

.sell-optional {
  font-family: var(--font-body);
  font-size: 0.75rem;
  letter-spacing: 0;
  text-transform: none;
  color: #B9CDC0;
  margin-left: 6px;
}

.sell-form input[type="text"],
.sell-form input[type="email"],
.sell-form input[type="tel"],
.sell-form textarea {
  display: block;
  width: 100%;
  margin-top: 5px;
  padding: 10px 12px;
  font-family: var(--font-body);
  font-size: 0.95rem;
  text-transform: none;
  letter-spacing: 0;
  color: var(--text-dark);
  background: var(--field);
  border: 1px solid var(--border);
  border-radius: 6px;
}

.sell-form textarea { resize: vertical; }

.sell-form input:focus-visible,
.sell-form textarea:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 1px;
}

/* Two across on a desktop, stacked on a phone — nothing here is worth
   squeezing side by side on a narrow screen. */
.sell-row { display: grid; grid-template-columns: 1fr 1fr; gap: 0 14px; }
@media (max-width: 560px) { .sell-row { grid-template-columns: 1fr; } }

/* The default control is an unstyled OS button that looks nothing like the
   rest of the page. Style the ::file-selector-button rather than hiding the
   input, so keyboard and screen-reader behaviour stays intact. */
.sell-form input[type="file"] {
  display: block;
  width: 100%;
  margin-top: 6px;
  padding: 8px;
  font-family: var(--font-body);
  font-size: 0.85rem;
  text-transform: none;
  letter-spacing: 0;
  color: #D9E4DC;
  background: rgba(255, 255, 255, 0.08);
  border: 1px dashed rgba(255, 255, 255, 0.4);
  border-radius: 6px;
}

.sell-form input[type="file"]::file-selector-button {
  margin-right: 12px;
  padding: 7px 14px;
  font-family: var(--font-display);
  font-size: 0.8rem;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--forest);
  background: var(--on-dark);
  border: 0;
  border-radius: 5px;
  cursor: pointer;
}

.sell-file-list {
  list-style: none;
  margin: 0 0 14px;
  padding: 0;
  font-size: 0.85rem;
}

.sell-file-list li {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  padding: 6px 10px;
  margin-bottom: 5px;
  background: rgba(255, 255, 255, 0.1);
  border-radius: 5px;
}

.sell-file-list span {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.sell-file-list button {
  flex: none;
  background: none;
  border: 0;
  font-size: 1.15rem;
  line-height: 1;
  color: #B9CDC0;
  cursor: pointer;
}

.sell-file-list button:hover { color: var(--on-dark); }

/* Off-screen rather than display:none — some bots skip hidden fields, and the
   point is for them to fill it in. */
.sell-hp {
  position: absolute;
  left: -9999px;
  width: 1px;
  height: 1px;
  overflow: hidden;
}

.sell-status {
  margin-top: 12px;
  font-size: 0.9rem;
  color: #D9E4DC;
}

.sell-status--ok    { color: #FFFFFF; font-weight: 600; }
.sell-status--error { color: #FFB4AB; }

.sell-alt {
  margin-top: 14px;
  font-size: 0.85rem;
  color: #B9CDC0;
}

.sell-alt a { color: var(--on-dark); text-decoration: underline; }

@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .sell-status--error { color: #F2B8B5; }
}
:root[data-theme="dark"] .sell-status--error { color: #F2B8B5; }

/* The Formspree contact form was removed — the sell form above it does the same
   job and does it better. What remains is the address, the local-delivery note
   and the social links, so the grid collapses to a single centred column
   instead of leaving an empty half. */
.contact-grid--solo {
  grid-template-columns: 1fr;
  max-width: 46rem;
  margin-inline: auto;
  text-align: center;
}

.contact-grid--solo .social-links { justify-content: center; }

/* --- Copy a card title ------------------------------------------------------
   Grid titles are not links, so a click copies them. Checking comps means
   pasting an exact title into eBay or 130point, and hand-selecting 60
   characters is the fiddliest part of that.

   It is a real <button> rather than a click handler on the <h3> so it is
   reachable by keyboard and announced as interactive, but it inherits the
   heading's type so nothing looks like a control until you go near it. */
.copy-title {
  font: inherit;
  color: inherit;
  text-align: inherit;
  letter-spacing: inherit;
  text-transform: inherit;
  background: none;
  border: 0;
  padding: 2px 4px;
  margin: -2px -4px;
  border-radius: 4px;
  cursor: pointer;
  position: relative;
  transition: background 0.15s ease;
}

.copy-title:hover,
.copy-title:focus-visible { background: var(--band); }

/* A quiet copy glyph, only once you are on it — a permanent icon next to every
   title in a 24-card grid would be noise. */
.copy-title::after {
  content: "⧉";
  margin-left: 6px;
  opacity: 0;
  font-size: 0.85em;
  transition: opacity 0.15s ease;
}

.copy-title:hover::after,
.copy-title:focus-visible::after { opacity: 0.55; }

.copy-title--done { background: var(--band); }

.copy-title--done::after {
  content: "Copied";
  opacity: 1;
  margin-left: 8px;
  font-family: var(--font-body);
  font-size: 0.7rem;
  letter-spacing: 0.03em;
  text-transform: none;
  color: var(--accent);
}

@media (prefers-reduced-motion: reduce) {
  .copy-title, .copy-title::after { transition: none; }
}

/* The lightbox caption sits on a near-black green, where the grid's cream hover
   and dark-green "Copied" would both disappear. Same control, inverted. */
.lb-stage .copy-title:hover,
.lb-stage .copy-title:focus-visible { background: rgba(255, 255, 255, 0.14); }

.lb-stage .copy-title--done { background: rgba(255, 255, 255, 0.14); }

.lb-stage .copy-title--done::after { color: #FFFFFF; }

/* --- Away / shipping delay notice -------------------------------------------
   Sits above the promo bar and reads as information rather than marketing, so
   it takes a warm neutral instead of the forest green. Not dismissible: a buyer
   who closes it and then waits four days for a card has been poorly served. */
.away-bar {
  background: #F4E9CE;
  color: #4A3B1A;
  border-bottom: 1px solid #E3D3AC;
}

.away-inner {
  padding-top: 9px;
  padding-bottom: 9px;
  text-align: center;
}

.away-text {
  margin: 0;
  font-size: 0.88rem;
  line-height: 1.45;
}

.away-text strong { font-family: var(--font-display); letter-spacing: 0.01em; }

@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .away-bar {
    background: #3A3020;
    color: #F0E4C8;
    border-bottom-color: #4E4128;
  }
}
:root[data-theme="dark"] .away-bar {
  background: #3A3020;
  color: #F0E4C8;
  border-bottom-color: #4E4128;
}

@media (max-width: 640px) { .away-text { font-size: 0.82rem; } }
