/* SLIRPZ RIPZ — slirpz.com
   ===========================================================================
   DESIGN NOTES, so the ideas do not get "tidied" away later.

   THE PAGE HAS ONE JOB: get the visitor into an eBay Live show. The live call to
   action is in the sticky bar, in the hero, after the steps, and again at the end,
   because people decide at a different point than a page expects them to.

   THE PAGE IS A STACK OF GRADED SLABS. Each section below the hero is a plastic
   shell with a cream label across the top — descriptor left, grade badge right —
   exactly how a graded card is presented. It is the one visual grammar that
   belongs to this business and to nobody else.

   THE SIGNATURE is the wall: real card art out of the library, two rows drifting
   in opposite directions behind the hero, blurred and dimmed to atmosphere. The
   library holds 38,710 pictures of cards that nobody else has. A page about
   opening packs that shows five of them is wasting its only unrepeatable asset.

   THE HERO CARD still tilts toward the pointer with a holo band sliding across
   it. Catching the light is what makes a card worth chasing, so the page opens by
   doing it — once, and nowhere else, so it lands.

   TWO COLOURS ARE RESERVED AND MEAN ONE THING EACH. Gold is money: if something
   gold is not a price, it is wrong. Red is on-air: the live dot and nothing else.
   The three holo accents separate the three Pokémon lanes.
   =========================================================================== */

*, *::before, *::after { box-sizing: border-box; }

:root {
  --ground: #08060d;
  --shell: #17131f;
  --shell-2: #1f1a2c;
  --label: #f6f3ea;          /* a grading label is printed stock — cream, never pure white */
  --label-ink: #14111c;
  --ink: #f0edf8;
  --dim: #a79fbd;
  --line: #2e2643;
  --gold: #ffc46b;           /* MONEY ONLY */
  --live: #ff4d5e;           /* ON AIR ONLY */
  --holo-1: #b678ff;
  --holo-2: #61e2c4;
  --holo-3: #ffb454;
  --holo: linear-gradient(100deg, #b678ff, #61e2c4 45%, #ffb454 90%);

  --display: Anton, 'Arial Narrow', 'Segoe UI Black', Impact, sans-serif;
  --labelface: 'Archivo Narrow', 'Arial Narrow', sans-serif;
  --body: Manrope, 'Segoe UI', system-ui, sans-serif;

  --max: 1180px;
}

html { scroll-behavior: smooth; }

body {
  margin: 0;
  background: var(--ground);
  color: var(--ink);
  font-family: var(--body);
  font-size: 17px;
  line-height: 1.65;
  -webkit-font-smoothing: antialiased;
}

h1, h2, h3 { font-family: var(--display); font-weight: 400; text-transform: uppercase; margin: 0; }
a { color: inherit; }
:focus-visible { outline: 3px solid var(--holo-2); outline-offset: 3px; border-radius: 4px; }

/* ------------------------------------------------------------------ topbar */
.topbar {
  position: sticky; top: 0; z-index: 50;
  display: flex; align-items: center; gap: 20px;
  padding: 12px max(18px, calc((100vw - var(--max)) / 2));
  background: rgba(8, 6, 13, .82);
  backdrop-filter: blur(14px);
  border-bottom: 1px solid var(--line);
}
.brand { display: flex; align-items: center; gap: 10px; text-decoration: none; font-family: var(--display); letter-spacing: .5px; font-size: 20px; }
.brand img { border-radius: 50%; }
.brand b { background: var(--holo); -webkit-background-clip: text; background-clip: text; color: transparent; }
.nav { display: flex; gap: 22px; margin-left: auto; font-size: 14px; }
.nav a { color: var(--dim); text-decoration: none; }
.nav a:hover { color: var(--ink); }

/* ------------------------------------------------------------------ buttons */
.btn {
  display: inline-flex; align-items: center; gap: 9px;
  padding: 14px 24px; border-radius: 999px;
  font-family: var(--labelface); font-weight: 700; font-size: 14px;
  letter-spacing: 1.2px; text-transform: uppercase; text-decoration: none;
  border: 1px solid transparent; transition: transform .16s ease, box-shadow .16s ease;
}
.btn:hover { transform: translateY(-2px); }
.btn-primary { background: var(--holo); color: var(--label-ink); box-shadow: 0 10px 30px rgba(182, 120, 255, .28); }
.btn-ghost { border-color: var(--line); color: var(--ink); background: rgba(255,255,255,.04); }
/* Cream, not red: this button is always on the page, so it cannot wear the on-air colour. It
   turns red only while the show actually is on. */
.btn-live { background: var(--label); color: var(--label-ink); padding: 11px 18px; font-size: 13px; }
body.is-live .btn-live { background: var(--live); color: #fff; }
.btn-wide { margin-top: 26px; }
/* A disabled control must read as BLOCKED, not merely dimmer. */
.btn[aria-disabled='true'] { opacity: .45; background: var(--shell-2); color: var(--dim); box-shadow: none; pointer-events: none; }

/* THE ON-AIR DOT IS OFF UNTIL SOMETHING KNOWS THE SHOW IS ON.
 *
 * It shipped pulsing red on five elements permanently, and the nav button was solid red — so a
 * page that is live a few evenings a week told every visitor, at every hour, that it was on air
 * now. That is the same failure the deck refuses on the overlay: never tell the audience
 * something untrue. It also broke this stylesheet's own rule that red means ON AIR and nothing
 * else, by making red the permanent brand colour of the main button.
 *
 * The dot is now dark and still by default. `body.is-live` turns it on, and NOTHING sets that
 * class yet — the eBay API that could tell us is not connected. When it is, one class does it.
 */
.dot { width: 9px; height: 9px; border-radius: 50%; background: #5b5470; flex: none; }
body.is-live .dot { background: var(--live); box-shadow: 0 0 0 0 rgba(255,77,94,.55); animation: pulse 2s infinite; }
body.is-live .btn-live .dot { background: #fff; }
@keyframes pulse {
  0%   { box-shadow: 0 0 0 0 rgba(255, 77, 94, .55); }
  70%  { box-shadow: 0 0 0 9px rgba(255, 77, 94, 0); }
  100% { box-shadow: 0 0 0 0 rgba(255, 77, 94, 0); }
}

/* --------------------------------------------------------------------- hero */
.hero { position: relative; overflow: hidden; padding: 74px max(18px, calc((100vw - var(--max)) / 2)) 54px; }

/* THE WALL. Blurred and dimmed hard so it is atmosphere and never competes with the type in
   front of it, and masked to nothing at every edge so it has no visible start or end. Each row
   holds its cards TWICE and travels exactly -50%, which is what makes the loop seamless. */
.wall {
  position: absolute; inset: -8% -12% auto -12%;
  display: grid; gap: 18px; opacity: .3;
  filter: blur(3px) saturate(1.3);
  pointer-events: none;
  /* Faded at BOTH ends. Without the top fade the wall meets the sticky header on a hard line,
     which reads as a banner someone forgot to finish rather than as depth behind the page. */
  -webkit-mask-image: linear-gradient(to bottom, transparent, #000 18% 50%, transparent 88%);
  mask-image: linear-gradient(to bottom, transparent, #000 18% 50%, transparent 88%);
}
.wall-row { display: flex; gap: 14px; width: max-content; animation: drift 90s linear infinite; }
.wall-rev { animation-direction: reverse; animation-duration: 125s; }
.wall-row img { width: 132px; border-radius: 8px; display: block; }
@keyframes drift { from { transform: translateX(0); } to { transform: translateX(-50%); } }

.hero-grid { position: relative; display: grid; grid-template-columns: 1.05fr .95fr; gap: 40px; align-items: center; }
.eyebrow { display: inline-flex; align-items: center; gap: 9px; font-family: var(--labelface); font-weight: 700; text-transform: uppercase; letter-spacing: 2.4px; font-size: 12px; color: var(--dim); margin: 0 0 18px; }

/* The one place the type is allowed to shout. */
.hero-h1 { font-size: clamp(56px, 9.5vw, 128px); line-height: .84; letter-spacing: .5px; }
.hero-h1 span { display: block; }
.hero-h1 .holo { background: var(--holo); -webkit-background-clip: text; background-clip: text; color: transparent; }

.lede { max-width: 54ch; color: #cdc6dd; margin: 24px 0 28px; }
.cta-row { display: flex; flex-wrap: wrap; gap: 12px; }
.note { color: var(--gold); font-size: 14px; margin: 14px 0 0; }

.when { margin: 34px 0 0; display: grid; gap: 1px; background: var(--line); border: 1px solid var(--line); border-radius: 14px; overflow: hidden; }
.when > div { display: grid; grid-template-columns: 108px 1fr; gap: 14px; background: #15111f; padding: 12px 16px; }
.when dt { font-family: var(--labelface); font-weight: 700; text-transform: uppercase; letter-spacing: 1.6px; font-size: 11px; color: var(--dim); }
.when dd { margin: 0; font-size: 15px; }

.hero-fan { display: grid; place-items: center; }
.fan { position: relative; width: min(430px, 100%); aspect-ratio: 733 / 1024; perspective: 1200px; }
/* TOP/LEFT/RIGHT ONLY — never `inset: 0`. Pinning bottom as well as top makes the box the full
   height of the fan, so each card's shadow is cast by a container-sized rectangle rather than by
   the card, and the fan sits on a visible grey slab. */
.fan img { position: absolute; top: 0; left: 0; right: 0; width: 78%; height: auto; margin: 0 auto; border-radius: 10px; box-shadow: 0 18px 40px rgba(0,0,0,.55); transition: transform .5s cubic-bezier(.2,.7,.3,1); }
.fan .b1 { transform: translate(-34%, 4%) rotate(-15deg); }
.fan .b2 { transform: translate(-16%, 1%) rotate(-7deg); }
.fan .b3 { transform: translate(16%, 1%) rotate(7deg); }
.fan .b4 { transform: translate(34%, 4%) rotate(15deg); }
.front-wrap { position: absolute; top: 0; left: 0; right: 0; width: 84%; margin: 0 auto; transform-style: preserve-3d; transition: transform .18s ease-out; --holo-angle: 115deg; }
.front-wrap img { position: static; width: 100%; border-radius: 12px; box-shadow: 0 30px 70px rgba(0,0,0,.7); }
.front-wrap::after {
  content: ''; position: absolute; inset: 0; border-radius: 12px; pointer-events: none;
  background: linear-gradient(var(--holo-angle), transparent 30%, rgba(255,255,255,.42) 47%, rgba(150,220,255,.3) 53%, transparent 70%);
  mix-blend-mode: screen;
}

.stats { position: relative; list-style: none; display: flex; flex-wrap: wrap; gap: 46px; margin: 52px 0 0; padding: 0; }
.stats b { display: block; font-family: var(--display); font-size: 40px; line-height: 1; }
.stats span { font-family: var(--labelface); font-weight: 700; text-transform: uppercase; letter-spacing: 1.8px; font-size: 11px; color: var(--dim); }

/* --------------------------------------------------------------------- slab */
.slab { max-width: var(--max); margin: 30px auto; border: 1px solid var(--line); border-radius: 20px; overflow: hidden; background: linear-gradient(180deg, var(--shell-2), var(--shell)); }
.label { display: flex; align-items: center; justify-content: space-between; gap: 16px; background: var(--label); color: var(--label-ink); padding: 9px 18px; border-bottom: 3px solid var(--ground); font-family: var(--labelface); font-weight: 700; text-transform: uppercase; letter-spacing: 2.4px; font-size: 11px; }
.label span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.label b { flex: none; background: var(--label-ink); color: var(--label); border-radius: 999px; padding: 3px 11px; font-size: 10px; }
.window { padding: 34px 30px 40px; }
.window h2 { font-size: clamp(30px, 4.2vw, 46px); line-height: .95; margin-bottom: 14px; }
.sub { color: var(--dim); max-width: 62ch; margin: 0 0 26px; font-size: 15px; }
.sub-tight { margin: 34px 0 16px; }

/* -------------------------------------------------------------------- steps */
.steps { counter-reset: s; list-style: none; margin: 0; padding: 0; display: grid; gap: 14px; max-width: 74ch; }
.steps li { counter-increment: s; position: relative; padding: 14px 16px 14px 58px; border: 1px solid var(--line); border-radius: 14px; background: rgba(255,255,255,.025); font-size: 15px; color: #cdc6dd; }
.steps li b { color: var(--ink); }
.steps li::before { content: counter(s); position: absolute; left: 16px; top: 13px; width: 28px; height: 28px; border-radius: 50%; display: grid; place-items: center; font-family: var(--display); font-size: 15px; color: var(--label-ink); background: var(--holo); }

/* -------------------------------------------------------------------- lanes */
.lanes { display: grid; gap: 16px; grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); }
.lane { border: 1px solid var(--line); border-top: 3px solid var(--line); border-radius: 14px; background: rgba(255,255,255,.035); padding: 16px 18px; transition: transform .18s ease; }
.lane:hover { transform: translateY(-3px); }
.lane h3 { font-family: var(--body); font-weight: 800; text-transform: none; font-size: 16px; margin-bottom: 6px; }
.lane p { margin: 0; color: var(--dim); font-size: 14px; }
.lane-1 { border-top-color: var(--holo-1); }
.lane-2 { border-top-color: var(--holo-2); }
.lane-3 { border-top-color: var(--holo-3); }

/* ------------------------------------------------------------------- find us */
.ebay-card { display: grid; grid-template-columns: 1fr auto; align-items: center; gap: 4px 20px; text-decoration: none; border: 1px solid var(--line); border-radius: 18px; padding: 26px 28px; background: radial-gradient(120% 160% at 0% 0%, rgba(255,77,94,.16), transparent 60%), rgba(255,255,255,.04); transition: transform .18s ease, border-color .18s ease; }
.ebay-card:hover { transform: translateY(-4px); border-color: var(--live); }
.ebay-k { display: inline-flex; align-items: center; gap: 9px; grid-column: 1; font-family: var(--labelface); font-weight: 700; text-transform: uppercase; letter-spacing: 2px; font-size: 11px; color: var(--dim); }
.ebay-v { grid-column: 1; font-family: var(--display); font-size: clamp(34px, 5vw, 52px); line-height: 1.05; }
.ebay-note { grid-column: 1; color: var(--dim); font-size: 14px; }
.ebay-go { grid-column: 2; grid-row: 1 / span 3; font-size: 34px; color: var(--live); }

.tiles { display: grid; gap: 14px; grid-template-columns: repeat(auto-fit, minmax(190px, 1fr)); }
.tile { display: grid; gap: 3px; text-decoration: none; border: 1px solid var(--line); border-radius: 14px; padding: 14px 16px; background: rgba(255,255,255,.03); transition: transform .18s ease, border-color .18s ease; }
.tile:hover { transform: translateY(-3px); border-color: var(--holo-1); }
.tile-k { font-family: var(--labelface); font-weight: 700; text-transform: uppercase; letter-spacing: 1.8px; font-size: 10px; color: var(--dim); }
.tile-v { font-family: var(--display); font-size: 22px; }

/* ------------------------------------------------------------------- footer */
.footer { margin-bottom: 60px; }
.foot-grid { display: grid; grid-template-columns: auto 1fr; gap: 22px; align-items: start; }
.foot-mark { border-radius: 50%; }
.foot-lead { margin: 0 0 12px; font-size: 15px; }
.fine { color: var(--dim); font-size: 12.5px; line-height: 1.6; margin: 0 0 10px; max-width: 88ch; }
.store-link { display: inline-block; margin-top: 8px; color: var(--holo-2); text-decoration: none; font-family: var(--labelface); font-weight: 700; text-transform: uppercase; letter-spacing: 1.6px; font-size: 12px; }
.store-link:hover { text-decoration: underline; }

/* --------------------------------------------------------------- responsive */
@media (max-width: 980px) {
  .hero-grid { grid-template-columns: 1fr; }
  .hero-fan { order: -1; }
  .fan { width: min(320px, 74%); }
  .nav { display: none; }
}
@media (max-width: 640px) {
  body { font-size: 16px; }
  .window { padding: 26px 18px 32px; }
  .stats { gap: 28px; }
  .stats b { font-size: 32px; }
  .when > div { grid-template-columns: 1fr; gap: 2px; }
  .wall-row img { width: 96px; }
  .btn { padding: 13px 20px; }
  .foot-grid { grid-template-columns: 1fr; }
}

/* Every transition here is decoration; none of it carries meaning, so all of it can go. */
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  .wall-row, .dot { animation: none; }
  .btn, .tile, .lane, .ebay-card, .fan img, .front-wrap { transition: none; }
  .front-wrap::after { display: none; }
}

/* ---------------------------------------------------------------- the cursor */
/* A POKEBALL THAT OPENS WHEN YOU CLICK.
 *
 * Two SVG cursors, swapped on :active. A CSS cursor cannot animate — it is a static image the OS
 * draws — so "opens" is the second image, shown while the button is held. That is the whole trick
 * and it is why the open state has to read instantly: the halves split, and a spark sits in the
 * gap where the card would come out.
 *
 * THE HOTSPOT IS THE CENTRE (16 16), not the top-left. Left at the default the pointer would sit
 * on the ball's edge and every click would land 16px up and left of where it looked — which feels
 * like the site is misaligned rather than like the cursor is wrong.
 *
 * `, auto` and `, pointer` at the end are not decoration: if the data URI ever fails to parse the
 * browser falls back to a real cursor instead of leaving the visitor with no pointer at all.
 *
 * THE BALL STAYS OVER TEXT TOO. The first version let paragraphs keep the I-beam, on the grounds
 * that a caret tells you text is selectable. He watched it and the flicker between ball and beam
 * as the pointer crossed a heading was worse than losing that hint — on a page nobody comes to in
 * order to select text, consistency wins. `*` carries it everywhere so no element can opt itself
 * back out, which is what the per-element list kept doing.
 */
:root {
  --ball: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='32' height='32' viewBox='0 0 32 32'%3E%3Ccircle cx='16' cy='16' r='13' fill='%23fff' stroke='%230b0b0b' stroke-width='2'/%3E%3Cpath d='M3 16a13 13 0 0 1 26 0Z' fill='%23ee3b3b' stroke='%230b0b0b' stroke-width='2'/%3E%3Cpath d='M3 16h26' stroke='%230b0b0b' stroke-width='3'/%3E%3Ccircle cx='16' cy='16' r='4.6' fill='%23fff' stroke='%230b0b0b' stroke-width='2'/%3E%3C/svg%3E") 16 16;
  --ball-open: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='32' height='32' viewBox='0 0 32 32'%3E%3Cpath d='M3 12a13 13 0 0 1 26 0Z' fill='%23ee3b3b' stroke='%230b0b0b' stroke-width='2'/%3E%3Cpath d='M3 20a13 13 0 0 0 26 0Z' fill='%23fff' stroke='%230b0b0b' stroke-width='2'/%3E%3Cpath d='M16 13.2l1.5 2.8 2.8 1.5-2.8 1.5L16 21.8l-1.5-2.8L11.7 17.5l2.8-1.5Z' fill='%23ffe08a'/%3E%3C/svg%3E") 16 16;
}

body, * { cursor: var(--ball), auto; }
a, button, .btn, .tile, .lane, .ebay-card, summary, [role='button'] { cursor: var(--ball), pointer; }
body:active, body:active * { cursor: var(--ball-open), pointer; }

/* A custom cursor is a pointing device only. Touch has no pointer, and forcing one there just
   costs two image downloads for something nobody will ever see. */
@media (hover: none), (pointer: coarse) {
  body, *, a, button, .btn, .tile, .lane, .ebay-card { cursor: auto; }
}

/* --------------------------------------------------------------- the reveal */
/* Slabs rise as they come into view, staggered. The hidden state is added BY JAVASCRIPT, never in
   the stylesheet — if the script fails to run, nothing is hidden and the page is simply static.
   A reveal that hides content and then never un-hides it is a blank page, which is the one
   failure mode this effect can have and the only one worth engineering against. */
.slab.reveal { opacity: 0; transform: translateY(18px); }
.slab.reveal.in { opacity: 1; transform: none; transition: opacity .6s ease, transform .6s cubic-bezier(.2,.7,.3,1); }

/* ---------------------------------------------------------------- the grain */
/* A very light film grain over everything. Flat dark backgrounds band badly on cheap panels —
   visible steps across the hero gradient — and a little noise breaks the bands up. At 3.5% it is
   below the threshold of "an effect" and above the threshold of doing its job. */
body::after {
  content: ''; position: fixed; inset: 0; z-index: 100; pointer-events: none; opacity: .035;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='140' height='140'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.85' numOctaves='3'/%3E%3C/filter%3E%3Crect width='140' height='140' filter='url(%23n)'/%3E%3C/svg%3E");
}

@media (prefers-reduced-motion: reduce) {
  .slab.reveal, .slab.reveal.in { opacity: 1; transform: none; transition: none; }
}

/* ------------------------------------------------------------ foil stamping */
/* THE HEADLINE IS FOIL-STAMPED, NOT GRADIENT-FILLED.
 *
 * A gradient across letterforms is the house style of every AI-built landing page. Foil stamping
 * is what is actually on the cards this show opens: a metallic layer pressed onto stock, which
 * catches light in narrow bands and misses in patches where the press did not bite.
 *
 * So the fill is a set of tight diagonal stripes over a cream base, clipped to the text. The
 * stripes SHIFT with the pointer while the letters stay put — the material moves, not the type,
 * which is exactly what foil does when you tilt a card under a lamp.
 *
 * `--foil` is written by app.js on pointermove, throttled to one requestAnimationFrame. On a
 * device with no fine pointer it simply never changes and the stamp sits still, which is a
 * perfectly good static headline.
 */
.hero-h1 span {
  --foil: 0px;
  background-image:
    repeating-linear-gradient(102deg,
      rgba(255,255,255,.00) 0px, rgba(255,255,255,.00) 6px,
      rgba(255,255,255,.42) 8px, rgba(255,255,255,.00) 13px,
      rgba(255,255,255,.00) 22px),
    linear-gradient(180deg, #fffdf6, #d9d2ea 62%, #b9b0d4);
  background-position: var(--foil) 0, 0 0;
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
  /* The press mark: one hard shadow down-right, the way stamped foil sits proud of the stock. */
  filter: drop-shadow(1px 2px 0 rgba(0,0,0,.55));
}

/* The last line keeps the holo, because that IS the chase-card colour and the line is "day." */
.hero-h1 .holo {
  background-image:
    repeating-linear-gradient(102deg,
      rgba(255,255,255,.00) 0px, rgba(255,255,255,.00) 6px,
      rgba(255,255,255,.55) 8px, rgba(255,255,255,.00) 13px,
      rgba(255,255,255,.00) 22px),
    var(--holo);
  background-position: var(--foil) 0, 0 0;
}

@media (prefers-reduced-motion: reduce) {
  .hero-h1 span { --foil: 0px !important; }
}

/* ------------------------------------------------------------- the tear strip */
/* Under every grading label sits a perforation, the way a booster wrapper tears.
 *
 * The slab and the wrapper are the two objects this business handles all night, and the page
 * already had the slab. This is three pixels of the other one: a dotted rule where the label meets
 * the window, so the label reads as something you peel rather than a coloured bar.
 *
 * Pure CSS — a radial-gradient repeated along the axis. No image, no request, no layout cost, and
 * it scales with the slab because the dots are sized in em.
 */
.label { position: relative; }
.label::after {
  content: ''; position: absolute; left: 0; right: 0; bottom: -3px; height: 3px;
  background-image: radial-gradient(circle at 50% 120%, var(--ground) 46%, transparent 47%);
  background-size: 9px 6px; background-repeat: repeat-x;
  pointer-events: none;
}
