/* Typography.
   Inter / Roboto / system-ui defaults are the single most-cited "this was
   generated" tell, so they are deliberately not first here. Prices, codes,
   counts and IDs are set in mono - this is a shop selling redemption codes,
   so the monospace reads as domain-appropriate rather than decorative.

   To go further, self-host a real display face and point --font-display at it:
     @font-face { font-family: "YourFace"; src: url("assets/yourface.woff2") format("woff2"); font-display: swap; }
   That is the one change that most cleanly breaks the default look. */
:root {
  --font-body: ui-sans-serif, "Segoe UI Variable Text", "Segoe UI", Ubuntu, Cantarell, "Noto Sans", sans-serif;
  --font-display: ui-sans-serif, "Segoe UI Variable Display", "Segoe UI Semibold", Ubuntu, Cantarell, sans-serif;
  --font-mono: ui-monospace, SFMono-Regular, "Cascadia Mono", "Liberation Mono", Menlo, monospace;

  /* Monochrome. The only colour on the site is the payment marks, which is
     the point: nothing competes with them. Depth comes from layered greys and
     a faint white glow, not hue. */
  --bg: #0d0e10;
  --bg-alt: #121316;
  --panel: #18191c;
  --panel-solid: #18191c;
  --panel-2: #222327;
  --line: #2b2d31;
  --line-strong: #414349;
  --text: #f2f2f3;
  --muted: #aaaab0;
  --dim: #7d7e85;
  --accent: #ffffff;
  --accent-hover: #e4e4e4;
  --accent-soft: rgba(255, 255, 255, 0.08);
  --moon: #ffffff;
  --green: #d8d8d8;
  --star: #ffffff;
  --danger: #ff6b6b;
  --radius: 10px;
  --radius-sm: 6px;
  --maxw: 1160px;
  /* Page gutter. Narrowed at the phone breakpoints near the end of this file -
     24px each side costs a seventh of a 360px screen. */
  --gutter: 24px;
  /* Smallest square a finger can hit reliably. Applied to controls under
     @media (pointer: coarse) only, so the desktop layout keeps its tighter
     icon buttons and chips. */
  --tap: 44px;
  --shadow: 0 24px 60px rgba(0, 0, 0, 0.7);
  --glow: 0 0 24px -6px rgba(255, 255, 255, .28);
}

* { box-sizing: border-box; }
html {
  scroll-behavior: smooth;
  /* The header is sticky at 64px, so an in-page jump (#buy, #faq, the legal
     TOC) would otherwise land with its heading tucked underneath it. Set on
     <html> so it covers every anchor on the site rather than the handful that
     carry their own scroll-margin. */
  scroll-padding-top: 84px;
  /* iOS inflates body text when a page is rotated to landscape, which on this
     layout pushes the hero copy out of its own box. Opt out; the type is
     already sized in relative-friendly units. */
  -webkit-text-size-adjust: 100%;
  text-size-adjust: 100%;
}

body {
  margin: 0;
  background: var(--bg);
  color: var(--text);
  font-family: var(--font-body);
  font-size: 15px;
  line-height: 1.62;
  -webkit-font-smoothing: antialiased;
  overflow-x: hidden;
  /* Default is a translucent grey-blue flash on every tap, which on a black
     site reads as a rendering fault. The :active and .is-active states below
     are what should signal a press. */
  -webkit-tap-highlight-color: transparent;
}

/* No page-wide radial "atmosphere" glow. A flat ground with real contrast
   reads as a shop; layered coloured haze reads as a generated landing page. */
body > * { position: relative; z-index: 1; }

a { color: inherit; text-decoration: none; }
img { max-width: 100%; display: block; }
button { font: inherit; cursor: pointer; }
::selection { background: rgba(255,255,255,.3); }
:focus-visible { outline: 2px solid var(--text); outline-offset: 3px; }
.skip-link { position: fixed; z-index: 1000; left: 14px; top: 14px; padding: 10px 14px; border-radius: var(--radius-sm); background: var(--accent); color: #000; transform: translateY(-160%); }
.skip-link:focus { transform: translateY(0); }

/* The gutter is a variable so the phone breakpoints can narrow it in one place
   instead of restating the padding on .wrap, .hero-inner and .home-section
   separately - all three read from it.

   env(safe-area-inset-*) is what keeps content clear of the rounded corners
   and the camera cutout when a notched phone is held in landscape, where the
   inset is applied to the side rather than the top. max() rather than a plain
   sum: on every device with no inset the value resolves to 0 and the gutter
   stays exactly --gutter. */
.wrap {
  width: 100%;
  max-width: var(--maxw);
  margin: 0 auto;
  padding-left: max(var(--gutter), env(safe-area-inset-left));
  padding-right: max(var(--gutter), env(safe-area-inset-right));
}

/* ---------- announcement ---------- */
.announce {
  background: #17181b;
  color: #fff;
  font-size: 12.5px;
  font-weight: 500;
}
.announce .wrap {
  display: flex;
  justify-content: space-between;
  gap: 16px;
  padding-top: 9px;
  padding-bottom: 9px;
}
.announce span:last-child { color: rgba(255, 255, 255, .82); }

/* ---------- header ---------- */
.site-header {
  position: sticky;
  top: 0;
  z-index: 40;
  background: rgba(13, 14, 16, .86);
  backdrop-filter: blur(10px);
  border-bottom: 1px solid var(--line);
}
.site-header .wrap { display: flex; align-items: center; gap: 24px; height: 64px; }

.brand {
  font-family: var(--font-display);
  display: inline-flex;
  align-items: center;
  gap: 9px;
  font-size: 17px;
  font-weight: 700;
  letter-spacing: -0.025em;
  margin-right: auto;
}
.brand .mark {
  width: 26px;
  height: 26px;
  border-radius: 7px;
  /* A hairline, not the old white glow. The logo tile is near-black, and a
     white halo around a dark square reads as a rendering fault; a 1px edge is
     what actually separates it from the near-black header. */
  box-shadow: inset 0 0 0 1px rgba(255, 255, 255, .10);
  display: grid;
  place-items: center;
  overflow: hidden;   /* the artwork's own corners are square; the radius clips them */
}
.brand .mark img { display: block; width: 100%; height: 100%; object-fit: cover; }

.nav { display: flex; gap: 4px; font-size: 14px; }
.nav a {
  color: var(--muted);
  padding: 7px 13px;
  border-radius: 8px;
  transition: color .15s, background .15s;
}
.nav a:hover { color: var(--text); background: var(--panel-2); }
.nav a.active { color: var(--text); background: var(--panel-2); box-shadow: inset 0 0 0 1px var(--line-strong); }

.header-actions { display: flex; align-items: center; gap: 8px; }
.icon-btn {
  width: 35px; height: 35px;
  display: grid; place-items: center;
  border: 0;
  border-radius: 10px;
  background: transparent;
  color: var(--muted);
  transition: background .15s, color .15s;
}
.icon-btn:hover { background: var(--panel-2); color: var(--text); }
.btn-login {
  border: 1px solid var(--line-strong);
  background: transparent;
  color: var(--text);
  padding: 7px 16px;
  border-radius: 10px;
  font-size: 14px;
  transition: background .15s, border-color .15s;
}
.btn-login:hover { background: var(--panel-2); }
.btn-login.is-active { border-color: rgba(255,255,255,.45); background: var(--accent-soft); }
.cart-btn { position: relative; }
.cart-count {
  position: absolute;
  top: -1px; right: -1px;
  min-width: 17px; height: 17px;
  padding: 0 4px;
  border-radius: 999px;
  background: var(--accent);
  color: #000;
  font-size: 10px;
  font-weight: 700;
  display: grid;
  place-items: center;
  box-shadow: 0 0 0 2px var(--bg);
}
.cart-count[hidden] { display: none; }

/* ---------- buttons ---------- */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 9px;
  padding: 12px 22px;
  border-radius: var(--radius-sm);
  border: 1px solid transparent;
  font-size: 14.5px;
  font-weight: 600;
  letter-spacing: -0.01em;
  transition: background .16s, border-color .16s, transform .16s, box-shadow .16s;
}
.btn:active { transform: translateY(1px); }
.btn:disabled { opacity: .4; box-shadow: none; cursor: default; transform: none; }
.btn-primary { background: var(--accent); color: #000; box-shadow: var(--glow); }
.btn-primary:hover:not(:disabled) { background: var(--accent-hover); box-shadow: 0 0 30px -4px rgba(255,255,255,.4); }
.btn-ghost { border-color: var(--line-strong); color: var(--text); background: var(--panel); }
.btn-ghost:hover:not(:disabled) { background: var(--panel-2); border-color: rgba(255,255,255,.24); }
.btn-block { width: 100%; }
.btn-lg { padding: 14px 26px; font-size: 15px; }

/* ---------- chips (catalog filters, rating filters) ---------- */
.chips { display: flex; gap: 6px; flex-wrap: wrap; }
.chip {
  padding: 6px 13px;
  border: 1px solid var(--line);
  border-radius: 999px;
  background: var(--panel);
  color: var(--muted);
  font-size: 12.5px;
  white-space: nowrap;
  transition: color .15s, border-color .15s, background .15s;
}
.chip:hover { color: var(--text); border-color: var(--line-strong); }
.chip.is-active { background: var(--accent); border-color: transparent; color: #000; font-weight: 600; }

/* ---------- pill tab group (segmented control) ---------- */
.pill-tabs {
  display: inline-flex;
  gap: 4px;
  flex-wrap: wrap;
  justify-content: center;
  padding: 4px;
  border: 1px solid var(--line);
  border-radius: 999px;
  background: var(--panel);
}
.pill-tab {
  padding: 7px 16px;
  border: 0;
  border-radius: 999px;
  background: none;
  color: var(--muted);
  font-size: 13px;
  font-weight: 500;
  transition: color .15s, background .15s;
}
.pill-tab:hover { color: var(--text); }
.pill-tab.is-active { background: var(--accent); color: #000; font-weight: 600; }

/* ---------- hero ---------- */


.pill {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 6px 14px 6px 8px;
  border-radius: 999px;
  border: 1px solid var(--line-strong);
  background: var(--panel);
  font-size: 12.5px;
  color: var(--muted);
  margin-bottom: 22px;
}
.pill b { color: var(--text); font-weight: 600; }
.pill .dot {
  width: 7px; height: 7px;
  border-radius: 50%;
  background: var(--green);
  box-shadow: 0 0 0 3px rgba(255,255,255,.16);
}

h1 {
  font-family: var(--font-display);
  font-size: clamp(32px, 4.6vw, 46px);
  line-height: 1.04;
  letter-spacing: -0.04em;
  margin: 0 0 20px;
  font-weight: 700;
}

.hero p.lede {
  color: var(--muted);
  font-size: 17px;
  max-width: 540px;
  margin: 0 auto 32px;
}
.hero-cta { display: flex; gap: 12px; justify-content: center; flex-wrap: wrap; }

.hero-stats {
  display: flex;
  justify-content: center;
  gap: 0;
  margin-top: 46px;
  flex-wrap: wrap;
}
.hero-stats div {
  padding: 0 34px;
  border-right: 1px solid var(--line);
  text-align: center;
}
.hero-stats div:last-child { border-right: 0; }
.hero-stats b { display: block; font-size: 24px; letter-spacing: -0.03em; }
.hero-stats span { font-size: 11px; letter-spacing: .13em; text-transform: uppercase; color: var(--dim); }

.trust {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 16px;
  flex-wrap: wrap;
  padding: 34px 0 0;
  font-size: 12.5px;
  color: var(--dim);
}
.pay-chip {
  padding: 3px 8px;
  border-radius: 5px;
  display: inline-grid;
  place-items: center;
  font-size: 10px;
  font-weight: 800;
  letter-spacing: .04em;
  color: #0b1120;
}

/* ---------- sections ---------- */
section { padding: 74px 0; }
.section-head { text-align: center; margin-bottom: 42px; }
.section-head h2 {
  font-size: clamp(27px, 3.6vw, 38px);
  letter-spacing: -0.035em;
  margin: 0 0 10px;
  font-weight: 700;
  line-height: 1.15;
}
.section-head p { color: var(--muted); margin: 0; }
.kicker {
  display: inline-block;
  font-size: 11.5px;
  letter-spacing: .16em;
  text-transform: uppercase;
  color: var(--accent-hover);
  font-weight: 600;
  margin-bottom: 12px;
}

.surface {
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: var(--radius);
}

/* ---------- product grid ---------- */
.grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(250px, 1fr)); gap: 20px; }
.card {
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  overflow: hidden;
  transition: transform .18s, border-color .18s, box-shadow .18s;
}
.card:hover { border-color: var(--accent); }
.card-media {
  aspect-ratio: 1 / 1;
  display: grid;
  place-items: center;
  padding: 22px;
  position: relative;
  background:
    #0f0f0f;
}
.card-media img { transition: transform .25s ease; filter: drop-shadow(0 14px 26px rgba(0,0,0,.5)); }
.card:hover .card-media img { transform: translateY(-4px) scale(1.03); }
.badge {
  position: absolute;
  top: 11px; left: 11px;
  background: var(--accent);
  color: #000;
  font-size: 10px;
  font-weight: 700;
  letter-spacing: .07em;
  padding: 4px 9px;
  border-radius: 6px;
}
.card-body { padding: 15px 16px 17px; }
.card-title { font-size: 15px; font-weight: 600; margin: 0 0 8px; letter-spacing: -0.01em; }
.card-meta { display: flex; justify-content: space-between; align-items: center; margin-bottom: 13px; }
.stock-pill {
  font-size: 11.5px;
  color: var(--green);
  background: rgba(255,255,255,.06);
  border: 1px solid rgba(255,255,255,.18);
  padding: 2px 9px;
  border-radius: 999px;
}
.price { font-size: 17px; font-weight: 700; letter-spacing: -0.02em; }
.price .was { font-size: 12.5px; color: var(--dim); text-decoration: line-through; margin-left: 7px; font-weight: 500; }

/* ---------- features ---------- */
.features { display: grid; grid-template-columns: repeat(auto-fit, minmax(230px, 1fr)); gap: 18px; }
.feature {
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 24px 22px;
  transition: border-color .18s, transform .18s;
}
.feature:hover { border-color: var(--line-strong); }
.feature .ico {
  width: 36px; height: 36px;
  border-radius: 11px;
  background: var(--accent-soft);
  border: 1px solid rgba(255,255,255,.26);
  color: var(--text);
  display: grid; place-items: center;
  margin-bottom: 16px;
}
.feature h3 { margin: 0 0 7px; font-size: 15px; font-weight: 600; }
.feature p { margin: 0; color: var(--muted); font-size: 13.5px; }

/* ---------- stats band ---------- */
/* auto-fit, not repeat(3): the band renders only the figures it can actually
   count, so it can legitimately hold one or two cells rather than three. */
.stats {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--panel);
  overflow: hidden;
}
.stat { padding: 30px 20px; text-align: center; border-right: 1px solid var(--line); }
.stat:last-child { border-right: 0; }
.stat b { display: block; font-size: 32px; letter-spacing: -0.035em; line-height: 1.1; }
.stat span { color: var(--muted); font-size: 13px; }

/* ---------- reviews ---------- */
.review-head {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: 16px;
  flex-wrap: wrap;
  margin-bottom: 24px;
}
.review-head h2 { margin: 0; font-size: clamp(25px, 3.2vw, 32px); letter-spacing: -0.035em; }
.rating-line { display: flex; align-items: center; gap: 9px; font-size: 13px; color: var(--muted); }
.stars { color: var(--star); letter-spacing: 1.5px; }
.reviews { display: grid; grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); gap: 14px; }

/* Card is a flex column with the body set to flex:1, so the product strip sits
   on the bottom edge of every card in a row regardless of how long the review
   is - a grid row of ragged footers is what makes a wall of these look untidy. */
.review {
  display: flex;
  flex-direction: column;
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  overflow: hidden;
  transition: border-color .18s;
}
.review:hover { border-color: var(--line-strong); }
.review .top {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 13px 14px 0;
  font-size: 11.5px;
  color: var(--dim);
}
.review .rv-date { margin-left: auto; white-space: nowrap; }
.verified {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  color: var(--green);
  font-weight: 500;
}
.review p { flex: 1; margin: 0; padding: 9px 14px 13px; font-size: 13.5px; }
.review .who {
  display: flex;
  align-items: center;
  gap: 9px;
  padding: 9px 14px;
  border-top: 1px solid var(--line);
  background: var(--bg-alt);
  font-size: 11.5px;
  color: var(--dim);
}
.avatar {
  width: 22px; height: 22px;
  border-radius: 50%;
  background: #2a2a2a;
  display: grid; place-items: center;
  font-size: 10px; font-weight: 700; color: #061024;
  flex: none;
}

/* ---------- faq ---------- */
.faq { max-width: 730px; margin: 0 auto; display: grid; gap: 11px; }
details.q {
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  padding: 15px 19px;
  transition: border-color .18s, background .18s;
}
details.q:hover { border-color: var(--line-strong); }
details.q[open] { background: var(--panel-2); border-color: rgba(255,255,255,.28); }
details.q summary {
  list-style: none;
  cursor: pointer;
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 12px;
  font-size: 14.5px;
  font-weight: 500;
}
details.q summary::-webkit-details-marker { display: none; }
details.q summary::after { content: "+"; color: var(--muted); font-size: 19px; line-height: 1; }
details.q[open] summary::after { content: "\2013"; color: var(--accent-hover); }
details.q p { margin: 11px 0 2px; color: var(--muted); font-size: 13.5px; }

/* ---------- about / join ---------- */
.about {
  max-width: 640px;
  margin: 0 auto;
  text-align: center;
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 38px 32px;
}
.about h2 { font-family: var(--font-display); margin: 0 0 12px; font-size: 28px; letter-spacing: -0.035em; }
.about h2 span { color: var(--dim); }
.about p { color: var(--muted); margin: 0 0 22px; font-size: 14.5px; }
.about .row { display: flex; gap: 10px; justify-content: center; flex-wrap: wrap; }

.join {
  position: relative;
  overflow: hidden;
  background: #101010;
  border-radius: var(--radius);
  padding: 32px 34px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 22px;
  flex-wrap: wrap;
}

.join > * { position: relative; }
.join h3 { margin: 0 0 6px; font-size: 21px; letter-spacing: -0.025em; }
.join p { margin: 0; color: rgba(255,255,255,.86); font-size: 13.5px; max-width: 450px; }
.join .btn { background: #fff; color: #12244d; }
.join .btn:hover { background: #e9efff; }

/* ---------- footer ---------- */
.site-footer {
  border-top: 1px solid var(--line);
  background: var(--bg-alt);
  margin-top: 56px;
  padding: 44px 0 22px;
}
.foot-top {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  gap: 40px;
  padding-bottom: 32px;
}
.foot-brand { max-width: 330px; }
.foot-brand .brand { font-size: 16px; margin-bottom: 12px; }
.foot-brand p { color: var(--muted); font-size: 13.5px; margin: 0; }

.foot-links { display: flex; gap: 56px; }
.foot-links h4 {
  margin: 0 0 13px;
  font-size: 11px;
  font-weight: 600;
  letter-spacing: .13em;
  text-transform: uppercase;
  color: var(--dim);
}
.foot-links a {
  display: block;
  margin-bottom: 9px;
  color: var(--muted);
  font-size: 13.5px;
  transition: color .15s;
}
.foot-links a:hover { color: var(--text); }

.foot-bottom {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 22px;
  flex-wrap: wrap;
  padding-top: 20px;
  border-top: 1px solid var(--line);
}
.foot-pay { display: flex; align-items: center; gap: 9px; }
.foot-pay > span:first-child {
  font-size: 11px;
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--dim);
  margin-right: 3px;
}
.coin-mark { width: 24px; height: 24px; display: block; opacity: .92; transition: opacity .15s, transform .15s; }
.coin-mark:hover { opacity: 1; transform: translateY(-1px); }
.coin-mark svg { width: 100%; height: 100%; display: block; }

.foot-legal {
  display: flex;
  gap: 18px;
  flex-wrap: wrap;
  color: var(--dim);
  font-size: 12px;
  margin-left: auto;
}

/* ---------- product page ---------- */
.crumbs { display: flex; align-items: center; gap: 9px; color: var(--dim); font-size: 13px; padding: 28px 0 6px; }
.crumbs a:hover { color: var(--text); }
.crumbs .sep { opacity: .45; }
.crumbs .now { color: var(--text); }

.product-title { font-size: clamp(30px, 4.6vw, 46px); letter-spacing: -0.04em; margin: 14px 0 8px; font-weight: 700; }
.product-sub { color: var(--muted); margin: 0 0 30px; display: flex; align-items: center; gap: 12px; flex-wrap: wrap; font-size: 13.5px; }
.product { display: grid; grid-template-columns: minmax(0, 1.5fr) minmax(0, 1fr); gap: 36px; align-items: start; }

.gallery { border: 1px solid var(--line); border-radius: var(--radius); overflow: hidden; }
.gallery .main {
  aspect-ratio: 4 / 3;
  display: grid;
  place-items: center;
  padding: 30px;
  background: #0f0f0f;
}
.gallery .main img { filter: drop-shadow(0 26px 44px rgba(0,0,0,.55)); }
/* Only drawn when a product has more than one photo, so a single-image product
   keeps the plain framed shot it has always had. Scrolls sideways rather than
   wrapping: a second row would push the buy box down the page on mobile. */
.thumbs {
  display: flex; gap: 10px; padding: 12px;
  border-top: 1px solid var(--line); background: var(--panel);
  overflow-x: auto;
  scrollbar-width: thin;
}
.thumb {
  width: 64px; height: 64px;
  flex: 0 0 auto;
  border-radius: 10px;
  border: 1px solid var(--line);
  background: #0f0f0f;
  display: grid; place-items: center;
  padding: 8px;
  cursor: pointer;
  transition: border-color .15s;
}
.thumb img { max-width: 100%; max-height: 100%; object-fit: contain; }
.thumb:hover { border-color: var(--line-strong); }
.thumb.is-active { border-color: var(--accent); box-shadow: 0 0 0 1px var(--accent); }
.thumb:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

/* same reasoning as the checkout summary: stick the column, not the box */
.product > div:last-child { position: sticky; top: 84px; }
.buybox {
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 24px;
}
.buybox .price-row { display: flex; align-items: center; justify-content: space-between; gap: 12px; }
.buybox .amount { font-family: var(--font-mono); font-size: 32px; font-weight: 700; letter-spacing: -0.04em; line-height: 1; }
.buybox .was { font-size: 14px; color: var(--dim); text-decoration: line-through; margin-left: 9px; font-weight: 500; }
.save {
  font-size: 11.5px;
  font-weight: 600;
  color: var(--green);
  background: rgba(255,255,255,.06);
  border: 1px solid rgba(255,255,255,.18);
  padding: 3px 10px;
  border-radius: 999px;
}
.stock-line { display: flex; align-items: center; gap: 8px; font-size: 13px; color: var(--muted); padding: 14px 0 18px; border-bottom: 1px solid var(--line); }
.stock-line .dot { width: 7px; height: 7px; border-radius: 50%; background: var(--green); box-shadow: 0 0 0 3px rgba(255,255,255,.14); }
.stock-line b { color: var(--text); }

.qty-row { display: flex; align-items: center; justify-content: space-between; padding: 18px 0; }
.stepper { display: inline-flex; align-items: center; border: 1px solid var(--line-strong); border-radius: var(--radius-sm); overflow: hidden; }
.stepper button { width: 36px; height: 36px; background: transparent; border: 0; color: var(--muted); font-size: 16px; }
.stepper button:hover { background: var(--panel-2); color: var(--text); }
.stepper input {
  width: 48px; height: 36px;
  background: transparent;
  border: 0;
  border-left: 1px solid var(--line-strong);
  border-right: 1px solid var(--line-strong);
  color: var(--text);
  text-align: center;
  font: inherit;
  -moz-appearance: textfield;
}
.stepper input::-webkit-outer-spin-button,
.stepper input::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }

.buy-actions { display: grid; gap: 10px; }
.perks { list-style: none; margin: 20px 0 0; padding: 18px 0 0; border-top: 1px solid var(--line); display: grid; gap: 10px; }
.perks li { display: flex; align-items: flex-start; gap: 10px; font-size: 13px; color: var(--muted); }
.perks svg { flex: none; margin-top: 3px; color: var(--green); }

.purchases {
  margin-top: 16px;
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 15px 18px;
  color: var(--muted);
  font-size: 13.5px;
  display: flex;
  align-items: center;
  gap: 10px;
}
.purchases b { color: var(--text); }

.tabs { display: flex; gap: 28px; border-bottom: 1px solid var(--line); margin: 44px 0 24px; }
.tab {
  background: none;
  border: 0;
  border-bottom: 2px solid transparent;
  padding: 0 0 13px;
  color: var(--muted);
  font-size: 14.5px;
  font-weight: 500;
  transition: color .15s;
}
.tab:hover { color: var(--text); }
.tab.is-active { color: var(--text); border-bottom-color: var(--accent); }
.tab-panel { display: none; max-width: 740px; }
.tab-panel.is-active { display: block; }
.tab-panel p { color: var(--muted); }
.tos {
  border-left: 2px solid rgba(255,255,255,.45);
  background: var(--panel);
  border-radius: 0 var(--radius-sm) var(--radius-sm) 0;
  padding: 12px 16px;
  font-size: 13.5px;
}

/* ---------- cart drawer ---------- */
.drawer-scrim {
  position: fixed;
  inset: 0;
  background: rgba(0, 0, 0, .68);
  backdrop-filter: blur(3px);
  opacity: 0;
  pointer-events: none;
  transition: opacity .2s;
  z-index: 50;
}
.drawer-scrim.is-open { opacity: 1; pointer-events: auto; }
.drawer {
  position: fixed;
  top: 0; right: 0; bottom: 0;
  width: min(390px, 100%);
  /* --bg-alt, not a hardcoded navy. The cart and the menu are the two surfaces
     a phone visitor spends the most time in, and they were the last two places
     carrying the blue palette this site was rebuilt away from - a navy sheet
     sliding over a pure-black page is the kind of mismatch that reads as a
     bug. Sits one step above the page ground so the --panel cards inside it
     still separate. */
  background: var(--bg-alt);
  border-left: 1px solid var(--line);
  transform: translateX(100%);
  transition: transform .24s cubic-bezier(.32,.72,0,1);
  z-index: 60;
  display: flex;
  flex-direction: column;
}
.drawer.is-open { transform: none; }
.drawer > header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 19px 20px;
  border-bottom: 1px solid var(--line);
  font-weight: 600;
}
.drawer .items { flex: 1; overflow-y: auto; padding: 16px 20px; display: grid; gap: 12px; align-content: start; }
.drawer .empty { color: var(--dim); font-size: 13.5px; text-align: center; padding: 48px 0; }
.line-item {
  display: grid;
  grid-template-columns: 50px 1fr auto;
  gap: 12px;
  align-items: center;
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  padding: 11px;
}
.line-item .li-img {
  width: 50px; height: 50px;
  border-radius: 9px;
  background: #0f0f0f;
  display: grid; place-items: center;
  padding: 6px;
}
.line-item .li-name { font-size: 13.5px; font-weight: 600; }
.line-item .li-sub { font-size: 12px; color: var(--dim); }
.line-item .li-price { font-size: 13.5px; font-weight: 600; }
.li-remove { background: none; border: 0; padding: 2px 0 0; color: var(--dim); font-size: 12px; }
.li-remove:hover { color: var(--danger); }
.drawer > footer { border-top: 1px solid var(--line); padding: 18px 20px; display: grid; gap: 12px; }
.total-row { display: flex; justify-content: space-between; font-size: 15px; font-weight: 600; }
.drawer .fine { font-size: 11.5px; color: var(--dim); text-align: center; }

/* ---------- mobile sidebar ---------- */

/* Both the waffle and the panel are off until 900px, where `.nav` goes away.
   A waffle beside a visible nav is two controls doing one job. */
.menu-btn { display: none; }

.sidenav {
  display: none;
  position: fixed;
  top: 0; left: 0; bottom: 0;
  width: min(300px, 84vw);
  background: var(--bg-alt);   /* see the note on .drawer */
  border-right: 1px solid var(--line);
  flex-direction: column;
  transform: translateX(-100%);
  z-index: 60;
  /* Hidden rather than merely off-screen, so its links leave the tab order
     while the panel is shut. The delay keeps it visible for the slide out and
     drops it the instant the transform lands. */
  visibility: hidden;
  transition: transform .24s cubic-bezier(.32,.72,0,1), visibility 0s .24s;
}
.sidenav.is-open {
  transform: none;
  visibility: visible;
  transition: transform .24s cubic-bezier(.32,.72,0,1), visibility 0s;
}

.sidenav > header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  height: 64px;              /* matches the site header showing beside it */
  padding: 0 14px 0 18px;
  border-bottom: 1px solid var(--line);
}
.sidenav > header .brand { margin-right: 0; font-size: 16px; }

.sidenav-links {
  flex: 1;
  overflow-y: auto;
  padding: 12px;
  display: grid;
  gap: 2px;
  align-content: start;
}
/* Left as a block rather than a flex row: .nav-dot is an inline-block that
   sits on `vertical-align`, which a flex parent would ignore. */
.sidenav-links a {
  position: relative;
  display: block;
  padding: 13px 14px;
  border-radius: 10px;
  color: var(--muted);
  font-size: 15px;
  font-weight: 500;
  transition: color .15s, background .15s;
}
.sidenav-links a:hover { color: var(--text); background: var(--panel-2); }
.sidenav-links a.active {
  color: var(--text);
  background: var(--panel-2);
  box-shadow: inset 0 0 0 1px var(--line-strong);
}

.sidenav-foot { border-top: 1px solid var(--line); padding: 16px; display: grid; gap: 14px; }
.sidenav-legal { display: flex; flex-wrap: wrap; gap: 6px 16px; }
.sidenav-legal a { color: var(--dim); font-size: 12.5px; }
.sidenav-legal a:hover { color: var(--text); }

/* ---------- toast ---------- */
.toast {
  position: fixed;
  left: 50%;
  bottom: 26px;
  transform: translate(-50%, 20px);
  background: var(--panel-2);
  border: 1px solid var(--line-strong);
  border-radius: var(--radius-sm);
  padding: 12px 20px;
  font-size: 13.5px;
  box-shadow: var(--shadow);
  opacity: 0;
  pointer-events: none;
  transition: opacity .2s, transform .2s;
  z-index: 70;
}
.toast.is-on { opacity: 1; transform: translate(-50%, 0); }

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
}

/* ---------- inner page shell ---------- */
/* Centred masthead on every inner page, matching the reviews page and the home
   page sections. The breadcrumb stays left - it is navigation, not part of the
   title block, and centring it reads as decoration. */
.page-head { padding: 46px 0 34px; border-bottom: 1px solid var(--line); margin-bottom: 40px; text-align: center; }
.page-head h1 { font-size: clamp(30px, 4.4vw, 44px); margin: 0 0 10px; }
.page-head h1 span { color: var(--dim); }
.page-head p { color: var(--muted); margin: 0 auto; max-width: 620px; font-size: 15.5px; }
.page-head .crumbs { padding: 0 0 14px; text-align: left; }
main.page { padding-bottom: 60px; }

/* ---------- admin: thin header in place of the storefront chrome ---------- */
.admin-header .wrap { gap: 14px; }
.admin-tag {
  margin-left: 9px;
  padding: 3px 9px;
  border-radius: 999px;
  border: 1px solid var(--line-strong);
  color: var(--muted);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: .02em;
  text-transform: uppercase;
  vertical-align: 2px;
}

/* Admin is a tool somebody scans, not a landing page somebody arrives at - the
   full-width centred hero every other page.page-head gets just pushes the
   controls further down the screen, worst of all on a phone. */
body[data-page="admin"] .page-head { padding: 20px 0 18px; margin-bottom: 22px; text-align: left; border-bottom-color: var(--line); }
body[data-page="admin"] .page-head h1 { font-size: 21px; margin: 0 0 3px; }
body[data-page="admin"] .page-head p { margin: 0; max-width: none; font-size: 13px; }
body[data-page="admin"] .page-head .crumbs { padding: 0 0 8px; }

.subnav {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
  margin-bottom: 32px;
  /* Stays put while a long panel (the product table, a giveaway's entrant
     list) scrolls underneath, so switching tabs is never a scroll back to the
     top first. */
  position: sticky;
  top: 65px;
  z-index: 30;
  background: var(--bg);
  padding: 10px 0;
}
.subnav a {
  padding: 8px 15px;
  border-radius: 999px;
  border: 1px solid var(--line);
  background: var(--panel);
  color: var(--muted);
  font-size: 13.5px;
  transition: color .15s, border-color .15s, background .15s;
}
.subnav a:hover { color: var(--text); border-color: var(--line-strong); }
.subnav a.is-active { color: #000; background: var(--accent); border-color: transparent; }
/* One of these between each cluster of tabs (catalog / community / store) -
   a hairline is enough to read as "these belong together" without giving the
   group its own row, which would break the single scrolling strip on mobile. */
.subnav-sep { width: 1px; align-self: stretch; background: var(--line); margin: 2px 2px; flex: none; }

.empty-state {
  text-align: center;
  color: var(--dim);
  padding: 44px 0;
  border: 1px dashed var(--line-strong);
  border-radius: var(--radius);
  grid-column: 1 / -1;
}

/* ---------- state pills (shared: status, orders, tickets) ---------- */
.state {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  font-size: 12px;
  font-weight: 500;
  padding: 4px 11px;
  border-radius: 999px;
  white-space: nowrap;
}
.state .dot { width: 6px; height: 6px; border-radius: 50%; background: currentColor; }
.state-operational { color: var(--green); background: rgba(255,255,255,.06); border: 1px solid rgba(255,255,255,.2); }
.state-degraded { color: var(--star); background: rgba(255,255,255,.06); border: 1px solid rgba(255,255,255,.22); }
.state-down { color: var(--danger); background: rgba(248, 113, 113, .1); border: 1px solid rgba(248, 113, 113, .26); }
.state-muted { color: var(--dim); background: var(--panel-2); border: 1px solid var(--line); }

/* ---------- reviews page ---------- */
.rv-masthead { text-align: center; padding: 34px 0 26px; }
.rv-eyebrow { margin: 0 0 14px; font-size: 13px; font-weight: 600; color: var(--muted); }
.rv-eyebrow[hidden] { display: none; }
.rv-masthead h1 { margin: 0; font-size: clamp(34px, 5.6vw, 52px); }
/* Two-tone headline. The palette is monochrome, so the second word steps down
   in brightness rather than changing hue - same emphasis, no new colour. */
.rv-masthead h1 span { color: var(--dim); }
.rv-sub { margin: 16px auto 0; max-width: 52ch; color: var(--muted); font-size: 15px; }

.rv-controls { display: grid; justify-items: center; gap: 14px; margin-bottom: 30px; }
.rv-controls[hidden] { display: none; }
.rv-filters:empty { display: none; }
.rv-filters .chip span { color: var(--dim); }
.rv-filters .chip.is-active span { color: rgba(0, 0, 0, .55); }

.rv-grid {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 14px;
  align-content: start;
}
.rv-grid:empty { display: none; }

.rv-pager {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  flex-wrap: wrap;
  margin-top: 28px;
}
.rv-pager[hidden] { display: none; }
.rv-range { margin: 0; color: var(--dim); font-size: 12.5px; }
.pages { display: flex; gap: 6px; margin-left: auto; }
.page-btn {
  min-width: 33px;
  height: 33px;
  padding: 0 10px;
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  background: var(--panel);
  color: var(--muted);
  font-size: 13px;
  transition: color .15s, border-color .15s, background .15s;
}
.page-btn:hover:not(:disabled) { color: var(--text); border-color: var(--line-strong); }
.page-btn.is-active { background: var(--accent); border-color: transparent; color: #000; font-weight: 600; }
.page-btn:disabled { opacity: .35; cursor: default; }

@media (max-width: 980px) { .rv-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 620px) { .rv-grid { grid-template-columns: 1fr; } }

/* ---------- bordered panel: checkout, tickets, orders, admin, 404 ---------- */
.panel-block { border: 1px solid var(--line); border-radius: var(--radius); background: var(--panel); overflow: hidden; margin-bottom: 26px; }
.panel-block > h3 { margin: 0; padding: 16px 20px; border-bottom: 1px solid var(--line); font-size: 14px; font-weight: 600; }

/* ---------- account pages ---------- */

.table-wrap { border: 1px solid var(--line); border-radius: var(--radius); overflow-x: auto; background: var(--panel); }
table.data { width: 100%; border-collapse: collapse; min-width: 640px; }
table.data th {
  text-align: left;
  font-size: 11.5px;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--dim);
  font-weight: 600;
  padding: 14px 18px;
  border-bottom: 1px solid var(--line);
  white-space: nowrap;
}
table.data td { padding: 15px 18px; border-bottom: 1px solid var(--line); font-size: 13.5px; vertical-align: middle; }
table.data tr:last-child td { border-bottom: 0; }
table.data tbody tr:hover { background: var(--panel-2); }
table.data .right { text-align: right; }
.muted-text { color: var(--dim); }
.btn-link { background: none; border: 0; padding: 0; color: var(--accent-hover); font-size: 13.5px; font-weight: 500; }
.btn-link:hover { text-decoration: underline; }
.btn-link.is-code {
  font-family: var(--font-mono);
  font-size: 12.5px;
  color: var(--text);
  background: var(--panel-2);
  border: 1px solid var(--line-strong);
  border-radius: 7px;
  padding: 4px 9px;
}
.btn-link.is-code:hover { text-decoration: none; border-color: var(--accent); }

.account-grid { display: grid; grid-template-columns: minmax(0, 1fr) 300px; gap: 26px; align-items: start; }
.account-grid > * { min-width: 0; }

.side-card { border: 1px solid var(--line); border-radius: var(--radius); background: var(--panel); padding: 22px; }
.side-card h3 { margin: 0 0 14px; font-size: 14px; font-weight: 600; }
.side-card p { margin: 0 0 16px; color: var(--muted); font-size: 13.5px; }

.section-title { display: flex; align-items: center; justify-content: space-between; gap: 14px; margin: 0 0 16px; }
.section-title h2 { margin: 0; font-size: 19px; letter-spacing: -0.025em; }

.form-grid { display: grid; gap: 14px; }
/* Chunks a long form (the product form is fourteen fields deep) into named
   groups, so it reads as four short forms in a row rather than one that never
   ends. Plain text, not a fieldset - no field's name or id changes, so
   nothing that binds to them by selector needed to move. */
.form-section {
  margin: 8px 0 -4px;
  padding-top: 14px;
  border-top: 1px solid var(--line);
  font-size: 11.5px;
  font-weight: 700;
  letter-spacing: .04em;
  text-transform: uppercase;
  color: var(--dim);
}
.form-section:first-of-type { margin-top: 0; padding-top: 0; border-top: 0; }
.field { display: grid; gap: 7px; }
.field label { font-size: 13px; color: var(--muted); }
.field input, .field textarea, .field select {
  width: 100%;
  background: var(--bg-alt);
  border: 1px solid var(--line-strong);
  border-radius: var(--radius-sm);
  color: var(--text);
  padding: 11px 13px;
  font: inherit;
  font-size: 14px;
  transition: border-color .15s, box-shadow .15s;
}
.field textarea { min-height: 118px; resize: vertical; }
.field input:focus, .field textarea:focus, .field select:focus {
  outline: none;
  border-color: var(--accent);
  box-shadow: 0 0 0 3px var(--accent-soft);
}
.field .hint { font-size: 12px; color: var(--dim); }

/* The ticket field in the entrants table. Sized to the two digits it can hold
   rather than to the column, so the table still reads as a table. */
.entry-weight {
  width: 64px;
  background: var(--bg-alt);
  border: 1px solid var(--line-strong);
  border-radius: var(--radius-sm);
  color: var(--text);
  padding: 5px 8px;
  font: inherit;
  font-size: 13.5px;
  font-variant-numeric: tabular-nums;
  transition: border-color .15s, box-shadow .15s;
}
.entry-weight:focus {
  outline: none;
  border-color: var(--accent);
  box-shadow: 0 0 0 3px var(--accent-soft);
}
/* Drawn giveaways: the weights explain the result, so they stop being fields. */
.entry-weight:disabled { opacity: .55; border-color: var(--line); cursor: not-allowed; }

/* Ticking the winners by hand. Only rendered while a giveaway can still be
   drawn, so there is no disabled state to dress. */
.entry-pick { width: 15px; height: 15px; accent-color: var(--accent); }

/* ============================================================
   Intro loader

   Plays once per tab (index.html gates it on sessionStorage). Entirely CSS:
   the bar fills for 1.5s, then the wordmark scales up and fades while the
   backdrop dissolves underneath it, so the page is revealed by a crossfade
   rather than a hard cut. Because nothing here depends on JS, a script error
   can never leave a visitor stuck behind a black screen.
   ============================================================ */
@keyframes loaderBar   { from { transform: scaleX(0); } to { transform: scaleX(1); } }
@keyframes loaderPulse { 0%, 100% { transform: scale(1); opacity: .9; } 50% { transform: scale(1.04); opacity: 1; } }
@keyframes loaderZoom  { 0% { transform: scale(1); opacity: 1; } 100% { transform: scale(1.45); opacity: 0; } }
@keyframes loaderFade  { to { opacity: 0; } }
@keyframes loaderClear { to { background-color: transparent; visibility: hidden; pointer-events: none; } }

.page-loader {
  position: fixed;
  inset: 0;
  /* above the sticky header and the cart drawer scrim */
  z-index: 200;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 22px;
  background: var(--bg);
  animation: loaderClear .55s ease 1.52s forwards;
}
.page-loader__mark {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  font-family: var(--font-display);
  font-size: clamp(24px, 5vw, 34px);
  font-weight: 700;
  letter-spacing: -0.035em;
  color: var(--text);
  will-change: transform, opacity;
  /* loaderZoom is listed last so it takes over transform/opacity from the
     idle pulse once it starts, and keeps them via forwards. */
  animation:
    loaderPulse 1.1s ease-in-out infinite,
    loaderZoom .6s cubic-bezier(.22, 1, .36, 1) 1.5s forwards;
}
.page-loader__fade {
  width: 176px;
  height: 3px;
  overflow: hidden;
  border-radius: 999px;
  background: var(--line);
  animation: loaderFade .22s ease 1.42s forwards;
}
.page-loader__bar {
  height: 100%;
  width: 100%;
  transform-origin: left;
  border-radius: 999px;
  background: var(--accent);
  box-shadow: var(--glow);
  animation: loaderBar 1.5s cubic-bezier(.45, 0, .2, 1) forwards;
}
/* Second and later page loads in the same tab: never rendered at all. */
.loader-seen .page-loader { display: none; }

@media (prefers-reduced-motion: reduce) {
  /* Show the brand for a beat, then get out of the way without any motion. */
  .page-loader { animation: loaderClear .01s linear .35s forwards; }
  .page-loader__mark { animation: none; }
  .page-loader__fade { animation: none; }
  .page-loader__bar { animation: none; }
}
/* ============================================================
   Home page - hero, sections, steps
   ============================================================ */

.hero {
  position: relative;
  overflow: hidden;
  display: flex;
  align-items: center;
  min-height: clamp(420px, 68vh, 640px);
  border-bottom: 1px solid var(--line);
  /* Built from the palette variables rather than fixed hex, so retuning the
     greys in :root retunes the hero with everything else. */
  background:
    radial-gradient(ellipse at 20% 0%, var(--panel-2) 0%, transparent 55%),
    radial-gradient(ellipse at 85% 30%, var(--panel) 0%, transparent 50%),
    var(--bg);
}
.hero-video {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  /* Greyscale on purpose: a colourful banner would break the one rule this
     palette follows, which is that the payment marks are the only colour. */
  filter: grayscale(1) contrast(1.05);
  opacity: .45;
  pointer-events: none;
}
/* Drifting starfield. Pure background-image, no DOM nodes, no JS. */
.hero-stars {
  position: absolute;
  inset: -50% -10% -10%;
  pointer-events: none;
  opacity: .5;
  background-image:
    radial-gradient(1.5px 1.5px at 12% 22%, rgba(255,255,255,.55) 50%, transparent 50%),
    radial-gradient(1.5px 1.5px at 68% 12%, rgba(255,255,255,.4) 50%, transparent 50%),
    radial-gradient(1px 1px at 42% 62%, rgba(255,255,255,.5) 50%, transparent 50%),
    radial-gradient(1.5px 1.5px at 88% 48%, rgba(255,255,255,.45) 50%, transparent 50%),
    radial-gradient(1px 1px at 26% 78%, rgba(255,255,255,.4) 50%, transparent 50%),
    radial-gradient(1px 1px at 78% 82%, rgba(255,255,255,.35) 50%, transparent 50%);
  background-size: 340px 340px;
  animation: starDrift 90s linear infinite;
}
@keyframes starDrift { to { transform: translate3d(0, 340px, 0); } }
.hero-scrim {
  position: absolute;
  inset: 0;
  pointer-events: none;
  background: linear-gradient(180deg, rgba(0,0,0,.35) 0%, rgba(0,0,0,.15) 45%, var(--bg) 100%);
}
/* Block padding only. This element also carries .wrap, and a `padding`
   shorthand here would overwrite the safe-area-aware left/right gutter that
   .wrap sets. Same reason on .home-section below. */
.hero-inner { position: relative; z-index: 1; display: grid; grid-template-columns: minmax(0, 1fr) minmax(340px, .78fr); align-items: center; gap: clamp(38px, 7vw, 94px); padding-top: 64px; padding-bottom: 64px; }
.hero-copy { text-align: left; }
.hero-badge {
  display: inline-block;
  padding: 6px 14px;
  border: 1px solid var(--line-strong);
  border-radius: 999px;
  background: var(--accent-soft);
  font-size: 11.5px;
  font-weight: 600;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--text);
}
.hero-title {
  font-family: var(--font-display);
  font-size: clamp(32px, 6vw, 58px);
  font-weight: 700;
  letter-spacing: -0.04em;
  line-height: 1.04;
  margin: 20px 0 0;
  /* Wide enough that the <br> in the markup is what breaks the line, not the
     container - the second line is the longer of the two. */
  max-width: 26ch;
}
/* Two-tone headline. The palette is monochrome, so the emphasised half steps
   down in brightness instead of changing hue. */
.hero-title span { color: var(--dim); }
.hero-sub {
  margin: 18px 0 0;
  max-width: 60ch;
  color: var(--muted);
  font-size: clamp(15px, 1.6vw, 17px);
}
.hero-actions {
  margin-top: 32px;
  display: flex;
  align-items: center;
  justify-content: flex-start;
  gap: 18px;
  flex-wrap: wrap;
}
.hero-link {
  font-size: 14px;
  font-weight: 600;
  color: var(--text);
  border-bottom: 1px solid var(--line-strong);
  padding-bottom: 2px;
  transition: border-color .15s, color .15s;
}
.hero-link:hover { border-color: var(--accent); }

/* ---------- hero supporting rows ---------- */

/* Plain statements under the buttons. Deliberately not metrics - see the
   comment on the stats band in app.js. */
.check-row {
  list-style: none;
  display: flex;
  justify-content: flex-start;
  flex-wrap: wrap;
  gap: 10px 26px;
  margin: 26px 0 0;
  padding: 0;
  font-size: 13px;
  color: var(--muted);
}
.check-row li { display: inline-flex; align-items: center; gap: 7px; }
.check-row svg { flex: none; color: var(--green); }

.pay-strip {
  display: flex;
  align-items: center;
  justify-content: flex-start;
  flex-wrap: wrap;
  gap: 8px 12px;
  margin-top: 30px;
  font-size: 12.5px;
  color: var(--dim);
}
.pay-strip:empty { display: none; }
.pay-strip-label { display: inline-flex; align-items: center; gap: 6px; color: var(--muted); }
.pay-strip-note { color: var(--dim); }
.pay-strip .coin-mark { width: 22px; height: 22px; }

.hero-product { position: relative; min-height: 430px; display: grid; place-items: center; isolation: isolate; border: 1px solid var(--line); border-radius: 18px; overflow: hidden; background: linear-gradient(145deg, var(--panel-2), var(--bg-alt)); box-shadow: var(--shadow); }
.hero-product::before { content: ''; position: absolute; inset: 8%; border: 1px solid rgba(255,255,255,.09); border-radius: 50%; transform: rotate(-15deg); }
.hero-product__glow { position: absolute; width: 60%; aspect-ratio: 1; border-radius: 50%; background: rgba(255,255,255,.11); filter: blur(45px); }
.hero-product > img { position: relative; z-index: 1; width: auto; height: auto; max-width: 84%; max-height: 330px; object-fit: contain; filter: drop-shadow(0 28px 30px rgba(0,0,0,.5)); transition: transform .45s cubic-bezier(.22,1,.36,1); }
.hero-product:hover > img { transform: translateY(-6px) rotate(1.5deg) scale(1.025); }
.hero-product__meta { position: absolute; z-index: 2; left: 16px; right: 16px; bottom: 16px; display: flex; align-items: end; justify-content: space-between; gap: 16px; padding: 13px 14px; border: 1px solid rgba(255,255,255,.1); border-radius: 10px; background: rgba(13,14,16,.78); backdrop-filter: blur(12px); }
.hero-product__meta span { min-width: 0; }
.hero-product__meta small, .hero-product__meta b { display: block; }
.hero-product__meta small { color: var(--muted); font-size: 10px; letter-spacing: .12em; text-transform: uppercase; }
.hero-product__meta b { margin-top: 2px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 13px; }
.hero-product__meta strong { flex: none; font: 700 15px/1 var(--font-mono); }

/* ---------- scroll product showcase ---------- */
.product-showcase {
  --showcase-bg-live: #101114;
  --showcase-ink-live: #f4f4f4;
  --showcase-muted-live: #969696;
  position: relative;
  height: var(--showcase-scroll, 180vh);
  padding: 0;
  background: var(--showcase-bg-live);
  color: var(--showcase-ink-live);
  transition: background-color .08s linear, color .08s linear;
}
.showcase-stage {
  position: sticky;
  top: 64px;
  height: calc(100vh - 64px);
  min-height: 560px;
  overflow: hidden;
  display: grid;
  align-items: center;
  border-block: 1px solid color-mix(in srgb, currentColor 14%, transparent);
  background:
    radial-gradient(circle at 25% 50%, color-mix(in srgb, currentColor 8%, transparent), transparent 42%),
    var(--showcase-bg-live);
}
.showcase-wrap {
  display: grid;
  grid-template-columns: minmax(0, 1.15fr) minmax(320px, .85fr);
  align-items: center;
  gap: clamp(36px, 7vw, 100px);
}
.showcase-visual {
  position: relative;
  min-height: min(68vh, 700px);
  perspective: 1100px;
  transform-style: preserve-3d;
}
.showcase-orbit {
  position: absolute;
  inset: 12% 4%;
  border: 1px solid color-mix(in srgb, currentColor 11%, transparent);
  border-radius: 50%;
  transform: rotate(-12deg);
}
.showcase-orbit::after {
  content: '';
  position: absolute;
  width: 7px;
  height: 7px;
  left: 12%;
  top: 17%;
  border-radius: 50%;
  background: currentColor;
  box-shadow: 0 0 20px currentColor;
  opacity: .45;
}
.showcase-product {
  position: absolute;
  inset: 6%;
  display: grid;
  place-items: center;
  transform-style: preserve-3d;
  will-change: transform, opacity;
}
.showcase-product__image {
  position: relative;
  z-index: 3;
  max-width: 90%;
  max-height: 90%;
  width: auto;
  height: auto;
  object-fit: contain;
  border-radius: 8px;
  transform: translateZ(34px);
  filter: drop-shadow(0 32px 34px rgba(0, 0, 0, .42));
}
.showcase-product__echo {
  position: absolute;
  inset: 11%;
  display: grid;
  place-items: center;
  opacity: .2;
  filter: blur(28px) saturate(.4);
  transform: translate3d(-24px, 18px, -45px) scale(.98);
}
.showcase-product__echo img { max-width: 88%; max-height: 88%; }
.showcase-product__plate {
  position: absolute;
  z-index: 1;
  width: 64%;
  aspect-ratio: 1;
  border-radius: 50%;
  background: color-mix(in srgb, currentColor 7%, transparent);
  border: 1px solid color-mix(in srgb, currentColor 12%, transparent);
  transform: translate3d(0, 20%, -20px) rotateX(74deg);
  box-shadow: 0 28px 70px rgba(0, 0, 0, .24);
}
.showcase-product__shine {
  position: absolute;
  z-index: 4;
  inset: 12% 19%;
  pointer-events: none;
  background: linear-gradient(105deg, transparent 28%, rgba(255,255,255,.13) 45%, transparent 62%);
  transform: translateZ(42px);
  mix-blend-mode: screen;
}
.showcase-copy { position: relative; min-height: 430px; }
.showcase-story__fallback { display: none; }
.showcase-story {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  justify-content: center;
  pointer-events: none;
  will-change: transform, opacity;
}
.showcase-story.is-current { pointer-events: auto; }
.showcase-story > * { transition: transform .55s cubic-bezier(.22, 1, .36, 1), opacity .4s ease; }
.showcase-story:not(.is-current) > * { transform: translateY(12px); opacity: .35; }
.showcase-story > :nth-child(2) { transition-delay: .035s; }
.showcase-story > :nth-child(3) { transition-delay: .07s; }
.showcase-story > :nth-child(4) { transition-delay: .105s; }
.showcase-story > :nth-child(5) { transition-delay: .14s; }
.showcase-count {
  margin: 0 0 32px;
  font: 12px/1 var(--font-mono);
  letter-spacing: .14em;
  color: var(--showcase-muted-live);
}
.showcase-kicker {
  margin: 0 0 12px;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: .18em;
  text-transform: uppercase;
  color: var(--showcase-muted-live);
}
.showcase-story h2 {
  margin: 0;
  max-width: 12ch;
  font-family: var(--font-display);
  font-size: clamp(38px, 5vw, 68px);
  line-height: .98;
  letter-spacing: -.05em;
}
.showcase-description {
  max-width: 47ch;
  margin: 24px 0 0;
  color: var(--showcase-muted-live);
  font-size: clamp(14px, 1.4vw, 16px);
}
.showcase-buy { display: flex; align-items: center; gap: 22px; margin-top: 30px; }
.showcase-price { font: 700 clamp(20px, 2vw, 26px)/1 var(--font-mono); }
.showcase-price del { margin-left: 9px; color: var(--showcase-muted-live); font-size: 13px; font-weight: 500; }
.showcase-progress {
  position: absolute;
  left: max(var(--gutter), env(safe-area-inset-left));
  right: max(var(--gutter), env(safe-area-inset-right));
  bottom: 25px;
  height: 1px;
  background: color-mix(in srgb, currentColor 16%, transparent);
  transform: translateZ(0);
}
.showcase-progress span { display: block; width: 100%; height: 1px; transform: scaleX(0); transform-origin: left; background: currentColor; }

@media (max-width: 760px) {
  .product-showcase { height: max(var(--showcase-scroll, 180vh), 150vh); }
  .showcase-stage { top: 64px; min-height: 0; }
  .showcase-wrap { grid-template-columns: 1fr; grid-template-rows: minmax(250px, 48vh) minmax(235px, auto); gap: 0; align-content: center; }
  .showcase-visual { min-height: 0; height: 100%; }
  .showcase-product { inset: 2% 14%; }
  .showcase-product__image { max-height: 94%; }
  .showcase-copy { min-height: 235px; }
  .showcase-story { justify-content: flex-start; text-align: center; align-items: center; }
  .showcase-count { position: absolute; top: -10px; left: 0; margin: 0; }
  .showcase-kicker { margin-top: 13px; }
  .showcase-story h2 { max-width: 17ch; font-size: clamp(29px, 8.5vw, 46px); }
  .showcase-description { margin-top: 13px; max-width: 52ch; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
  .showcase-buy { margin-top: 17px; }
  .showcase-progress { bottom: 14px; }
}

/* Motion is enhancement only. The fallback becomes a clean horizontal product
   shelf, with every item readable and reachable without sticky positioning. */
@media (prefers-reduced-motion: reduce) {
  .product-showcase,
  .product-showcase.is-reduced { height: auto; background: var(--bg); color: var(--text); }
  .showcase-stage { position: relative; top: auto; height: auto; min-height: 0; padding: 54px 0; overflow: visible; }
  .showcase-wrap { display: block; }
  .showcase-visual, .showcase-progress { display: none; }
  .showcase-copy { display: grid; grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); gap: 14px; min-height: 0; }
  .showcase-story { position: relative; inset: auto; display: flex; min-height: 300px; padding: 24px; border: 1px solid var(--line); border-radius: var(--radius); background: var(--panel); opacity: 1 !important; transform: none !important; pointer-events: auto; }
  .showcase-story[aria-hidden="true"] { display: flex; }
  .showcase-story > *, .showcase-story:not(.is-current) > * { opacity: 1; transform: none; transition: none; }
  .showcase-story__fallback {
    display: block;
    width: 100%;
    height: 220px;
    margin: 0 0 24px;
    object-fit: contain;
    border-radius: var(--radius-sm);
    background: #0f0f0f;
    filter: drop-shadow(0 16px 24px rgba(0,0,0,.35));
  }
  .showcase-story h2 { font-size: 30px; }
  .showcase-count { position: static; margin: 0 0 24px; }
}

/* ---------- home sections ---------- */
.home-section { padding-top: 62px; padding-bottom: 62px; }
/* Explicit, matching every other [hidden] rule here: the padding above would
   otherwise be the only thing standing between a hidden section and a 124px
   gap in the page. */
.home-section[hidden] { display: none; }
.home-section.is-tight { padding-top: 0; padding-bottom: 34px; }
.sec-more { display: flex; justify-content: center; margin: 28px 0 0; }

/* ---------- how it works ---------- */
.steps {
  list-style: none;
  max-width: 620px;
  margin: 0 auto;
  padding: 0;
  display: grid;
  gap: 10px;
}
.steps li {
  display: flex;
  align-items: flex-start;
  gap: 16px;
  padding: 18px 20px;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--panel);
}
.step-n {
  flex: none;
  width: 28px;
  height: 28px;
  display: grid;
  place-items: center;
  border-radius: 999px;
  border: 1px solid var(--line-strong);
  background: var(--panel-2);
  font-family: var(--font-mono);
  font-size: 12.5px;
  color: var(--muted);
}
.steps h3 { margin: 3px 0 5px; font-size: 15px; font-weight: 600; letter-spacing: -0.015em; }
.steps p { margin: 0; color: var(--muted); font-size: 13.5px; }
.eyebrow {
  margin: 0;
  font-size: 11.5px;
  font-weight: 700;
  letter-spacing: .16em;
  text-transform: uppercase;
  color: var(--muted);
}

.sec-head { display: flex; align-items: flex-end; justify-content: space-between; gap: 16px; margin-bottom: 26px; }
.sec-head h2 { font-family: var(--font-display); font-size: clamp(22px, 3vw, 30px); letter-spacing: -0.03em; margin: 8px 0 0; }
.sec-head h2 span { color: var(--dim); }
.sec-head .sec-sub { margin: 10px auto 0; color: var(--muted); font-size: 14.5px; max-width: 56ch; }
.sec-head.is-center { justify-content: center; text-align: center; }

/* ---------- closing contact panel ---------- */
/* Sits directly under the FAQ, which is the question it answers when the FAQ
   did not. */
.faq + .contact-banner { margin-top: 36px; }
.contact-banner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 22px;
  flex-wrap: wrap;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--panel);
  padding: 30px;
}
.contact-banner h2 { font-family: var(--font-display); font-size: 21px; letter-spacing: -0.03em; margin: 0 0 8px; }
.contact-banner .cb-copy > p { margin: 0 0 14px; color: var(--muted); font-size: 14px; max-width: 54ch; }
.contact-banner .contacts { display: flex; gap: 10px; flex-wrap: wrap; align-items: center; }

@media (max-width: 560px) {
  /* Block padding only - the inline gutter comes from .wrap via --gutter. */
  .home-section { padding-top: 46px; padding-bottom: 46px; }
  .hero-inner { grid-template-columns: 1fr; gap: 30px; padding-top: 52px; padding-bottom: 52px; }
  .hero-copy { text-align: center; }
  .hero-title, .hero-sub { margin-left: auto; margin-right: auto; }
  .hero-actions, .check-row, .pay-strip { justify-content: center; }
  .hero-product { width: min(100%, 390px); min-height: 330px; margin: 0 auto; }
  .hero-product > img { max-height: 245px; }
  .check-row { gap: 8px 18px; }
  .hero-actions { flex-direction: column; gap: 14px; }
  .hero-actions .btn { width: 100%; }
}

/* ---------- catalog front page ---------- */
.finder {
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 18px;
  margin: 30px 0 18px;
  position: sticky;
  top: 76px;
  z-index: 18;
  box-shadow: 0 16px 34px rgba(0,0,0,.24);
}
.search-row {
  display: flex;
  align-items: center;
  gap: 11px;
  padding: 12px 15px;
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  background: var(--bg-alt);
  color: var(--dim);
  transition: border-color .15s, box-shadow .15s;
}
.search-row:focus-within { border-color: var(--accent); box-shadow: 0 0 0 3px var(--accent-soft); }
.search-row input {
  flex: 1;
  min-width: 0;
  background: none;
  border: 0;
  outline: none;
  color: var(--text);
  font: inherit;
  font-size: 14.5px;
}
.search-row input::-webkit-search-cancel-button { filter: invert(.6); }
.finder .chips { margin: 14px 0 0; }

.result-count { color: var(--dim); font-size: 12.5px; margin: 0 0 26px; }

/* padding-top: 0 undoes the page-level `section { padding: 74px 0 }` above.
   Each category group is a <section>, so it was picking up the vertical rhythm
   meant for top-level page sections and opening a 74px hole between the result
   count and the first category heading - on desktop as well as mobile.
   Spacing between categories is margin-bottom's job. */
.cat { margin-bottom: 42px; padding-top: 0; padding-bottom: 0; }
.cat-head {
  font-family: var(--font-display);
  display: flex;
  align-items: center;
  gap: 10px;
  font-size: 21px;
  letter-spacing: -0.03em;
  margin: 0 0 4px;
  padding-bottom: 12px;
  border-bottom: 1px solid var(--line);
}
.cat-icon { font-size: 18px; }
.cat-group {
  font-size: 12px;
  font-weight: 500;
  color: var(--dim);
  letter-spacing: .02em;
  margin: 22px 0 12px;
}

/* 200px, not 168: a card on sale carries a price pill, a struck-through was
   price and a stock count on one line, and that row does not fit inside 168. */
.pgrid { display: grid; grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); gap: 14px; }

.pcard {
  display: flex;
  flex-direction: column;
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  overflow: hidden;
  transition: transform .16s, border-color .16s, box-shadow .16s;
}

/* Catalog placeholder, shown only until app.js paints the real cards. Sized
   off .pcard so the swap does not move the page: same aspect-ratio media box
   plus the two body rows a card carries. */
.pcard-skel {
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  background: var(--panel);
  aspect-ratio: 1 / 1.42;
  animation: skelPulse 1.4s ease-in-out infinite;
}
@keyframes skelPulse { 0%, 100% { opacity: 1; } 50% { opacity: .55; } }

/* Anyone who has asked not to see motion gets the same box, holding still. */
@media (prefers-reduced-motion: reduce) {
  .pcard-skel { animation: none; }
}
.pcard:hover { border-color: var(--accent); }
.pcard-media {
  position: relative;
  aspect-ratio: 1;
  display: grid;
  place-items: center;
  padding: 14px;
  background: #0f0f0f;
}
/* Bounded on both axes. Uploaded art is any shape it likes, and a wide shot
   sized by height alone renders past the padding and out to the card edge. */
.pcard-media img {
  max-width: 100%;
  max-height: 100%;
  width: auto;
  height: auto;
  object-fit: contain;
  filter: drop-shadow(0 10px 18px rgba(0,0,0,.5));
}
.pcard-out {
  position: absolute;
  inset: auto 0 0;
  background: rgba(8, 12, 22, .86);
  color: var(--danger);
  font-size: 11px;
  font-weight: 600;
  text-align: center;
  padding: 5px 0;
}
.pcard.is-out .pcard-media img { opacity: .45; }
/* A flex column filling the card, with the foot pushed to the bottom edge by
   margin-top:auto. Grid rows sit wherever the content ends instead, so one
   two-line name or one extra tag drops that card's price row below its
   neighbours' - a row of cards with the prices at four different heights is
   what makes a full catalog look untidy. */
.pcard-body {
  flex: 1;
  display: flex;
  flex-direction: column;
  gap: 8px;
  padding: 12px 12px 13px;
}
.pcard-title {
  font-size: 13px;
  font-weight: 600;
  line-height: 1.35;
  letter-spacing: -0.005em;
  /* Two lines, then an ellipsis: an unusually long name otherwise sets the
     height of every card in its row. */
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 2;
  line-clamp: 2;
  overflow: hidden;
}
.pcard-tags { display: flex; flex-wrap: wrap; gap: 4px; }
/* Products are not required to carry tags. The element still ships empty, and
   an empty flex item still takes its share of the 8px gap. */
.pcard-tags:empty { display: none; }
.ptag {
  font-size: 10px;
  color: var(--dim);
  background: var(--panel-2);
  border: 1px solid var(--line);
  border-radius: 5px;
  padding: 2px 6px;
  white-space: nowrap;
}
.pcard-foot {
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 4px 8px;
  margin-top: auto;
  padding-top: 2px;
}
.pcard-price {
  font-family: var(--font-mono);
  font-size: 13px;
  font-weight: 700;
  white-space: nowrap;
  background: var(--panel-2);
  border: 1px solid var(--line);
  border-radius: 7px;
  padding: 3px 9px;
}
.pcard-price .was { font-size: 10.5px; font-weight: 500; color: var(--dim); text-decoration: line-through; margin-left: 5px; }
.pcard-stock { font-size: 10.5px; color: var(--dim); white-space: nowrap; }
.pcard-action { display: flex; align-items: center; justify-content: space-between; margin-top: 3px; padding-top: 9px; border-top: 1px solid var(--line); color: var(--muted); font-size: 11px; font-weight: 650; transition: color .16s; }
.pcard:hover .pcard-action { color: var(--text); }
.catalog-dock { display: none; }

@media (max-width: 760px) {
  .hero-inner { grid-template-columns: 1fr; gap: 30px; }
  .hero-copy { text-align: center; }
  .hero-title, .hero-sub { margin-left: auto; margin-right: auto; }
  .hero-actions, .check-row, .pay-strip { justify-content: center; }
  .hero-product { width: min(100%, 430px); min-height: 350px; margin: 0 auto; }
}

@media (max-width: 560px) {
  .hero-product { width: min(100%, 390px); min-height: 330px; }
  .hero-product > img { max-height: 245px; }
  .finder { top: 70px; margin-left: calc(var(--gutter) * -1); margin-right: calc(var(--gutter) * -1); border-left: 0; border-right: 0; border-radius: 0; padding: 12px var(--gutter); }
  .finder .chips { flex-wrap: nowrap; overflow-x: auto; padding-bottom: 2px; scrollbar-width: none; }
  .finder .chips::-webkit-scrollbar { display: none; }
  .finder .chip { flex: none; }
  .catalog-dock { position: fixed; z-index: 38; left: 10px; right: 10px; bottom: max(10px, env(safe-area-inset-bottom)); display: flex; align-items: center; justify-content: space-between; gap: 12px; padding: 10px 10px 10px 14px; border: 1px solid var(--line-strong); border-radius: 12px; background: rgba(24,25,28,.93); backdrop-filter: blur(14px); box-shadow: 0 18px 50px rgba(0,0,0,.55); opacity: 0; transform: translateY(130%); pointer-events: none; transition: opacity .2s, transform .2s; }
  .catalog-dock.is-on { opacity: 1; transform: translateY(0); pointer-events: auto; }
  .catalog-dock span { min-width: 0; }
  .catalog-dock small, .catalog-dock b { display: block; }
  .catalog-dock small { color: var(--muted); font-size: 10px; }
  .catalog-dock b { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 12px; }
  .catalog-dock .btn { flex: none; width: auto; padding: 10px 13px; font-size: 12px; }
  .panel-open .catalog-dock { opacity: 0; transform: translateY(130%); pointer-events: none; }
}

@media (prefers-reduced-motion: reduce) {
  .catalog-dock { transition: none; }
}

.product-proof, .trust-ledger { list-style: none; margin: 18px 0 0; padding: 0; display: grid; gap: 1px; border: 1px solid var(--line); border-radius: var(--radius-sm); overflow: hidden; background: var(--line); }
.product-proof li, .trust-ledger li { display: flex; justify-content: space-between; gap: 18px; padding: 11px 13px; background: var(--panel); font-size: 12px; }
.product-proof b, .trust-ledger b { font-weight: 650; }
.product-proof span, .trust-ledger span { color: var(--muted); text-align: right; }
.trust-ledger { margin: 24px 0; }
.trust-ledger li { padding: 14px 16px; font-size: 13px; }
@media (max-width: 560px) {
  .product-proof li, .trust-ledger li { display: block; }
  .product-proof span, .trust-ledger span { display: block; margin-top: 3px; text-align: left; }
}


.pay-methods { display: flex; gap: 6px; margin-top: 14px; flex-wrap: wrap; }

.checkout-steps { list-style: none; display: grid; grid-template-columns: repeat(3, 1fr); gap: 8px; margin: 0 0 14px; padding: 0; }
.checkout-steps li { padding: 9px 11px; border: 1px solid var(--line); border-radius: var(--radius-sm); color: var(--dim); font: 12px/1.2 var(--font-mono); background: var(--bg-alt); }
.checkout-steps li span { margin-left: 5px; font-family: var(--font-body); }
.checkout-steps li.is-current { color: var(--text); border-color: var(--line-strong); background: var(--panel-2); }
.checkout-caution { margin: 4px 0 0; padding: 10px 12px; border-left: 2px solid var(--line-strong); color: var(--muted); background: var(--bg-alt); font-size: 12px; }

/* ---------- single-product front page ---------- */
.spotlight {
  display: grid;
  grid-template-columns: minmax(0, 1.15fr) minmax(0, .85fr);
  gap: 34px;
  align-items: start;
  padding: 32px 0 12px;
}
/* Holds a .gallery now rather than a bare <img>, so the frame and the dark
   plate come from there. Duplicating them here would draw a border inside a
   border on any product with a thumbnail strip. */
.spot-media {
  border: 1px solid var(--line);
  border-radius: var(--radius);
  overflow: hidden;
}
.spot-media .gallery { border: 0; border-radius: 0; }
/* Taller and free-form rather than the product page's 4:3 - this is the whole
   front page when there is only one product to show. */
.spot-media .gallery .main { aspect-ratio: auto; min-height: 340px; padding: 22px; }
/* Scoped to .main: unscoped, this would also catch the 64px thumbnails and
   let each one render 460px tall. */
.spot-media .main img { max-height: 460px; width: auto; border-radius: 4px; }
.spot-kicker {
  margin: 0 0 8px;
  font-size: 12px;
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--dim);
}
.spot-title {
  font-family: var(--font-display);
  font-size: clamp(26px, 3.4vw, 36px);
  letter-spacing: -0.03em;
  line-height: 1.12;
  margin: 0 0 10px;
}
.spot-rating { display: flex; align-items: center; gap: 9px; margin: 0 0 20px; font-size: 13px; color: var(--muted); }
.spot-buy .buybox { padding: 20px; }

.spot-about {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
  gap: 34px;
  padding: 40px 0;
  margin-top: 28px;
  border-top: 1px solid var(--line);
}
.spot-about h2 { font-family: var(--font-display); font-size: 18px; letter-spacing: -0.02em; margin: 0 0 12px; }
.spot-about p { color: var(--muted); font-size: 14px; margin: 0 0 12px; }
.how-list { margin: 0 0 14px; padding-left: 18px; display: grid; gap: 9px; }
.how-list li { color: var(--muted); font-size: 14px; }
.how-list b { color: var(--text); font-weight: 600; }
.how-note { color: var(--dim) !important; font-size: 13px !important; }
.how-note a { color: var(--accent-hover); }

.spot-reviews { padding: 8px 0 40px; border-top: 1px solid var(--line); }
.spot-reviews .section-title { margin: 28px 0 16px; }
.spot-reviews .empty-state a { color: var(--accent-hover); }

@media (max-width: 860px) {
  .spotlight { grid-template-columns: 1fr; gap: 22px; padding-top: 20px; }
  .spot-media .gallery .main { min-height: 0; }
  .spot-media .main img { max-height: 320px; }
}

/* ---------- review extras ---------- */
.who-product {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  min-width: 0;
  color: var(--muted);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.who-product.is-gone { color: var(--dim); }
.who-thumb {
  flex: none;
  width: 20px;
  height: 20px;
  border-radius: 4px;
  overflow: hidden;
  border: 1px solid var(--line);
  background: #0f0f0f;
}
.who-thumb img { width: 100%; height: 100%; object-fit: cover; }
.who-by {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  margin-left: auto;
  white-space: nowrap;
}
.src-chip {
  font-size: 10.5px;
  color: var(--accent-hover);
  background: var(--accent-soft);
  border: 1px solid rgba(255,255,255,.26);
  border-radius: 999px;
  padding: 1px 8px;
}

/* ---------- admin ---------- */
.warn-banner {
  display: flex;
  gap: 14px;
  align-items: flex-start;
  padding: 16px 18px;
  border-radius: var(--radius);
  border: 1px solid rgba(255,255,255,.26);
  background: rgba(251, 191, 36, .07);
  color: var(--star);
  margin-bottom: 26px;
}
.warn-banner svg { flex: none; margin-top: 2px; }
.warn-banner b { font-size: 14px; }
.warn-banner p { margin: 4px 0 0; color: var(--muted); font-size: 13px; }
.warn-banner code, .prose code, .side-card code {
  font-family: var(--font-mono);
  font-size: 12px;
  background: var(--panel-2);
  border-radius: 4px;
  padding: 1px 5px;
}

.pending-count {
  display: inline-grid;
  place-items: center;
  min-width: 17px;
  height: 17px;
  padding: 0 5px;
  border-radius: 999px;
  background: var(--accent);
  color: #fff;
  font-size: 10.5px;
  font-weight: 700;
  margin-left: 5px;
}
.pending-count[hidden] { display: none; }

.field-row { display: grid; grid-template-columns: repeat(auto-fit, minmax(84px, 1fr)); gap: 10px; }
.field input[type="color"] { height: 38px; padding: 3px; cursor: pointer; }
.check-row { display: flex; align-items: center; gap: 9px; font-size: 13px; color: var(--muted); cursor: pointer; }
.check-row input { width: 15px; height: 15px; accent-color: var(--accent); }
.preview-row { display: flex; align-items: center; gap: 12px; }
.preview-row img { border-radius: 7px; background: #0f0f0f; padding: 4px; }

/* ---------- admin: blocked addresses ----------

   A list of addresses with an unblock next to each. Deliberately not a
   .vis-list: those rows are a measurement with a share bar behind them, and
   these are a standing decision with an undo. */
.ban-list { border: 1px solid var(--line); border-radius: var(--radius-sm); overflow: hidden; }
.ban-row {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 10px;
  padding: 10px 12px;
  border-bottom: 1px solid var(--line);
  font-size: 13px;
}
.ban-row:last-child { border-bottom: 0; }
.ban-row code { font-family: var(--font-mono); font-size: 12.5px; color: var(--text); word-break: break-all; }
/* The note and the date under the address, not beside it - an IPv6 address
   plus a reason does not fit on one line in a 300px column. */
.ban-row .ban-why { display: block; margin-top: 3px; color: var(--dim); font-size: 12px; }
.ban-row .ban-act { flex: none; }
.ban-list .empty { padding: 18px 12px; color: var(--dim); font-size: 12.5px; text-align: center; }
/* The address this admin is connected from, if they have blocked it. Worth
   pointing at: the storefront looks broken from here and this is why. */
.ban-row.is-you code { color: var(--danger); }

/* ---------- admin: payments ----------

   The coin's own mark next to its name, so the box you are pasting an address
   into is identified by the same badge the buyer sees at checkout rather than
   by a three-letter ticker in a label. */
.wallet-label { display: flex; align-items: center; gap: 8px; color: var(--text); font-size: 13.5px; }
.wallet-label .coin-mark { width: 18px; height: 18px; }
/* An address is a long unbroken string of characters that must be compared by
   eye, so it is set in the monospace face at the size the rest of the form
   uses rather than shrunk to fit. */
.field input.wallet-address { font-family: var(--font-mono); font-size: 12.5px; letter-spacing: .01em; }
/* Off, not broken: an empty box is a deliberate "we do not take this coin",
   and it reads as an unfinished form without something saying so. */
.wallet-off .wallet-label { color: var(--dim); }

/* ---------- admin: visitors ---------- */
.sr-only { position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0; }
.vis-head { display:flex; align-items:flex-end; justify-content:space-between; gap:24px; margin:4px 0 24px; }
.vis-head h2 { margin:3px 0 5px; font-size:clamp(28px,4vw,40px); letter-spacing:-.045em; }
.vis-head p { margin:0; color:var(--muted); max-width:620px; font-size:14px; }
.vis-eyebrow,.vis-kicker { color:#62d8ff; font-size:10px; font-weight:700; letter-spacing:.14em; text-transform:uppercase; }
.vis-head-actions { display:flex; align-items:center; gap:10px; flex:none; }
.vis-refresh { display:inline-flex; align-items:center; gap:7px; min-height:37px; padding:8px 12px; border:1px solid var(--line-strong); border-radius:999px; background:var(--panel); color:var(--muted); font:inherit; font-size:12px; cursor:pointer; }
.vis-refresh:hover { color:var(--text); border-color:rgba(98,216,255,.45); }
.vis-refresh svg,.vis-search svg { width:15px; fill:none; stroke:currentColor; stroke-width:1.8; stroke-linecap:round; stroke-linejoin:round; }
.vis-refresh.is-loading svg { animation:vis-spin .8s linear infinite; }
@keyframes vis-spin { to { transform:rotate(360deg); } }

.vis-stats {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
  gap: 10px;
  margin-bottom: 18px;
}
.vis-stat {
  border: 1px solid var(--line);
  border-radius: 14px;
  background:linear-gradient(145deg,rgba(255,255,255,.035),rgba(255,255,255,.012));
  padding: 17px 18px;
}
.vis-stat b { display:block; font-family:var(--font-mono); font-size:25px; letter-spacing:-.045em; line-height:1.2; }
.vis-stat span { font-size:11px; color:var(--dim); letter-spacing:.04em; text-transform:uppercase; }

.vis-command-grid { display:grid; grid-template-columns:minmax(0,1.35fr) minmax(310px,.65fr); gap:14px; margin-bottom:14px; }
.vis-globe-card,.vis-pulse-card,.vis-funnel-card { position:relative; overflow:hidden; border:1px solid var(--line); border-radius:18px; background:#0b0e14; }
.vis-card-head { display:flex; justify-content:space-between; align-items:flex-start; gap:18px; padding:19px 21px 0; }
.vis-card-head h3,.vis-section-head h3 { margin:3px 0 0; font-size:16px; letter-spacing:-.02em; }
.vis-live { display:inline-flex; align-items:center; gap:7px; color:var(--dim); font-size:11px; }
.vis-live i { width:6px;height:6px;border-radius:50%;background:#50e3a4;box-shadow:0 0 10px #50e3a4; }
.vis-globe-stage { position:relative; height:330px; overflow:hidden; touch-action:none; }
.vis-globe-stage::before { content:"";position:absolute;inset:0;background-image:radial-gradient(circle,rgba(255,255,255,.36) 0 1px,transparent 1.4px);background-size:47px 47px;opacity:.13;pointer-events:none; }
.vis-globe-stage canvas { position:absolute; inset:0; width:100%; height:100%; z-index:1; }
.vis-globe-help { position:absolute; z-index:2; left:18px; bottom:8px; margin:0; color:rgba(255,255,255,.32); font-size:10.5px; pointer-events:none; }
.vis-globe-tip { position:absolute; z-index:3; min-width:128px; padding:8px 10px; border:1px solid rgba(98,216,255,.28); border-radius:9px; background:rgba(5,10,18,.92); box-shadow:0 8px 30px rgba(0,0,0,.35); pointer-events:none; }
.vis-globe-tip b,.vis-globe-tip span { display:block; font-size:11px; }.vis-globe-tip span{margin-top:2px;color:var(--dim)}
.vis-globe-empty { position:absolute; z-index:2; inset:50% auto auto 50%; transform:translate(-50%,-50%); color:var(--dim); font-size:12px; }
.vis-country-strip { display:grid; grid-template-columns:repeat(4,1fr); border-top:1px solid var(--line); }
.vis-country-strip>div { padding:12px 15px; border-right:1px solid var(--line); }.vis-country-strip>div:last-child{border-right:0}
.vis-country-strip span { display:flex;align-items:center;gap:6px;color:var(--dim);font-size:10px;font-weight:700;letter-spacing:.08em; }
.vis-country-strip i { width:6px;height:6px;border-radius:50%;background:hsl(calc(192 + var(--rank)*12) 90% 65%); }
.vis-country-strip b { display:inline-block;margin:4px 4px 0 0;font-family:var(--font-mono);font-size:16px; }.vis-country-strip small{color:var(--dim);font-size:9px}

.vis-chart {
  display: flex;
  align-items: flex-end;
  gap: 3px;
  height: 302px;
  padding: 28px 20px 18px;
  background:repeating-linear-gradient(to bottom,transparent 0,transparent calc(25% - 1px),rgba(255,255,255,.04) 25%);
}
/* Each bar is a column so the count can sit above it and the date under it,
   with the coloured part taking whatever height is left. */
.vis-bar { flex: 1 1 0; display: grid; grid-template-rows: auto 1fr auto; gap: 5px; min-width: 0; height: 100%; }
.vis-bar i {
  align-self: end;
  border-radius: 4px 4px 0 0;
  background:linear-gradient(180deg,#61ddff 0%,#2478ff 100%);
  /* Every bar keeps a sliver of height, so a quiet day is a visible zero
     rather than a gap in the row. */
  min-height: 2px;
}
.vis-bar em, .vis-bar span {
  font-style: normal;
  font-size: 10.5px;
  text-align: center;
  color: var(--dim);
  white-space: nowrap;
  overflow: hidden;
}
.vis-bar em { color: var(--muted); }
.vis-bar.is-top em { color: var(--text); font-weight: 600; }
.vis-chart-legend { display:flex;justify-content:space-between;padding:0 20px 16px;color:var(--dim);font-size:10px; }.vis-chart-legend span{display:flex;align-items:center;gap:6px}.vis-chart-legend i{width:7px;height:7px;border-radius:2px;background:#45baff}

.vis-funnel-card { margin-bottom:28px; background:var(--panel); }
.vis-funnel-card .vis-card-head { align-items:center; padding-bottom:14px; }
.vis-funnel { padding:0 14px 14px; margin:0; grid-template-columns:repeat(auto-fit,minmax(120px,1fr)); }
.vis-funnel .vis-stat { background:var(--bg-alt); }
.vis-section-head { margin:0 0 12px; }

.vis-cols {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
  gap: 18px;
  margin-bottom: 8px;
}
.vis-cols .panel-block { margin-bottom:0; overflow:hidden; border-radius:14px; }
.vis-cols .panel-block h3 { padding:16px 18px; border-bottom:1px solid var(--line); }

/* A row is a label, a count, and a bar behind both showing its share. The bar
   is the row's own background so nothing has to be measured in JavaScript. */
.vis-row {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 10px 18px;
  font-size: 13.5px;
  border-bottom: 1px solid var(--line);
}
.vis-row:last-child { border-bottom: 0; }
.vis-row::before {
  content: "";
  position: absolute;
  inset: 0 auto 0 0;
  width: var(--share, 0%);
  background: var(--accent-soft);
  pointer-events: none;
}
.vis-row > * { position: relative; }
.vis-row .label { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.vis-row .count { color: var(--muted); font-variant-numeric: tabular-nums; flex: none; }
.vis-list .empty { padding: 26px 18px; color: var(--dim); font-size: 13px; text-align: center; }

/* Addresses are links, in mono like every other identifier on the site. */
.vis-ip {
  font-family: var(--font-mono);
  font-size: 12.5px;
  color: var(--text);
  text-decoration: none;
  border-bottom: 1px dotted var(--line-strong);
}
.vis-ip:hover { border-bottom-color: var(--accent); }

/* The recent list is clickable - each row opens that visit's journey. */
tr[data-vis-session] { cursor: pointer; }
.vis-path { font-family: var(--font-mono); font-size: 12.5px; }
.vis-who {
  display: inline-block;
  margin-left: 7px;
  padding: 1px 7px;
  border-radius: 999px;
  background: var(--accent-soft);
  color: var(--text);
  font-size: 11px;
}

.vis-activity-head { display:flex;align-items:flex-end;justify-content:space-between;gap:16px;margin:30px 0 12px; }
.vis-activity-head h2 { margin:3px 0 2px;font-size:22px; }.vis-activity-head .muted-text{font-size:11px}
.vis-search { display:flex;align-items:center;gap:8px;width:min(270px,40%);padding:9px 12px;border:1px solid var(--line);border-radius:10px;background:var(--panel);color:var(--dim); }
.vis-search:focus-within { border-color:rgba(98,216,255,.5);box-shadow:0 0 0 3px rgba(98,216,255,.08); }
.vis-search input { min-width:0;width:100%;padding:0;border:0;outline:0;background:transparent;color:var(--text);font:inherit;font-size:12px; }

@media (max-width:900px){.vis-command-grid{grid-template-columns:1fr}.vis-chart{height:220px}.vis-globe-stage{height:300px}}
@media (max-width:650px){
  .vis-head{align-items:flex-start;flex-direction:column}.vis-head-actions{width:100%;justify-content:space-between;overflow-x:auto}.vis-refresh{flex:none}
  .vis-stats{grid-template-columns:repeat(2,1fr)}.vis-stat:last-child:nth-child(odd){grid-column:1/-1}
  .vis-globe-stage{height:280px}.vis-country-strip{grid-template-columns:repeat(2,1fr)}.vis-country-strip>div:nth-child(2){border-right:0}.vis-country-strip>div:nth-child(-n+2){border-bottom:1px solid var(--line)}
  .vis-activity-head{align-items:stretch;flex-direction:column}.vis-search{width:100%}
}

/* ---------- admin: image uploads ----------
   The drop zone, the gallery being edited on the product form, and the library
   of everything uploaded. All three show the same 1:1 framed thumbnail, so a
   picture looks the same wherever it is being handled. */

.uploader {
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
  padding: 14px;
  border: 1px dashed var(--line-strong);
  border-radius: var(--radius-sm);
  background: var(--bg-alt);
  transition: border-color .15s, background .15s;
}
.uploader.is-over { border-color: var(--accent); background: var(--accent-soft); }
.uploader .btn { flex: none; }

.shots, .media-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(88px, 1fr));
  gap: 10px;
  margin-top: 12px;
}
/* Wider tiles in the library, which has a filename and a size under each. */
.media-grid { grid-template-columns: repeat(auto-fill, minmax(132px, 1fr)); gap: 14px; }

.shot, .media-item {
  position: relative;
  margin: 0;
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  background: #0f0f0f;
  overflow: hidden;
}
.shot img, .media-item img {
  display: block;
  width: 100%;
  aspect-ratio: 1;
  object-fit: contain;
  padding: 8px;
}
/* The first image is the one on the cards, the cart and the checkout, so it is
   marked - the order is otherwise invisible once the tiles are all the same. */
.shot-tag {
  position: absolute; top: 6px; left: 6px;
  padding: 2px 7px;
  border-radius: 999px;
  background: var(--accent);
  color: #061024;
  font-size: 10px;
  font-weight: 700;
  letter-spacing: .04em;
  text-transform: uppercase;
}
.media-item figcaption {
  display: grid;
  gap: 2px;
  padding: 8px 10px 10px;
  border-top: 1px solid var(--line);
  font-size: 11.5px;
  /* Filenames are one long unbroken word often enough to matter. */
  overflow-wrap: anywhere;
}

/* Revealed on hover and whenever a button inside has keyboard focus, so the
   controls are reachable without a pointer. */
.shot-bar {
  position: absolute; inset: auto 0 0 0;
  display: flex; gap: 1px;
  padding: 5px;
  background: linear-gradient(180deg, transparent, rgba(0,0,0,.85) 45%);
  opacity: 0;
  transition: opacity .15s;
}
.media-item .shot-bar { inset: 0 0 auto 0; background: linear-gradient(180deg, rgba(0,0,0,.85), transparent); justify-content: flex-end; }
.shot:hover .shot-bar, .media-item:hover .shot-bar,
.shot-bar:focus-within { opacity: 1; }
.shot-bar button {
  flex: 1;
  padding: 4px 6px;
  border: 0;
  border-radius: 5px;
  background: rgba(255,255,255,.12);
  color: var(--text);
  font: inherit;
  font-size: 12px;
  line-height: 1.4;
  cursor: pointer;
}
.media-item .shot-bar button { flex: 0 0 auto; }
.shot-bar button:hover:not(:disabled) { background: rgba(255,255,255,.24); }
.shot-bar button:disabled { opacity: .3; cursor: default; }
.shot-bar button.danger:hover { background: var(--danger); color: #fff; }

/* Path field and its Add button on one line - the button is not a submit, so
   it needs to read as part of the field rather than as the form's action. */
.url-add { display: flex; gap: 8px; }
.url-add input { flex: 1; min-width: 0; }
.url-add .btn { flex: none; padding-left: 14px; padding-right: 14px; }

.admin-prod { display: flex; align-items: center; gap: 10px; }
.admin-prod img { border-radius: 6px; background: #0f0f0f; padding: 3px; flex: none; }
.admin-prod span span { display: block; font-size: 11.5px; }
.btn-link.danger { color: var(--danger); margin-left: 12px; }

.admin-review {
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  background: var(--panel);
  padding: 15px 17px;
  margin-bottom: 11px;
}
.ar-head { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; margin-bottom: 8px; font-size: 12.5px; }
.admin-review p { margin: 0 0 8px; font-size: 13.5px; }
.ar-actions { display: flex; gap: 9px; margin-top: 12px; flex-wrap: wrap; }
.ar-actions .btn { padding: 8px 16px; font-size: 13px; }

.code-area {
  width: 100%;
  min-height: 180px;
  resize: vertical;
  background: var(--bg-alt);
  border: 1px solid var(--line-strong);
  border-radius: var(--radius-sm);
  color: var(--text);
  padding: 13px;
  font-family: var(--font-mono);
  font-size: 12px;
  line-height: 1.55;
}
.code-area:focus { outline: none; border-color: var(--accent); box-shadow: 0 0 0 3px var(--accent-soft); }

.contacts { display: grid; gap: 8px; margin-top: 14px; }
.contact-row {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  color: var(--muted) !important;
  font-size: 13.5px;
  margin: 0 !important;
}
.contact-row:hover { color: var(--text) !important; }
.contact-note { color: var(--dim); font-size: 12px; }
.contact-todo {
  margin: 14px 0 0;
  padding: 11px 13px;
  border: 1px dashed rgba(255,255,255,.35);
  border-radius: var(--radius-sm);
  color: var(--star) !important;
  font-size: 12.5px;
}

/* ---------- checkout QR ---------- */
.qr-block { display: grid; gap: 12px; }
.qr-block .btn svg { flex: none; }

.qr-panel { display: grid; gap: 10px; justify-items: center; }
.qr-panel[hidden] { display: none; }

/* Fixed square so the panel does not resize when the code lands - the button
   below it would otherwise jump under the cursor mid-click. */
.qr-stage {
  position: relative;
  width: 194px;
  height: 194px;
  display: grid;
  place-items: center;
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  background: var(--panel-2);
  overflow: hidden;
}

.qr-loader {
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  align-content: center;
  gap: 10px;
  font-size: 12px;
  color: var(--dim);
  transition: opacity .18s;
}
.qr-spinner {
  width: 22px;
  height: 22px;
  border-radius: 50%;
  border: 2px solid var(--line-strong);
  border-top-color: var(--accent);
  animation: qr-spin .7s linear infinite;
}
@keyframes qr-spin { to { transform: rotate(360deg); } }

.qr-canvas {
  border-radius: 3px;
  opacity: 0;
  transform: scale(.94);
  transition: opacity .22s ease, transform .22s ease;
}

.qr-panel.is-ready .qr-loader { opacity: 0; pointer-events: none; }
.qr-panel.is-ready .qr-canvas { opacity: 1; transform: none; }
/* Generation failed: the note explains it, so drop the empty white square. */
.qr-panel.is-failed .qr-stage { display: none; }

.qr-note { margin: 0; max-width: 34ch; text-align: center; font-size: 11.5px; color: var(--dim); }

@media (prefers-reduced-motion: reduce) {
  .qr-spinner { animation-duration: 2s; }
  .qr-canvas { transition: none; transform: none; }
}

/* ---------- checkout ---------- */
.checkout-grid { display: grid; grid-template-columns: minmax(0, 1fr) 300px; gap: 22px; align-items: start; }
.checkout-grid > * { min-width: 0; }
.checkout-grid > aside { position: sticky; top: 88px; }

.co-pad { padding: 22px; display: grid; gap: 20px; }
.co-empty { padding: 48px 24px; text-align: center; }
.co-empty p { color: var(--muted); margin: 0 0 18px; }
.co-label {
  display: block;
  margin-bottom: 10px;
  font-size: 11px;
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--dim);
}
.co-fine { margin: 0; text-align: center; color: var(--dim); font-size: 12px; }
.co-foot { display: flex; justify-content: space-between; gap: 14px; flex-wrap: wrap; }

.co-coins { min-width: 0; }
.coin-grid { display: grid; gap: 8px; }
.coin {
  display: grid;
  grid-template-columns: 26px minmax(0, 1fr) auto;
  align-items: center;
  gap: 12px;
  text-align: left;
  padding: 11px 13px;
  border-radius: var(--radius-sm);
  border: 1px solid var(--line);
  background: var(--bg-alt);
  color: var(--text);
  transition: border-color .15s, background .15s;
}
.coin:hover { border-color: var(--line-strong); }
.coin.is-active { border-color: var(--accent); background: var(--panel-2); }
.coin-ico { width: 26px; height: 26px; }
.coin-ico svg { width: 100%; height: 100%; display: block; }
.coin-main { min-width: 0; display: grid; }
.coin-main b { font-size: 14px; font-weight: 600; display: flex; align-items: baseline; gap: 6px; }
.coin-main em { font-style: normal; font-size: 10.5px; letter-spacing: .06em; color: var(--dim); }
.coin-main span { font-size: 11.5px; color: var(--dim); }
.coin-amt { font-family: var(--font-mono); font-size: 11.5px; color: var(--muted); white-space: nowrap; }

.pay-head { display: flex; align-items: baseline; justify-content: space-between; gap: 14px; }
.pay-head h3 { margin: 0; font-size: 16px; font-weight: 600; }
.pay-timer { font-size: 12px; color: var(--dim); }
.pay-timer b { font-family: var(--font-mono); color: var(--text); font-size: 13px; }
.pay-timer b.is-low { opacity: .65; }

.copy-field { display: grid; gap: 7px; }
.copy-field label { font-size: 12.5px; color: var(--muted); display: flex; align-items: center; gap: 9px; flex-wrap: wrap; }
.net-chip {
  font-size: 10.5px;
  color: var(--muted);
  background: var(--panel-2);
  border: 1px solid var(--line);
  padding: 2px 8px;
  border-radius: 999px;
}
.copy-row {
  display: flex;
  align-items: center;
  gap: 10px;
  border: 1px solid var(--line-strong);
  border-radius: var(--radius-sm);
  background: var(--bg-alt);
  padding: 10px 10px 10px 13px;
}
.copy-row code { flex: 1; min-width: 0; font-family: var(--font-mono); font-size: 12.5px; overflow-wrap: anywhere; }
.copy-btn {
  flex: none;
  background: var(--panel-2);
  border: 1px solid var(--line-strong);
  border-radius: 5px;
  color: var(--text);
  font-size: 11.5px;
  padding: 5px 11px;
  transition: border-color .15s;
}
.copy-btn:hover { border-color: var(--accent); }

.pay-status {
  display: flex;
  align-items: flex-start;
  gap: 12px;
  padding: 14px 16px;
  border-radius: var(--radius-sm);
  border: 1px solid var(--line);
  background: var(--panel-2);
  flex-wrap: wrap;
}
.pay-status b { font-size: 13.5px; }
.pay-status p { margin: 3px 0 0; color: var(--muted); font-size: 12.5px; }
.pay-status.is-expired { border-color: rgba(255,107,107,.35); }
/* payment seen on-chain but not yet confirmed - visibly different from both
   "waiting" and "expired" */
.pay-status.is-seen { border-color: var(--line-strong); background: var(--panel); }
.spinner {
  width: 15px; height: 15px;
  flex: none;
  margin-top: 3px;
  border-radius: 50%;
  border: 2px solid var(--line-strong);
  border-top-color: var(--text);
  animation: spin .8s linear infinite;
}
@keyframes spin { to { transform: rotate(360deg); } }
@media (prefers-reduced-motion: reduce) { .spinner { animation-duration: 3s; } }

.done-head { display: flex; align-items: center; gap: 14px; }
.done-check {
  width: 40px; height: 40px;
  flex: none;
  border-radius: 50%;
  display: grid; place-items: center;
  color: var(--text);
  background: var(--panel-2);
  border: 1px solid var(--line-strong);
}
.done-head h2 { margin: 0 0 3px; font-size: 19px; letter-spacing: -0.02em; }
.done-head p { margin: 0; color: var(--muted); font-size: 13px; }
.codes { display: grid; gap: 9px; }
.code-row {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 8px 12px;
  padding: 12px 12px 12px 15px;
  border: 1px solid var(--line-strong);
  background: var(--panel-2);
  border-radius: var(--radius-sm);
}
.code-row .code-for { font-size: 11.5px; color: var(--muted); flex: 0 0 100%; }
.code-row code { flex: 1; font-family: var(--font-mono); font-size: 14px; letter-spacing: .05em; overflow-wrap: anywhere; }
.code-note { margin: 0; color: var(--dim); font-size: 12px; }
.done-actions { display: flex; gap: 10px; flex-wrap: wrap; }

.summary-item {
  display: grid;
  grid-template-columns: 40px 1fr auto;
  gap: 11px;
  align-items: center;
  padding-bottom: 13px;
  margin-bottom: 13px;
  border-bottom: 1px solid var(--line);
}
.summary-item .li-img { width: 40px; height: 40px; border-radius: 6px; background: #0f0f0f; display: grid; place-items: center; padding: 4px; }
.summary-total { display: flex; justify-content: space-between; font-size: 15px; font-weight: 700; }
.summary-crypto {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 10px;
  margin-top: 12px;
  padding: 10px 12px;
  border-radius: var(--radius-sm);
  background: var(--panel-2);
  font-size: 12.5px;
  color: var(--muted);
}
.summary-crypto b { font-family: var(--font-mono); color: var(--text); font-size: 12px; }
.summary-help { margin: 14px 0 0; color: var(--dim); font-size: 12px; }
/* long product names and crypto amounts must wrap inside the sticky card
   rather than widening it */
.summary-card { min-width: 0; overflow-wrap: anywhere; }
.summary-help a { color: var(--text); text-decoration: underline; }

/* ---------- legal pages ---------- *//* ---------- legal pages ---------- */
.legal { display: grid; grid-template-columns: 230px minmax(0, 1fr); gap: 46px; align-items: start; }
.legal > nav { min-width: 0; }
.toc { position: sticky; top: 88px; display: grid; gap: 2px; }
.toc-title { font-size: 11.5px; letter-spacing: .13em; text-transform: uppercase; color: var(--dim); font-weight: 600; margin-bottom: 10px; }
.toc a {
  padding: 7px 12px;
  border-left: 2px solid var(--line);
  color: var(--muted);
  font-size: 13.5px;
  transition: color .15s, border-color .15s;
}
.toc a:hover { color: var(--text); }
.toc a.is-active { color: var(--text); border-left-color: var(--accent); }

.prose { max-width: 720px; }
.prose h2 {
  font-size: 21px;
  letter-spacing: -0.025em;
  margin: 40px 0 12px;
  scroll-margin-top: 90px;
}
.prose h2:first-child { margin-top: 0; }
.prose p, .prose li { color: var(--muted); font-size: 14.5px; }
.prose p { margin: 0 0 14px; }
.prose ul { margin: 0 0 16px; padding-left: 20px; display: grid; gap: 8px; }
.prose b { color: var(--text); }
.prose a { color: var(--accent-hover); }
.prose a:hover { text-decoration: underline; }
.callout {
  border: 1px solid rgba(255,255,255,.28);
  background: var(--accent-soft);
  border-radius: var(--radius-sm);
  padding: 16px 18px;
  margin: 0 0 20px;
}
.callout p { margin: 0; color: var(--text); font-size: 13.5px; }
.updated { color: var(--dim); font-size: 13px; margin-bottom: 26px; }

/* ---------- responsive ---------- */
@media (max-width: 900px) {
  .product { grid-template-columns: 1fr; }
  .account-grid { grid-template-columns: 1fr; }
  .checkout-grid { grid-template-columns: 1fr; }
  .checkout-grid > aside { position: static; }
  .legal { grid-template-columns: 1fr; gap: 26px; }
  .toc { position: static; display: flex; flex-wrap: nowrap; max-width: 100%; overflow-x: auto; padding-bottom: 6px; }
  .toc a { border-left: 0; border-bottom: 2px solid var(--line); white-space: nowrap; }
  .toc a.is-active { border-bottom-color: var(--accent); }
  .product > div:last-child { position: static; }
  .nav { display: none; }
  /* The nav's replacement. The negative margin pulls the brand back off the
     wrap's 24px gap, which is spacing for a nav bar, not for an icon. */
  .menu-btn { display: grid; margin-right: -12px; }
  .sidenav { display: flex; }

  /* Footer. .foot-top is "1fr auto", and the auto column (three link lists in
     a 56px-gapped flex row) claims its max-content width - which on a phone is
     the whole viewport, starving the brand column down to a few pixels and
     wrapping the contact text one word per line. Stack them instead. */
  .foot-top { grid-template-columns: 1fr; gap: 30px; }
  .foot-brand { max-width: none; }
  .foot-links { flex-wrap: wrap; gap: 26px 44px; }
}
@media (max-width: 560px) {
  .btn-login { display: none; }
  /* Three link lists side by side no longer fit; two columns read better than
     a squeezed three. */
  .foot-links > div { min-width: 40%; }
}

/* ============================================================
   Giveaways
   ============================================================ */

/* A dot on the nav link while a draw is taking entries. Sized and positioned
   off the link's own box rather than given a badge with a number in it: the
   count is not actionable, "something is running" is. */
.nav a { position: relative; }
.nav-dot {
  display: inline-block;
  width: 6px; height: 6px;
  margin-left: 1px;
  vertical-align: 5px;
  border-radius: 999px;
  background: var(--accent);
  box-shadow: 0 0 0 3px rgba(255,255,255,.12);
}

/* ---------- header account chip ---------- */

/* <details>, so it opens, closes and takes focus without any script. */
.acct { position: relative; }
.acct > summary {
  display: flex;
  align-items: center;
  gap: 7px;
  padding: 5px 10px 5px 6px;
  border: 1px solid var(--line-strong);
  border-radius: 999px;
  color: var(--text);
  font-size: 13.5px;
  cursor: pointer;
  list-style: none;
  transition: background .15s, border-color .15s;
}
.acct > summary::-webkit-details-marker { display: none; }
.acct > summary:hover { background: var(--panel-2); }
.acct[open] > summary { background: var(--panel-2); border-color: rgba(255,255,255,.28); }
.acct > summary img { border-radius: 999px; }
.acct-name { max-width: 110px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

.acct-menu {
  position: absolute;
  top: calc(100% + 8px);
  right: 0;
  z-index: 40;
  width: 262px;
  padding: 14px;
  background: var(--panel-solid);
  border: 1px solid var(--line-strong);
  border-radius: 12px;
  box-shadow: var(--shadow);
}
.acct-who { margin: 0 0 10px; font-size: 13px; color: var(--muted); line-height: 1.5; }
.acct-who b { color: var(--text); }
.acct-good { display: block; margin-top: 4px; color: var(--text); }
.acct-hint { display: block; margin-top: 4px; color: var(--dim); }
.acct-link {
  display: block;
  padding: 8px 0;
  font-size: 13.5px;
  color: var(--text);
  border-top: 1px solid var(--line);
}
.acct-link:hover { color: var(--muted); }
.acct-out {
  width: 100%;
  margin-top: 4px;
  padding: 9px 0;
  font: inherit;
  font-size: 13.5px;
  color: var(--muted);
  text-align: left;
  background: none;
  border: 0;
  border-top: 1px solid var(--line);
  cursor: pointer;
}
.acct-out:hover { color: var(--text); }

/* ---------- sign-in panel ---------- */

.gw-account { margin-bottom: 26px; }
.gw-account[hidden] { display: none; }
.gw-acct-row {
  display: flex;
  align-items: center;
  gap: 22px;
  padding: 22px 24px;
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: var(--radius);
}
.gw-acct-row > div:first-child { flex: 1; }
.gw-acct-row h2 { font-size: 17px; margin: 0 0 6px; letter-spacing: -0.01em; }
.gw-acct-row p { margin: 0; color: var(--muted); font-size: 13.5px; line-height: 1.6; max-width: 62ch; }
.gw-acct-row .btn { flex: none; }

.gw-avatar { border-radius: 999px; flex: none; }
.gw-avatar-blank {
  display: inline-block;
  width: 44px; height: 44px;
  border-radius: 999px;
  background: var(--panel-2);
  border: 1px solid var(--line-strong);
  flex: none;
}
.gw-acct-who { flex: 1; }
.gw-acct-who b { display: block; font-size: 15px; margin-bottom: 3px; }
.gw-acct-good, .gw-acct-hint { font-size: 13px; }
.gw-acct-good { color: var(--text); }
.gw-acct-hint { color: var(--dim); }
.gw-acct-hint a, .gw-acct-good a { color: var(--text); text-decoration: underline; text-underline-offset: 2px; }
.gw-acct-out { flex: none; }

/* ---------- sign-in outcome note ---------- */

.gw-note {
  margin: 0 0 22px;
  padding: 12px 16px;
  font-size: 13.5px;
  border-radius: var(--radius-sm);
  border: 1px solid var(--line-strong);
  background: var(--panel);
  color: var(--text);
}
.gw-note[hidden] { display: none; }
.gw-note.is-good { border-color: rgba(255,255,255,.3); }
.gw-note.is-warn { border-color: rgba(255,107,107,.45); color: #ffc9c9; }
.gw-note.is-plain { color: var(--muted); }

/* ---------- the draws ---------- */

.gw-list { display: grid; gap: 18px; }
.gw-loading { color: var(--dim); font-size: 14px; padding: 30px 0; }

/* One draw gets the full width and reads like a banner. From the second card
   on, the list becomes a real grid and the cards go image-on-top, so two
   giveaways sit side by side instead of running a screen and a half down the
   page. :has() is doing the counting - there is no class for it in the JS. */
.gw-list:has(> .gw-card:nth-child(2)) {
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 330px), 1fr));
}
.gw-list:has(> .gw-card:nth-child(2)) .gw-card {
  grid-template-columns: 1fr;
  grid-template-rows: auto 1fr;
}
.gw-list:has(> .gw-card:nth-child(2)) .gw-media {
  border-right: 0;
  border-bottom: 1px solid var(--line);
  padding: 24px;
}
/* The art is landscape and the band is now the full width of the card, so the
   cap is on height alone - a small one here leaves the picture stranded in the
   middle of a wide empty band, which is smaller than it was in the old 232px
   side column, not larger. */
.gw-list:has(> .gw-card:nth-child(2)) .gw-media img { max-height: 230px; }
.gw-list:has(> .gw-card:nth-child(2)) .gw-body {
  display: flex;
  flex-direction: column;
  padding: 20px 22px 22px;
}
/* Children of a flex column are flex items, and a flex item stretches. Without
   this the inline-block pill runs the full width of the card and stops looking
   like a pill at all. */
.gw-list:has(> .gw-card:nth-child(2)) .gw-bonus { align-self: flex-start; }
/* Buttons line up across the row however much description each draw carries. */
.gw-list:has(> .gw-card:nth-child(2)) .gw-cta { margin-top: auto; }
.gw-list:has(> .gw-card:nth-child(2)) .gw-stats { gap: 10px 22px; }
/* Three lines, then an ellipsis. The full text is on the product page. */
.gw-list:has(> .gw-card:nth-child(2)) .gw-desc {
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 3;
  line-clamp: 3;
  overflow: hidden;
}

.gw-card {
  display: grid;
  grid-template-columns: 232px 1fr;
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  overflow: hidden;
  transition: border-color .2s;
}
.gw-card:hover { border-color: var(--line-strong); }
.gw-card.is-done { opacity: .82; }
.gw-card.is-done:hover { opacity: 1; }

.gw-media {
  position: relative;
  display: grid;
  place-items: center;
  padding: 24px;
  background: var(--bg-alt);
  border-right: 1px solid var(--line);
}
.gw-media img {
  max-width: 100%;
  max-height: 190px;
  filter: drop-shadow(0 14px 26px rgba(0,0,0,.55));
}
.gw-flag {
  position: absolute;
  top: 12px; left: 12px;
  padding: 4px 9px;
  border-radius: 999px;
  font-size: 10.5px;
  font-weight: 700;
  letter-spacing: .06em;
  text-transform: uppercase;
  background: var(--accent);
  color: #000;
}
.gw-card.is-done .gw-flag { background: var(--panel-2); color: var(--muted); box-shadow: inset 0 0 0 1px var(--line-strong); }

.gw-body { padding: 22px 24px 24px; }
.gw-title { font-size: 19px; margin: 0 0 7px; letter-spacing: -0.02em; }
.gw-prize {
  display: block;
  margin: 0 0 10px;
  font-size: 14px;
  color: var(--muted);
}
a.gw-prize { color: var(--text); text-decoration: underline; text-underline-offset: 3px; text-decoration-color: var(--line-strong); }
a.gw-prize:hover { text-decoration-color: var(--accent); }
.gw-bonus {
  display: inline-block;
  margin-bottom: 12px;
  padding: 4px 10px;
  border-radius: 999px;
  border: 1px solid var(--line-strong);
  font-size: 11.5px;
  color: var(--text);
}
.gw-desc {
  margin: 0 0 16px;
  font-size: 13.5px;
  color: var(--muted);
  line-height: 1.65;
  max-width: 68ch;
  white-space: pre-line;
}

.gw-stats {
  display: flex;
  /* Wraps rather than overflowing: a long countdown next to a six-figure pool
     will not always sit on one line on a narrow phone. */
  flex-wrap: wrap;
  gap: 12px 30px;
  padding: 14px 0;
  margin-bottom: 16px;
  border-top: 1px solid var(--line);
  border-bottom: 1px solid var(--line);
}
.gw-stats b {
  display: block;
  font-size: 17px;
  font-weight: 650;
  letter-spacing: -0.02em;
  /* Tabular figures, so a ticking countdown does not shuffle the numbers
     beside it left and right every second. */
  font-variant-numeric: tabular-nums;
}
.gw-stats span { font-size: 11.5px; color: var(--dim); text-transform: uppercase; letter-spacing: .06em; }

.gw-cta { display: flex; flex-direction: column; align-items: flex-start; gap: 9px; }
.gw-cta .btn { flex: none; }
.gw-cta-note { margin: 0; font-size: 12.5px; color: var(--dim); line-height: 1.55; }
.gw-cta-note a { color: var(--muted); text-decoration: underline; text-underline-offset: 2px; }
.gw-cta-note a:hover { color: var(--text); }

.gw-entered {
  display: flex;
  align-items: center;
  gap: 8px;
  margin: 0;
  font-size: 14px;
  font-weight: 600;
  color: var(--text);
}
.gw-entered svg { color: var(--green); }

.gw-won-label {
  margin: 0;
  font-size: 11.5px;
  text-transform: uppercase;
  letter-spacing: .07em;
  color: var(--dim);
}
.gw-winners { display: flex; flex-wrap: wrap; gap: 8px; margin: 0; padding: 0; list-style: none; }
.gw-winners li {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 5px 12px 5px 5px;
  border-radius: 999px;
  background: var(--panel-2);
  border: 1px solid var(--line-strong);
  font-size: 13.5px;
}
.gw-winners img { border-radius: 999px; }
.gw-winners .gw-avatar-blank { width: 24px; height: 24px; }
.gw-you-won { margin: 4px 0 0; font-size: 13.5px; font-weight: 600; color: var(--text); }

.gw-discord svg { flex: none; }

/* ---------- nothing running ---------- */

.gw-empty {
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  padding: 62px 24px;
  background: var(--panel);
  border: 1px dashed var(--line-strong);
  border-radius: var(--radius);
  color: var(--dim);
}
.gw-empty h2 { font-size: 19px; margin: 16px 0 8px; color: var(--text); letter-spacing: -0.02em; }
.gw-empty p { margin: 0 0 20px; font-size: 14px; color: var(--muted); max-width: 46ch; line-height: 1.6; }

/* ---------- finished draws ---------- */

.gw-past { margin-top: 46px; }
.gw-past[hidden] { display: none; }

/* ---------- the rules ---------- */

.gw-fine {
  margin: 46px 0 20px;
  padding: 24px 26px;
  background: var(--bg-alt);
  border: 1px solid var(--line);
  border-radius: var(--radius);
}
.gw-fine h2 { font-size: 15px; margin: 0 0 12px; color: var(--muted); font-weight: 600; }
.gw-fine ul { margin: 0; padding-left: 18px; }
.gw-fine li { font-size: 13px; color: var(--dim); line-height: 1.7; }

@media (max-width: 860px) {
  .gw-card { grid-template-columns: 1fr; }
  .gw-media { border-right: 0; border-bottom: 1px solid var(--line); padding: 30px; }
  .gw-media img { max-height: 160px; }
  .gw-acct-row { flex-wrap: wrap; gap: 16px; }
  .gw-acct-row .btn, .gw-acct-out, .gw-acct-out .btn { width: 100%; }
}
@media (max-width: 560px) {
  .gw-stats { gap: 20px; }
  /* The name goes, the picture stays - it is the part that says "that is you"
     and it costs 22 pixels. */
  .acct-name { display: none; }
  .acct-menu { width: min(262px, calc(100vw - 32px)); }
}

/* ============================================================
   Mobile and touch

   Everything above this point is the layout. This block is the set of
   corrections that only matter on a phone, kept together at the end so the
   rules it overrides are already in the cascade and none of it needs
   !important. Four kinds of rule live here, in order:

     1. capability queries  - pointer:coarse and hover:none, which are about
                              the input device, not the screen width. A touch
                              laptop gets these; a narrow desktop window does
                              not, which is the correct split.
     2. safe-area insets    - keeping fixed panels clear of the home indicator.
     3. width breakpoints   - 760 / 560 / 400, narrowing the layout.
     4. landscape           - short viewports, where vertical padding is the
                              scarce resource rather than horizontal.
   ============================================================ */

/* ---------- 1a. iOS focus zoom ----------

   Mobile Safari zooms the whole page in when a text field smaller than 16px
   takes focus, and it does not zoom back out on blur - the visitor is left on
   a page scrolled sideways, mid-checkout, having to pinch their way back. It
   is the single most-felt bug on this site from a phone.

   The fix is the font-size, not the viewport: a maximum-scale/user-scalable=no
   meta tag would also stop the zoom, but by taking pinch-zoom away from
   everyone, which is a real accessibility regression and is ignored by iOS
   anyway. 16px is the threshold, so every field that takes typed input gets
   exactly that. Applied by pointer type so the desktop layout keeps its
   smaller fields. */
@media (pointer: coarse) {
  .field input,
  .field textarea,
  .field select,
  .search-row input,
  .stepper input,
  .code-area,
  .entry-weight,
  input[type="text"],
  input[type="email"],
  input[type="search"],
  input[type="number"],
  input[type="password"],
  input[type="url"],
  textarea,
  select {
    font-size: 16px;
  }
}

/* ---------- 1b. touch targets ----------

   The desktop sizes here are 26-36px, which is fine for a cursor and too small
   for a fingertip. --tap (44px) is the floor. Padding is used to reach it
   where the control's own box should stay visually small - a chip that grows
   to 44px tall looks wrong, so it keeps its height and gains an invisible
   hit area instead. */
@media (pointer: coarse) {
  .btn { min-height: var(--tap); }
  .btn-lg { min-height: 50px; }
  /* Not a .btn - it is the header's own login control, and it survives down to
     560px where it is hidden for space. */
  .btn-login { min-height: var(--tap); }

  .icon-btn {
    width: var(--tap);
    height: var(--tap);
  }

  /* Quantity stepper. The buttons are the most-missed targets on the product
     page: 36px squares either side of a field, so a near-miss lands in the
     input and pops the keyboard open instead of changing the count. */
  .stepper button { width: var(--tap); height: var(--tap); }
  .stepper input { height: var(--tap); width: 56px; }

  /* Copy buttons on the payment step. Missing these means the buyer hand-types
     a crypto address, so they are worth the extra height. */
  .copy-btn { min-height: 38px; padding: 9px 16px; font-size: 12.5px; }

  .nav a { padding: 11px 14px; }
  .sidenav-links a { padding: 15px 14px; }
  .subnav a { padding: 11px 16px; }
  .toc a { padding: 11px 14px; }
  .chip { padding: 9px 15px; }
  .pill-tab { padding: 10px 16px; }
  .page-btn { min-width: 40px; min-height: 40px; }
  .coin { padding: 14px 13px; }

  /* Text-styled buttons ("Remove", "Change coin or email", the admin row
     actions). These have no box of their own, so they get vertical padding and
     a negative margin that keeps the layout spacing unchanged - the target
     grows, the design does not move. */
  .btn-link,
  .li-remove {
    padding-top: 10px;
    padding-bottom: 10px;
    margin-top: -10px;
    margin-bottom: -10px;
  }

  /* FAQ rows. The <summary> is the whole hit area and it should feel like it. */
  details.q summary { padding-top: 14px; padding-bottom: 14px; }

  /* Footer link columns. Padding replaces the margin so the rows butt up
     against each other at 44px tall - a stack of full-width rows with no dead
     gap between them, which is how a footer list should behave on a phone. */
  .foot-links a { padding: 11px 0; margin-bottom: 0; }
  .sidenav-legal a { padding: 9px 0; }

  /* Brand lockups (header and footer) and the contact rows are all inline-flex
     already, so a min-height centres their content for free. */
  .brand,
  .contact-row { min-height: var(--tap); }

  /* Breadcrumbs. The negative margin gives back exactly what the padding takes,
     so the crumb strip keeps the height it has on desktop. */
  .crumbs a { padding: 11px 0; margin: -11px 0; }

  /* Admin colour swatches - the only inputs the 16px rule above does not
     reach, since a colour well has no text to size. */
  .field input[type="color"] { height: var(--tap); }
}

/* ---------- 1c. hover states on touch ----------

   A touch browser fires :hover on tap and leaves it applied until something
   else is tapped, so every lift, scale and glow here sticks to whichever card
   the visitor last touched. Movement is the part that reads as broken, so the
   transforms are cancelled and the colour changes are left alone - those are
   harmless, and on a tap they double as press feedback.

   This block is deliberately blunt rather than restating each rule under
   @media (hover: hover): there are around sixty hover rules above and only the
   handful that move something are a problem. */
@media (hover: none) {
  .card:hover .card-media img,
  .coin-mark:hover {
    transform: none;
  }
  /* The primary button's hover glow is brighter than its resting one and has
     no reason to stay lit on the last thing tapped. */
  .btn-primary:hover:not(:disabled) { box-shadow: var(--glow); }

  /* Press feedback instead. A tap is instantaneous, so without this the only
     confirmation a card was hit is the page changing. (.btn keeps its
     existing :active nudge, which already works correctly on touch.) */
  .pcard:active,
  .card:active,
  .coin:active { border-color: var(--accent); }
}

/* ---------- 2. safe-area insets ----------

   Fixed elements pinned to the bottom of the viewport sit under the home
   indicator on a gesture-navigation phone: the cart's Checkout button and the
   menu's legal links are both directly under it, and the toast is close
   enough to be clipped. Padding, not margin, so the panel background still
   runs to the physical edge of the screen. */
.drawer > footer {
  padding-bottom: max(18px, calc(18px + env(safe-area-inset-bottom)));
}
.sidenav-foot {
  padding-bottom: max(16px, calc(16px + env(safe-area-inset-bottom)));
}
/* The toast moves to the top on phones.

   Bottom-centre is fine on a desktop, where the cart drawer is a 390px panel
   on the right and the toast clears it. On a phone the drawer is full width
   and its footer holds the Checkout button, so a bottom-centred toast lands
   exactly on top of the primary action - and "Added to cart" is the toast that
   fires as that button appears, so it covered the checkout CTA every single
   time. Top-centre is clear of both that footer and the home indicator.

   Slides down from above rather than up from below, so the entrance still
   moves away from the edge it is anchored to. */
@media (max-width: 560px) {
  .toast {
    top: max(14px, calc(14px + env(safe-area-inset-top)));
    bottom: auto;
    left: 50%;
    width: max-content;
    max-width: calc(100vw - 28px);
    transform: translate(-50%, -20px);
    text-align: center;
  }
  .toast.is-on { transform: translate(-50%, 0); }
}

@media (min-width: 561px) {
  .toast {
    bottom: max(26px, calc(26px + env(safe-area-inset-bottom)));
  }
}
/* Landscape, notch on the left or right: the panel edge itself is off-screen. */
.drawer { padding-right: env(safe-area-inset-right); }
.sidenav { padding-left: env(safe-area-inset-left); }

/* Scrolling inside either panel should not hand off to the page behind it once
   it hits the end - the list bounces and the page underneath moves, which
   makes the panel feel detached. (The page is already scroll-locked in JS
   while a panel is open; this stops the rubber-band handoff on iOS, which the
   lock does not cover.) */
.drawer .items,
.sidenav-links {
  overscroll-behavior: contain;
  -webkit-overflow-scrolling: touch;
}

/* ---------- 3a. tablet and below (760px) ---------- */
@media (max-width: 760px) {
  /* Checkout is the one flow where a mistake costs money, so it gets the most
     attention. Below this width the address and its Copy button no longer fit
     on one line: the address wraps to three lines and the button ends up
     floating beside the middle of it. Stack them and run the button full
     width - it becomes the easiest thing on the screen to hit, which is what
     it should be. */
  .copy-row {
    flex-direction: column;
    align-items: stretch;
    gap: 12px;
    padding: 13px;
  }
  .copy-row code { font-size: 13px; line-height: 1.6; }
  .copy-btn { width: 100%; }

  /* The QR is scanned by a second device held over the screen, so on a phone
     it wants to be bigger, not smaller. Capped in vw so it cannot outgrow the
     panel it sits in. */
  .qr-stage { width: min(260px, 74vw); height: min(260px, 74vw); }

  .co-pad { padding: 18px; gap: 18px; }
  .pay-head { flex-wrap: wrap; gap: 6px 14px; }
  .done-head { align-items: flex-start; }

  /* Admin. Ten tabs wrapping to four rows pushes the panel below the fold
     before anything has been read; a single scrolling strip is the same
     treatment .toc already gets on this breakpoint. */
  .subnav {
    flex-wrap: nowrap;
    overflow-x: auto;
    overscroll-behavior-x: contain;
    scrollbar-width: none;
    margin-left: calc(var(--gutter) * -1);
    margin-right: calc(var(--gutter) * -1);
    padding: 2px var(--gutter) 10px;
  }
  .subnav::-webkit-scrollbar { display: none; }
  .subnav a { flex: none; white-space: nowrap; }

  /* The data tables keep their horizontal scroll rather than restacking as
     cards - the rows are written by admin.js without per-cell labels, so a
     stacked card would be a column of unlabelled values. Narrowing the minimum
     and letting each scroller snap makes the scroll usable instead. */
  table.data { min-width: 520px; }
  .table-wrap { overscroll-behavior-x: contain; -webkit-overflow-scrolling: touch; }
}

/* ---------- 3b. phone (560px) ---------- */
@media (max-width: 560px) {
  :root { --gutter: 18px; }

  /* Two across, not one. A single column turns a ten-product catalog into a
     very long scroll and makes each card a banner; two lets the grid still
     read as a catalog. The cards get tighter type to suit the narrower box. */
  .pgrid { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 10px; }
  .pcard-title { font-size: 13px; }
  .pcard-price { font-size: 14px; }
  .pcard-body { padding: 11px 12px 13px; }
  .pcard-stock { font-size: 10px; }

  /* The tag chips go. They are the same two or three phrases on every card
     ("Instant delivery", "Unredeemed"), so in a grid they carry nothing that
     tells one product from another - and at this width they wrap to two rows
     and cost about 44px of every tile, which is more than the price and stock
     lines put together. The product page still lists them. */
  .pcard-tags { display: none; }

  /* Keeps price and stock on one line: with the tags gone there is room, but
     a struck-through "was" price alongside a 5-digit price is still the case
     that wraps and leaves the two cards in a row misaligned. */
  .pcard-price .was { font-size: 9.5px; margin-left: 4px; }

  .cat { margin-bottom: 26px; }
  .result-count { margin-bottom: 16px; }

  .hero-title { max-width: 18ch; }
  .home-section .sec-head { margin-bottom: 20px; }

  /* Steps and FAQ read fine stacked; the reviews grid is already 1fr here. */
  .steps { gap: 14px; }
  .contact-banner { padding: 22px; }
  .contact-banner .contacts .btn { width: 100%; }

  /* Cart drawer: full width. A 390px panel on a 375px screen is already
     effectively full width but leaves a sliver of scrim that swallows taps
     meant for the panel edge. */
  .drawer { width: 100%; }

  .page-head { padding: 30px 0 24px; margin-bottom: 28px; }
  .co-foot { justify-content: center; }
  .checkout-grid { gap: 16px; }

  /* Announcement strip. The two lines are laid out with space-between, which on
     a phone means both wrap to two lines each and the strip costs ~118px above
     the header - a fifth of the screen, spent before the visitor has seen the
     shop. The second line ("ask before you send anything") is advice that the
     contact banner and the Discord CTA both repeat further down; the first is
     the delivery promise and is the one that has to survive. Same call already
     made for .btn-login and .acct-name at this width. */
  .announce .wrap { justify-content: center; text-align: center; }
  .announce span:last-child { display: none; }

  /* Table cells: the desktop 15px/18px padding is what forces the horizontal
     scroll to be long. Tightening it fits one more column on screen. */
  table.data th, table.data td { padding: 11px 12px; font-size: 12.5px; }
}

/* ---------- 3c. small phone (400px) ----------

   360px-class Androids and the iPhone SE. The gutter is the main lever: at
   24px a side the content box on a 360px screen is 312px, and every fixed
   minimum above starts fighting it. */
@media (max-width: 400px) {
  :root { --gutter: 14px; }

  /* The grid stays two across here rather than dropping to one. A single
     column on a phone gives every tile a full-width square image, which turns
     an eight-product catalog into a ten-thousand-pixel scroll and makes each
     product read as a banner ad. At 320px - the narrowest phone still in use -
     two columns are 141px each, which the title, price and stock all still fit
     inside. Only the image gets shorter, so the tiles stop being square and a
     whole row lands on screen at once. */
  .pgrid { gap: 8px; }
  .pcard-media { aspect-ratio: 4 / 5; padding: 10px; }
  .pcard-body { padding: 9px 10px 11px; }
  .pcard-title { font-size: 12.5px; }

  .hero-title { font-size: clamp(27px, 8.4vw, 34px); }
  .hero-badge { font-size: 10.5px; padding: 5px 11px; }
  /* Three statements on one line each, centred, rather than an uneven wrap. */
  .check-row { flex-direction: column; align-items: center; gap: 9px; }

  .sec-head h2 { font-size: 21px; }
  .about { padding-left: 18px; padding-right: 18px; }
  .about .row .btn { width: 100%; }

  /* Crypto addresses are the longest unbreakable string on the site. */
  .copy-row code { font-size: 12px; }
  .code-row code { font-size: 13px; }

  .foot-links { gap: 22px 30px; }
  .foot-bottom { flex-direction: column; align-items: flex-start; gap: 14px; }
}

/* ---------- 4. short viewports ----------

   A phone in landscape is ~360px tall with the URL bar showing. The hero's
   min-height is a clamp on 68vh, which is correct in portrait and leaves the
   headline alone on screen in landscape with the buttons below the fold. */
@media (max-height: 520px) and (orientation: landscape) {
  .hero { min-height: 0; }
  .hero-inner { padding-top: 36px; padding-bottom: 36px; }
  .hero-title { font-size: clamp(26px, 4.4vw, 36px); }
  .check-row, .pay-strip { margin-top: 16px; }
  .home-section { padding-top: 38px; padding-bottom: 38px; }
}
