/* payxem.shop storefront
   Design direction: an editorial, calm retail surface. Deliberately not
   Gumroad's pink brutalism and not Etsy's warm orange craft-market look. The
   jade accent carries over from the landing page, set on a cool neutral ground
   with a tight type scale, so the products read as considered tools rather than
   impulse buys. One accent, used sparingly, everything else quiet. */

:root{
  --ground:#F6F7F8;
  --panel:#FFFFFF;
  --panel-2:#FBFCFC;
  --ink:#11161C;
  --ink-soft:#4A5560;
  --ink-faint:#78838E;
  --rule:#E1E5E9;
  --rule-soft:#EDF0F2;
  --accent:#0B7A5E;
  --accent-hover:#096B52;
  --accent-soft:#E6F2EE;
  --shadow:0 1px 2px rgba(17,22,28,.04), 0 6px 18px rgba(17,22,28,.05);
  --radius:12px;
}
@media (prefers-color-scheme: dark){
  :root:not([data-theme="light"]){
    --ground:#0C1013;
    --panel:#141A1F;
    --panel-2:#171E24;
    --ink:#EDF1F4;
    --ink-soft:#A3AEB8;
    --ink-faint:#7B868F;
    --rule:#232C33;
    --rule-soft:#1C242A;
    --accent:#3FBF98;
    --accent-hover:#57CFAB;
    --accent-soft:#12261F;
    --shadow:0 1px 2px rgba(0,0,0,.3), 0 6px 18px rgba(0,0,0,.28);
  }
}
:root[data-theme="dark"]{
  --ground:#0C1013; --panel:#141A1F; --panel-2:#171E24;
  --ink:#EDF1F4; --ink-soft:#A3AEB8; --ink-faint:#7B868F;
  --rule:#232C33; --rule-soft:#1C242A;
  --accent:#3FBF98; --accent-hover:#57CFAB; --accent-soft:#12261F;
  --shadow:0 1px 2px rgba(0,0,0,.3), 0 6px 18px rgba(0,0,0,.28);
}

*{box-sizing:border-box}
html,body{margin:0;padding:0}
body{
  background:var(--ground); color:var(--ink);
  font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif;
  font-size:16px; line-height:1.6; -webkit-font-smoothing:antialiased;
  min-height:100vh; display:flex; flex-direction:column;
}
img{max-width:100%;display:block}
a{color:inherit}

/* 1200 rather than the 1080 this started at. At 1080 the content column was
   narrower than the laptop frame it sat in, and because every editorial
   paragraph is also capped at a readable measure, the text ended up occupying
   roughly the left half of the screen with dead space to its right. Widening
   the frame is only half the fix; the other half is the two-column editorial
   layout further down, which gives that space something to hold. */
.wrap{width:100%;max-width:1200px;margin:0 auto;padding:0 24px}
.wrap-narrow{max-width:720px}
@media (max-width:700px){.wrap{padding:0 16px}}

/* header */
.site-head{border-bottom:1px solid var(--rule);background:var(--panel)}
.site-head .wrap{display:flex;align-items:center;justify-content:space-between;gap:16px;height:62px}
.mark{display:inline-flex;align-items:center;font-size:17px;font-weight:700;letter-spacing:-.015em;text-decoration:none;color:var(--ink)}
.mark .dot{color:var(--accent)}
/* The wordmark ships at 80px tall and renders at 30px, so it stays sharp on
   high density screens. The light and dark files are swapped by <picture>, so
   only one of the two is ever downloaded.
   30px rather than the 22px a single line wordmark would want: this mark sets
   ".shop" as a small second line under "em", and below about 28px that line
   stops being readable. The header is 62px tall, so 30px still clears. */
.mark .logo{height:30px;width:auto;display:block}
.mark:focus-visible{outline:2px solid var(--accent);outline-offset:4px;border-radius:4px}
.head-note{font-size:12.5px;color:var(--ink-faint);font-weight:520}

/* notice strip */
.strip{background:var(--accent-soft);border-bottom:1px solid var(--rule)}
.strip .wrap{display:flex;align-items:center;gap:9px;padding-top:10px;padding-bottom:10px;font-size:13.5px;color:var(--ink);font-weight:560}
.dotmark{width:7px;height:7px;border-radius:50%;background:var(--accent);flex:none}

main{flex:1}

/* hero */
.hero{padding:56px 0 38px}
.eyebrow{display:inline-block;font-size:11px;font-weight:650;letter-spacing:.11em;text-transform:uppercase;color:var(--accent);margin:0 0 14px}
h1{font-size:clamp(28px,5vw,44px);line-height:1.1;letter-spacing:-.03em;font-weight:700;margin:0 0 14px;text-wrap:balance}
.lede{font-size:17px;color:var(--ink-soft);margin:0;max-width:56ch}
/* Laptop up: headline left, lede to its right, bottom aligned so the two read
   as one band across the full frame instead of a narrow left-hand stack.
   Below the breakpoint these are plain block children in source order, so the
   stacked mobile hero is exactly what it was. */
@media (min-width:1000px){
  .hero-in{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,400px);gap:0 72px;align-items:end}
  .hero-lead h1{margin-bottom:0}
  .hero-in .lede{max-width:none;padding-bottom:5px}
}

/* section head */
.sec-head{display:flex;align-items:baseline;justify-content:space-between;gap:16px;margin:0 0 18px;padding-top:8px}
.sec-head h2{font-size:15px;font-weight:670;letter-spacing:-.01em;margin:0}
.sec-head .count{font-size:13px;color:var(--ink-faint);font-variant-numeric:tabular-nums}
/* "View all" in a section head. The vertical padding is a tap target and the
   matching negative margin takes it back out of the layout, so the control is
   44px tall to a thumb while still sitting on the heading's baseline. Same
   trick as the header icons, which had no room to grow either. */
.sec-link{appearance:none;-webkit-appearance:none;border:0;background:none;
  font:inherit;font-size:13px;font-weight:600;color:var(--accent);
  cursor:pointer;padding:11px 0;margin:-11px 0;white-space:nowrap}
.sec-link:hover{color:var(--accent-hover);text-decoration:underline}

/* product grid */
.grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(248px,1fr));gap:18px;padding-bottom:56px}
/* Laptop and up get exactly four across, the density Etsy runs at. Pinned
   rather than left to auto-fill, because auto-fill against the 1032px content
   width lands on three and a wider min would never reach four. Narrower
   screens keep the auto-fill behaviour above, untouched. */
@media (min-width:1000px){.grid{grid-template-columns:repeat(4,1fr)}}
.card{
  background:var(--panel);border:1px solid var(--rule);border-radius:var(--radius);
  overflow:hidden;text-decoration:none;color:inherit;display:flex;flex-direction:column;
  transition:border-color .16s ease, transform .16s ease, box-shadow .16s ease;
}
.card:hover{border-color:var(--accent);transform:translateY(-2px);box-shadow:var(--shadow)}
.card:focus-visible{outline:2px solid var(--accent);outline-offset:3px}
.thumb{
  aspect-ratio:16/10;background:var(--panel-2);border-bottom:1px solid var(--rule-soft);
  display:flex;align-items:center;justify-content:center;position:relative;overflow:hidden;
}
/* Product image. The images are generated at 16:10 to match this box exactly,
   so `cover` never actually crops; it is here to stay safe if a seller later
   uploads a different ratio. */
.thumb img{width:100%;height:100%;object-fit:cover;display:block}
.thumb .kind{
  font-size:10.5px;font-weight:680;letter-spacing:.1em;text-transform:uppercase;
  color:var(--accent);background:var(--accent-soft);padding:5px 9px;border-radius:999px;
}

/* product gallery */
.gallery{margin:0 0 26px}
.shot{
  aspect-ratio:16/10;width:100%;background:var(--panel-2);
  border:1px solid var(--rule);border-radius:var(--radius);overflow:hidden;
}
.shot img{width:100%;height:100%;object-fit:cover;display:block}
.shots{display:flex;gap:10px;margin-top:10px;flex-wrap:wrap}
.shots button{
  width:92px;aspect-ratio:16/10;padding:0;background:var(--panel-2);cursor:pointer;
  border:1px solid var(--rule);border-radius:7px;overflow:hidden;
  transition:border-color .16s ease, opacity .16s ease;opacity:.72;
}
.shots button img{width:100%;height:100%;object-fit:cover;display:block}
.shots button:hover{opacity:1}
.shots button[aria-current="true"]{border-color:var(--accent);opacity:1}
.shots button:focus-visible{outline:2px solid var(--accent);outline-offset:2px}
@media (max-width:880px){.shots button{width:76px}}
.card-body{padding:15px 16px 16px;display:flex;flex-direction:column;gap:6px;flex:1}
.card-title{font-size:15px;font-weight:640;letter-spacing:-.012em;line-height:1.32;margin:0}
.card-sub{font-size:13.5px;color:var(--ink-soft);margin:0;flex:1}
/* Stacked, not a space-between row. Once the price grew a struck-through
   reference and a percentage badge, a single row could not hold price and store
   name together: the badge wrapped on some cards and the store name broke onto
   two lines on others, so no two cards in a row lined up. Price on its own
   line, seller underneath. */
.card-foot{display:flex;flex-direction:column;align-items:flex-start;gap:3px;margin-top:6px}
.price{font-size:15px;font-weight:700;letter-spacing:-.02em;font-variant-numeric:tabular-nums}
.store-name{font-size:12.5px;color:var(--ink-faint);font-weight:540}

/* product page */
.prod{display:grid;grid-template-columns:minmax(0,1fr) 330px;gap:44px;padding:36px 0 64px;align-items:start}
@media (max-width:880px){.prod{grid-template-columns:1fr;gap:28px}}

.crumb{font-size:13px;color:var(--ink-faint);margin:0 0 16px}
.crumb a{color:var(--accent);text-decoration:none;font-weight:560}
.crumb a:hover{text-decoration:underline}

.prod h1{font-size:clamp(24px,3.6vw,33px);margin:0 0 10px}
.prod-sub{font-size:17px;color:var(--ink-soft);margin:0 0 26px;max-width:54ch}

.hl{background:var(--panel);border:1px solid var(--rule);border-radius:var(--radius);padding:20px 22px;margin:0 0 26px}
.hl h2{font-size:12px;font-weight:660;letter-spacing:.09em;text-transform:uppercase;color:var(--ink-faint);margin:0 0 13px}
.hl ul{margin:0;padding:0;list-style:none;display:flex;flex-direction:column;gap:10px}
.hl li{position:relative;padding-left:25px;font-size:14.5px;color:var(--ink)}
.hl li::before{
  content:"";position:absolute;left:0;top:8px;width:7px;height:7px;border-radius:2px;
  background:var(--accent);
}

.prose{font-size:15.5px;color:var(--ink-soft);max-width:60ch}
.prose p{margin:0 0 14px}

/* buy rail */
.rail{position:sticky;top:22px;display:flex;flex-direction:column;gap:14px}
@media (max-width:880px){.rail{position:static}}
.buy{background:var(--panel);border:1px solid var(--rule);border-radius:var(--radius);padding:22px;box-shadow:var(--shadow)}
.buy .amount{font-size:32px;font-weight:700;letter-spacing:-.03em;line-height:1;margin:0 0 3px;font-variant-numeric:tabular-nums}
.buy .amount-note{font-size:12.5px;color:var(--ink-faint);margin:0 0 18px}
.btn{
  display:block;width:100%;text-align:center;border:0;border-radius:9px;
  padding:13px 16px;font-size:15px;font-weight:640;font-family:inherit;
  background:var(--accent);color:#fff;cursor:pointer;text-decoration:none;
}
.btn:hover{background:var(--accent-hover)}
.btn:disabled{background:var(--rule);color:var(--ink-faint);cursor:not-allowed}
.btn:focus-visible{outline:2px solid var(--accent);outline-offset:3px}
.buy .after{font-size:12.5px;color:var(--ink-faint);margin:12px 0 0;text-align:center}

.facts{list-style:none;margin:18px 0 0;padding:18px 0 0;border-top:1px solid var(--rule-soft);display:flex;flex-direction:column;gap:9px}
.facts li{display:flex;justify-content:space-between;gap:12px;font-size:13px}
.facts li[hidden]{display:none}
.facts .k{color:var(--ink-faint)}
.facts .v{color:var(--ink);font-weight:560;text-align:right}
.facts .voucher-saving{color:var(--accent)}

.seller{background:var(--panel);border:1px solid var(--rule);border-radius:var(--radius);padding:18px 20px}
.seller .lbl{font-size:11px;font-weight:660;letter-spacing:.09em;text-transform:uppercase;color:var(--ink-faint);margin:0 0 8px}
.seller .nm{font-size:15px;font-weight:650;letter-spacing:-.012em;margin:0 0 4px}
.seller .tl{font-size:13px;color:var(--ink-soft);margin:0 0 10px}
.seller a{font-size:13px;color:var(--accent);text-decoration:none;font-weight:580}
.seller a:hover{text-decoration:underline}
.seller .own{font-size:12px;color:var(--ink-faint);margin:10px 0 0;padding-top:10px;border-top:1px solid var(--rule-soft);line-height:1.5}

/* states */
.state{padding:60px 0;text-align:center;color:var(--ink-faint);font-size:15px}

footer{border-top:1px solid var(--rule);padding:24px 0 34px;font-size:13px;color:var(--ink-faint);background:var(--panel)}
footer p{margin:0 0 4px}
footer .sep{margin:0 7px;opacity:.5}

/* ==========================================================================
   Home page editorial, below the listing.
   The reference points are Etsy's expandable "read the full description"
   blocks and Gumroad's flat, high contrast section rhythm. Both are adapted
   to this site's existing tokens rather than imported wholesale: one accent,
   quiet rules, no new typeface and no second colour.
   ========================================================================== */

/* assurance row, the summary band directly under the grid */
.assure{background:var(--panel);border-top:1px solid var(--rule);border-bottom:1px solid var(--rule)}
.assure-list{list-style:none;margin:0;padding:32px 0;display:grid;grid-template-columns:repeat(4,1fr);gap:28px}
@media (max-width:880px){.assure-list{grid-template-columns:repeat(2,1fr);gap:24px}}
@media (max-width:520px){.assure-list{grid-template-columns:1fr;gap:20px;padding:26px 0}}
.assure-item{margin:0}
.assure-ico{
  display:flex;align-items:center;justify-content:center;width:30px;height:30px;
  border-radius:8px;background:var(--accent-soft);color:var(--accent);margin:0 0 12px;
}
.assure-ico svg{width:16px;height:16px;display:block}
.assure-t{font-size:13.5px;font-weight:650;letter-spacing:-.01em;margin:0 0 4px}
.assure-d{font-size:13px;color:var(--ink-soft);margin:0;line-height:1.5}

/* editorial blocks

   The layout problem this solves: a single column of prose capped at a
   readable ~64ch leaves most of a laptop frame empty, which reads as a broken
   page rather than a deliberate measure. The fix is the pattern Etsy uses on
   its About pages and Gumroad uses on its marketing sections: the section
   heading takes a fixed left rail and the body fills the remaining width. The
   line length stays comfortable, but the block now spans the frame.

   Below 1000px the grid does not apply, the children stack in source order,
   and the mobile layout is unchanged. */
.editorial{padding:0 0 8px}
.ed-block{padding:46px 0;border-bottom:1px solid var(--rule-soft)}
.ed-block:first-child{padding-top:50px}
.ed-h{font-size:clamp(21px,3vw,27px);line-height:1.2;letter-spacing:-.026em;font-weight:700;margin:0 0 16px;text-wrap:balance}
.ed-lede{font-size:16.5px;color:var(--ink-soft);margin:0 0 24px;max-width:62ch}
.prose-lg{font-size:16px;max-width:64ch}
.prose-lg p{margin:0 0 16px}
.prose-lg p:last-child{margin-bottom:0}

@media (min-width:1000px){
  .ed-block{display:grid;grid-template-columns:minmax(0,300px) minmax(0,1fr);gap:0 64px;padding:56px 0}
  .ed-block:first-child{padding-top:60px}
  /* The rail holds the heading only, so it is short. Sticking it to the top of
     the viewport keeps it beside the paragraph being read in the long blocks
     instead of scrolling away at the first screen. */
  .ed-side{position:sticky;top:26px;align-self:start}
  .ed-side .ed-h{margin-bottom:0}
  .ed-side .ed-lede{margin:14px 0 0;max-width:none}
  /* 70ch not 64: the main column is about 790px here, and 70ch lands close
     enough to its right edge that the block reads as full width. */
  .ed-main.prose-lg,.ed-main .prose-lg{max-width:70ch}
  .ed-main .qa-body,.ed-main .note-box p{max-width:70ch}
}

/* three steps */
.steps{list-style:none;margin:0 0 22px;padding:0;display:grid;grid-template-columns:repeat(3,1fr);gap:16px}
@media (max-width:880px){.steps{grid-template-columns:1fr}}
.step{background:var(--panel);border:1px solid var(--rule);border-radius:var(--radius);padding:20px}
.step-n{display:block;font-size:10.5px;font-weight:680;letter-spacing:.11em;text-transform:uppercase;color:var(--accent);margin:0 0 10px}
.step-t{font-size:14.5px;font-weight:650;letter-spacing:-.012em;margin:0 0 6px}
.step-d{font-size:13.5px;color:var(--ink-soft);margin:0;line-height:1.55}

/* aside note */
.note-box{background:var(--panel-2);border:1px solid var(--rule);border-radius:var(--radius);padding:20px 22px}
.note-box .note-lbl{font-size:11px;font-weight:660;letter-spacing:.09em;text-transform:uppercase;color:var(--ink-faint);margin:0 0 8px}
.note-box p{font-size:14.5px;color:var(--ink-soft);margin:0;max-width:64ch;line-height:1.6}

/* expandable sections, the Etsy "read the full description" pattern */
.qa-list{border-top:1px solid var(--rule)}
.qa{border-bottom:1px solid var(--rule)}
.qa summary{
  display:flex;align-items:center;justify-content:space-between;gap:18px;
  padding:18px 2px;cursor:pointer;list-style:none;
  font-size:16px;font-weight:650;letter-spacing:-.015em;color:var(--ink);
  transition:color .14s ease;
}
.qa summary::-webkit-details-marker{display:none}
.qa summary::marker{content:""}
.qa summary:hover{color:var(--accent)}
.qa summary:focus-visible{outline:2px solid var(--accent);outline-offset:2px;border-radius:5px}
.qa-more{flex:none;font-size:12.5px;font-weight:570;color:var(--accent)}
.qa-more::after{content:"Read more"}
.qa[open] .qa-more::after{content:"Show less"}
.qa-body{padding:0 2px 22px;max-width:64ch}
.qa-body p{margin:0 0 14px}
.qa-body p:last-child{margin-bottom:0}

/* seller band */
.sell{
  background:var(--accent-soft);border:1px solid var(--rule);border-radius:var(--radius);
  padding:30px 32px;margin:46px 0 60px;
}
@media (max-width:520px){.sell{padding:24px 22px;margin:34px 0 46px}}
.sell h2{font-size:clamp(19px,2.4vw,23px);line-height:1.24;letter-spacing:-.022em;font-weight:700;margin:0 0 12px}
.sell p{font-size:15px;color:var(--ink-soft);margin:0 0 10px;max-width:62ch;line-height:1.6}
.sell p:last-child{margin-bottom:0}
.sell .fee{color:var(--ink);font-weight:620}
.sell .sell-note{font-size:13.5px;color:var(--ink-faint);margin-top:14px}
/* Same left-rail split as the editorial blocks above, so the band lines up
   with them rather than starting a third alignment. */
@media (min-width:1000px){
  .sell{display:grid;grid-template-columns:minmax(0,300px) minmax(0,1fr);gap:0 64px;align-items:start;padding:34px 36px}
  .sell h2{margin-bottom:0}
  .sell p{max-width:66ch}
}

/* ==========================================================================
   Phones.
   The grid was one product per row below 520px, which turned ten products into
   a very long scroll and made every card a full width banner. Etsy and Gumroad
   both run two across on a phone, so that is what this does, with the card
   typography stepped down to suit a ~170px card and the price and store name
   stacked because they will not sit side by side at that width.
   ========================================================================== */
@media (max-width:700px){
  .grid{grid-template-columns:repeat(2,1fr);gap:12px;padding-bottom:40px}
  .card-body{padding:11px 12px 13px;gap:4px}
  .card-title{font-size:13.5px;line-height:1.3}
  /* Clamped rather than left to run: without this a long subtitle sets the
     height of its whole row and the grid goes ragged. */
  .card-sub{font-size:12px;line-height:1.45;display:-webkit-box;-webkit-line-clamp:3;-webkit-box-orient:vertical;overflow:hidden}
  .card-foot{flex-direction:column;align-items:flex-start;gap:1px;margin-top:6px}
  .price{font-size:14px}
  .store-name{font-size:11px}
  .thumb .kind{font-size:9.5px;padding:4px 7px}

  .hero{padding:32px 0 24px}
  .lede{font-size:15.5px}
  .strip .wrap{font-size:12.5px}
  .sec-head{margin-bottom:14px}

  .ed-block,.ed-block:first-child{padding:34px 0}
  .ed-lede{font-size:15.5px;margin-bottom:20px}
  .prose-lg{font-size:15.5px}
  .qa summary{font-size:15px;padding:15px 2px;gap:12px}
  .qa-body{padding-bottom:18px;font-size:15px}
  .note-box{padding:17px 18px}
  .note-box p{font-size:14px}
  .assure-ico{width:28px;height:28px;margin-bottom:10px}
  footer{padding:20px 0 28px}
}
/* Very narrow phones keep two across, but the gutter and the card padding come
   in further rather than the layout changing again. */
@media (max-width:380px){
  .grid{gap:10px}
  .card-body{padding:10px 10px 12px}
  .card-title{font-size:13px}
}

/* ==========================================================================
   Offer pricing, ratings, saved items and the cart.  2026-09-07.

   One new colour token enters the palette here, --star. Ratings are amber
   everywhere a buyer has ever seen a rating, and painting them jade would read
   as a brand flourish rather than as a score. It is the only exception to the
   one-accent rule on this site and it is used for nothing but stars.
   ========================================================================== */

:root{ --star:#D99026; --star-dim:#D9DDE1; }
@media (prefers-color-scheme: dark){
  :root:not([data-theme="light"]){ --star:#E9A94A; --star-dim:#39424A; }
}
:root[data-theme="dark"]{ --star:#E9A94A; --star-dim:#39424A; }

/* ── header actions ──────────────────────────────────────────────────────── */

.head-actions{display:flex;align-items:center;gap:6px}
.head-act{
  position:relative;display:inline-flex;align-items:center;justify-content:center;
  width:36px;height:36px;border-radius:9px;color:var(--ink-soft);
  text-decoration:none;transition:background-color .14s ease,color .14s ease;
}
.head-act:hover{background:var(--accent-soft);color:var(--accent)}
.head-act:focus-visible{outline:2px solid var(--accent);outline-offset:2px}
.head-act svg{width:19px;height:19px;display:block;fill:none;stroke:currentColor;stroke-width:1.7;stroke-linecap:round;stroke-linejoin:round}
/* Count badge. Hidden at zero via the hidden attribute, which the global
   [hidden] rule in this file does not fight because nothing here sets display
   on it. */
.head-badge{
  position:absolute;top:-1px;right:-2px;min-width:16px;height:16px;padding:0 4px;
  border-radius:999px;background:var(--accent);color:#fff;
  font-size:10.5px;font-weight:700;line-height:16px;text-align:center;
  font-variant-numeric:tabular-nums;
}
.head-actions .head-note{margin-right:6px}
/* The label goes before the icons do: on a phone the two counts are the part
   that has to survive. */
@media (max-width:560px){ .head-actions .head-note{display:none} }

/* The account control. A button, not a link, and wider than the icon actions
   because "Sign in" has to be readable as an invitation rather than guessed at
   from a silhouette. Injected by shop.js into every page's header, so it never
   drifts between one page and the next. */
.head-acct{
  width:auto;gap:7px;padding:0 12px 0 10px;
  font:inherit;font-size:14px;font-weight:600;cursor:pointer;
  border:1px solid var(--rule);background:var(--panel-2);color:var(--ink);
  margin-left:2px;
}
.head-acct:hover{border-color:var(--accent);background:var(--accent-soft);color:var(--accent)}
.head-acct-label{max-width:11ch;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.head-account{position:relative}
.head-acct-caret{font-size:14px;line-height:1;margin-left:1px}
.account-menu{
  position:absolute;z-index:75;top:calc(100% + 9px);right:0;width:270px;
  padding:7px;border:1px solid var(--rule);border-radius:13px;background:var(--panel);
  box-shadow:0 16px 45px rgba(15,23,42,.18);
}
.account-menu[hidden]{display:none}
.account-menu a,.account-menu button{
  display:block;width:100%;padding:10px 11px;border:0;border-radius:8px;
  background:transparent;color:var(--ink);text-decoration:none;text-align:left;
  font:inherit;cursor:pointer;
}
.account-menu a:hover,.account-menu button:hover{background:var(--panel-2)}
.account-menu a:focus-visible,.account-menu button:focus-visible{outline:2px solid var(--accent);outline-offset:-2px}
.account-menu strong{display:block;font-size:13.5px;font-weight:650}
.account-menu small{display:block;margin-top:2px;color:var(--ink-faint);font-size:11.5px;line-height:1.35}
.account-menu-rule{display:block;height:1px;margin:6px 4px;background:var(--rule)}
.account-menu .account-menu-sell strong{color:var(--accent)}
.account-menu button{color:var(--ink-soft);font-size:13px}
/* On a phone it collapses to the icon. The cart and the two counts are what
   have to survive at 360px, and a person icon is understood everywhere. */
@media (max-width:480px){
  .head-acct{width:36px;padding:0;border-color:transparent;background:transparent}
  .head-acct-label{display:none}
  .head-acct-caret{display:none}
  .account-menu{position:fixed;top:66px;left:12px;right:12px;width:auto}
}

/* ── buyer account ─────────────────────────────────────────────────────── */
.account-page{padding:38px 0 70px}
.account-heading{margin:0 0 28px}
.account-heading h1{margin:0 0 6px;font-size:clamp(26px,4vw,36px);letter-spacing:-.035em}
.account-heading p{margin:0;color:var(--ink-soft)}
.account-layout{display:grid;grid-template-columns:220px minmax(0,1fr);gap:34px;align-items:start}
.account-nav{position:sticky;top:20px;display:grid;gap:4px;padding:8px;border:1px solid var(--rule);border-radius:13px;background:var(--panel)}
.account-nav a{padding:10px 12px;border-radius:8px;color:var(--ink-soft);text-decoration:none;font-size:14px;font-weight:590}
.account-nav a:hover,.account-nav a.is-on{background:var(--accent-soft);color:var(--accent)}
.account-nav .sell-link{margin-top:6px;border-top:1px solid var(--rule);border-radius:0;padding-top:15px}
.account-panel{display:none;border:1px solid var(--rule);border-radius:15px;background:var(--panel);padding:26px}
.account-panel.is-on{display:block}
.account-panel h2{margin:0 0 6px;font-size:22px;letter-spacing:-.025em}
.account-intro{margin:0 0 22px;color:var(--ink-soft);font-size:14px;line-height:1.55}
.account-grid{display:grid;grid-template-columns:1fr 1fr;gap:15px}
.account-grid .wide{grid-column:1/-1}
.account-field{display:block}
.account-field span{display:block;margin:0 0 6px;font-size:12px;font-weight:670;color:var(--ink-soft);text-transform:uppercase;letter-spacing:.025em}
.account-field input,.account-field select{width:100%;padding:11px 12px;border:1.5px solid var(--rule);border-radius:9px;background:var(--panel);color:var(--ink);font:inherit}
.account-field input:focus,.account-field select:focus{outline:none;border-color:var(--accent)}
.account-field input[readonly]{background:var(--panel-2);color:var(--ink-faint)}
.account-actions{display:flex;align-items:center;gap:14px;margin-top:20px}
.account-msg{margin:0;color:var(--ink-soft);font-size:13px}.account-msg.good{color:var(--accent)}.account-msg.bad{color:#B4342A}
.account-list{list-style:none;margin:0;padding:0;display:grid;gap:11px}
.account-item{display:flex;justify-content:space-between;gap:18px;padding:16px;border:1px solid var(--rule);border-radius:11px;background:var(--panel-2)}
.account-item-main{min-width:0}.account-item h3{margin:0 0 4px;font-size:15px}.account-item p{margin:0;color:var(--ink-soft);font-size:12.5px;line-height:1.5}
.account-item-side{flex:none;text-align:right}.account-item-side .price{display:block;margin-bottom:8px}
.account-empty{padding:28px;border:1px dashed var(--rule);border-radius:11px;text-align:center;color:var(--ink-soft)}
.account-empty a{color:var(--accent)}
.module-boundary{
  margin:0 0 64px;padding:24px;border:1px dashed var(--rule);
  border-radius:var(--radius);background:var(--panel);color:var(--ink-soft);
}
.module-boundary h2{
  margin:0 0 8px;font-size:20px;line-height:1.25;letter-spacing:-.02em;color:var(--ink);
}
.module-boundary p{margin:0 0 18px;max-width:64ch}
.account-check{display:flex;gap:10px;align-items:flex-start;padding:14px 0;border-bottom:1px solid var(--rule);font-size:14px;line-height:1.5}.account-check input{margin-top:3px;accent-color:var(--accent)}
.security-note{padding:17px;border-radius:11px;background:var(--panel-2);font-size:14px;line-height:1.6;color:var(--ink-soft)}
.security-note strong{color:var(--ink)}
@media (max-width:760px){.account-layout{grid-template-columns:1fr}.account-nav{position:static;grid-template-columns:repeat(2,1fr)}.account-nav .sell-link{margin:0;border:0;border-radius:8px;padding-top:10px}.account-panel{padding:20px}.account-grid{grid-template-columns:1fr}.account-grid .wide{grid-column:auto}}

/* ── price block ─────────────────────────────────────────────────────────── */

/* 🔴 .price-now is the amount that will be charged. .price-was is a label.
   Never wire a total to the struck-through figure. */
/* nowrap on purpose. "$9.99  $29.97  67% off" is about 170px at card width,
   so it fits on one line, and allowing it to wrap is what made the grid ragged
   before: the badge dropped to a second line on some cards and not others. */
.pricebox{display:flex;align-items:baseline;gap:7px;flex-wrap:nowrap}
.price-was{
  font-size:12.5px;color:var(--ink-faint);text-decoration:line-through;
  text-decoration-thickness:1px;font-variant-numeric:tabular-nums;
}
.price-off{
  font-size:10.5px;font-weight:700;letter-spacing:.02em;color:var(--accent);
  background:var(--accent-soft);padding:2px 6px;border-radius:5px;white-space:nowrap;
}
.pricebox-lg{gap:10px;margin:0 0 3px}
.pricebox-lg .price{font-size:32px;font-weight:700;letter-spacing:-.03em;line-height:1}
.pricebox-lg .price-was{font-size:16px}
.pricebox-lg .price-off{font-size:12px;padding:3px 8px}

/* ── stars ───────────────────────────────────────────────────────────────── */

.stars{display:inline-flex;align-items:center;gap:6px;line-height:1}
.stars-track{position:relative;display:inline-block;white-space:nowrap}
.stars-base{color:var(--star-dim);letter-spacing:1px}
/* The filled layer sits over the empty one and is clipped to a percentage
   width, so 4.9 renders as 4.9 of five stars rather than being rounded to a
   whole one. */
.stars-fill{
  position:absolute;left:0;top:0;overflow:hidden;white-space:nowrap;
  color:var(--star);letter-spacing:1px;
}
.stars-base,.stars-fill{font-size:12.5px}
.stars-num{font-size:12px;font-weight:660;color:var(--ink);font-variant-numeric:tabular-nums}
.stars-count{font-size:11.5px;color:var(--ink-faint);font-variant-numeric:tabular-nums}
.stars-lg .stars-base,.stars-lg .stars-fill{font-size:17px}
.stars-lg .stars-num{font-size:15px}
.stars-lg .stars-count{font-size:13px}

/* ── card, with its actions ──────────────────────────────────────────────── */

/* The card is a link, so the heart and the add button cannot live inside it:
   a button nested in an anchor is invalid and taps through to the product page
   on some mobile browsers. The shell exists to hold all three as siblings and
   to be the positioning context for the heart. */
.card-shell{position:relative;display:flex;flex-direction:column}
.card-shell .card{flex:1}
.card-rate{margin:1px 0 2px}
/* Full width under the card so it reads as part of it rather than a small
   button floating underneath. */
.card-acts{margin-top:8px}
.card-acts .cart-btn{width:100%;padding:9px 13px}
/* Etsy's position for it: over the image, top right. */
.card-acts .wish-btn{position:absolute;top:9px;right:9px;z-index:2}

.wish-btn{
  display:inline-flex;align-items:center;justify-content:center;gap:7px;
  width:32px;height:32px;padding:0;border:1px solid var(--rule);
  border-radius:999px;background:var(--panel);color:var(--ink-faint);
  cursor:pointer;font-family:inherit;
  transition:color .14s ease,border-color .14s ease,background-color .14s ease;
}
.wish-btn svg{width:17px;height:17px;display:block;fill:none;stroke:currentColor;stroke-width:1.7;stroke-linecap:round;stroke-linejoin:round}
.wish-btn:hover{color:var(--accent);border-color:var(--accent)}
.wish-btn:focus-visible{outline:2px solid var(--accent);outline-offset:2px}
/* Saved is a filled heart, not just a colour change: colour alone is not a
   state a colour blind buyer can read. */
.wish-btn[aria-pressed="true"]{color:var(--accent);border-color:var(--accent);background:var(--accent-soft)}
.wish-btn[aria-pressed="true"] svg{fill:currentColor}
/* The labelled version on the product page, full width under the cart button. */
.wish-btn-solo{
  position:static;width:100%;height:auto;padding:11px 14px;border-radius:9px;
  font-size:14px;font-weight:620;color:var(--ink-soft);
}
.wish-btn-solo span{display:inline-block}

.cart-btn{
  display:inline-flex;align-items:center;justify-content:center;
  border:1px solid var(--rule);border-radius:8px;background:var(--panel);
  color:var(--ink);padding:8px 13px;font-size:13px;font-weight:620;
  font-family:inherit;cursor:pointer;
  transition:border-color .14s ease,background-color .14s ease,color .14s ease;
}
.cart-btn:hover{border-color:var(--accent);color:var(--accent)}
.cart-btn:focus-visible{outline:2px solid var(--accent);outline-offset:2px}
.cart-btn-block{
  width:100%;background:var(--accent);border-color:var(--accent);color:#fff;
  padding:13px 16px;font-size:15px;font-weight:640;border-radius:9px;
}
.cart-btn-block:hover{background:var(--accent-hover);border-color:var(--accent-hover);color:#fff}

/* ── product page rating and reviews ─────────────────────────────────────── */

.prod-rate{margin:0 0 12px}
.prod-rate:empty{display:none}

/* The grid's own row gap does the separating, so no top margin here. */
.reviews{margin:0;padding-top:8px;border-top:1px solid var(--rule)}
.reviews .sec-head{padding-top:20px}
/* Pinned to the first column rather than left to auto-placement, so the
   reviews can never drift under the sticky buy rail if a fourth child is ever
   added to this grid. */
@media (min-width:881px){ .prod .reviews{grid-column:1} }
.rv-summary{margin:0 0 18px}
.rv-list{list-style:none;margin:0;padding:0}
.rv{padding:16px 0;border-top:1px solid var(--rule-soft)}
.rv:first-child{border-top:0;padding-top:0}
.rv-head{display:flex;align-items:center;gap:10px;flex-wrap:wrap;margin:0 0 7px}
.rv-who{font-size:13.5px;font-weight:640;color:var(--ink)}
/* A review written by the team is labelled as such. It is never dressed up as
   an ordinary customer voice. */
.rv-tag{
  font-size:10.5px;font-weight:680;letter-spacing:.06em;text-transform:uppercase;
  color:var(--ink-faint);border:1px solid var(--rule);padding:2px 6px;border-radius:5px;
}
.rv-when{font-size:12.5px;color:var(--ink-faint);margin-left:auto}
.rv-body{font-size:14.5px;color:var(--ink-soft);margin:0;line-height:1.6;max-width:66ch}
.rv-note{font-size:13px;color:var(--ink-faint);margin:18px 0 0;line-height:1.55;max-width:62ch}

/* ── toast ───────────────────────────────────────────────────────────────── */

.px-toast{
  position:fixed;left:50%;bottom:26px;transform:translate(-50%,14px);
  background:var(--ink);color:var(--ground);
  padding:11px 18px;border-radius:999px;font-size:13.5px;font-weight:600;
  box-shadow:0 6px 24px rgba(0,0,0,.22);z-index:60;
  opacity:0;pointer-events:none;transition:opacity .18s ease,transform .18s ease;
}
.px-toast.on{opacity:1;transform:translate(-50%,0)}
@media (prefers-reduced-motion: reduce){
  .px-toast{transition:opacity .18s ease}
  .px-toast.on{transform:translate(-50%,0)}
}

/* ── cart page ───────────────────────────────────────────────────────────── */

/* Same two column shape as the product page, so the cart does not invent a
   third layout: list on the left, totals in a sticky rail on the right. */
.cart-page{display:grid;grid-template-columns:minmax(0,1fr) 330px;gap:44px;padding:30px 0 64px;align-items:start}
@media (max-width:880px){.cart-page{grid-template-columns:1fr;gap:26px}}
.cart-h{font-size:19px;font-weight:680;letter-spacing:-.02em;margin:0}
.sec-head-2{margin-top:40px;padding-top:24px;border-top:1px solid var(--rule)}

.lines{list-style:none;margin:0;padding:0}
.line{
  display:flex;align-items:flex-start;gap:15px;padding:15px 0;
  border-bottom:1px solid var(--rule-soft);
}
.line:first-child{padding-top:4px}
.line-thumb{
  flex:none;width:104px;aspect-ratio:16/10;border:1px solid var(--rule);
  border-radius:9px;overflow:hidden;background:var(--panel-2);
  display:flex;align-items:center;justify-content:center;
  /* The thumbnail is a link, so without this the format pill inside it picks
     up the underline. */
  text-decoration:none;
}
.line-thumb .kind{font-size:9.5px;padding:4px 7px;text-align:center}
.line-thumb img{width:100%;height:100%;object-fit:cover;display:block}
.line-body{flex:1;min-width:0;display:flex;flex-direction:column;gap:4px}
.line-title{font-size:14.5px;font-weight:640;letter-spacing:-.012em;margin:0;line-height:1.35}
.line-title a{text-decoration:none}
.line-title a:hover{color:var(--accent)}
.line-sub{font-size:12.5px;color:var(--ink-faint);margin:0}
.line-side{flex:none;display:flex;flex-direction:column;align-items:flex-end;gap:8px}
.line-x{
  border:0;background:none;padding:0;font-family:inherit;font-size:12.5px;
  font-weight:560;color:var(--ink-faint);cursor:pointer;text-decoration:underline;
}
.line-x:hover{color:var(--ink)}
.line-x:focus-visible{outline:2px solid var(--accent);outline-offset:2px;border-radius:3px}
.line-gone .line-title{color:var(--ink-faint);font-weight:600}
.line-gone .line-sub{font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:11.5px}
.cart-note{font-size:13.5px;color:var(--ink-faint);margin:14px 0 0}
.facts-top{margin-top:0;padding-top:0;border-top:0;margin-bottom:16px;padding-bottom:16px;border-bottom:1px solid var(--rule-soft)}
.buy .amount-note{min-height:1em}
.voucher-box{margin:-2px 0 16px}
.voucher-box > label{display:block;margin:0 0 6px;font-size:11.5px;font-weight:700;letter-spacing:.02em;text-transform:uppercase;color:var(--ink-soft)}
.voucher-row{display:grid;grid-template-columns:minmax(0,1fr) auto;gap:8px}
.voucher-row input{min-width:0;width:100%;font:inherit;font-size:14px;padding:10px 11px;border:1.5px solid var(--rule);border-radius:9px;background:var(--panel);color:var(--ink);text-transform:uppercase}
.voucher-row input:focus{outline:none;border-color:var(--accent)}
.voucher-row button{font:inherit;font-size:13px;font-weight:700;padding:0 14px;border:1.5px solid var(--rule);border-radius:9px;background:var(--panel-2);color:var(--ink);cursor:pointer}
.voucher-row button:hover{border-color:var(--accent);color:var(--accent)}
.voucher-row button:disabled{opacity:.55;cursor:not-allowed}
.voucher-msg{margin:7px 0 0;font-size:12px;line-height:1.4;color:var(--ink-faint)}
.voucher-msg.good{color:var(--accent)}
.voucher-msg.bad{color:#B4342A}

/* ── phones ──────────────────────────────────────────────────────────────── */

@media (max-width:700px){
  /* Two cards across leaves no room for an add button per card, so the heart
     over the image carries the whole job and the button is dropped rather than
     squeezed into something too small to hit reliably. */
  .card-acts .cart-btn{display:none}
  .card-acts{margin-top:0}
  .card-acts .wish-btn{top:7px;right:7px;width:29px;height:29px}
  .card-acts .wish-btn svg{width:15px;height:15px}
  .card-rate .stars-count{display:none}
  .pricebox{gap:5px}
  .price-was{font-size:11.5px}
  .price-off{display:none}
  .card-foot .pricebox{flex-direction:row;align-items:baseline}

  .pricebox-lg .price{font-size:27px}
  .reviews{margin-top:30px}
  .rv-when{margin-left:0;width:100%}

  .line-thumb{width:78px}
  .line-title{font-size:13.5px}
  .cart-page{padding-top:20px}
}

/* ── policy pages ────────────────────────────────────────────────────────────
   Same left rail pattern as the editorial blocks on the home page. A policy is
   the one document people actually scan rather than read, so the rail carries a
   sticky contents list and the body fills the rest of the frame instead of
   sitting as a narrow column with dead space beside it. */

.legal{padding:34px 0 70px}
/* The title block and the summary card are two columns from laptop up, for the
   same reason the home page hero is: a 70ch measure alone in a 1200px frame
   reads as text on half the screen. Stacked below 1000px, in source order. */
.legal-hero{padding-bottom:26px;border-bottom:1px solid var(--rule)}
.legal-top{max-width:70ch}
.legal-top h1{font-size:clamp(26px,4vw,38px);margin:0 0 10px}
.legal-updated{font-size:13px;color:var(--ink-faint);margin:0}
.legal-intro{font-size:16.5px;color:var(--ink-soft);margin:16px 0 0;line-height:1.6}
.legal-side .legal-intro{margin:0}

.tldr{background:var(--accent-soft);border:1px solid var(--rule);border-radius:var(--radius);padding:20px 22px;margin:26px 0 0;max-width:70ch}
.tldr .note-lbl{font-size:11px;font-weight:660;letter-spacing:.09em;text-transform:uppercase;color:var(--accent);margin:0 0 10px}
.tldr ul{margin:0;padding:0;list-style:none;display:flex;flex-direction:column;gap:8px}
.tldr li{position:relative;padding-left:22px;font-size:14.5px;color:var(--ink);line-height:1.55}
.tldr li::before{content:"";position:absolute;left:2px;top:8px;width:7px;height:7px;border-radius:50%;background:var(--accent)}

.legal-grid{padding-top:34px}
.legal-nav{margin:0 0 30px}
.legal-nav .nav-lbl{font-size:11px;font-weight:660;letter-spacing:.09em;text-transform:uppercase;color:var(--ink-faint);margin:0 0 12px}
.legal-nav ol{list-style:none;margin:0;padding:0;counter-reset:sec;display:flex;flex-direction:column;gap:2px}
.legal-nav li{counter-increment:sec}
.legal-nav a{display:block;padding:5px 0;font-size:13.5px;color:var(--ink-soft);text-decoration:none;line-height:1.4}
.legal-nav a::before{content:counter(sec) ". ";color:var(--ink-faint);font-variant-numeric:tabular-nums}
.legal-nav a:hover{color:var(--accent)}

.legal-doc{counter-reset:h2sec;max-width:72ch;font-size:15.5px;color:var(--ink-soft);line-height:1.68}
.legal-doc section{padding:0 0 8px;scroll-margin-top:20px}
.legal-doc section + section{margin-top:34px;padding-top:30px;border-top:1px solid var(--rule-soft)}
.legal-doc h2{counter-increment:h2sec;font-size:19px;font-weight:680;letter-spacing:-.018em;color:var(--ink);margin:0 0 14px;line-height:1.3}
.legal-doc h2::before{content:counter(h2sec) ". ";color:var(--accent);font-variant-numeric:tabular-nums}
.legal-doc h3{font-size:14.5px;font-weight:660;letter-spacing:-.008em;color:var(--ink);margin:22px 0 8px}
.legal-doc p{margin:0 0 14px}
.legal-doc p:last-child{margin-bottom:0}
.legal-doc ul{margin:0 0 14px;padding:0;list-style:none;display:flex;flex-direction:column;gap:9px}
.legal-doc li{position:relative;padding-left:22px}
.legal-doc li::before{content:"";position:absolute;left:3px;top:10px;width:5px;height:5px;border-radius:50%;background:var(--accent);opacity:.75}
.legal-doc a{color:var(--accent);text-decoration:none;font-weight:560}
.legal-doc a:hover{text-decoration:underline}
.legal-doc strong{color:var(--ink);font-weight:650}
.legal-note{background:var(--panel);border:1px solid var(--rule);border-radius:var(--radius);padding:16px 18px;margin:0 0 14px;font-size:14.5px}
.legal-note p:last-child{margin-bottom:0}

@media (min-width:1000px){
  .legal-hero{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,430px);gap:0 60px;align-items:start}
  .legal-top{max-width:56ch}
  .legal-hero .tldr{margin:0;max-width:none}
  .legal-side{padding-top:38px}

  .legal-grid{display:grid;grid-template-columns:minmax(0,250px) minmax(0,1fr);gap:0 64px;align-items:start}
  .legal-nav{position:sticky;top:22px;margin:0;max-height:calc(100vh - 48px);overflow-y:auto}
}

/* Hub page */
/* Cards, not prose, so the shared list bullet and the section counter both have
   to be switched back off inside this list. */
/* Beats `.legal-doc ul`, which is a flex column with bullet dots. Specificity,
   not source order, is what decides here. */
.legal-doc .pol-list{list-style:none;margin:0;padding:0;display:grid;grid-template-columns:repeat(2,1fr);gap:16px}
@media (max-width:760px){.legal-doc .pol-list{grid-template-columns:1fr}}
/* A blog index holding a single post should fill the row rather than sit in
   half of one. Scoped to an only child so it stops applying by itself the
   moment a second post is published, and so it can never reach the four card
   list on /policies. Browsers without :has simply keep the old half width. */
.legal-doc .pol-list:has(> .pol:only-child){grid-template-columns:minmax(0,1fr)}
/* Blog post illustration. Carries width and height in the markup so the space
   is reserved before the image arrives and the text below it does not jump. */
.legal-doc .post-fig{margin:0 0 28px}
.legal-doc .post-fig img{display:block;width:100%;height:auto;border:1px solid var(--rule);border-radius:var(--radius)}
.legal-doc .post-fig figcaption{margin:10px 0 0;font-size:13px;line-height:1.5;color:var(--ink-faint)}
.legal-doc .pol-list li{padding-left:0}
.legal-doc .pol-list li::before{content:none}
.pol{background:var(--panel);border:1px solid var(--rule);border-radius:var(--radius);padding:22px}
/* The whole card is one link, so the link weight and colour have to be reset
   back to body text or every word inside inherits the accent link style. */
.legal-doc .pol a{text-decoration:none;color:inherit;display:block;font-weight:400}
.legal-doc .pol a:hover{text-decoration:none}
.pol:hover{border-color:var(--accent)}
.legal-doc .pol h3{font-size:16px;font-weight:660;letter-spacing:-.015em;margin:0 0 7px;color:var(--ink)}
.legal-doc .pol p{font-size:14px;color:var(--ink-soft);margin:0;line-height:1.55}
.pol .pol-go{display:inline-block;margin-top:12px;font-size:13px;font-weight:580;color:var(--accent)}

/* Footer links */
.foot-nav{list-style:none;margin:0 0 12px;padding:0;display:flex;flex-wrap:wrap;gap:6px 18px}
.foot-nav a{font-size:13px;color:var(--ink-soft);text-decoration:none}
.foot-nav a:hover{color:var(--accent);text-decoration:underline}

@media (max-width:700px){
  .legal{padding:24px 0 50px}
  .legal-doc{font-size:15px}
  .legal-doc h2{font-size:17.5px}
}

/* ── measurement notice pill ──────────────────────────────────────────────────
   shop.js appends this on a first visit and REMOVES IT FROM THE DOM when it is
   dismissed. It is never toggled with the hidden attribute, which is the only
   reason the display:flex below is safe.

   A NOTICE, not a consent gate: one button, and dismissing it changes nothing
   about what is collected. Cloudflare Web Analytics is injected at the edge, so
   no button on the page could switch it off. See the long note in shop.js
   before adding a second button here.

   🔴 Do not switch this to `bar.hidden = true`. An author rule of
   `.px-notice{display:flex}` outranks the user agent's `[hidden]{display:none}`,
   so the bar would stay visible with no way to dismiss it. If you ever do need
   the attribute, add `.px-notice[hidden]{display:none}` in the same commit. */
.px-notice{
  position:fixed;left:50%;bottom:18px;transform:translateX(-50%);
  width:calc(100% - 24px);max-width:640px;
  display:flex;align-items:center;gap:14px;
  padding:10px 12px 10px 18px;
  background:var(--panel);color:var(--ink-soft);
  border:1px solid var(--rule);border-radius:999px;
  font-size:13px;line-height:1.45;
  box-shadow:0 8px 28px rgba(17,22,28,.16);
  /* Above the toast (60) so an "Added to your cart" cannot bury it. */
  z-index:70;
}
.px-notice p{margin:0;flex:1 1 auto}
.px-notice a{color:var(--accent)}
.px-notice-acts{display:flex;gap:8px;flex:0 0 auto}
.px-notice button{
  font:inherit;font-weight:600;cursor:pointer;white-space:nowrap;
  padding:7px 15px;border-radius:999px;
  border:1px solid var(--rule);background:var(--panel-2);color:var(--ink);
}
.px-notice button:hover{border-color:var(--accent);color:var(--accent)}
/* --panel, not #fff: on the dark palette --panel is near black, which is the
   readable choice on the brighter dark-mode accent. Same trick as .px-toast. */
.px-notice button.yes{background:var(--accent);border-color:var(--accent);color:var(--panel)}
.px-notice button.yes:hover{background:var(--accent-hover);border-color:var(--accent-hover);color:var(--panel)}

/* Phone: the pill becomes a card and the two buttons share the full width,
   because a 44px tap target matters more than the pill silhouette. */
@media (max-width:640px){
  .px-notice{
    bottom:12px;flex-wrap:wrap;gap:11px;
    padding:14px 16px;border-radius:16px;
  }
  .px-notice-acts{width:100%}
  /* 12px vertical, not 10px, so the button clears a 44px tap target. */
  .px-notice button{flex:1 1 0;padding:12px 15px}
}

/* ── account and seller dashboard (/auth) ──────────────────────────────────────
   The first page on payxem.shop that is a tool rather than a shopfront, so it
   gets the first real form styles on the site. Everything below is scoped under
   .sell-page so nothing here can reach the storefront, which has no forms and
   must not inherit any of it.

   Deliberately reuses the existing tokens and .btn rather than introducing a
   second visual language. A seller dashboard that looks like a different product
   from the storefront it publishes to is a worse dashboard. */

.sell-page{padding:28px 0 64px}
.sell-page .wrap{max-width:820px}

/* One screen is visible at a time: sign in, open a shop, or the dashboard. They
   are swapped by removing `hidden`, and none of them sets `display` in this
   stylesheet, so the UA's [hidden]{display:none} keeps working.
   🔴 Do NOT give .sell-card a display rule: that outranks [hidden] and every
   panel renders at once. Same trap already documented on .px-notice. */
.sell-card{
  background:var(--panel);border:1px solid var(--rule);border-radius:var(--radius);
  padding:24px;box-shadow:var(--shadow);margin-bottom:18px;
}
.sell-card h2{margin:0 0 6px;font-size:19px;letter-spacing:-.01em}
.sell-card h3{margin:22px 0 6px;font-size:15px;letter-spacing:-.005em}
.sell-card p{margin:0 0 14px;color:var(--ink-soft);font-size:14.5px}
.sell-card p:last-child{margin-bottom:0}

.sell-field{display:block;margin:0 0 14px}
.sell-field > span{
  display:block;font-size:13px;font-weight:600;color:var(--ink);
  margin:0 0 5px;letter-spacing:.01em;
}
.sell-field input,.sell-field select,.sell-field textarea{
  font:inherit;font-size:15px;width:100%;
  padding:10px 12px;border-radius:9px;
  border:1px solid var(--rule);background:var(--panel-2);color:var(--ink);
}
.sell-field textarea{min-height:90px;resize:vertical;line-height:1.55}
.sell-field input:focus,.sell-field select:focus,.sell-field textarea:focus{
  outline:2px solid var(--accent);outline-offset:1px;border-color:var(--accent);
}
.sell-field .hint{display:block;margin-top:5px;font-size:12.5px;color:var(--ink-faint);font-weight:400}

.sell-row{display:flex;gap:14px;flex-wrap:wrap}
.sell-row .sell-field{flex:1 1 180px;min-width:0}

/* The click-wrap. Boxed rather than a bare checkbox in a paragraph, because
   this control is the seller's signature and it should not be possible to tick
   it without having noticed it. */
.sell-accept{
  display:flex;gap:11px;align-items:flex-start;
  padding:14px;border-radius:10px;
  border:1px solid var(--rule);background:var(--panel-2);
  margin:0 0 16px;font-size:14px;color:var(--ink-soft);line-height:1.5;
}
.sell-accept input{margin:3px 0 0;flex:0 0 auto;width:17px;height:17px;accent-color:var(--accent)}
.sell-accept a{color:var(--accent)}

.sell-acts{display:flex;gap:10px;align-items:center;flex-wrap:wrap;margin-top:4px}
.sell-acts .btn{flex:0 0 auto}

/* Seller earnings. Three figures that must be readable at a glance and must
   not be mistaken for each other: what is payable, what is still clearing, and
   what has already been sent. They wrap to one column on a phone rather than
   shrinking, because a money figure that has to be squinted at is worse than a
   taller card. */
.earn-figs{
  display:grid;gap:12px;margin:0 0 16px;
  grid-template-columns:1fr;
}
@media (min-width:560px){ .earn-figs{grid-template-columns:repeat(3,1fr)} }
.earn-fig{
  padding:14px 15px;border-radius:10px;
  border:1px solid var(--rule);background:var(--panel-2);
  min-width:0;
}
.earn-k{
  display:block;font-size:12px;font-weight:650;letter-spacing:.04em;
  text-transform:uppercase;color:var(--ink-faint);
}
.earn-v{
  display:block;margin-top:6px;font-size:23px;font-weight:750;
  letter-spacing:-.02em;line-height:1.15;
  /* A long figure breaks rather than pushing the card wider. */
  overflow-wrap:anywhere;
}
.earn-s{display:block;margin-top:4px;font-size:12.5px;color:var(--ink-faint)}

/* The payout block. Separated by a rule because asking to be paid is a
   different kind of action from reading a number. */
.earn-payout{
  margin:0 0 18px;padding-top:16px;
  border-top:1px solid var(--rule-soft);
}
.earn-note{margin:0 0 12px;font-size:14px;color:var(--ink-soft);line-height:1.6}

/* Refunds. Stated, not hidden, but quiet: it is information, not a warning. */
.earn-refunded{
  margin:-6px 0 16px;font-size:13px;color:var(--ink-faint);line-height:1.55;
}

/* Secondary action. Same shape as .btn so the two sit level, quiet fill so the
   primary action stays the obvious one. */
.btn-quiet{
  font:inherit;font-weight:600;font-size:14.5px;cursor:pointer;
  padding:11px 20px;border-radius:999px;
  border:1px solid var(--rule);background:var(--panel-2);color:var(--ink);
}
.btn-quiet:hover{border-color:var(--accent);color:var(--accent)}
.btn-quiet:disabled{color:var(--ink-faint);cursor:not-allowed;border-color:var(--rule)}
.btn-quiet:focus-visible{outline:2px solid var(--accent);outline-offset:3px}

/* One message element per panel, colour set by a modifier. Empty and hidden by
   default so a stale error can never linger under a form the seller has since
   corrected. */
.sell-msg{margin:14px 0 0;font-size:14px;line-height:1.5;color:var(--ink-soft)}
.sell-msg.bad{color:#B4342A}
.sell-msg.good{color:var(--accent)}
@media (prefers-color-scheme: dark){:root:not([data-theme="light"]) .sell-msg.bad{color:#F08B80}}
:root[data-theme="dark"] .sell-msg.bad{color:#F08B80}

/* Seller click-wrap is a real modal because it is a separate legal action from
   opening the store. It appears only for signed-in buyers with no current
   agreement acceptance. */
.seller-consent{
  position:fixed;inset:0;z-index:90;display:flex;align-items:flex-end;
  justify-content:center;padding:0;
}
.seller-consent[hidden]{display:none}
.seller-consent-on,.seller-consent-on body{overflow:hidden}
.seller-consent-back{
  position:absolute;inset:0;background:rgba(9,13,16,.6);
  -webkit-backdrop-filter:blur(3px);backdrop-filter:blur(3px);
}
.seller-consent-card{
  position:relative;width:100%;max-width:570px;max-height:92vh;overflow-y:auto;
  padding:25px 22px 23px;background:var(--panel);border:1px solid var(--rule);
  border-radius:18px 18px 0 0;box-shadow:0 -10px 40px rgba(0,0,0,.28);
}
.seller-consent-card h2{margin:0 0 9px;font-size:23px;letter-spacing:-.02em}
.seller-consent-card > p{font-size:14px;line-height:1.6;color:var(--ink-soft)}
.seller-consent-card a{color:var(--accent)}
.seller-consent-card .eyebrow{margin:0 0 5px;color:var(--accent);font-size:12px}
.seller-consent-card .sell-accept{margin-top:17px}
.seller-consent-card .seller-consent-evidence{
  margin:0 0 18px;padding:11px 13px;border-left:3px solid var(--accent);
  background:var(--panel-2);font-size:12.5px;line-height:1.55;
}
.seller-consent-card .seller-consent-later{text-decoration:none;color:var(--ink)}
@media (min-width:600px){
  .seller-consent{align-items:center;padding:24px}
  .seller-consent-card{border-radius:16px;box-shadow:0 20px 60px rgba(0,0,0,.32)}
}

/* Listings */
.sell-head{display:flex;align-items:baseline;justify-content:space-between;gap:14px;margin:0 0 14px}
.sell-head h2{margin:0}
.sell-list{list-style:none;margin:0;padding:0;display:grid;gap:10px}
.sell-item{
  display:flex;gap:14px;align-items:center;
  padding:13px 15px;border:1px solid var(--rule);border-radius:10px;background:var(--panel-2);
}
.sell-item-main{flex:1 1 auto;min-width:0}
.sell-item-t{font-weight:650;font-size:15px;letter-spacing:-.005em;margin:0 0 2px}
.sell-item-d{font-size:13px;color:var(--ink-faint);margin:0}
.sell-item-acts{flex:0 0 auto;display:flex;gap:8px;flex-wrap:wrap;justify-content:flex-end}

/* Listing state. Reads as a label, never as a decoration: a seller has to be
   able to tell at a glance which listings are actually earning. */
.sell-tag{
  display:inline-block;font-size:11.5px;font-weight:700;letter-spacing:.04em;
  text-transform:uppercase;padding:3px 9px;border-radius:999px;
  border:1px solid var(--rule);background:var(--panel);color:var(--ink-faint);
}
.sell-tag.published{border-color:var(--accent);background:var(--accent-soft);color:var(--accent)}
.sell-tag.pending_review{border-color:#C08A2E;color:#C08A2E}
.sell-tag.rejected,.sell-tag.suspended{border-color:#B4342A;color:#B4342A}

.sell-note{
  font-size:13.5px;color:var(--ink-soft);line-height:1.55;
  padding:12px 14px;border-radius:9px;
  border:1px solid var(--rule);background:var(--panel-2);margin:0 0 16px;
}
.sell-note strong{color:var(--ink)}

@media (max-width:640px){
  .sell-card{padding:18px}
  .sell-item{flex-wrap:wrap;gap:10px}
  .sell-item-acts{width:100%;justify-content:flex-start}
  /* 44px tap targets once the row has stacked. */
  .sell-item-acts .btn,.sell-item-acts .btn-quiet{padding:11px 16px}
}

/* ── currency selector + converted prices ─────────────────────────────────────
   Sits in the header beside the cart. Kept as a real <select> rather than a
   custom dropdown: it is five options, the native control is keyboard and
   screen reader correct for free, and on a phone it opens the system picker
   which is the best possible version of this control.

   🔴 The price charged is always US dollars. .px-usd-note is the line that
   says so, and it is hidden while USD is selected because there is nothing to
   disclose then. */

.cur-pick{position:relative;display:inline-flex;align-items:center}
.cur-pick select{
  font:inherit;font-size:13px;font-weight:650;letter-spacing:.02em;
  color:var(--ink);background:var(--panel-2);
  border:1px solid var(--rule);border-radius:999px;
  padding:6px 26px 6px 11px;cursor:pointer;
  -webkit-appearance:none;appearance:none;line-height:1.2;
}
.cur-pick select:hover{border-color:var(--accent);color:var(--accent)}
.cur-pick select:focus-visible{outline:2px solid var(--accent);outline-offset:2px}
.cur-pick select:disabled{opacity:.6;cursor:default}
/* The chevron. A background image would need two files for the two themes, so
   it is drawn with borders and follows currentColor. */
.cur-pick::after{
  content:"";position:absolute;right:11px;top:50%;
  width:5px;height:5px;margin-top:-4px;
  border-right:1.5px solid var(--ink-faint);border-bottom:1.5px solid var(--ink-faint);
  transform:rotate(45deg);pointer-events:none;
}

/* "Charged in USD". Quiet, present wherever a converted total is a decision
   point, never shouted. */
.px-usd-note{
  display:block;margin:6px 0 0;
  font-size:12.5px;line-height:1.45;color:var(--ink-faint);font-weight:400;
}
.pricebox .px-usd-note,.pricebox-lg .px-usd-note{flex-basis:100%}

@media (max-width:700px){
  /* The header is tight on a phone. The label goes, the control stays. */
  .cur-pick select{padding:6px 24px 6px 9px;font-size:12.5px}
}

/* ── you may also like ────────────────────────────────────────────────────────
   A third grid child on the product page, a sibling of the two columns rather
   than a block inside the left one, for the same reason the reviews section is:
   grid auto placement then puts it under the description on a desktop and after
   the buy box on a phone, instead of pushing the price below a long list. */

.also{grid-column:1/-1;margin:8px 0 0;padding-top:28px;border-top:1px solid var(--rule)}
.also .sec-head-2{margin-bottom:16px}
.also h2{margin:0;font-size:19px;letter-spacing:-.012em}
.also .also-sub{margin:4px 0 0;font-size:14px;color:var(--ink-faint)}
.also .grid{margin-top:4px}
@media (min-width:1000px){
  /* Three across on a desktop regardless of the page's own column count: this
     row is a fixed three, so it should not inherit the four across storefront
     grid and leave one empty cell. */
  .also .grid{grid-template-columns:repeat(3,1fr)}
}

/* ── seller sign in ───────────────────────────────────────────────────────────
   Mobile first. One column with the form on top, because on a phone the form is
   the whole job and the pitch is what you read while waiting for the email. At
   900px it becomes two columns with the card on the left at a fixed, narrow
   measure: an auth card that stretches with the viewport is the thing that made
   this page feel unfinished.

   🔴 No display rule on #s-email, #s-code or #s-2fa. They are swapped with the
   hidden attribute, and any display here would outrank [hidden] and show all
   three at once. Same trap as .px-notice and .sell-card. */

.auth{padding:34px 0 72px}
.auth-inner{display:grid;gap:34px;align-items:start}
@media (min-width:900px){
  .auth{padding:48px 0 72px}
  /* The card first in source order and first on screen. 400px is the measure a
     single field wants; the rest of the row carries the pitch. */
  .auth-inner{grid-template-columns:400px minmax(0,1fr);gap:64px;align-items:center}
  /* Fills the viewport so a short form sits in the middle of the page rather
     than clinging to the top with a screen of dead space under it.
     🔴 min-height goes on .auth-inner, NOT on .auth: .auth is toggled with the
     hidden attribute, and this is where a stray display or layout rule would
     outrank [hidden]. .auth-inner is never hidden, so it is the safe place. */
  .auth-inner{min-height:min(66vh,560px)}
}

.auth-card{
  background:var(--panel);border:1px solid var(--rule);
  border-radius:16px;padding:26px 24px 22px;box-shadow:var(--shadow);
}
@media (min-width:900px){.auth-card{padding:32px 30px 26px}}

.auth-h{margin:0 0 6px;font-size:23px;line-height:1.25;letter-spacing:-.02em}
.auth-sub{margin:0 0 20px;font-size:14.5px;line-height:1.55;color:var(--ink-soft)}
.auth-sub strong{color:var(--ink);font-weight:650;word-break:break-word}

/* Full width, and tall enough to be the obvious next action on a phone. */
.btn-block{width:100%;display:block;padding:13px 20px;font-size:15px;margin-top:2px}

/* The code field. Wide tracking and a tabular face so six digits read as six
   digits and a mistyped one is easy to spot. */
.code-input{
  font-variant-numeric:tabular-nums;
  font-size:22px !important;letter-spacing:.34em;text-align:center;
  padding:12px 10px !important;font-weight:650;
}
.code-input::placeholder{letter-spacing:.34em;color:var(--ink-faint);opacity:.5;font-weight:400}

/* A button that reads as a link. Used for resend and for changing the email,
   which are secondary to the one primary action above them. */
.linkish{
  font:inherit;font-size:14px;font-weight:600;
  background:none;border:0;padding:0;margin:0;
  color:var(--accent);cursor:pointer;text-decoration:underline;
  text-underline-offset:2px;
}
.linkish:hover{color:var(--accent-hover)}
.linkish:disabled{color:var(--ink-faint);cursor:default;text-decoration:none}
.linkish:focus-visible{outline:2px solid var(--accent);outline-offset:3px;border-radius:3px}

.auth-alt{margin:18px 0 0;font-size:14px;color:var(--ink-soft);line-height:1.6}
.auth-alt a{color:var(--accent)}
.auth-alt .dot{margin:0 8px;color:var(--ink-faint)}
.auth-fine{margin:14px 0 0;font-size:12.5px;line-height:1.55;color:var(--ink-faint)}
.auth-fine a{color:var(--accent)}

/* The pitch beside the form. */
.auth-aside h2{margin:6px 0 10px;font-size:27px;line-height:1.2;letter-spacing:-.025em}
@media (min-width:900px){.auth-aside h2{font-size:31px}}
.auth-lede{margin:0 0 22px;font-size:15.5px;line-height:1.6;color:var(--ink-soft);max-width:48ch}
.auth-points{list-style:none;margin:0;padding:0;display:grid;gap:15px;max-width:52ch}
.auth-points li{
  font-size:14.5px;line-height:1.55;color:var(--ink-soft);
  padding-left:26px;position:relative;
}
/* A check drawn with two borders, so there is no icon file and it follows the
   accent in both themes. */
.auth-points li::before{
  content:"";position:absolute;left:2px;top:5px;
  width:11px;height:6px;
  border-left:2px solid var(--accent);border-bottom:2px solid var(--accent);
  transform:rotate(-45deg);
}
.auth-points strong{display:block;color:var(--ink);font-weight:650;margin-bottom:1px}

/* "optional" beside a field label. Inline, unlike .hint, which is a block note
   under the input. */
.sell-field .opt{
  font-weight:400;font-size:12px;color:var(--ink-faint);
  text-transform:none;letter-spacing:0;margin-left:5px;
}

/* The dashboard's "View my shop" is an anchor styled as a button, so it needs
   the underline taken off and the text centred like a real one. */
a.btn-quiet{display:inline-block;text-decoration:none;text-align:center}

/* ── create account ─────────────────────────────────────────────────────────
   🔴 #s-tabs, the [data-su] step panels and the wizard's own notes are all
   swapped with the hidden attribute. Anything given a display rule here MUST
   restate [hidden]{display:none} at the same specificity, or the rule outranks
   the UA sheet and the element shows through. Same trap as .sell-card. */

.auth-tabs{
  display:flex;gap:6px;padding:4px;margin:0 0 22px;
  background:var(--panel-2);border:1px solid var(--rule);border-radius:999px;
}
.auth-tabs[hidden]{display:none}
.auth-tab{
  flex:1 1 0;min-width:0;font:inherit;font-size:14px;font-weight:650;
  padding:9px 10px;border:0;border-radius:999px;cursor:pointer;
  background:transparent;color:var(--ink-soft);
}
.auth-tab:hover{color:var(--ink)}
.auth-tab.is-on{background:var(--panel);color:var(--ink);box-shadow:var(--shadow)}
.auth-tab:focus-visible{outline:2px solid var(--accent);outline-offset:2px}

/* Three bars, filled up to the step you are on. Aria-hidden: the headings
   already say where you are, and a screen reader gains nothing from this. */
.su-dots{display:flex;gap:7px;margin:0 0 20px}
.su-dots span{height:4px;flex:1 1 0;border-radius:999px;background:var(--rule)}
.su-dots span.is-on{background:var(--accent)}

/* A note under the country field. No display rule, so hidden works on it. */
.su-note{
  margin:-6px 0 14px;padding:10px 12px;border-radius:9px;
  font-size:12.5px;line-height:1.5;color:var(--ink-soft);
  background:var(--panel-2);border:1px solid var(--rule);
}

/* The bot trap. Off screen rather than display:none, because a form filler
   that respects display:none would skip it and never be caught. */
.su-trap{position:absolute;left:-9999px;width:1px;height:1px;overflow:hidden}

/* Back, under a full width primary. Quiet, and never the thing a thumb finds
   first. */
.btn-block-quiet{width:100%;display:block;margin-top:9px;background:transparent;border-color:transparent}
.btn-block-quiet:hover{border-color:var(--rule)}

/* Country combobox. The list is positioned against .combo and is toggled with
   style.display by the page's own script, so it keeps display:none as its
   resting state here. */
.combo{position:relative}
.combo-list{
  display:none;position:absolute;z-index:30;top:calc(100% + 5px);left:0;right:0;
  max-height:236px;overflow-y:auto;
  background:var(--panel);border:1px solid var(--rule);border-radius:11px;
  box-shadow:0 12px 30px rgba(0,0,0,.14);
}
.combo-list [data-c]{
  padding:10px 13px;font-size:14.5px;line-height:1.35;cursor:pointer;
  border-bottom:1px solid var(--rule);
}
.combo-list [data-c]:last-child{border-bottom:0}
.combo-list [data-c]:hover,.combo-list [data-c].is-hi{background:var(--panel-2);color:var(--accent)}
.combo-none{padding:12px 13px;font-size:13.5px;color:var(--ink-faint)}

/* ── the buyer sign in dialog ────────────────────────────────────────────────
   Built and injected by shop.js on first open, so every page gets the same one.

   🔴 Every panel in here is swapped with the hidden attribute. The rules below
   that set display all restate [hidden]{display:none} at the same specificity.
   Miss one and all four panels stack up inside the card at once. Same trap as
   .sell-card and .auth-tabs. */

.px-auth{position:fixed;inset:0;z-index:80;display:flex;align-items:flex-end;justify-content:center}
.px-auth[hidden]{display:none}
@media (min-width:600px){.px-auth{align-items:center;padding:24px}}
/* Locks the page behind the dialog so a phone does not scroll the storefront
   under it while the keyboard is up. */
.px-auth-on,.px-auth-on body{overflow:hidden}

.px-auth-back{
  position:absolute;inset:0;background:rgba(9,13,16,.55);
  -webkit-backdrop-filter:blur(2px);backdrop-filter:blur(2px);
}

.px-auth-card{
  position:relative;width:100%;max-width:420px;max-height:92vh;overflow-y:auto;
  background:var(--panel);border:1px solid var(--rule);
  border-radius:18px 18px 0 0;padding:24px 22px 22px;
  box-shadow:0 -10px 40px rgba(0,0,0,.25);
}
@media (min-width:600px){.px-auth-card{border-radius:16px;box-shadow:0 20px 60px rgba(0,0,0,.3)}}

.px-auth-x{
  position:absolute;top:10px;right:12px;width:32px;height:32px;
  font:inherit;font-size:24px;line-height:1;cursor:pointer;
  background:none;border:0;color:var(--ink-faint);border-radius:8px;
}
.px-auth-x:hover{color:var(--ink);background:var(--panel-2)}
.px-auth-x:focus-visible{outline:2px solid var(--accent);outline-offset:2px}

.px-auth-tabs{
  display:flex;gap:6px;padding:4px;margin:6px 0 20px;
  background:var(--panel-2);border:1px solid var(--rule);border-radius:999px;
}
.px-auth-tabs[hidden]{display:none}
.px-auth-tab{
  flex:1 1 0;min-width:0;font:inherit;font-size:14px;font-weight:650;
  padding:9px 10px;border:0;border-radius:999px;cursor:pointer;
  background:transparent;color:var(--ink-soft);
}
.px-auth-tab:hover{color:var(--ink)}
.px-auth-tab.is-on{background:var(--panel);color:var(--ink);box-shadow:var(--shadow)}
.px-auth-tab:focus-visible{outline:2px solid var(--accent);outline-offset:2px}

.px-auth-h{margin:0 0 6px;font-size:21px;line-height:1.25;letter-spacing:-.02em}
.px-auth-sub{margin:0 0 18px;font-size:14px;line-height:1.55;color:var(--ink-soft)}
.px-auth-sub strong{color:var(--ink);font-weight:650;word-break:break-word}

.px-auth-field{display:block;margin:0 0 14px}
.px-auth-field > span{
  display:block;margin:0 0 6px;font-size:12.5px;font-weight:650;
  letter-spacing:.02em;text-transform:uppercase;color:var(--ink-soft);
}
.px-auth-field input,.px-auth-field select{
  width:100%;font:inherit;font-size:15px;padding:11px 13px;
  border:1.5px solid var(--rule);border-radius:10px;
  background:var(--panel);color:var(--ink);
}
.px-auth-field input:focus,.px-auth-field select:focus{outline:none;border-color:var(--accent)}
.px-auth-field small{display:block;margin-top:5px;font-size:12px;line-height:1.4;color:var(--ink-faint)}

.px-auth-accept{
  display:flex;gap:11px;align-items:flex-start;
  padding:13px;border-radius:10px;margin:0 0 15px;
  border:1px solid var(--rule);background:var(--panel-2);
  font-size:13px;color:var(--ink-soft);line-height:1.5;
}
.px-auth-accept input{margin:2px 0 0;flex:0 0 auto;width:17px;height:17px;accent-color:var(--accent)}
.px-auth-accept a{color:var(--accent)}

/* Off screen rather than display:none, so a form filler still finds it. */
.px-auth-trap{position:absolute;left:-9999px;width:1px;height:1px;overflow:hidden}

/* The primary action, and an anchor styled as one on the signed in panel. */
.px-auth-go{width:100%;display:block;padding:13px 20px;font-size:15px;text-align:center;text-decoration:none}

.px-auth-msg{margin:13px 0 0;font-size:13.5px;line-height:1.5;color:var(--ink-soft)}
.px-auth-msg.bad{color:#B4342A}
.px-auth-msg.good{color:var(--accent)}
@media (prefers-color-scheme: dark){:root:not([data-theme="light"]) .px-auth-msg.bad{color:#F08B80}}
:root[data-theme="dark"] .px-auth-msg.bad{color:#F08B80}

.px-auth-alt{margin:16px 0 0;font-size:13.5px;color:var(--ink-soft);line-height:1.6;text-align:center}
.px-auth-alt .dot{margin:0 8px;color:var(--ink-faint)}
.px-auth-fine{margin:13px 0 0;font-size:12px;line-height:1.55;color:var(--ink-faint)}

/* ── secure card checkout ─────────────────────────────────────────────── */
.checkout-box,.checkout-done{
  margin-top:18px;padding-top:18px;border-top:1px solid var(--rule);
}
.checkout-box[hidden],.checkout-done[hidden]{display:none}
.checkout-head{display:flex;align-items:baseline;justify-content:space-between;gap:12px;margin-bottom:7px}
.checkout-head strong{font-size:15px}
.checkout-head span{font-size:13px;font-weight:700;color:var(--accent);white-space:nowrap}
.checkout-safe{margin:0 0 15px;font-size:12px;line-height:1.5;color:var(--ink-faint)}
.checkout-field{display:block;margin:0 0 12px;text-align:left}
.checkout-field > span{
  display:block;margin:0 0 5px;font-size:11.5px;font-weight:700;
  letter-spacing:.02em;text-transform:uppercase;color:var(--ink-soft);
}
.checkout-field input{
  width:100%;font:inherit;font-size:15px;padding:11px 12px;
  border:1.5px solid var(--rule);border-radius:9px;background:var(--panel);color:var(--ink);
}
.checkout-field input:focus{outline:none;border-color:var(--accent)}
.checkout-row{display:grid;grid-template-columns:1fr 1fr;gap:10px}
.checkout-msg{margin:11px 0 0;font-size:12.5px;line-height:1.45;color:var(--ink-soft)}
.checkout-msg.bad{color:#B4342A}
.checkout-done h2{margin:0 0 7px;font-size:18px}
.checkout-done > p{margin:0 0 13px;font-size:13px;line-height:1.5;color:var(--ink-soft)}
.download-link{
  display:flex;align-items:center;justify-content:space-between;gap:12px;
  margin-top:8px;padding:11px 12px;border:1px solid var(--rule);border-radius:9px;
  color:var(--ink);text-decoration:none;background:var(--panel-2);font-size:13px;
}
.download-link:hover{border-color:var(--accent)}
.download-link span{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.download-link strong{color:var(--accent);font-size:12px}
@media (prefers-color-scheme: dark){:root:not([data-theme="light"]) .checkout-msg.bad{color:#F08B80}}
:root[data-theme="dark"] .checkout-msg.bad{color:#F08B80}

/* ==========================================================================
   Phones, properly, and the installed app.  2026-10-25.

   This block is last on purpose. Everything in it either overrides a rule
   above at equal specificity or adds something new, so the whole section can
   be deleted in one piece and the site returns exactly to what it was.

   What it fixes was measured, not guessed: every page was laid out in a
   390px, 360px and 320px frame and every element's box was read back. The
   layout itself was already sound, with no horizontal overflow at any width.
   What was wrong was the things a layout measurement does not show you: touch
   targets below the 44px minimum, form fields that make iOS zoom the page,
   and a wordmark being crushed on the narrowest phones.
   ========================================================================== */

/* Stops iOS inflating body text in landscape, which it does on its own and
   which breaks every measure capped in ch. */
html{-webkit-text-size-adjust:100%;text-size-adjust:100%}

/* The grey flash iOS paints over a tapped link, in the site's own accent and
   at a weight that reads as feedback rather than as a defect. */
body{-webkit-tap-highlight-color:rgba(11,122,94,.14)}

/* 100vh on a phone is the viewport with the browser's toolbars hidden, so a
   full height element is taller than what you can see and the page jiggles as
   the toolbar slides away. dvh is that measurement done honestly. The vh line
   stays directly above as the fallback for anything that does not know dvh. */
body{min-height:100vh;min-height:100dvh}
.px-auth-card{max-height:92dvh}
.seller-consent-card{max-height:92dvh}

/* ── safe areas ─────────────────────────────────────────────────────────────
   The viewport meta on every page now carries viewport-fit=cover, which is
   what makes env() report anything at all. Without the padding below that
   setting would run text under the notch in landscape and put the two fixed
   bars beneath the home indicator. */
@media (max-width:700px){
  .wrap{
    padding-left:max(16px,env(safe-area-inset-left));
    padding-right:max(16px,env(safe-area-inset-right));
  }
}
/* Each of these restates the padding it is adding to rather than using a bare
   env(), because this block sits at the end of the file and a single rule here
   would otherwise flatten the phone values set further up: the footer is 28px
   on a phone and 34px above it, and the notice is 12px and 18px. */
footer{padding-bottom:calc(34px + env(safe-area-inset-bottom))}
.px-toast{bottom:calc(26px + env(safe-area-inset-bottom))}
.px-notice{bottom:calc(18px + env(safe-area-inset-bottom))}
@media (max-width:700px){
  footer{padding-bottom:calc(28px + env(safe-area-inset-bottom))}
}
@media (max-width:640px){
  .px-notice{bottom:calc(12px + env(safe-area-inset-bottom))}
}

/* Launched from a home screen there is no browser chrome, so the header is
   what sits under the status bar and has to clear it itself. */
@media (display-mode:standalone){
  .site-head{padding-top:env(safe-area-inset-top)}
}

/* ── iOS zooms any field it thinks is too small to read ─────────────────────
   🔴 Below 16px, Safari on iOS zooms the page in when a field takes focus and
   does not zoom back out. It happens on the card number at checkout and on the
   voucher box, which are the two worst places on the site for the layout to
   jump under a thumb.

   pointer:coarse rather than a width, because the trigger is the touch
   keyboard and not the screen size: an iPad in landscape is 1024px wide and
   zooms exactly the same. Desktop is untouched, so the 15px fields a mouse
   sees are still 15px. */
@media (pointer:coarse){
  .sell-field input,.sell-field select,.sell-field textarea,
  .px-auth-field input,.px-auth-field select,
  .checkout-field input,
  .voucher-row input,
  .account-field input,.account-field select{
    font-size:16px;
  }
}

/* ── touch targets ──────────────────────────────────────────────────────────
   44px is the floor. Where a control cannot be 44px wide without pushing
   something off a 320px screen, it is made 44px TALL instead and widened only
   as far as it fits: a target that is tall and a little narrow is hit
   reliably, and one that has been squeezed into its neighbour is not. */
@media (max-width:700px){
  /* The header is the tightest row on the site: a wordmark and four controls
     inside 288px on the narrowest phone still sold. The icons go to 40px and
     the gap closes to 4px, which is what that width will take. */
  .head-actions{gap:4px}
  .head-act{width:40px;height:40px}
  /* The rest of the 44px comes from above and below, where there is room to
     spare in a 62px header. Vertical only, so two adjacent icons cannot
     overlap each other's target and swallow the wrong tap. */
  .head-act::after{content:"";position:absolute;left:0;right:0;top:-2px;bottom:-2px}
  .head-act svg{width:20px;height:20px}

  /* The currency pill. Taller, not wider: the width is what the header cannot
     spare, and the 62px header has room above and below that nothing uses. */
  .cur-pick select{padding:12px 24px 12px 9px}

  /* 🔴 The wordmark was being crushed, not scaled. At 320px flex was taking
     38px out of a fixed ratio image: 118px of logo rendered as 81px without
     the height changing, so the letters came out visibly narrow. It is the
     brand, so it is the one thing in this row that does not flex. */
  .mark{flex:none}
  .mark .logo{flex:none}

  /* Footer navigation is a list of links, not prose, so each one is a target
     in its own right. At 13px they were 16px tall. */
  .foot-nav{gap:0 18px}
  .foot-nav a{display:inline-flex;align-items:center;min-height:44px}

  /* The heart over a product image. 29px was small for the one control a
     phone has on a card, and this one costs no layout width because it is
     positioned over the thumbnail. */
  .card-acts .wish-btn{width:38px;height:38px;top:6px;right:6px}
  .card-acts .wish-btn svg{width:18px;height:18px}

  /* Remove-from-cart, and the resend and change-email buttons. Text sized
     controls with nothing around them to catch a near miss. */
  .line-x,.linkish{padding:11px 0;display:inline-block}

  /* The dialog close button, in the corner where a thumb is least accurate. */
  .px-auth-x{width:40px;height:40px;top:8px;right:8px}

  /* Tab strips and the account rail were landing at 40 and 42. */
  .auth-tab,.px-auth-tab{padding:12px 10px}
  .account-nav a{padding:12px 12px}
}

/* The narrowest phones still in use are 320px, and a folded Galaxy is 280px.
   Pinning the wordmark above takes 38px of give out of this row, so that width
   has to come back from somewhere or the header scrolls sideways. Measured at
   320px: the header needs 23px and these four rules return 26px of it, from
   the padding and the gaps rather than from any control's own size.
   🔴 Change any number here and re-measure at 320px. This row has no slack
   left in it, and the symptom of getting it wrong is the whole page scrolling
   horizontally, not the header alone. */
@media (max-width:360px){
  .site-head .wrap{gap:7px}
  .cur-pick select{padding:10px 20px 10px 6px;font-size:12px}
  .cur-pick::after{right:8px}
  .head-actions{gap:1px}
  .head-act{width:36px}
}

/* ── the install invitation ─────────────────────────────────────────────────
   shop.js appends this and REMOVES IT FROM THE DOM when it is answered, and it
   is only ever appended once the measurement notice has been dismissed, so the
   two can never stack in the same corner.

   🔴 Do not switch this to `bar.hidden = true`. The display:flex below
   outranks the user agent's [hidden]{display:none} and the bar would stay on
   screen with no way to dismiss it. Same trap as .px-notice and .sell-card. */
.px-install{
  position:fixed;left:50%;bottom:18px;transform:translateX(-50%);
  bottom:calc(18px + env(safe-area-inset-bottom));
  width:calc(100% - 24px);max-width:520px;
  display:flex;align-items:center;gap:13px;
  padding:12px 14px;
  background:var(--panel);color:var(--ink-soft);
  border:1px solid var(--rule);border-radius:16px;
  font-size:13px;line-height:1.45;
  box-shadow:0 8px 28px rgba(17,22,28,.18);
  /* Above the toast at 60, below the sign-in dialog at 80: an invitation to
     install must never cover a code being typed. */
  z-index:70;
}
.px-install-ico{flex:0 0 auto;width:40px;height:40px;border-radius:10px}
.px-install-body{flex:1 1 auto;min-width:0}
.px-install-body strong{display:block;font-size:13.5px;font-weight:660;color:var(--ink)}
.px-install-body span{display:block;margin-top:1px;font-size:12.5px;color:var(--ink-faint)}
.px-install-acts{flex:0 0 auto;display:flex;align-items:center;gap:8px}
.px-install-yes,.px-install-no{
  font:inherit;font-weight:620;cursor:pointer;white-space:nowrap;
  border-radius:999px;padding:11px 16px;min-height:44px;
}
.px-install-yes{border:1px solid var(--accent);background:var(--accent);color:var(--panel)}
.px-install-yes:hover{background:var(--accent-hover);border-color:var(--accent-hover)}
.px-install-no{
  border:1px solid transparent;background:transparent;color:var(--ink-faint);
  padding:11px 10px;font-weight:560;
}
.px-install-no:hover{color:var(--ink)}
.px-install-yes:focus-visible,.px-install-no:focus-visible{outline:2px solid var(--accent);outline-offset:2px}

/* On a phone the row cannot hold an icon, two lines of text and two buttons,
   so the buttons drop to their own full width row underneath. */
@media (max-width:560px){
  .px-install{flex-wrap:wrap;gap:11px;padding:14px 16px}
  .px-install-acts{width:100%}
  .px-install-yes{flex:1 1 auto;text-align:center}
}

/* Already installed. Nothing in here is wrong in a browser tab, it is simply
   noise once the site is on a home screen. */
@media (display-mode:standalone){
  .px-install{display:none}
}
