/* catalog.css — the product pages.
   Loaded AFTER policy.css, which supplies the shell: theme tokens, header,
   .wrap, footer, tables and .note.

   THE LOOK
   The first version of these pages was the policy-page shell with a product in
   it, and it read like a terms-of-sale page that happened to have a price on
   it. The storefront, the business card and the link-preview cover all share
   one scene — violet ground, a tilted orbit, scattered stars, holo on the
   accent — specified in BRAND/STYLE-GUIDE.md and built in BRAND/og-cover.html.
   The product hero below is that same scene, with the same numbers, so a
   visitor arriving from Google lands on the same brand the ads sold them.

   Everything BELOW the hero stays on the flat dark ground. The scene is
   atmosphere for the buy decision; specifications and shipping terms are read,
   and reading them over a gradient is worse, not better. */

:root{
  --holo-line:linear-gradient(90deg,#6EE7F0 0%,#A78BFA 28%,#FF9EC4 54%,#FFE39A 76%,#6EE7F0 100%);
  --spark-cyan:#6EE7F0; --spark-pink:#FF9EC4; --spark-gold:#FFE39A;
}

/* The inverted brand chip, matching the storefront's .chipmk and the favicon.
   The gradient sits on the inner SPAN: background-clip:text consumes the
   element's own background, so a chip painting the gradient on itself could
   not also have a dark ground. */
.brand .bn{display:block;font-family:'Bricolage Grotesque',system-ui,sans-serif;font-size:19px;letter-spacing:-.02em;font-weight:800}

/* ── width ────────────────────────────────────────────────────────────────
   policy.css caps .wrap at 760px, which is right for a page of prose and far
   too narrow for a product: the hero was a letterbox down the middle of a
   black screen with the whole scene squeezed into it.

   So the page runs wide and the PROSE does not. The hero, the thumbnails and
   the related grid get the full 1220px; the copy below keeps a ~75-character
   measure, because a specification paragraph set 1200px wide is genuinely
   harder to read -- the eye loses the line on the way back. Two different
   jobs, two different widths, one page. */
body.pdp-page .wrap{max-width:1220px}
body.pdp-page main{max-width:820px}

.crumbs{font-size:13px;color:var(--ink-2);margin:24px 0 16px}
.crumbs a{color:var(--ink-2);text-decoration:none}
.crumbs a:hover{color:var(--ink);text-decoration:underline}
.crumbs span{opacity:.5;margin:0 6px}

/* ── the space scene ──────────────────────────────────────────────────────
   Numbers lifted from BRAND/og-cover.html: darkest top-left, violet glows
   rising from bottom-left and top-right. Stars are one tiled background
   rather than 40 elements — same look, no DOM, nothing to animate. */
.scene{
  position:relative;overflow:hidden;border-radius:22px;margin:0 0 34px;padding:34px;
  background:
    radial-gradient(62% 78% at 12% 104%, rgba(139,92,246,.58) 0%, rgba(91,61,245,.22) 42%, transparent 72%),
    radial-gradient(54% 66% at 96% -8%, rgba(167,139,250,.46) 0%, rgba(110,231,240,.10) 46%, transparent 74%),
    radial-gradient(40% 44% at 78% 96%, rgba(255,158,196,.20) 0%, transparent 70%),
    linear-gradient(150deg,#0B0A18 0%,#141032 42%,#1B1440 72%,#241a4d 100%);
  box-shadow:0 24px 60px rgba(0,0,0,.45);
}
/* stars: four sizes at four offsets, one layer */
.scene:before{
  content:"";position:absolute;inset:0;pointer-events:none;opacity:.55;
  background-image:
    radial-gradient(1.6px 1.6px at 18% 22%, #fff, transparent),
    radial-gradient(1.2px 1.2px at 67% 12%, #fff, transparent),
    radial-gradient(1.9px 1.9px at 86% 44%, #fff, transparent),
    radial-gradient(1.1px 1.1px at 32% 68%, #fff, transparent),
    radial-gradient(1.5px 1.5px at 54% 84%, #fff, transparent),
    radial-gradient(1.2px 1.2px at 8% 52%, #fff, transparent),
    radial-gradient(1.7px 1.7px at 94% 76%, #fff, transparent),
    radial-gradient(1.1px 1.1px at 44% 34%, #fff, transparent);
}
/* the tilted orbit, signature of the card art */
.scene:after{
  content:"";position:absolute;width:128%;height:74%;left:6%;top:16%;pointer-events:none;
  border:1.5px solid rgba(199,183,255,.20);border-radius:50%;transform:rotate(-17deg);
  box-shadow:0 0 60px rgba(167,139,250,.10) inset;
}

.pdp{position:relative;z-index:2;display:grid;grid-template-columns:minmax(0,1.02fr) minmax(0,1fr);gap:36px;align-items:center}

.pdp-art{
  background:radial-gradient(120% 100% at 50% 0%, rgba(167,139,250,.16) 0%, rgba(20,16,50,.35) 62%, rgba(11,10,24,.45) 100%);
  border:1px solid rgba(199,183,255,.16);border-radius:18px;padding:26px;
  display:grid;place-items:center;min-height:330px;
}
.pdp-art img{max-width:100%;height:auto;filter:drop-shadow(0 18px 30px rgba(0,0,0,.55))}
/* desktops get the main photo inside a <picture> (1x/2x); display:contents keeps
   the <img> the layout child, exactly as it was without the wrapper */
.pdp-art picture{display:contents}
.pdp-thumbs{display:flex;gap:10px;margin-top:14px}
.pdp-thumbs button{
  width:76px;height:76px;padding:7px;cursor:pointer;border-radius:12px;
  background:rgba(20,16,50,.5);border:1px solid rgba(199,183,255,.18);
}
.pdp-thumbs button[aria-current="true"]{border-color:var(--spark-cyan);box-shadow:0 0 0 1px var(--spark-cyan)}
.pdp-thumbs img{width:100%;height:100%;object-fit:contain;display:block}

.peyebrow{font-family:'JetBrains Mono',ui-monospace,monospace;font-size:12px;letter-spacing:.14em;text-transform:uppercase;color:#B9BAD1}
.pdp-buy h1{
  font-family:'Bricolage Grotesque',system-ui,sans-serif;font-weight:800;
  font-size:clamp(29px,4.2vw,44px);line-height:1.04;margin:12px 0 16px;color:#FFF;
}
/* holo on the set name only, exactly as the cover does it */
.pdp-buy h1 .holo{
  background:var(--holo-line);-webkit-background-clip:text;background-clip:text;color:transparent;
}
.pdp-price{font-family:'Bricolage Grotesque',system-ui,sans-serif;font-weight:800;font-size:34px;margin:0 0 4px;color:#FFF}
.pdp-price small{font-size:14px;font-weight:600;color:#B9BAD1;margin-left:7px}
.pdp-price .pdp-was{font-size:20px;font-weight:700;color:#8D8FA8;text-decoration-thickness:2px;margin-right:6px}
.pdp-gst{font-size:13px;color:#B9BAD1;margin:0 0 20px}

/* The stock line used to be a rainbow pill reading "In stock in Sydney",
   which said nothing the page did not already say and spent the holo gradient
   on a housekeeping detail. Holo is now reserved for the set name and the one
   button that takes money. */
.status{
  font-size:13.5px;color:#B9BAD1;margin-bottom:14px;display:flex;align-items:center;gap:8px;
}
.status:before{content:"";width:7px;height:7px;border-radius:50%;background:var(--spark-cyan);box-shadow:0 0 10px var(--spark-cyan)}
.status.preorder:before{background:var(--spark-gold);box-shadow:0 0 10px var(--spark-gold)}

.buybtn{
  /* width:100% because a <button> sizes to its text where an <a> did not, and
     the add-to-cart button has to be the widest thing in the column. */
  display:block;width:100%;border:none;cursor:pointer;
  text-align:center;text-decoration:none;color:#15172B;font-weight:800;
  font-family:'Bricolage Grotesque',system-ui,sans-serif;font-size:17px;letter-spacing:-.01em;
  padding:17px;border-radius:13px;background:var(--holo-line);background-size:200% 100%;
  box-shadow:0 10px 30px rgba(167,139,250,.28);transition:transform .12s,background-position .5s;
}
.buybtn:hover{transform:translateY(-1px);background-position:100% 0;text-decoration:none}

.trust{list-style:none;padding:0;margin:22px 0 0;font-size:14px;color:#B9BAD1}
.trust li{padding:8px 0;border-bottom:1px solid rgba(199,183,255,.13)}
.trust li:last-child{border-bottom:none}
.trust b{color:#FFF;font-weight:600}

/* ── related grid, on the flat ground below ─────────────────────────────── */
.grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(190px,1fr));gap:16px;margin:18px 0 40px;padding:0;list-style:none}
.grid a{display:block;text-decoration:none;color:inherit;background:var(--card);border:1px solid var(--line);border-radius:14px;padding:14px;transition:transform .12s,border-color .12s}
.grid a:hover{transform:translateY(-2px);border-color:#A78BFA;text-decoration:none}
.grid img{width:100%;height:130px;object-fit:contain;margin-bottom:10px}
.grid b{display:block;font-size:14px;font-weight:600;line-height:1.3}
.grid span{display:block;font-size:13px;color:var(--ink-2);margin-top:3px}

@media (max-width:760px){
  .scene{padding:20px;border-radius:18px;margin-bottom:26px}
  .pdp{grid-template-columns:1fr;gap:24px;align-items:start}
  .pdp-art{padding:16px;min-height:0}
  .scene:after{width:150%;left:-12%}
}

/* ── guides (/guides/) ────────────────────────────────────────────────────
   Long-form reading pages. The list cards match the .grid tiles without the
   image; sources and the product-page pointer sit quieter than body copy. */
.guidelist{list-style:none;padding:0;margin:8px 0 28px;display:grid;gap:12px}
.guidelist li{margin:0}
.guidelist a{display:block;text-decoration:none;color:inherit;background:var(--card);border:1px solid var(--line);border-radius:14px;padding:16px 18px;transition:transform .12s,border-color .12s}
.guidelist a:hover{transform:translateY(-2px);border-color:#A78BFA;text-decoration:none}
.guidelist b{display:block;font-family:'Bricolage Grotesque',system-ui,sans-serif;font-size:17px;font-weight:700;letter-spacing:-.01em;line-height:1.3}
.guidelist span{display:block;font-size:14px;color:var(--ink-2);margin-top:4px}
.sources{font-size:14px;color:var(--ink-2)}
.sources a{color:var(--ink-2)}
.guidelinks{font-size:14.5px;color:var(--ink-2)}
/* the top 3 hits on a product page: a numbered podium, not a plain list */
.tophits{list-style:none;counter-reset:hit;padding:0;margin:0 0 12px;display:grid;gap:10px}
.tophits li{counter-increment:hit;display:grid;grid-template-columns:40px 1fr;column-gap:12px;align-items:center;margin:0;padding:12px 14px;border:1px solid var(--line);border-radius:14px;background:var(--card)}
.tophits li::before{content:counter(hit);grid-row:span 2;display:grid;place-items:center;width:40px;height:40px;border-radius:50%;font-family:'Bricolage Grotesque',system-ui,sans-serif;font-weight:800;font-size:18px;color:#15172B;background:linear-gradient(160deg,#FFE39A 0%,#E9C46A 100%)}
.tophits li:nth-child(2)::before{background:linear-gradient(160deg,#ECEDF4 0%,#B9BAD1 100%)}
.tophits li:nth-child(3)::before{background:linear-gradient(160deg,#F2C29B 0%,#C98A5B 100%)}
.tophits b{font-size:16px;line-height:1.3}
.tophits span{font-size:13.5px;color:var(--ink-2)}
.hitsnote{font-size:13.5px;color:var(--ink-2)}
/* the top hits tables in the guides: card name, then rarity and number under it */
/* the glossary guide: a term, then its meaning */
.gloss{margin:0 0 18px}
.gloss dt{font-weight:800;margin-top:14px}
.gloss dd{margin:2px 0 0;color:var(--ink-2)}
.hitstable td{vertical-align:top}
.hitstable small{display:block;margin-top:2px;font-size:12.5px;color:var(--ink-2);white-space:nowrap}
main.guide td{vertical-align:top}
.guidelist .gicon{display:block;font-size:22px;line-height:1;margin:0 0 8px;color:inherit}
.guidelist{grid-template-columns:repeat(auto-fill,minmax(250px,1fr))}

/* ── guide pages: the Archive sky ─────────────────────────────────────────
   Owner's ask (2026-10-07): the guides wear the same planet background as
   the Archive on the homepage. Same violet field, star tiles, orbit rings and
   three CSS planets, fixed to the viewport so it stays put while reading.
   Static on purpose: the homepage version drifts, but a long reading page
   gains nothing from motion behind the text and it costs scroll smoothness. */
body.guide-page::before{
  opacity:1;
  background:
    radial-gradient(46% 30% at 84% 6%,rgba(167,139,250,.22),transparent 70%),
    radial-gradient(40% 26% at 8% 72%,rgba(110,231,240,.16),transparent 70%),
    radial-gradient(36% 24% at 68% 94%,rgba(255,158,196,.12),transparent 70%),
    radial-gradient(120% 95% at 50% 30%,#2E2159 0%,#251A4B 45%,#170F33 100%);
}
body.guide-page::after{
  opacity:.8;
  background-image:radial-gradient(rgba(255,255,255,.5) 1px,transparent 1.6px),radial-gradient(rgba(214,205,245,.35) 1.3px,transparent 2px),radial-gradient(rgba(255,255,255,.3) .8px,transparent 1.4px),radial-gradient(rgba(190,178,240,.32) 1px,transparent 1.7px);
  background-size:210px 210px,340px 340px,120px 120px,260px 260px;
  background-position:14px 28px,120px 160px,64px 90px,30px 210px;
}
.gsky{position:fixed;inset:0;z-index:-1;overflow:hidden;pointer-events:none}
.gsky .vorbit{position:absolute;left:50%;width:min(150vw,1560px);aspect-ratio:2.6/1;border:1.5px solid rgba(214,205,245,.15);border-radius:50%;transform:translateX(-50%) rotate(-14deg)}
.gsky .vorbit.o1{top:4%}
.gsky .vorbit.o2{bottom:-14%;transform:translateX(-50%) rotate(11deg);border-color:rgba(214,205,245,.11)}
.gsky .vplanet{position:absolute;border-radius:50%}
.gsky .vplanet.p1{top:110px;right:-64px;width:200px;height:200px;background:radial-gradient(circle at 30% 26%,#CBB9FF 0%,#8B6FE0 34%,#4B3590 62%,#22174E 100%);box-shadow:inset -30px -24px 50px rgba(8,5,26,.7),0 0 70px rgba(167,139,250,.3)}
.gsky .vplanet.p1:before{content:"";position:absolute;inset:24% -38%;border-radius:50%;border:10px solid rgba(214,205,245,.3);border-top-color:rgba(214,205,245,.07);transform:rotate(-18deg)}
.gsky .vplanet.p1:after{content:"";position:absolute;left:18%;top:20%;width:26px;height:26px;border-radius:50%;background:rgba(255,255,255,.13);box-shadow:52px 34px 0 -6px rgba(255,255,255,.1),20px 68px 0 -9px rgba(255,255,255,.08)}
.gsky .vplanet.p2{bottom:90px;left:-46px;width:130px;height:130px;background:radial-gradient(circle at 34% 30%,#A9F0F6 0%,#4FB6CC 40%,#1F5E7E 70%,#0E2C46 100%);box-shadow:inset -20px -16px 36px rgba(4,14,26,.7),0 0 54px rgba(110,231,240,.28)}
.gsky .vplanet.p3{top:46%;left:2.5%;width:54px;height:54px;background:radial-gradient(circle at 32% 30%,#FFD9EA 0%,#E08BB8 45%,#8C3E6E 78%,#4A1F3C 100%);box-shadow:inset -9px -7px 18px rgba(30,6,20,.6),0 0 34px rgba(255,158,196,.3)}
.gsky .vspk{position:absolute;line-height:1;font-style:normal;text-shadow:0 0 12px currentColor}
html[data-theme="light"] body.guide-page::before{
  opacity:1;
  background:
    radial-gradient(46% 30% at 84% 6%,rgba(167,139,250,.28),transparent 70%),
    radial-gradient(40% 26% at 8% 72%,rgba(110,231,240,.22),transparent 70%),
    radial-gradient(36% 24% at 68% 94%,rgba(255,158,196,.2),transparent 70%),
    radial-gradient(120% 95% at 50% 30%,#ECE6FB 0%,#E1D9F6 46%,#D2C7F0 100%);
}
html[data-theme="light"] body.guide-page::after{
  display:block;opacity:.6;
  background-image:radial-gradient(rgba(109,84,201,.5) 1px,transparent 1.6px),radial-gradient(rgba(150,120,220,.34) 1.3px,transparent 2px),radial-gradient(rgba(109,84,201,.3) .8px,transparent 1.4px),radial-gradient(rgba(120,95,210,.3) 1px,transparent 1.7px);
}
html[data-theme="light"] .gsky .vorbit{border-color:rgba(109,84,201,.2)}
html[data-theme="light"] .gsky .vorbit.o2{border-color:rgba(109,84,201,.14)}

/* the hero: words left, the box art right, the lavender tint on the title */
.ghero{display:grid;grid-template-columns:minmax(0,1fr) auto;gap:30px;align-items:center;margin:6px 0 28px}
.ghero h1{
  margin:10px 0 12px;font-family:'Bricolage Grotesque',system-ui,sans-serif;
  font-size:clamp(30px,5vw,50px);line-height:1.08;letter-spacing:-.03em;font-weight:800;
  background:linear-gradient(180deg,#F3EEFF 10%,#C4B0FF 95%);-webkit-background-clip:text;background-clip:text;color:transparent;
  -webkit-box-decoration-break:clone;box-decoration-break:clone;
}
html[data-theme="light"] .ghero h1{background:linear-gradient(180deg,#8B6CF0 0%,#5A3BC9 100%);-webkit-background-clip:text;background-clip:text}
.ghero-txt>p{margin:0;color:var(--ink-2);font-size:17px;max-width:60ch}
.ghero .updated{margin-top:16px}
.ghero-art{display:block;width:clamp(150px,21vw,270px)}
.ghero-art img{display:block;width:100%;height:auto;filter:drop-shadow(0 18px 30px rgba(0,0,0,.45))}

/* the reading column and the shop card beside it */
.glayout{display:grid;grid-template-columns:minmax(0,1fr) 290px;gap:28px;align-items:start;margin-bottom:40px}
body.guide-page main.guide{
  max-width:none;min-width:0;background:rgba(16,12,38,.74);border:1px solid rgba(214,205,245,.14);
  border-radius:22px;padding:34px clamp(18px,4vw,42px) 30px;box-shadow:0 24px 60px rgba(0,0,0,.32);
}
html[data-theme="light"] body.guide-page main.guide{background:rgba(255,255,255,.9);border-color:rgba(109,84,201,.16);box-shadow:0 18px 48px rgba(60,40,120,.12)}
main.guide h2{clear:both}
main.guide .tablewrap{clear:both}
.gside{position:sticky;top:86px}
.gside-card{background:rgba(16,12,38,.84);border:1px solid rgba(214,205,245,.16);border-radius:18px;padding:18px;box-shadow:0 18px 44px rgba(0,0,0,.3)}
html[data-theme="light"] .gside-card{background:rgba(255,255,255,.94);border-color:rgba(109,84,201,.16);box-shadow:0 14px 36px rgba(60,40,120,.12)}
.gside-h{display:block;font-family:'Bricolage Grotesque',system-ui,sans-serif;font-size:16px;font-weight:800;margin:0 0 10px}
.gside ul{list-style:none;padding:0;margin:0 0 14px;display:grid;gap:6px}
.gside li{margin:0}
.gside li a{display:flex;gap:10px;align-items:center;text-decoration:none;color:inherit;padding:6px;border-radius:12px;border:1px solid transparent}
.gside li a:hover{border-color:#A78BFA;background:rgba(167,139,250,.08);text-decoration:none}
.gside img{width:52px;height:52px;object-fit:contain;flex:0 0 52px}
.gside b{display:block;font-size:14px;font-weight:600;line-height:1.25}
.gside i{display:block;font-style:normal;font-size:12.5px;color:var(--ink-2)}
.gside .buybtn{font-size:15px;padding:13px}
.gside-fine{font-size:12.5px;color:var(--ink-2);margin:10px 0 0;text-align:center}

/* pictures inside the read */
.gfig{float:right;width:min(42%,250px);margin:4px 0 18px 26px;text-align:center}
.gfig img{display:block;width:100%;height:auto;aspect-ratio:1;object-fit:contain;filter:drop-shadow(0 14px 22px rgba(0,0,0,.4))}
.gfig figcaption{font-size:13px;color:var(--ink-2);margin-top:6px;line-height:1.4}

/* the shop block at the end of every read */
.gcta{clear:both;margin:42px 0 30px;padding:26px clamp(16px,3vw,28px);border-radius:20px;background:linear-gradient(150deg,rgba(139,92,246,.24),rgba(110,231,240,.08));border:1px solid rgba(167,139,250,.38)}
.gcta h2{margin-top:0}
.gcta .grid{margin:16px 0 18px}
.gcta-btns{display:flex;flex-wrap:wrap;gap:12px;margin:0}
.gcta-btns .buybtn{display:inline-block;width:auto;padding:14px 22px;font-size:16px}
.gghost{display:inline-flex;align-items:center;padding:13px 20px;border-radius:13px;border:1px solid var(--line);font-weight:700;text-decoration:none;color:var(--ink);background:var(--card)}
.gghost:hover{border-color:#A78BFA;text-decoration:none}

/* phones and tablets: no side card, a floating shop button instead */
.gfab{
  position:fixed;right:16px;bottom:calc(16px + env(safe-area-inset-bottom));z-index:30;display:none;align-items:center;gap:8px;
  padding:12px 18px;border-radius:999px;font-weight:800;font-size:15px;text-decoration:none;color:#15172B;
  font-family:'Bricolage Grotesque',system-ui,sans-serif;
  background:linear-gradient(160deg,#C9B8FF 0%,#9A7BF7 100%);box-shadow:0 10px 28px rgba(0,0,0,.45),inset 0 0 0 1px rgba(255,255,255,.2);
}
.gfab:hover{text-decoration:none}
@media (max-width:1099px){
  /* minmax(0,1fr), not 1fr: a bare 1fr column grows to the min-content of
     its widest child, and a 420px table pushed the reading column past the
     edge of a phone screen */
  .glayout{grid-template-columns:minmax(0,1fr)}
  .gside{display:none}
  .gfab{display:inline-flex}
  body.guide-page footer{padding-bottom:84px}
}
@media (max-width:700px){
  .ghero{grid-template-columns:1fr;gap:14px}
  .ghero-art{width:150px;order:-1}
  .gfig{float:none;width:min(66%,230px);margin:6px auto 20px}
  .gsky .vplanet.p1{top:80px;right:-58px;width:120px;height:120px}
  .gsky .vplanet.p2{bottom:70px;left:-44px;width:90px;height:90px}
  .gsky .vplanet.p3{display:none}
}

@media (prefers-reduced-motion:reduce){
  .buybtn,.grid a,.guidelist a{transition:none}
}

/* ── page backdrop ────────────────────────────────────────────────────────
   Below the hero the page was one flat grey slab, which made a product page
   feel like a document rather than part of the shop. This is the same space
   scene as the hero, fixed to the viewport and turned right down, so it reads
   as depth behind the content instead of competing with the product.

   Fixed rather than scrolling: a gradient that scrolls with a long page
   arrives at the footer as a hard edge. `inset:0` with `position:fixed` and a
   negative z-index keeps it behind everything without wrapping the page in an
   extra element. */
body.pdp-page{position:relative}
body.pdp-page::before{
  content:"";position:fixed;inset:0;z-index:-1;pointer-events:none;
  background:
    radial-gradient(58% 52% at 8% 8%, rgba(139,92,246,.16) 0%, transparent 68%),
    radial-gradient(50% 46% at 96% 30%, rgba(110,231,240,.08) 0%, transparent 70%),
    radial-gradient(60% 50% at 78% 98%, rgba(255,158,196,.09) 0%, transparent 72%);
}
/* a faint starfield over the glow, dimmer than the hero's so it never pulls
   the eye away from the product */
body.pdp-page::after{
  content:"";position:fixed;inset:0;z-index:-1;pointer-events:none;opacity:.3;
  background-image:
    radial-gradient(1.4px 1.4px at 12% 16%, #fff, transparent),
    radial-gradient(1.1px 1.1px at 72% 9%, #fff, transparent),
    radial-gradient(1.6px 1.6px at 88% 62%, #fff, transparent),
    radial-gradient(1px 1px at 26% 74%, #fff, transparent),
    radial-gradient(1.3px 1.3px at 58% 88%, #fff, transparent),
    radial-gradient(1.1px 1.1px at 4% 46%, #fff, transparent),
    radial-gradient(1.5px 1.5px at 92% 22%, #fff, transparent),
    radial-gradient(1px 1px at 40% 38%, #fff, transparent),
    radial-gradient(1.2px 1.2px at 66% 54%, #fff, transparent);
}
/* The light theme is a paper look, and stars on paper read as dust. */
html[data-theme="light"] body.pdp-page::after{display:none}
html[data-theme="light"] body.pdp-page::before{opacity:.55}

/* ── header controls ──────────────────────────────────────────────────────
   The storefront header carries theme, members and cart. Landing on a product
   page used to strip all three and leave a back link, which is why the cart is
   now persisted in localStorage: the count here is the same cart the shop
   has, read from the same key. */
/* Back to shop is the single most used control on a product page, so it is a
   button at the top left rather than a word in a row of words. */
.backbtn{
  display:inline-flex;align-items:center;gap:7px;margin-right:16px;
  border:1px solid var(--line);background:var(--card);color:var(--ink);
  border-radius:10px;padding:9px 14px;font-size:14px;font-weight:600;
  text-decoration:none;white-space:nowrap;transition:border-color .12s,transform .12s;
}
.backbtn:hover{border-color:#A78BFA;transform:translateX(-2px);text-decoration:none}

.signinbtn{
  display:inline-flex;align-items:center;gap:7px;margin-right:9px;cursor:pointer;
  border:1px solid var(--line);background:var(--card);color:var(--ink);
  border-radius:10px;padding:8px 13px;font-size:14px;font-weight:600;white-space:nowrap;
}
.signinbtn:hover{border-color:#A78BFA}

.themebtn{
  border:1px solid var(--line);background:var(--card);color:var(--ink);
  border-radius:10px;padding:8px 11px;cursor:pointer;font-size:14px;line-height:1;margin-right:9px;
}
.cartbtn{
  display:inline-flex;align-items:center;gap:8px;text-decoration:none;
  border:1px solid var(--line);background:var(--card);color:var(--ink);
  border-radius:10px;padding:8px 13px;font-size:14px;font-weight:600;white-space:nowrap;
}
.cartbtn:hover{border-color:#A78BFA;text-decoration:none}
.cartbtn .count{
  min-width:20px;text-align:center;border-radius:999px;padding:1px 6px;
  /* the favicon's purple, same as the storefront badge */
  background:linear-gradient(160deg,#B9A6FF 0%,#9A7BF7 100%);color:#15172B;font-size:12px;font-weight:700;
}

/* ── trust list ───────────────────────────────────────────────────────────
   The label used to be a bold run-in inside the sentence, which put bold text
   on a page where nothing else is bold and made four ordinary facts look like
   four warnings. It is a quiet column label now. */
.trust{display:grid;gap:0}
.trust li{display:grid;grid-template-columns:82px 1fr;gap:12px;align-items:baseline}
.tl{
  font-family:'JetBrains Mono',ui-monospace,monospace;font-size:10.5px;font-weight:700;
  letter-spacing:.1em;text-transform:uppercase;color:var(--spark-cyan);
}

@media (max-width:860px){
  .cartbtn .lbl,.signinbtn span,.brand small{display:none}
  .backbtn{padding:9px 11px}
}
/* Phones. Five controls plus the brand did not fit: on a 375px screen the
   theme button sat on top of the wordmark and the Cart button was pushed half
   off the right edge, on the pages the ads land on. The back button keeps its
   label for screen readers but shows only the arrow, and under 386px (so
   below the 390px iPhones) the wordmark goes and the chip alone carries the
   brand. */
@media (max-width:560px){
  .hbar{gap:8px}
  .brand{flex:0 0 auto}
  .backbtn{margin-right:0;padding:9px 10px}
  .backbtn .bl{position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0 0 0 0);clip-path:inset(50%);white-space:nowrap}
  .themebtn,.signinbtn{margin-right:0;padding:8px 10px}
  .cartbtn{padding:8px 10px}
}
@media (max-width:385px){
  .brand .bn{display:none}
}
@media (max-width:760px){
  .trust li{grid-template-columns:1fr;gap:2px}
}

/* ── sparkles and a shooting star ─────────────────────────────────────────
   The scene had the gradient and the orbit but none of the things that make
   the storefront hero feel alive. These are the same four sparkle colours the
   style guide names, placed rather than randomised so every page composes the
   same way, and the shooting star is the one moving element on the page. */
.spk{
  position:absolute;z-index:1;pointer-events:none;line-height:1;
  font-family:'Inter',system-ui,sans-serif;text-shadow:0 0 12px currentColor;
}
.shoot{
  position:absolute;z-index:1;height:2px;width:190px;pointer-events:none;
  background:linear-gradient(90deg,transparent,rgba(255,227,154,.85));border-radius:2px;
}
.shoot:after{
  content:"";position:absolute;right:-3px;top:-2.5px;width:7px;height:7px;border-radius:50%;
  background:var(--spark-gold);box-shadow:0 0 14px 3px rgba(255,227,154,.75);
}
@media (prefers-reduced-motion:no-preference){
  .shoot{animation:shootBy 7s ease-in-out infinite}
  .spk{animation:twinkle 4.5s ease-in-out infinite}
  .spk:nth-of-type(2){animation-delay:.9s}
  .spk:nth-of-type(3){animation-delay:1.8s}
  .spk:nth-of-type(4){animation-delay:2.6s}
  .spk:nth-of-type(5){animation-delay:3.4s}
}
@keyframes twinkle{0%,100%{opacity:.35;transform:scale(.85)}50%{opacity:1;transform:scale(1.12)}}
@keyframes shootBy{
  0%{opacity:0;transform:translate(-60px,26px) rotate(19deg)}
  7%{opacity:1}
  22%{opacity:0;transform:translate(180px,-52px) rotate(19deg)}
  100%{opacity:0;transform:translate(180px,-52px) rotate(19deg)}
}

/* a violet wash behind the art so the product sits on colour, not on black */
.pdp-art{
  background:
    radial-gradient(58% 52% at 50% 42%, rgba(167,139,250,.30) 0%, rgba(110,231,240,.10) 52%, transparent 76%),
    radial-gradient(120% 100% at 50% 0%, rgba(20,16,50,.42) 0%, rgba(11,10,24,.5) 100%);
}

/* ── what it earns on the card ───────────────────────────────────────────── */
.earn{
  display:flex;align-items:center;gap:13px;margin-top:16px;padding:13px 15px;
  border:1px solid rgba(199,183,255,.20);border-radius:13px;
  background:rgba(20,16,50,.42);
}
/* The earn badge uses the reward card's own .mstamp, so there is one star in
   the codebase rather than two that drift. It only needs a size here. */
.earn-stamp{flex:0 0 54px;aspect-ratio:1}
.earn-txt{font-size:12.5px;line-height:1.5;color:#B9BAD1}
.earn-txt b{display:block;color:#FFF;font-size:13.5px;font-weight:700}
.earn-txt a{color:var(--spark-cyan);text-decoration:none}
.earn-txt a:hover{text-decoration:underline}

/* ── more sets, directly under the hero where it belongs ─────────────────── */
.morerow{margin:0 0 34px}
.morerow h2{font-family:'Bricolage Grotesque',system-ui,sans-serif;font-size:19px;margin:0 0 14px}
.moreall{margin:0 0 6px;font-size:14px}
.moreall a{color:var(--spark-cyan);text-decoration:none}
.moreall a:hover{text-decoration:underline}

/* ── cart drawer ─────────────────────────────────────────────────────────── */
.scrim,.mscrim{
  position:fixed;inset:0;z-index:60;background:rgba(6,6,16,.62);backdrop-filter:blur(2px);
  opacity:0;visibility:hidden;transition:opacity .2s;
}
.scrim.open,.mscrim.open{opacity:1;visibility:visible}

.drawer{
  position:fixed;top:0;right:0;bottom:0;width:min(420px,100%);z-index:61;
  display:flex;flex-direction:column;background:var(--card);border-left:1px solid var(--line);
  transform:translateX(102%);transition:transform .26s cubic-bezier(.4,.0,.2,1);
}
.drawer.open{transform:none}
.drawer-hd{display:flex;align-items:center;justify-content:space-between;padding:18px 20px;border-bottom:1px solid var(--line)}
.drawer-hd b{font-family:'Bricolage Grotesque',system-ui,sans-serif;font-size:17px}
.drawer-x{background:none;border:none;color:var(--ink-2);font-size:26px;line-height:1;cursor:pointer;padding:0 4px}
.drawer-x:hover{color:var(--ink)}
.drawer-body{flex:1;overflow-y:auto;padding:12px 20px}
.dempty{color:var(--ink-2);text-align:center;padding:44px 0;font-size:14px;line-height:1.6}
.dline{display:grid;grid-template-columns:54px 1fr auto;gap:12px;align-items:center;padding:12px 0;border-bottom:1px solid var(--line)}
.dline:last-child{border-bottom:none}
.dline img{width:54px;height:54px;object-fit:contain}
.dmid a{display:block;font-size:14px;font-weight:600;color:var(--ink);text-decoration:none;line-height:1.3}
.dmid a:hover{text-decoration:underline}
.dmid span{font-size:12.5px;color:var(--ink-2)}
.dqty{display:flex;align-items:center;gap:9px}
.dqty button{width:26px;height:26px;border-radius:7px;border:1px solid var(--line);background:transparent;color:var(--ink);cursor:pointer;font-size:14px;line-height:1}
.dqty button:hover{border-color:#A78BFA}
.dqty b{min-width:14px;text-align:center;font-size:14px}
.drawer-ft{padding:16px 20px 20px;border-top:1px solid var(--line)}
.drow{display:flex;justify-content:space-between;align-items:baseline;margin-bottom:6px;font-size:15px}
.drow.sm{font-size:12.5px;color:var(--ink-2);margin-bottom:14px}
.drawer-ft .buybtn{font-size:16px;padding:15px}
.drawer-ft .buybtn[aria-disabled="true"]{opacity:.45;pointer-events:none}

/* ── members panel ───────────────────────────────────────────────────────── */
.mpanel{
  position:fixed;z-index:62;left:50%;top:50%;transform:translate(-50%,-46%) scale(.97);
  width:min(420px,calc(100% - 32px));padding:26px;border-radius:20px;
  background:var(--card);border:1px solid var(--line);box-shadow:var(--shadow-lg,0 18px 50px rgba(0,0,0,.55));
  opacity:0;visibility:hidden;transition:opacity .2s,transform .2s;max-height:92vh;overflow-y:auto;
}
.mpanel.open{opacity:1;visibility:visible;transform:translate(-50%,-50%) scale(1)}
.mclose{position:absolute;top:12px;right:14px;background:none;border:none;color:var(--ink-2);font-size:26px;line-height:1;cursor:pointer}
.mclose:hover{color:var(--ink)}
.mpanel h3{font-family:'Bricolage Grotesque',system-ui,sans-serif;font-size:21px;margin:0 0 8px}
.msub{font-size:13.5px;color:var(--ink-2);margin:0 0 18px;line-height:1.55}
/* ── the reward card ──────────────────────────────────────────────────────
   Lifted VERBATIM from index.html rather than approximated. The first version
   here was a hand-rolled lookalike and it showed: wrong proportions, no orbit,
   no star field, flat stars. This is the same card, so it is the same card.

   If the storefront's version changes, re-extract rather than hand-editing
   both. url() paths resolve against this stylesheet, which sits at the site
   root next to index.html, so the star art path needs no adjusting. */

@keyframes shootBy{
  0%{opacity:0;transform:translate(-60px,26px) rotate(19deg)}
  7%{opacity:1}
  22%{opacity:0;transform:translate(180px,-52px) rotate(19deg)}
  100%{opacity:0;transform:translate(180px,-52px) rotate(19deg)}
}

/* a violet wash behind the art so the product sits on colour, not on black */
.pdp-art{
  background:
    radial-gradient(58% 52% at 50% 42%, rgba(167,139,250,.30) 0%, rgba(110,231,240,.10) 52%, transparent 76%),
    radial-gradient(120% 100% at 50% 0%, rgba(20,16,50,.42) 0%, rgba(11,10,24,.5) 100%);
}

/* ── what it earns on the card ───────────────────────────────────────────── */
.earn{
  display:flex;align-items:center;gap:13px;margin-top:16px;padding:13px 15px;
  border:1px solid rgba(199,183,255,.20);border-radius:13px;
  background:rgba(20,16,50,.42);
}
/* The earn badge uses the reward card's own .mstamp, so there is one star in
   the codebase rather than two that drift. It only needs a size here. */
.earn-stamp{flex:0 0 54px;aspect-ratio:1}
.earn-txt{font-size:12.5px;line-height:1.5;color:#B9BAD1}
.earn-txt b{display:block;color:#FFF;font-size:13.5px;font-weight:700}
.earn-txt a{color:var(--spark-cyan);text-decoration:none}
.earn-txt a:hover{text-decoration:underline}

/* ── more sets, directly under the hero where it belongs ─────────────────── */
.morerow{margin:0 0 34px}
.morerow h2{font-family:'Bricolage Grotesque',system-ui,sans-serif;font-size:19px;margin:0 0 14px}
.moreall{margin:0 0 6px;font-size:14px}
.moreall a{color:var(--spark-cyan);text-decoration:none}
.moreall a:hover{text-decoration:underline}

/* ── cart drawer ─────────────────────────────────────────────────────────── */
.scrim,.mscrim{
  position:fixed;inset:0;z-index:60;background:rgba(6,6,16,.62);backdrop-filter:blur(2px);
  opacity:0;visibility:hidden;transition:opacity .2s;
}
.scrim.open,.mscrim.open{opacity:1;visibility:visible}

.drawer{
  position:fixed;top:0;right:0;bottom:0;width:min(420px,100%);z-index:61;
  display:flex;flex-direction:column;background:var(--card);border-left:1px solid var(--line);
  transform:translateX(102%);transition:transform .26s cubic-bezier(.4,.0,.2,1);
}
.drawer.open{transform:none}
.drawer-hd{display:flex;align-items:center;justify-content:space-between;padding:18px 20px;border-bottom:1px solid var(--line)}
.drawer-hd b{font-family:'Bricolage Grotesque',system-ui,sans-serif;font-size:17px}
.drawer-x{background:none;border:none;color:var(--ink-2);font-size:26px;line-height:1;cursor:pointer;padding:0 4px}
.drawer-x:hover{color:var(--ink)}
.drawer-body{flex:1;overflow-y:auto;padding:12px 20px}
.dempty{color:var(--ink-2);text-align:center;padding:44px 0;font-size:14px;line-height:1.6}
.dline{display:grid;grid-template-columns:54px 1fr auto;gap:12px;align-items:center;padding:12px 0;border-bottom:1px solid var(--line)}
.dline:last-child{border-bottom:none}
.dline img{width:54px;height:54px;object-fit:contain}
.dmid a{display:block;font-size:14px;font-weight:600;color:var(--ink);text-decoration:none;line-height:1.3}
.dmid a:hover{text-decoration:underline}
.dmid span{font-size:12.5px;color:var(--ink-2)}
.dqty{display:flex;align-items:center;gap:9px}
.dqty button{width:26px;height:26px;border-radius:7px;border:1px solid var(--line);background:transparent;color:var(--ink);cursor:pointer;font-size:14px;line-height:1}
.dqty button:hover{border-color:#A78BFA}
.dqty b{min-width:14px;text-align:center;font-size:14px}
.drawer-ft{padding:16px 20px 20px;border-top:1px solid var(--line)}
.drow{display:flex;justify-content:space-between;align-items:baseline;margin-bottom:6px;font-size:15px}
.drow.sm{font-size:12.5px;color:var(--ink-2);margin-bottom:14px}
.drawer-ft .buybtn{font-size:16px;padding:15px}
.drawer-ft .buybtn[aria-disabled="true"]{opacity:.45;pointer-events:none}

/* ── members panel ───────────────────────────────────────────────────────── */
.mpanel{
  position:fixed;z-index:62;left:50%;top:50%;transform:translate(-50%,-46%) scale(.97);
  width:min(420px,calc(100% - 32px));padding:26px;border-radius:20px;
  background:var(--card);border:1px solid var(--line);box-shadow:var(--shadow-lg,0 18px 50px rgba(0,0,0,.55));
  opacity:0;visibility:hidden;transition:opacity .2s,transform .2s;max-height:92vh;overflow-y:auto;
}
.mpanel.open{opacity:1;visibility:visible;transform:translate(-50%,-50%) scale(1)}
.mclose{position:absolute;top:12px;right:14px;background:none;border:none;color:var(--ink-2);font-size:26px;line-height:1;cursor:pointer}
.mclose:hover{color:var(--ink)}
.mpanel h3{font-family:'Bricolage Grotesque',system-ui,sans-serif;font-size:21px;margin:0 0 8px}
.msub{font-size:13.5px;color:var(--ink-2);margin:0 0 18px;line-height:1.55}
/* ── the reward card ──────────────────────────────────────────────────────
   Lifted VERBATIM from index.html rather than approximated. The first version
   here was a hand-rolled lookalike and it showed: wrong proportions, no orbit,
   no star field, flat stars. This is the same card, so it is the same card.

   If the storefront's version changes, re-extract rather than hand-editing
   both. url() paths resolve against this stylesheet, which sits at the site
   root next to index.html, so the star art path needs no adjusting. */


/* CARD:BEGIN generated by scripts/build-pages.mjs from index.html, do not edit */
.mcard{position:relative;width:min(360px,100%);aspect-ratio:1.586;border-radius:18px;background:radial-gradient(130% 150% at 32% 12%,#38286B 0%,#241A52 52%,#150E33 100%);box-shadow:0 24px 60px rgba(0,0,0,.55),inset 0 0 0 1px rgba(255,255,255,.1);overflow:hidden;padding:16px 18px;display:flex;flex-direction:column;color:#fff}
.mcard:before{content:"";position:absolute;inset:0;background-image:radial-gradient(rgba(255,255,255,.55) 1px,transparent 1.5px),radial-gradient(rgba(214,205,245,.4) 1.2px,transparent 1.9px);background-size:120px 120px,190px 190px;background-position:8px 14px,60px 80px;opacity:.5}
.mcard:after{content:"";position:absolute;left:0;right:0;top:0;height:3px;background:var(--holo);background-size:200% 200%;animation:holo 5s linear infinite}
.morbit{position:absolute;top:-26px;right:-58px;width:230px;height:92px;border:1.5px solid rgba(214,205,245,.24);border-radius:50%;transform:rotate(-16deg);pointer-events:none}
.mspk{position:absolute;font-size:11px;animation:tw 4s ease-in-out infinite;text-shadow:0 0 8px currentColor;pointer-events:none}
.mrow1{position:relative;display:flex;justify-content:space-between;align-items:flex-start}
.mbrand b{display:block;font-family:'Bricolage Grotesque';font-weight:800;font-size:14px;letter-spacing:.2em;color:#fff}
.mbrand small{display:block;font-family:'JetBrains Mono';font-size:6.8px;letter-spacing:.24em;color:#B7BAD0;margin-top:3px}
.mmark{width:32px;height:32px;border-radius:9px;background:#15172B;
    display:grid;place-items:center;box-shadow:inset 0 0 0 1px rgba(255,255,255,.18),0 2px 8px rgba(0,0,0,.4)}
.mmark>span{font-family:'Noto Sans JP','Bricolage Grotesque',sans-serif;font-size:16px;font-weight:800;line-height:1;
    background:linear-gradient(135deg,#6EE7F0 0%,#7FB0FF 26%,#A78BFA 55%,#FF9EC4 100%);
    -webkit-background-clip:text;background-clip:text;color:transparent}
.mname{position:relative;font-family:'Bricolage Grotesque';font-weight:800;font-size:20px;letter-spacing:.02em;margin-top:auto;max-width:100%;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.mno{position:relative;font-family:'JetBrains Mono';font-size:11.5px;color:#B7BAD0;letter-spacing:.18em;margin-top:3px}
.mstamps{position:relative;display:flex;gap:7px;margin-top:2px}
.mstamp{position:relative;flex:0 1 52px;min-width:0;aspect-ratio:1;--star-img:url(img/03de969686ec.webp);
    --sweep:calc(360deg*var(--f,0));
    --mid:calc(36deg - var(--sweep)/2);
    /* The glow used to ride the centroid of the earned wedge on a linear
       ramp, which threw it a long way off centre at 2/5 and 3/5 and read as a
       mistake. It is centred at every tier now EXCEPT one fifth, which keeps a
       small lift so a single lit point is not glowing from the middle of a
       dark star. The ramp is 11% at --f:0.2 and exactly 0 from --f:0.4 up;
       --f:0 also reads 11% but an empty star's glow is at zero opacity, so it
       never paints. Only the position changed: the brightness ramp below and
       `circle closest-side` are untouched. */
    --gr:calc(max(0, 1 - max(0, var(--f,0) - 0.2) * 5) * 11%);
    --gx:calc(50% + var(--gr) * sin(var(--mid)));
    --gy:calc(50% - var(--gr) * cos(var(--mid)));
    filter:drop-shadow(0 1px 2px rgba(0,0,0,.5))}
.mstamp:before{content:"";position:absolute;inset:-24%;border-radius:50%;pointer-events:none;
    /* `circle` matters: without it an off-centre closest-side gradient sizes each
       axis independently and the pool stretches into a horizontal ellipse. */
    background:radial-gradient(circle closest-side at var(--gx,50%) var(--gy,50%),rgba(255,222,140,.75),rgba(255,200,95,.28) 54%,transparent 78%);
    opacity:calc(min(1, var(--f,0) * 5) * (0.5 + 0.5 * var(--f,0)))}
.mstamp i{position:absolute;inset:0;background:var(--star-img) center/contain no-repeat}
.mstamp .sb{filter:brightness(.13) saturate(.25) opacity(.9)}
.mstamp .sf{z-index:2;
    transform:scale(calc(1 + (1 - var(--f,0)) * 0.14));transform-origin:50% 50%;
    -webkit-mask-image:conic-gradient(from 36deg,transparent 0 calc(360deg - var(--sweep)),#000 calc(360deg - var(--sweep)) 360deg);
    mask-image:conic-gradient(from 36deg,transparent 0 calc(360deg - var(--sweep)),#000 calc(360deg - var(--sweep)) 360deg)}
.mstamp:after{
    content:"";position:absolute;inset:0;pointer-events:none;z-index:1;
    background:url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100'><polygon points='50,2 61.23,34.55 95.65,35.17 68.17,55.9 78.21,88.83 50,69.1 21.79,88.83 31.83,55.9 4.35,35.17 38.77,34.55' fill='none' stroke='%23FFD678' stroke-width='1.6' stroke-dasharray='4 6' stroke-linejoin='round' stroke-linecap='round'/></svg>") center/contain no-repeat;
    opacity:.4;
    -webkit-mask-image:conic-gradient(from 36deg,#000 0 calc(360deg - var(--sweep)),transparent calc(360deg - var(--sweep)) 360deg);
    mask-image:conic-gradient(from 36deg,#000 0 calc(360deg - var(--sweep)),transparent calc(360deg - var(--sweep)) 360deg)}
.msite{align-self:flex-end;margin-top:5px;font-family:'JetBrains Mono';font-size:8.5px;letter-spacing:.16em;color:#B7BAD0;opacity:.85}
@keyframes holo{0%{background-position:0% 50%}100%{background-position:200% 50%}}
@keyframes tw{0%,100%{opacity:.15;transform:scale(.7)}50%{opacity:1;transform:scale(1.1)}}
/* CARD:END */

@media (max-width:760px){
  .spk,.shoot{display:none}
  .earn{flex-direction:column;align-items:flex-start;gap:9px}
}
