/* ===========================================================================
   PetSwap design system v6 — bloxswaps design language, owner rules (Sep 2026):
   - BORDERLESS. Depth = surface tone (--surface-1/2/3) + soft shadow, never
     outlines. Allowed exceptions: 1px --hairline dividers inside tables/lists,
     the focus-visible ring, the selected-state ring on item cards and the item
     card's rarity-coloured bottom edge. Nothing else gets a border/inset ring.
   - SHINE IS OPT-IN. The glare sweep only renders on `.btn-shine` (header
     "Log In" + at most ONE main call to action per page).
   - THE MASCOT NEVER LOOPS. No float/bob/bounce/breathe/sway/spin on any
     mascot image; one fade-in entrance only (enforced below by a safety net).
   - CUSTOM CONTROLS EVERYWHERE: thin purple scrollbars, custom <select>
     (public/js/ui/select.js), checkboxes, radios, ranges; no native chrome.
   - Motion: press scale(.97), hover lift, fade-scale-in modals, slide-fade-in
     entrances, shimmer skeletons.
   =========================================================================== */

/* ---------- fonts (Rubik variable, bloxswaps' identity face) ---------- */
@font-face {
  font-family: 'Rubik';
  src: url('../fonts/Rubik-latin.woff2') format('woff2');
  font-weight: 300 900;
  font-display: swap;
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'Rubik';
  src: url('../fonts/Rubik-latin-ext.woff2') format('woff2');
  font-weight: 300 900;
  font-display: swap;
  unicode-range: U+0100-02BA, U+02BD-02C5, U+1E00-1E9F, U+2020, U+20A0-20AB, U+20AD-20C0;
}

/* ---------- tokens (bloxswaps dark theme, verbatim) ---------- */
:root {
  --background: #06080d;
  --foreground: #fbfcfe;
  --overlay: #0c0f15;
  --surface: #14181e;
  --surface-secondary: #1a1e25;
  --surface-tertiary: #20242c;
  --default: #22272f;
  --default-hover: color-mix(in oklab, var(--default) 96%, var(--foreground) 4%);
  --accent: #8b5cf6;
  --accent-hover: #a78bfa;
  --accent-soft: #3b2a58;
  --accent-border: #a78bfa;
  --grad-partner: #6d28d9;
  --success: #05ca62;
  --warning: #f8b74d;
  --danger: #db3b3e;
  --muted: #9ba0a9;
  --border: #15181f;
  --separator: #1a1e25;
  --segment: #373d47;
  --backdrop: rgba(0, 0, 0, .56);

  /* v6 surface ladder (borderless depth). 1 = cards/panels/modals,
     2 = fields + rows on a panel, 3 = hover/pressed on 2, pop = popovers. */
  --surface-1: #0e1118;
  --surface-2: #151923;
  --surface-3: #1b2030;
  --surface-pop: #161a25;
  --hairline: rgba(255, 255, 255, .05);            /* the ONLY divider colour */
  --shadow-card: 0 10px 30px rgba(0, 0, 0, .28);
  --shadow-pop: 0 18px 48px rgba(0, 0, 0, .55), 0 2px 10px rgba(0, 0, 0, .35);
  --ring-focus: 0 0 0 2px var(--background), 0 0 0 4px var(--accent);
  --sb-thumb: rgba(139, 92, 246, .34);
  --sb-thumb-hover: rgba(167, 139, 250, .7);

  --background-image-btn-grad: linear-gradient(to right, #8b5cf6, #7c3aed);
  --background-image-custom-radial: radial-gradient(47.97% 135.63% at 82.56% 100%, rgba(139, 92, 246, .16) 0%, rgba(10, 11, 18, 0) 100%);
  --background-image-dark-accent: linear-gradient(95deg, rgba(139, 92, 246, .15), rgba(109, 40, 217, .15));

  /* no inset hairline any more — popovers/modals/toasts separate by tone + shadow */
  --overlay-shadow: 0 8px 28px rgba(0, 0, 0, .4), 0 1px 3px rgba(0, 0, 0, .3);

  /* PS99 rarity palette as rgb triplets — powers washes, edges, glows, text */
  --rc-common: 169, 169, 169;
  --rc-uncommon: 65, 105, 225;
  --rc-rare: 60, 179, 113;
  --rc-epic: 160, 107, 255;
  --rc-legendary: 178, 34, 34;
  --rc-mythical: 255, 92, 208;
  --rc-exclusive: 210, 74, 255;
  --rc-huge: 255, 92, 138;
  --rc-titanic: 255, 215, 1;

  /* motion tokens (verbatim easings) */
  --ease-smooth: ease;
  --ease-out: cubic-bezier(0, 0, .2, 1);
  --ease-out-quad: cubic-bezier(.25, .46, .45, .94);
  --ease-out-quart: cubic-bezier(.165, .84, .44, 1);
  --ease-out-fluid: cubic-bezier(.32, .72, 0, 1);
  --ease-in-out: cubic-bezier(.4, 0, .2, 1);

  --radius-sm: 8px;
  --radius: 10px;
  --radius-md: 10px;
  --radius-lg: 14px;
  --radius-xl: 14px;
  --radius-2xl: 16px;
  --radius-3xl: 24px;

  --header-h: 64px;
  /* THE page column: the header bar, every page's .container and the footer share these two, so their edges line
     up on every page — width: min(var(--container), calc(100% - 2 * var(--gutter))). A full-width page (the swap
     desk) re-sets both on its header, never a different formula. */
  --container: 1280px;
  --gutter: 20px;
  --font: 'Rubik', ui-sans-serif, system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif;
}
@media (max-width: 640px) { :root { --gutter: 16px; } }
/* The header has two sizes (owner, Oct 17 2026: "for swap it will minimize"; Oct 19: "the header changes too much,
   theres 3 different sizes"): the normal one on every page — the market too — (64px, the 137x26 wordmark; 116x22 up
   to 420px) and a compact one on the swap desk only, whose page file sets <html data-hdr="c"> (56px, a 116x22
   wordmark; 100x19 up to 420px). A page switch into or out of the desk grows or shrinks the header from the old size
   into the new one — the only motion of a page switch (the page-switch block below: data-hdr-from, public/js/arrive.js).
   Only the bar's height and the wordmark change: the nav and the chips are the same in both sizes (the desk's column is
   full width: body.swap-body below). Every token stays on :root (market.js / legal.js read --header-h from the
   document element). */
:root { --logo-w: 137px; --logo-h: 26px; --logo-fs: 25px; }
:root[data-hdr=c] { --header-h: 56px; --logo-w: 116px; --logo-h: 22px; --logo-fs: 21px; }
@media (max-width: 420px) {
  :root { --logo-w: 116px; --logo-h: 22px; --logo-fs: 21px; }
  :root[data-hdr=c] { --logo-w: 100px; --logo-h: 19px; --logo-fs: 18px; }
}

/* ---------- base ---------- */
*, *::before, *::after { box-sizing: border-box; }
:root { color-scheme: dark; }
/* the canvas is the page's dark background too (not only body's): nothing light shows between two pages or around a
   page (with the color-scheme meta in every <head>, also before the first style is in) */
html { font-size: 16px; scrollbar-gutter: stable; background: var(--background); }
body {
  margin: 0;
  background: var(--background);
  color: var(--foreground);
  font: 500 15px/1.5 var(--font);
  -webkit-font-smoothing: antialiased;
  overflow-x: hidden;
}
img { max-width: 100%; display: block; }
a { color: inherit; text-decoration: none; }
button { font: inherit; cursor: pointer; background: none; border: none; color: inherit; }
input, select { font: inherit; color: inherit; }
h1, h2, h3, h4 { margin: 0; font-weight: 700; color: var(--foreground); }
/* no one-word orphans: wrapped headings balance their lines, running text avoids a lone last word (pages may opt out
   with text-wrap: wrap) */
h1, h2, h3, h4 { text-wrap: balance; }
p, li, dd, figcaption, blockquote { text-wrap: pretty; }
::selection { color: #fff; background-color: var(--accent); }

/* ---------- custom scrollbars: page + EVERY scroll container ----------
   Chromium/WebKit use the ::-webkit-scrollbar pseudos (8px, horizontal 6px,
   transparent track, rounded purple thumb that thickens + brightens on hover).
   Firefox has no pseudos, so it gets the standard properties instead. Do NOT set
   scrollbar-width/scrollbar-color anywhere else (except `scrollbar-width: none`
   to hide a bar): in Chromium they switch the element back to the plain OS bar. */
::-webkit-scrollbar { width: 8px; height: 6px; background: transparent; }
::-webkit-scrollbar-track, ::-webkit-scrollbar-track-piece { background: transparent; }
::-webkit-scrollbar-corner { background: transparent; }
::-webkit-scrollbar-button { display: none; width: 0; height: 0; }
::-webkit-scrollbar-thumb {
  background-color: var(--sb-thumb); background-clip: padding-box;
  border: 2px solid transparent; border-radius: 999px; min-height: 36px; min-width: 36px;
}
::-webkit-scrollbar-thumb:hover { background-color: var(--sb-thumb-hover); border-width: 1px; }
::-webkit-scrollbar-thumb:active { background-color: var(--accent-hover); border-width: 1px; }
::-webkit-scrollbar-thumb:horizontal { border-width: 1px; }
@supports not selector(::-webkit-scrollbar) {
  * { scrollbar-width: thin; scrollbar-color: var(--sb-thumb) transparent; }
}

/* ---------- focus: one ring, no browser outlines anywhere ---------- */
:focus { outline: none; }
:focus-visible { outline: none; box-shadow: var(--ring-focus); }
::-moz-focus-inner { border: 0; padding: 0; }
[hidden] { display: none !important; }
.sr-only { position: absolute !important; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; border: 0; }

.container { width: min(var(--container), calc(100% - 2 * var(--gutter))); margin-inline: auto; }

/* keyframes (verbatim bodies from bloxswaps layer css) */
@keyframes glare-sweep { 0%, 60% { background-position: -100% -100%; } to { background-position: 100% 100%; } }
@keyframes glare-sweep-t { 0%, 60% { transform: translate(0, 0); } to { transform: translate(-75%, -75%); } }
@keyframes fade-scale-in { 0% { opacity: 0; transform: scale(.92); } to { opacity: 1; transform: scale(1); } }
@keyframes fade-in { 0% { opacity: 0; } to { opacity: 1; } }
@keyframes fade-out { to { opacity: 0; } }
@keyframes slide-fade-in { 0% { opacity: 0; transform: translateY(8px); } to { opacity: 1; transform: translateY(0); } }
@keyframes slot-value-in { 0% { opacity: 0; transform: translateY(8px) scale(.8); } to { opacity: 1; transform: translateY(0) scale(1); } }
@keyframes pop-spring { 0% { opacity: 0; transform: scale(.8) translateY(20px); } 60% { opacity: 1; transform: scale(1.02) translateY(-2px); } 100% { opacity: 1; transform: scale(1) translateY(0); } }
@keyframes pulse { 50% { opacity: .5; } }
@keyframes skeleton { to { transform: translateX(200%); } }
@keyframes spin { to { transform: rotate(360deg); } }
@keyframes toast-life { from { transform: scaleX(1); } to { transform: scaleX(0); } }
@keyframes toast-bump { 35% { transform: scale(1.035); } }
@keyframes toast-ico-pop { from { transform: scale(.4) rotate(-20deg); opacity: 0; } }
@keyframes marquee-scroll { to { transform: translateX(-50%); } }
@keyframes ember-rise {
  0% { opacity: 0; transform: translate(0, 0) rotate(0deg); }
  12% { opacity: .7; }
  100% { opacity: 0; transform: translate(var(--drift, 30px), -420px) rotate(540deg); }
}
/* hero-float-a/b/c: decorative orbs / item art only — NEVER on a mascot image */
@keyframes hero-float-a { 0%, 100% { translate: 0 0; } 50% { translate: 0 -14px; } }
@keyframes hero-float-b { 0%, 100% { translate: 0 -8px; } 50% { translate: 0 10px; } }
@keyframes hero-float-c { 0%, 100% { translate: 0 6px; } 50% { translate: 0 -12px; } }
@keyframes mascot-in { from { opacity: 0; } }   /* ends at the element's own opacity */

/* ---------- mascot: no looping motion, anywhere (owner rule) ----------
   Safety net for every mascot <img> on every page: whatever animation a page
   gives it is replaced by ONE opacity fade-in; the direct parent of a mascot
   image may still run a one-time entrance but can never loop. */
img.mascot, img[src*="/assets/img/mascot/"] { animation: mascot-in 420ms var(--ease-out) both !important; }
:has(> img.mascot), :has(> img[src*="/assets/img/mascot/"]) { animation-iteration-count: 1 !important; }

/* ==========================================================================
   HEADER — transparent, h-16, hide-on-scroll; nav = ghost text pills
   ========================================================================== */
.site-header {
  position: fixed;
  inset: 0 0 auto 0;
  z-index: 50;
  height: var(--header-h);
  transition: transform 300ms var(--ease-out);
}
/* the scrolled bar's background is a layer of its own under the bar's parts, so a page switch into or out of the swap
   desk can scale it from the old height (the page-switch block below) without touching the parts */
.site-header::before { content: ''; position: absolute; inset: 0; z-index: -1; pointer-events: none; transition: background-color 300ms var(--ease-out); }
.site-header.is-scrolled::before { background: rgba(6, 8, 13, .86); backdrop-filter: blur(12px); -webkit-backdrop-filter: blur(12px); }
.site-header.is-hidden { transform: translateY(-100%); }
/* the bar is the page column (--container / --gutter): the wordmark starts where the page content starts and the
   last chip ends where it ends, on every page and at every width */
.site-header .bar {
  height: 100%;
  margin: 0 auto;
  width: min(var(--container), calc(100% - 2 * var(--gutter)));
  display: flex;
  align-items: center;
  gap: 16px;
}
/* the swap desk is full width: its header (and toasts) follow the desk's panels — the same tokens swap.css gives
   .sw-screen (1848px, 16px gutters, 10px at 901-1180px) — change both together */
body.swap-body :is(.site-header, #toasts) { --container: 1848px; --gutter: 16px; }
@media (min-width: 900.02px) and (max-width: 1180px) { body.swap-body :is(.site-header, #toasts) { --gutter: 10px; } }
/* the staff console's column (admin.css .adm-page: min(1480px, 100% - 40px), 100% - 32px up to 900px) */
body.adm-body :is(.site-header, #toasts) { --container: 1480px; }
@media (max-width: 900px) { body.adm-body :is(.site-header, #toasts) { --gutter: 16px; } }
.logo { display: flex; align-items: center; gap: 10px; margin-right: 12px; font-size: 20px; font-weight: 700; color: var(--foreground); letter-spacing: .01em; }
.logo i { font-style: normal; font-weight: 600; color: var(--accent); }
.logo-mark {
  width: 34px; height: 34px; border-radius: 10px; flex: none;
  background: var(--background-image-btn-grad);
  box-shadow: 0 0 14px rgba(139, 92, 246, .4);
  position: relative;
}
.logo-mark::after {
  content: '';
  position: absolute; inset: 8px; border-radius: 5px;
  background: var(--background) center / contain no-repeat url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='%23a78bfa'%3E%3Cpath d='M4.5 9.5a3.5 3.5 0 1 1 2.6-5.85A4.5 4.5 0 0 1 15.5 4c.6 0 1.17.12 1.7.33A3.5 3.5 0 0 1 19.5 11c0 .34-.05.67-.14.98A4.25 4.25 0 0 1 17 19.4V20a2 2 0 0 1-2 2h-.5l-.75-2h-3.5L9.5 22H9a2 2 0 0 1-2-2v-.6a4.26 4.26 0 0 1-2.64-8.42A3.53 3.53 0 0 1 4.5 9.5Z'/%3E%3C/svg%3E");
}

.main-nav { display: flex; align-items: center; gap: 8px; }
.nav-link {
  display: inline-flex; align-items: center;
  height: 36px; padding: 0 12px;
  border-radius: var(--radius-md);
  font-size: 14px; font-weight: 500;
  color: rgba(255, 255, 255, .8);
  transition: color 150ms var(--ease-smooth), background-color 150ms var(--ease-smooth);
}
.nav-link:hover { color: var(--foreground); background: rgba(255, 255, 255, .05); }
.nav-link.active { color: var(--foreground); font-weight: 600; }

.header-spacer { flex: 1; }
.header-actions { display: flex; align-items: center; gap: 8px; }
.discord-chip {
  display: inline-flex; align-items: center; gap: 8px; height: 36px; padding: 0 13px;
  border-radius: 999px; font-size: 13px; font-weight: 500; color: #7289DA;
  background: rgba(114, 137, 218, .15);
  position: relative;
}
.discord-chip { transition: background-color 150ms var(--ease-smooth), color 150ms var(--ease-smooth); }
.discord-chip:hover { background: rgba(114, 137, 218, .24); color: #99aaf0; }
.live-dot { width: 8px; height: 8px; border-radius: 50%; background: var(--success); animation: pulse 2s var(--ease-in-out) infinite; }

.user-chip {
  display: inline-flex; align-items: center; gap: 9px; height: 38px; padding: 0 12px 0 6px;
  border-radius: 999px; background: rgba(255, 255, 255, .05);
  font-weight: 500; font-size: 13px; color: var(--foreground);
}
.user-chip img, .user-avatar {
  width: 26px; height: 26px; border-radius: 50%; object-fit: cover;
  background: var(--default);
  display: grid; place-items: center; font-size: 12px; font-weight: 600; color: var(--foreground);
}

@media (max-width: 900px) { .main-nav, .discord-chip span { display: none; } }

.mobile-nav {
  display: none;
  position: fixed; z-index: 50; inset: auto 0 0 0;
  height: calc(56px + env(safe-area-inset-bottom));
  padding-bottom: env(safe-area-inset-bottom);
  background: var(--overlay);
  box-shadow: 0 -10px 30px rgba(0, 0, 0, .45);
  grid-template-columns: repeat(4, 1fr);
}
.mobile-nav a { display: grid; place-items: center; gap: 3px; padding-top: 8px; font-size: 10.5px; font-weight: 500; color: var(--muted); }
.mobile-nav a svg { width: 20px; height: 20px; }
.mobile-nav a.active { color: var(--accent); }
@media (max-width: 900px) { .mobile-nav { display: grid; } body { padding-bottom: 70px; } }

/* ==========================================================================
   BUTTONS — accent system, press scale(.97), glare-sweep primary
   ========================================================================== */
.btn {
  position: relative;
  display: inline-flex; align-items: center; justify-content: center; gap: 8px;
  height: 40px; padding: 0 16px;
  border-radius: var(--radius-md);
  font-size: 14px; font-weight: 500;
  color: var(--foreground);
  background: var(--default);
  isolation: isolate;
  overflow: hidden;
  transition: transform .25s var(--ease-smooth), background-color .1s var(--ease-out), box-shadow .1s var(--ease-out), color .1s var(--ease-out), filter .15s var(--ease-out);
  user-select: none;
  white-space: nowrap;
}
/* hover changes the colour only: the shorthand would also reset .btn-primary's gradient image (it then turned a
   washed-out flat lavender under a white label) */
.btn:hover { background-color: var(--default-hover); }
.btn:active { transform: scale(.97); }
.btn:disabled { opacity: .5; pointer-events: none; }

.btn-primary { background-image: var(--background-image-btn-grad); border: none; box-shadow: 0 2px 10px rgba(139, 92, 246, .3); }
.btn-primary:hover { background-color: var(--accent); filter: brightness(1.1); }
.btn-primary > * { position: relative; }

/* ---------- SHINE (glare sweep) — OPT-IN ONLY ----------
   Existing markup keeps its <span class="glare"></span>; it renders nothing
   unless the button (or any CTA element) also has .btn-shine. Policy: the header
   "Log In" button plus at most ONE main call to action per page. */
.glare { display: none !important; }
.btn-shine { position: relative; isolation: isolate; overflow: hidden; }
.btn-shine > * { position: relative; }
/* The sweep runs on the compositor: a box carrying the gradient moves by a transform instead of animating
   background-position (that repainted the button every frame: up to ~0.8 s of main thread per second on a phone), so
   no frame is painted on the main thread while it loops. The box is 400% of the button and repeats the old 250% tile
   (62.5% of it), placed so the tile moves exactly as background-position -100% → 100% moved it: translate(0) →
   translate(-75%) = 3 button widths, and the edge of the neighbouring tile that showed as the glare enters is there
   too — the same pixels all through the loop. It sits ABOVE the label: white over the white label leaves the same
   pixels, and the label stays in the page layer — under a composited layer it would lose its subpixel text. The swap
   desk's desktop "Send swap offer" keeps the painted sweep (swap.css). */
.btn-shine > .glare {
  display: block !important;
  position: absolute; inset: 1px; border-radius: inherit; overflow: hidden; pointer-events: none; z-index: 1;
}
.btn-shine > .glare::after {
  content: '';
  position: absolute; top: 0; left: 0; width: 400%; height: 400%;
  background-image: linear-gradient(-45deg, transparent 60%, rgba(255, 255, 255, .55) 70%, transparent 100%);
  background-size: 62.5% 62.5%;
  background-position: 100% 100%;
  transform: translate(0, 0);
  animation: glare-sweep-t 3.5s var(--ease-in-out) infinite;
  will-change: transform;
}
.btn-shine:disabled > .glare { display: none !important; }

.btn-ghost { background: transparent; color: rgba(255, 255, 255, .8); }
.btn-ghost:hover { background: rgba(255, 255, 255, .05); color: var(--foreground); }
/* legacy name — renders as a soft borderless button (no rings, owner rule) */
.btn-outline { background: rgba(255, 255, 255, .05); }
.btn-outline:hover { background: rgba(255, 255, 255, .09); }
.btn-lg { height: 48px; padding: 0 24px; font-size: 16px; font-weight: 600; }
.btn-sm { height: 34px; padding: 0 12px; font-size: 13px; border-radius: var(--radius-md); }
.btn-block { width: 100%; }

/* ==========================================================================
   SURFACES
   ========================================================================== */
.panel { background: var(--surface-1); border-radius: var(--radius-lg); box-shadow: var(--shadow-card); }

.stat-row { display: grid; grid-template-columns: repeat(4, 1fr); gap: 12px; }
@media (max-width: 900px) { .stat-row { grid-template-columns: repeat(2, 1fr); } }
.stat-card {
  position: relative;
  padding: 16px;
  border-radius: var(--radius-xl);
  background: linear-gradient(to bottom, rgba(255, 255, 255, .05), rgba(139, 92, 246, .07));
  backdrop-filter: blur(12px);
  -webkit-backdrop-filter: blur(12px);
  overflow: hidden;
}
.stat-card::after {                 /* underglow bar */
  content: '';
  position: absolute; left: 0; right: 0; bottom: 4px; height: 4px;
  background: var(--accent);
  transform: scaleX(.5);
  filter: blur(6px);
  opacity: .8;
}
.stat-value { font-size: clamp(22px, 2.4vw, 28px); font-weight: 700; color: var(--foreground); line-height: 1.2; font-variant-numeric: tabular-nums; }
.stat-label { font-size: 13px; font-weight: 400; color: var(--muted); margin-top: 2px; }

/* ==========================================================================
   ITEM CARD — bloxswaps anatomy: sharp corners, rarity wash, 2px bottom
   edge only, scrim text strip, hover scale + white shadow + dim veil
   ========================================================================== */
.pet-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(124px, 1fr));
  grid-auto-rows: 154px;
  gap: 2px;
}
@media (max-width: 640px) { .pet-grid { grid-template-columns: repeat(auto-fill, minmax(104px, 1fr)); grid-auto-rows: 134px; } }

.pet-card {
  --rc: var(--rc-common);
  position: relative;
  min-width: 0;
  height: 154px;
}
.pet-card .pc-veil {                 /* dimmed blur backdrop behind raised card */
  position: absolute; inset: 0;
  background: rgba(0, 0, 0, .4);
  backdrop-filter: blur(4px);
  -webkit-backdrop-filter: blur(4px);
  border-radius: var(--radius-md);
  opacity: 0;
  transition: opacity 300ms var(--ease-out);
  pointer-events: none;
}
.pet-card .pc-lift {                 /* hover wrapper */
  position: relative;
  height: 100%;
  transition: transform 300ms var(--ease-out), box-shadow 300ms var(--ease-out);
  will-change: transform;
}
.pet-card:hover { z-index: 30; }
.pet-card:hover .pc-veil { opacity: 1; }
.pet-card:hover .pc-lift {
  transform: scale(1.05);
  box-shadow: 0 25px 50px rgba(255, 255, 255, .05);
  z-index: 10;
}

.pc-inner {
  position: relative;
  height: 100%;
  display: flex; flex-direction: column;
  overflow: hidden;
  background: linear-gradient(180deg, rgba(10, 12, 20, .95) 0%, rgba(var(--rc), .08) 100%);
  border-bottom: 2px solid rgb(var(--rc));
  cursor: pointer;
}
.pc-art {
  position: absolute; inset: 16px 16px 48px;
  display: grid; place-items: center;
}
.pc-art img {
  width: 100%; height: 100%; object-fit: contain;
  transition: transform 300ms var(--ease-out);
}
.pet-card:hover .pc-art img { transform: scale(1.04); }
.pc-badge {
  position: absolute; top: 4px; right: 4px; z-index: 10;
  font-size: 10px; font-weight: 600;
  padding: 2px 7px; border-radius: 999px;
  background: rgba(0, 0, 0, .45);
  color: rgba(255, 255, 255, .8);
  transition: all 300ms var(--ease-out);
}
.pc-strip {                          /* scrim + text, replaces any bordered footer */
  position: absolute; inset: auto 0 0 0;
  padding: 12px 6px 4px;
  background: linear-gradient(to top, rgba(0, 0, 0, .75), rgba(0, 0, 0, .4) 50%, transparent);
  display: flex; flex-direction: column; gap: 1px;
}
.pc-type { font-size: 10px; font-weight: 600; text-transform: uppercase; letter-spacing: .025em; color: rgb(var(--rc)); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.pc-name { font-size: 11px; font-weight: 600; line-height: 16px; color: rgba(255, 255, 255, .9); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.pc-price { display: flex; align-items: center; gap: 3px; margin-top: 2px; }
.pc-price .coin { width: 12px; height: 12px; border-radius: 50%; flex: none; background: radial-gradient(circle at 35% 30%, #ffe9ad, var(--gold, #f8b74d) 55%, #b8860b); box-shadow: inset 0 -1px 0 rgba(0, 0, 0, .25); }
.pc-price span { font-size: 11px; font-weight: 500; color: rgba(255, 255, 255, .7); font-variant-numeric: tabular-nums; }

.trend { font-size: 10px; font-weight: 600; }
.trend.up { color: var(--success); }
.trend.down { color: var(--danger); }
.trend.flat { color: rgba(255, 255, 255, .3); }

.demand-meter { display: inline-flex; gap: 2px; align-items: center; }
.demand-meter i { width: 4px; height: 8px; border-radius: 2px; background: rgba(255, 255, 255, .12); }
.demand-meter i.on { background: rgb(var(--rc)); }

/* hover action bar (kept from v1 — slides up over the scrim) */
.pc-actions {
  position: absolute; inset: auto 0 0 0; z-index: 20;
  display: flex; align-items: center; justify-content: center; gap: 6px;
  padding: 6px;
  background: rgba(0, 0, 0, .72);
  backdrop-filter: blur(4px);
  transform: translateY(102%);
  transition: transform 300ms var(--ease-out-fluid);
}
.pet-card:hover .pc-actions, .pet-card:focus-within .pc-actions { transform: translateY(0); }
.pc-actions button {
  font-size: 11px; font-weight: 600; color: var(--foreground);
  padding: 5px 10px; border-radius: var(--radius-md);
  background: rgba(255, 255, 255, .08);
  transition: background-color 150ms var(--ease-smooth), transform 150ms var(--ease-smooth);
}
.pc-actions button:hover { background-image: var(--background-image-btn-grad); background-color: var(--accent); transform: translateY(-1px); }

.rarity-tag { display: inline-flex; align-items: center; gap: 8px; font-size: 12px; font-weight: 500; text-transform: uppercase; color: rgba(255, 255, 255, .7); }
.rarity-tag::before {
  content: '';
  width: 8px; height: 8px; border-radius: 3px; flex: none;
  background: linear-gradient(135deg, rgb(var(--rc)), rgba(var(--rc), .87));
  box-shadow: 0 0 6px rgba(var(--rc), .25);
}

/* ==========================================================================
   VALUES TABLE — bloxswaps mm2-values presentation
   ========================================================================== */
.vtable-wrap { background: var(--surface-secondary); border-radius: var(--radius-xl); padding: 4px; }
.vtable { width: 100%; border-collapse: collapse; }
.vtable th {
  text-align: left;
  font-size: 11px; font-weight: 600; text-transform: uppercase; letter-spacing: .04em;
  color: rgba(255, 255, 255, .45);
  padding: 10px 12px;
  border-bottom: 1px solid var(--hairline);
  white-space: nowrap;
}
.vtable td { padding: 8px 12px; font-variant-numeric: tabular-nums; }
.vtable .vt-row { cursor: pointer; transition: background-color 150ms var(--ease-smooth); border-radius: var(--radius-md); }
.vtable .vt-row:hover { background: rgba(255, 255, 255, .03); }
.vt-thumb { width: 44px; height: 44px; border-radius: var(--radius-md); background: rgba(255, 255, 255, .05); overflow: hidden; display: grid; place-items: center; }
.vt-thumb img { width: 100%; height: 100%; object-fit: contain; padding: 3px; }
.vt-name { font-size: 14px; font-weight: 500; color: var(--foreground); max-width: 260px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.vt-sub { font-size: 11px; color: rgba(255, 255, 255, .5); }
.vt-num { font-size: 14px; font-weight: 500; color: rgba(255, 255, 255, .8); }
.vt-value { font-size: 14px; font-weight: 600; color: var(--foreground); }
.vt-demand { display: inline-flex; align-items: center; gap: 6px; }

/* ==========================================================================
   FORM CONTROLS — borderless filled fields (field-border-width: 0)
   ========================================================================== */
.input-wrap { position: relative; display: flex; align-items: center; }
.input-wrap > svg { position: absolute; left: 12px; width: 16px; height: 16px; color: var(--muted); pointer-events: none; }
.input {
  width: 100%;
  height: 40px;
  padding: 0 12px;
  border-radius: var(--radius-xl);
  background: var(--surface);
  border: none;
  color: var(--foreground);
  outline: none;
  font-size: 14px; font-weight: 400;
  transition: background-color 150ms var(--ease-smooth), box-shadow 150ms var(--ease-out);
}
.input-wrap .input { padding-left: 36px; }
.input::placeholder { color: var(--muted); }
.input:hover { background: color-mix(in oklab, var(--surface) 90%, var(--foreground) 2%); }
.input:focus { box-shadow: 0 0 0 2px var(--accent); background: var(--surface-secondary); }
.input-wrap:focus-within { border-radius: var(--radius-xl); box-shadow: 0 0 0 2px var(--accent); }
.input-wrap:focus-within .input { box-shadow: none; }

.select {
  -webkit-appearance: none; appearance: none; padding-right: 32px; cursor: pointer;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 24 24' fill='none' stroke='%239ba0a9' stroke-width='2.5' stroke-linecap='round'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E");
  background-repeat: no-repeat; background-position: right 12px center;
}
/* native selects only survive with [data-native] (or [multiple]) — keep them dark */
select { color-scheme: dark; }
select option, select optgroup { background: var(--surface-2); color: var(--foreground); }

/* ---------- custom native controls (zero-specificity, pages can restyle) ---------- */
/* checkbox + radio: dark filled box, purple fill + white check / dot when on */
:where(input[type="checkbox"], input[type="radio"]) {
  -webkit-appearance: none; appearance: none;
  flex: none; display: inline-block; vertical-align: -3px;
  width: 18px; height: 18px; margin: 0;
  border: none; border-radius: 5px;
  background: rgba(255, 255, 255, .08) center / 12px 12px no-repeat;
  cursor: pointer;
  transition: background-color 150ms var(--ease-smooth), box-shadow 150ms var(--ease-out), transform 150ms var(--ease-out-quart);
}
:where(input[type="radio"]) { border-radius: 50%; }
:where(input[type="checkbox"], input[type="radio"]):hover:not(:disabled):not(:checked) { background-color: rgba(255, 255, 255, .13); }
:where(input[type="checkbox"], input[type="radio"]):active:not(:disabled) { transform: scale(.9); }
:where(input[type="checkbox"]):checked {
  background-color: var(--accent);
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='%23fff' stroke-width='2.4' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m3.5 8.5 3 3 6-7'/%3E%3C/svg%3E");
}
:where(input[type="checkbox"]):indeterminate {
  background-color: var(--accent);
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='%23fff' stroke-width='2.4' stroke-linecap='round'%3E%3Cpath d='M4 8h8'/%3E%3C/svg%3E");
}
:where(input[type="radio"]):checked { background: var(--accent) radial-gradient(circle, #fff 0 3.5px, transparent 4.5px); }
:where(input[type="checkbox"], input[type="radio"]):disabled { opacity: .45; cursor: not-allowed; }

/* range: slim purple track (JS keeps --fill in sync, see ui/forms.js) + round thumb */
:where(input[type="range"]) {
  -webkit-appearance: none; appearance: none;
  width: 100%; height: 22px; margin: 0; padding: 0;
  background: transparent; cursor: pointer;
}
:where(input[type="range"])::-webkit-slider-runnable-track {
  height: 4px; border-radius: 4px;
  background: linear-gradient(to right, var(--accent) var(--fill, 0%), rgba(255, 255, 255, .1) var(--fill, 0%));
}
:where(input[type="range"])::-moz-range-track {
  height: 4px; border-radius: 4px;
  background: linear-gradient(to right, var(--accent) var(--fill, 0%), rgba(255, 255, 255, .1) var(--fill, 0%));
}
:where(input[type="range"])::-webkit-slider-thumb {
  -webkit-appearance: none; appearance: none;
  width: 16px; height: 16px; margin-top: -6px; border: none; border-radius: 50%;
  background: #fff; box-shadow: 0 0 0 4px rgba(139, 92, 246, .35), 0 2px 8px rgba(0, 0, 0, .45);
  transition: transform 150ms var(--ease-out-quad), box-shadow 150ms var(--ease-out);
}
:where(input[type="range"])::-moz-range-thumb {
  width: 16px; height: 16px; border: none; border-radius: 50%;
  background: #fff; box-shadow: 0 0 0 4px rgba(139, 92, 246, .35), 0 2px 8px rgba(0, 0, 0, .45);
}
:where(input[type="range"]):hover::-webkit-slider-thumb { transform: scale(1.12); }
:where(input[type="range"]):focus-visible { box-shadow: none; }
:where(input[type="range"]):focus-visible::-webkit-slider-thumb { box-shadow: 0 0 0 4px var(--accent), 0 2px 8px rgba(0, 0, 0, .45); }
:where(input[type="range"]):focus-visible::-moz-range-thumb { box-shadow: 0 0 0 4px var(--accent), 0 2px 8px rgba(0, 0, 0, .45); }
:where(input[type="range"]):disabled { opacity: .45; cursor: not-allowed; }

/* number: no spin buttons (pages build their own steppers) */
input[type="number"] { -moz-appearance: textfield; appearance: textfield; }
input[type="number"]::-webkit-inner-spin-button, input[type="number"]::-webkit-outer-spin-button { -webkit-appearance: none; appearance: none; margin: 0; }
/* search: no native cancel/decoration (pages provide their own clear buttons) */
input[type="search"] { -webkit-appearance: none; appearance: none; }
input[type="search"]::-webkit-search-cancel-button,
input[type="search"]::-webkit-search-decoration,
input[type="search"]::-webkit-search-results-button,
input[type="search"]::-webkit-search-results-decoration { -webkit-appearance: none; appearance: none; display: none; }
textarea { resize: none; } /* no native grip: ui/forms.js grows textareas with their text */

.chips { display: flex; flex-wrap: wrap; gap: 8px; }
.chip {
  --rc: var(--rc-common);
  display: inline-flex; align-items: center; gap: 7px;
  height: 28px; padding: 0 12px;
  border-radius: 999px;
  font-size: 11px; font-weight: 500;
  color: rgba(255, 255, 255, .7);
  background: rgba(255, 255, 255, .05);
  transition: all 200ms var(--ease-out-quad);
}
.chip::before { content: ''; width: 8px; height: 8px; border-radius: 50%; flex: none; background: rgb(var(--rc)); box-shadow: 0 0 6px rgba(var(--rc), .25); }
.chip:hover { color: var(--foreground); background: rgba(255, 255, 255, .09); transform: translateY(-1px); }
.chip.on { color: var(--foreground); background: rgba(139, 92, 246, .14); box-shadow: 0 0 10px rgba(139, 92, 246, .12); }
.chip.on::before { background: var(--accent); box-shadow: 0 0 6px rgba(167, 139, 250, .5); }

.seg { display: inline-flex; height: 24px; padding: 2px; gap: 1px; border-radius: 999px; background: rgba(255, 255, 255, .05); }
.seg button { padding: 0 9px; border-radius: 999px; font-size: 10px; font-weight: 500; color: rgba(255, 255, 255, .3); transition: all 150ms var(--ease-smooth); }
.seg button:hover { color: rgba(255, 255, 255, .5); }
.seg button.on { background: rgba(255, 255, 255, .1); color: rgba(255, 255, 255, .8); }

/* ==========================================================================
   TOASTS + MODALS — overlay panels, inset hairline, slide/fade motion
   ========================================================================== */
/* toasts (ui/toast.js): newest on top, max 3, same message = one toast that pops; enter/leave are driven
   by the Web Animations API (height too, so the stack slides instead of jumping) */
/* desktop: under the header, right edge on the page column's edge (under the account chips) */
#toasts { position: fixed; top: calc(var(--header-h) + 12px); right: max(var(--gutter), calc((100% - var(--container)) / 2)); z-index: 400; display: flex; flex-direction: column; align-items: stretch;
  width: min(360px, calc(100vw - 32px)); pointer-events: none; }
.toast {
  --tc: #3ee48b; --tb: rgba(5, 202, 98, .15);
  position: relative; box-sizing: border-box;
  display: flex; align-items: center; gap: 10px;
  min-height: 48px; margin-bottom: 8px; padding: 9px 8px 9px 10px;
  border-radius: 14px;
  background: var(--surface-pop);
  box-shadow: 0 14px 34px rgba(0, 0, 0, .5), 0 2px 8px rgba(0, 0, 0, .3), 0 0 26px -8px var(--tb);
  color: #fff; font-size: 13.5px; font-weight: 600; line-height: 1.35;
  overflow: hidden; pointer-events: auto; cursor: default; touch-action: pan-y;
  transform-origin: top right;
}
.toast.err { --tc: #ff8587; --tb: rgba(219, 59, 62, .18); }
.toast.info { --tc: #c4b5fd; --tb: rgba(139, 92, 246, .2); }
.toast.bump { animation: toast-bump 300ms var(--ease-out-quart); }
.toast-ico { flex: none; display: grid; place-items: center; width: 30px; height: 30px; border-radius: 10px; color: var(--tc); background: var(--tb);
  animation: toast-ico-pop 360ms var(--ease-out-quart) 60ms backwards; }
.toast-msg { flex: 1 1 auto; min-width: 0; overflow-wrap: anywhere; }
.toast-x { flex: none; display: grid; place-items: center; width: 30px; height: 30px; border-radius: 9px; color: rgba(255, 255, 255, .4);
  transition: color 150ms var(--ease-smooth), background-color 150ms var(--ease-smooth); }
.toast-x:hover, .toast-x:focus-visible { color: #fff; background: rgba(255, 255, 255, .08); }
.toast-bar { position: absolute; left: 0; right: 0; bottom: 0; height: 2px; pointer-events: none; }
.toast-bar i { display: block; height: 100%; background: var(--tc); opacity: .8; transform-origin: left center; animation: toast-life var(--life, 3600ms) linear forwards; }
.toast.paused .toast-bar i { animation-play-state: paused; }
/* phones and tablets: toasts drop over the header band instead of over the page's own controls right under it (game
   tabs, panel titles). Tablets (641-899px): 420px, the right edge on the column edge (desktop's right), so they cover
   the account chips whole (a balance cut in half reads as another amount) and leave the wordmark alone; phones: the
   whole band, between the gutters */
@media (max-width: 899px) {
  #toasts { width: min(420px, calc(100% - 2 * var(--gutter))); top: calc(8px + env(safe-area-inset-top)); }
  .toast { padding-right: 4px; }
  .toast-x { width: 40px; height: 40px; }
}
@media (max-width: 640px) {
  #toasts { left: var(--gutter); right: var(--gutter); width: auto; }
  .toast { transform-origin: top center; }
}
/* an open dialog covers the header anyway: toasts go to the top edge, clear of a dialog's title and close button
   (a tall phone sheet reaches up to ~8% of the screen: they may touch only its grab handle) */
body.modal-open #toasts { top: calc(8px + env(safe-area-inset-top)); }
@media (prefers-reduced-motion: reduce) {
  .toast.bump, .toast-ico { animation: none; }
}

.overlay {
  position: fixed; inset: 0; z-index: 150;
  background: var(--backdrop);
  backdrop-filter: blur(12px);
  -webkit-backdrop-filter: blur(12px);
  display: grid; place-items: center;
  padding: 20px;
  animation: fade-in 150ms var(--ease-out) both;
}
.overlay.closing { animation: fade-out 100ms var(--ease-out) both; }
.modal {
  width: min(448px, 100%);
  max-height: min(84vh, 720px);
  overflow: auto;
  padding: 24px;
  border-radius: var(--radius-3xl);
  background: var(--overlay);
  box-shadow: var(--overlay-shadow);
  animation: fade-scale-in 250ms var(--ease-out-quad) both;
}
.modal.lg { width: min(560px, 100%); }
.modal-head { display: flex; align-items: flex-start; justify-content: space-between; gap: 12px; margin-bottom: 14px; }
.modal-title { font-size: 18px; font-weight: 700; }
.modal-close {
  width: 36px; height: 36px; border-radius: var(--radius-md);
  display: grid; place-items: center;
  color: var(--muted); background: rgba(255, 255, 255, .05);
  transition: all 150ms var(--ease-smooth); flex: none;
}
.modal-close:hover { color: var(--foreground); background: rgba(255, 255, 255, .1); }

/* ==========================================================================
   SKELETONS — pulse + shimmer (bloxswaps skeleton system)
   ========================================================================== */
.skel { position: relative; overflow: hidden; background: rgba(115, 115, 115, .4); border-radius: var(--radius-md); animation: pulse 2s var(--ease-in-out) infinite; }
.skel.sheen::after { content: ''; position: absolute; inset: 0; transform: translateX(-100%); background: linear-gradient(90deg, transparent, var(--surface-tertiary), transparent); animation: skeleton 2s linear infinite; }

/* ==========================================================================
   HERO — 48px/800 H1, red radial ambience, ember particles
   ========================================================================== */
.hero { position: relative; padding: calc(var(--header-h) + 72px) 0 56px; overflow: clip; }
.hero::before { content: ''; position: absolute; inset: 0; z-index: -2; background: radial-gradient(60% 40% at 50% 0%, rgba(139, 92, 246, .07) 0%, transparent 70%); pointer-events: none; }
.hero-bg { position: absolute; inset: 0; z-index: -1; }
.hero-bg .blob { position: absolute; border-radius: 50%; filter: blur(75px); opacity: .5; }
.hero-bg .blob.b1 { width: 520px; height: 520px; left: -140px; top: -120px; background: rgba(109, 40, 217, .22); }
.hero-bg .blob.b2 { width: 460px; height: 460px; right: -120px; top: 40px; background: rgba(139, 92, 246, .14); }
.hero-kicker {
  display: inline-flex; align-items: center; gap: 9px;
  height: 34px; padding: 0 14px; border-radius: 999px;
  font-size: 12px; font-weight: 500; color: rgba(255, 255, 255, .8);
  background: rgba(255, 255, 255, .04);
}
.hero h1 {
  margin: 20px 0 14px;
  font-size: clamp(34px, 4.6vw, 48px);
  font-weight: 800;
  line-height: 1.2;
  color: var(--foreground);
}
.hero h1 em { font-style: normal; color: var(--accent); }
.hero p.lede { max-width: 540px; font-size: 16px; font-weight: 400; line-height: 1.6; color: var(--muted); margin: 0 0 28px; }
.hero-cta { display: flex; flex-wrap: wrap; gap: 12px; align-items: center; }

.embers { position: absolute; inset: 0; z-index: -1; pointer-events: none; overflow: hidden; }
.ember { position: absolute; bottom: -8px; width: 4px; height: 4px; border-radius: 50%; background: var(--accent); opacity: 0; filter: blur(.4px); animation: ember-rise var(--dur, 6s) linear infinite; animation-delay: var(--delay, 0s); }

.hero-float { position: absolute; right: clamp(8px, 6vw, 90px); top: calc(var(--header-h) + 46px); z-index: -1; }
.hero-float .pet-card { position: absolute; width: 172px; box-shadow: 0 25px 50px rgba(0, 0, 0, .5); }
.hero-float .f1 { right: 150px; top: 8px; rotate: -6deg; animation: hero-float-a 7s var(--ease-in-out) infinite; }
.hero-float .f2 { right: 0; top: 74px; rotate: 5deg; animation: hero-float-b 8.5s var(--ease-in-out) infinite; }
.hero-float .f3 { right: 250px; top: 150px; rotate: 3deg; scale: .94; animation: hero-float-c 6.2s var(--ease-in-out) infinite; }
@media (max-width: 1100px) { .hero-float { display: none; } }

/* marquee (kept — edge-masked) */
.marquee { position: relative; overflow: hidden; mask-image: linear-gradient(to right, transparent, #000 6%, #000 94%, transparent); -webkit-mask-image: linear-gradient(to right, transparent, #000 6%, #000 94%, transparent); }
.marquee-track { display: flex; gap: 0; width: max-content; animation: marquee-scroll var(--marquee-dur, 46s) linear infinite; }
.marquee:hover .marquee-track { animation-play-state: paused; }
.marquee-item { flex: none; }
.marquee-item.pet-card { width: 128px; height: 154px; }

/* section scaffolding */
.section { margin-top: 64px; }
.section-head { display: flex; align-items: baseline; justify-content: space-between; gap: 16px; margin-bottom: 16px; flex-wrap: wrap; }
.section-title { font-size: clamp(22px, 2.4vw, 28px); font-weight: 700; }
.section-sub { color: var(--muted); font-size: 14px; font-weight: 400; }

/* steps — surface fills, no borders */
.steps { display: grid; grid-template-columns: repeat(3, 1fr); gap: 12px; counter-reset: step; }
@media (max-width: 900px) { .steps { grid-template-columns: 1fr; } }
.step { position: relative; padding: 24px; border-radius: var(--radius-xl); background: var(--surface); overflow: hidden; transition: background-color 200ms var(--ease-out-quad); }
.step:hover { background: var(--surface-secondary); }
.step-num {
  counter-increment: step;
  width: 34px; height: 34px; border-radius: var(--radius-md);
  display: grid; place-items: center;
  font-size: 15px; font-weight: 700; color: #fff;
  background-image: var(--background-image-btn-grad);
  box-shadow: 0 0 14px rgba(139, 92, 246, .35);
  margin-bottom: 14px;
}
.step-num::before { content: counter(step); }
.step h3 { font-size: 17px; margin-bottom: 6px; }
.step p { margin: 0; font-size: 13.5px; font-weight: 400; color: var(--muted); line-height: 1.6; }

/* ==========================================================================
   FOOTER — own darker surface + radial wash; no lines (no top rule, no heading bars, no divider)

   ========================================================================== */
.site-footer { margin-top: 90px; position: relative; background: linear-gradient(to bottom, #0f121c, #000); } /* the swap desk's SEO band runs straight into it (swap.css) */
.site-footer::before { content: ''; position: absolute; inset: 0; pointer-events: none; } /* no top line: tone separates the footer (shell.css paints a soft glow here) */
.site-footer::after { content: ''; position: absolute; inset: 0; background-image: var(--background-image-custom-radial); opacity: .3; pointer-events: none; }
.footer-grid { position: relative; z-index: 1; display: grid; grid-template-columns: 1.4fr 1fr 1fr 1fr; gap: 36px; padding: 56px 0 40px; }
@media (max-width: 900px) { .footer-grid { grid-template-columns: 1fr 1fr; } }
@media (max-width: 560px) { .footer-grid { grid-template-columns: 1fr; } }
.footer-blurb { font-size: 14px; font-weight: 400; color: rgba(255, 255, 255, .6); line-height: 1.6; margin-top: 12px; max-width: 300px; }
.footer-col h4 { position: relative; font-size: 17px; font-weight: 600; color: var(--foreground); margin-bottom: 24px; }
/* (no accent dash under the headings: decorative lines are not part of the borderless system) */

.footer-col a {
  display: block; padding: 6px 0;
  font-size: 14px; font-weight: 400; color: rgba(255, 255, 255, .7);
  transition: color 300ms var(--ease-out), transform 300ms var(--ease-out);
}
.footer-col a:hover { color: var(--accent); transform: translateX(4px); }
.footer-bottom { position: relative; z-index: 1; display: flex; align-items: center; justify-content: space-between; gap: 12px; flex-wrap: wrap; margin-top: 12px; padding: 20px 0 26px; font-size: 13px; font-weight: 400; color: rgba(255, 255, 255, .5); }

/* entrances */
.reveal { animation: slide-fade-in 400ms cubic-bezier(.25, 1, .5, 1) both; animation-delay: var(--rd, 0ms); }
.card-in { animation: pop-spring 350ms var(--ease-out-quart) both; animation-delay: var(--rd, 0ms); }
/* ==========================================================================
   SWAP SCREEN — full-viewport app layout (bloxswaps trade anatomy):
   offer panel | 260px controls | receive panel; cart zone + toolbar + grid
   ========================================================================== */
.swap-screen {
  position: relative;
  height: 100dvh;
  min-height: 640px;
  display: flex; flex-direction: column;
  padding-top: var(--header-h);
  overflow: hidden;
}
.swap-glow { position: absolute; inset: 0; pointer-events: none; z-index: 0; background: radial-gradient(60% 40% at 50% 0%, rgba(139, 92, 246, .06) 0%, transparent 70%); }
.swap-grid {
  position: relative; z-index: 1;
  flex: 1; min-height: 0;
  display: grid;
  grid-template-columns: minmax(0, 1fr) 260px minmax(0, 1fr);
  gap: 8px;
  padding: 8px 12px 12px;
}
@media (max-width: 1100px) {
  .swap-screen { height: auto; min-height: 100dvh; overflow: visible; }
  .swap-grid { grid-template-columns: 1fr; }
  .tpanel { min-height: 560px; }
  .swap-controls { order: 3; }
}

/* ---------- panels ---------- */
.tpanel {
  display: flex; flex-direction: column;
  min-height: 0;
  border-radius: var(--radius-lg);
  background: var(--surface-1);
  overflow: hidden;
}
.tpanel-head {
  flex: none;
  display: flex; align-items: center; justify-content: space-between;
  height: 40px; padding: 0 12px;
  border-bottom: 1px solid var(--hairline);
}
.tpanel-head.reverse { flex-direction: row-reverse; }
.tpanel-title { font-size: 14px; font-weight: 600; letter-spacing: .025em; color: rgba(255, 255, 255, .8); }
.tpanel-cart { display: flex; align-items: center; gap: 6px; }
.tpanel-cart-icon { width: 15px; height: 15px; color: rgba(255, 255, 255, .4); }
.tpanel-cart-icon.flip { transform: scaleX(-1); }
.tpanel-total { font-size: 12px; font-weight: 600; color: rgba(255, 255, 255, .85); max-width: 70px; min-width: 40px; text-align: right; font-variant-numeric: tabular-nums; }
.tpanel-head:not(.reverse) .tpanel-total { text-align: left; }
/* legacy name of .vicon (same coin, same bottom shade — no ring) */
.coin { display: inline-block; width: 14px; height: 14px; border-radius: 50%; flex: none; background: radial-gradient(circle at 35% 30%, #ffe9ad, #f8b74d 55%, #b8860b); box-shadow: inset 0 -1px 0 rgba(0, 0, 0, .25); }

/* ---------- cart zone (selected items, 168px, dot-grid when empty) ---------- */
.cart-zone {
  flex: none;
  position: relative;
  height: 168px;
  overflow: hidden;
}
.cart-zone::before {
  content: '';
  position: absolute; inset: 0; z-index: 0;
  background-image: radial-gradient(circle at 1px 1px, rgba(255, 255, 255, .04) 1px, transparent 0);
  background-size: 20px 20px;
  -webkit-mask-image: radial-gradient(50% 60%, black 0%, transparent 100%);
  mask-image: radial-gradient(50% 60%, black 0%, transparent 100%);
  /* a layer of its own: the browser masks it while compositing instead of re-painting the masked dots (an offscreen
     pass per tile, ~30 ms of GPU work on the swap desk) whenever anything near the cart zone changes — the desk's
     first frames, while the page switch into it runs */
  will-change: transform;
}
.cart-zone.side-offer::after { content: ''; position: absolute; top: 0; bottom: 0; left: 0; width: 1px; z-index: 0; background: linear-gradient(to bottom, transparent, rgba(139, 92, 246, .28), transparent); }
.cart-zone.side-get::after { content: ''; position: absolute; top: 0; bottom: 0; right: 0; width: 1px; z-index: 0; background: linear-gradient(to bottom, transparent, rgba(139, 92, 246, .28), transparent); }
.cart-empty {
  position: relative; z-index: 1;
  height: 100%;
  display: flex; align-items: center; justify-content: center;
  overflow: hidden;
}
.cart-empty .cart-copy { position: relative; z-index: 2; display: flex; flex-direction: column; gap: 2px; }
.side-offer .cart-copy { align-items: flex-start; text-align: left; padding-left: 24px; }
.side-get .cart-copy { align-items: flex-end; text-align: right; padding-right: 24px; }
.cart-copy p { margin: 0; font-size: 12px; font-weight: 400; color: rgba(255, 255, 255, .25); line-height: 1.6; }
.cart-copy small { font-size: 10px; color: rgba(255, 255, 255, .15); }
.cart-mascot {
  position: absolute; bottom: -85px; z-index: 1;
  width: 200px; height: 195px;
  opacity: .3;
  mix-blend-mode: color-dodge;
  pointer-events: none;
  background: center / contain no-repeat url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 120 100'%3E%3Cg transform='translate(60 52)' fill='%23ffffff'%3E%3Cellipse cx='0' cy='10' rx='17' ry='13.5'/%3E%3Cellipse cx='-15' cy='-7' rx='6.5' ry='8.5' transform='rotate(-18 -15 -7)'/%3E%3Cellipse cx='-5.5' cy='-14' rx='6' ry='8.5' transform='rotate(-6 -5.5 -14)'/%3E%3Cellipse cx='5.5' cy='-14' rx='6' ry='8.5' transform='rotate(6 5.5 -14)'/%3E%3Cellipse cx='15' cy='-7' rx='6.5' ry='8.5' transform='rotate(18 15 -7)'/%3E%3C/g%3E%3C/svg%3E");
}
.side-offer .cart-mascot { right: -16px; }
.side-get .cart-mascot { left: -16px; }
.cart-items {
  position: relative; z-index: 1;
  height: 100%;
  display: flex; gap: 4px; align-items: center;
  padding: 8px 12px;
  overflow-x: auto;
  scrollbar-width: none;
}
.cart-items::-webkit-scrollbar { display: none; }
.cart-chip {
  position: relative; flex: none;
  width: 92px; height: 118px;
  border-radius: var(--radius-md);
  overflow: hidden;
  background: linear-gradient(180deg, rgba(10, 12, 20, .95) 0%, rgba(var(--rc, var(--rc-common)), .08) 100%);
  border-bottom: 2px solid rgb(var(--rc, var(--rc-common)));
  animation: pop-spring 300ms var(--ease-out-quart) both;
}
.cart-chip img { position: absolute; inset: 10px 10px 30px; width: calc(100% - 20px); height: calc(100% - 40px); object-fit: contain; }
.cart-chip span { position: absolute; inset: auto 0 0 0; padding: 8px 5px 3px; background: linear-gradient(to top, rgba(0, 0, 0, .75), transparent); font-size: 9px; font-weight: 600; color: rgba(255, 255, 255, .9); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.cart-chip .cc-x {
  position: absolute; top: 3px; right: 3px; z-index: 5;
  width: 18px; height: 18px; border-radius: 5px;
  display: grid; place-items: center;
  background: rgba(0, 0, 0, .55); color: rgba(255, 255, 255, .85);
  font-size: 10px; font-weight: 700;
  opacity: 0; transition: opacity 150ms var(--ease-smooth);
}
.cart-chip:hover .cc-x { opacity: 1; }

/* ---------- panel toolbar ---------- */
.panel-toolbar {
  flex: none;
  display: flex; align-items: center; gap: 6px;
  height: 40px; padding: 0 8px;
  background: rgba(255, 255, 255, .02);
}
.ptool-search { display: flex; align-items: center; gap: 6px; flex: 1; min-width: 0; height: 100%; }
.ptool-search svg { color: rgba(255, 255, 255, .3); flex: none; }
.ptool-search input {
  width: 100%; height: 100%;
  background: transparent; border: none; outline: none;
  font-size: 12px; font-weight: 400; color: rgba(255, 255, 255, .8);
}
.ptool-search input::placeholder { color: rgba(255, 255, 255, .3); }
.ptool-divider { width: 1px; height: 16px; background: rgba(255, 255, 255, .06); flex: none; }
.ptool-sort {
  flex: none;
  height: 28px; padding: 0 6px; border-radius: var(--radius-lg);
  display: inline-flex; align-items: center; gap: 4px;
  font-size: 11px; font-weight: 500; color: rgba(255, 255, 255, .35);
  transition: color 150ms var(--ease-smooth);
}
.ptool-sort:hover { color: rgba(255, 255, 255, .6); }

/* ---------- item grid (panel body) ---------- */
.panel-grid {
  flex: 1; min-height: 0;
  overflow-y: auto;
  padding: 2px;
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(120px, 1fr));
  grid-auto-rows: 151px;
  gap: 2px;
  align-content: start;
}
.panel-grid .trade-item { border-radius: var(--radius-sm); }
.grid-signin {
  grid-column: 1 / -1;
  position: relative;
  min-height: 300px;
  display: grid; place-items: center;
}
.grid-signin .gs-inner { text-align: center; padding: 24px; position: relative; z-index: 1; }
.grid-signin .gs-skel {
  position: absolute; inset: 0;
  display: grid; grid-template-columns: repeat(auto-fill, minmax(120px, 1fr)); gap: 2px;
  opacity: .25; filter: blur(2px); pointer-events: none;
}
.grid-signin .gs-skel .skel { height: 151px; border-radius: var(--radius-sm); }
.grid-signin h3 { font-size: 17px; margin-bottom: 6px; }
.grid-signin p { font-size: 12.5px; font-weight: 400; color: rgba(255, 255, 255, .6); max-width: 340px; margin: 0 auto 16px; line-height: 1.6; }
.grid-empty {
  grid-column: 1 / -1;
  display: grid; place-items: center;
  padding: 40px 20px;
  text-align: center;
}
.grid-empty .diamond {
  width: 56px; height: 56px; margin: 0 auto 14px;
  border-radius: var(--radius-2xl);
  display: grid; place-items: center;
  background: rgba(248, 183, 77, .1);
  color: var(--warning);
  transform: rotate(45deg);
}
.grid-empty .diamond svg { transform: rotate(-45deg); width: 26px; height: 26px; }
.grid-empty h3 { font-size: 17px; margin-bottom: 4px; }
.grid-empty p { font-size: 13px; font-weight: 400; color: rgba(255, 255, 255, .6); margin: 0 0 16px; }

/* ---------- control column ---------- */
.swap-controls {
  display: flex; flex-direction: column;
  min-height: 0;
  padding-top: 8px;
  gap: 4px;
  overflow: hidden;
}
.trade-now {
  flex: none;
  width: 100%; height: 36px;
  border-radius: var(--radius-md);
  position: relative; isolation: isolate; overflow: hidden;
  display: flex; align-items: center; justify-content: center; gap: 8px;
  font-size: 14px; font-weight: 700; letter-spacing: .025em; color: #fff;
  transition: filter 150ms var(--ease-out), transform .25s var(--ease-smooth);
}
.trade-now::before { content: ''; position: absolute; inset: 0; z-index: -2; border-radius: inherit; background: linear-gradient(to top left, var(--grad-partner), var(--grad-partner) 50%, #c4b5fd); box-shadow: 0 4px 14px rgba(109, 40, 217, .45); transition: opacity 200ms var(--ease-out); }
.trade-now::after { content: ''; position: absolute; inset: 1px; z-index: -1; border-radius: inherit; background: linear-gradient(94deg, var(--grad-partner), var(--accent)); }
.trade-now:hover { filter: brightness(1.1); }
.trade-now:active { transform: scale(.97); }
.trade-now .glare { position: absolute; inset: 1px; border-radius: inherit; overflow: hidden; pointer-events: none; }
.trade-now .glare::after { content: ''; position: absolute; inset: 0; background-image: linear-gradient(-45deg, transparent 60%, rgba(255, 255, 255, .55) 70%, transparent 100%); background-size: 250% 250%; background-position: -100% -100%; animation: glare-sweep 3.5s var(--ease-in-out) infinite; }

.cacc { border-bottom: none; }
.cacc-trigger {
  width: 100%;
  display: flex; align-items: center; justify-content: space-between;
  padding: 10px 2px;
  font-size: 13px; font-weight: 600; letter-spacing: .025em; color: rgba(255, 255, 255, .8);
  text-align: left;
}
.cacc-chev { color: rgba(255, 255, 255, .3); transition: transform 200ms var(--ease-out-quad); }
.cacc[data-open="false"] .cacc-chev { transform: rotate(-90deg); }

.verdict { font-size: 14px; font-weight: 700; padding: 10px 14px; border-radius: var(--radius-lg); text-align: center; line-height: 1.45; }
.verdict.fair, .verdict.win { color: var(--success); background: color-mix(in oklab, var(--success) 12%, transparent); }
.verdict.lose { color: var(--danger); background: color-mix(in oklab, var(--danger) 12%, transparent); }
.diff-line { font-size: 12px; font-weight: 400; color: var(--muted); text-align: center; margin: 0; }
.sum-row { display: flex; align-items: center; justify-content: space-between; padding: 6px 2px 0; border-top: 1px solid var(--hairline); font-size: 12.5px; font-weight: 400; color: var(--muted); }
.sum-row b { color: var(--foreground); font-weight: 600; font-variant-numeric: tabular-nums; display: inline-flex; align-items: center; gap: 5px; }
.sum-row b .coin { width: 12px; height: 12px; }

.price-pair { display: flex; align-items: center; gap: 8px; }
.numfield {
  flex: 1; min-width: 0;
  display: flex; align-items: center; gap: 4px;
  height: 28px; padding: 0 8px;
  border-radius: var(--radius-md);
  background: rgba(255, 255, 255, .05);
  transition: background-color 150ms var(--ease-smooth), box-shadow 150ms var(--ease-out);
}
.numfield:focus-within { background: rgba(255, 255, 255, .08); box-shadow: 0 0 0 2px rgba(139, 92, 246, .45); }
.numfield .coin { width: 13px; height: 13px; }
.numfield input {
  width: 100%; min-width: 0;
  background: transparent; border: none; outline: none;
  font-size: 12px; font-weight: 400; color: rgba(255, 255, 255, .8);
  font-variant-numeric: tabular-nums;
}
.numfield input::placeholder { color: rgba(255, 255, 255, .5); }
.price-sep { width: 8px; height: 2px; border-radius: 1px; background: rgba(255, 255, 255, .15); flex: none; }
.filter-hint { font-size: 10.5px; font-weight: 400; color: rgba(255, 255, 255, .3); margin: 0; line-height: 1.5; }

.rarity-rows { display: flex; flex-direction: column; }
.rrow {
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
  height: 30px; padding: 0 4px;
  border-radius: var(--radius-md);
  cursor: pointer;
  transition: background-color 150ms var(--ease-smooth);
}
.rrow:hover { background: rgba(255, 255, 255, .03); }
.rrow + .rrow { position: relative; }
.rrow + .rrow::before { content: ''; position: absolute; top: 0; left: 4px; right: 4px; height: 1px; background: linear-gradient(to right, transparent, rgba(255, 255, 255, .06), transparent); }
.rrow-label { display: flex; align-items: center; gap: 8px; min-width: 0; font-size: 12.5px; font-weight: 500; color: rgba(255, 255, 255, .6); transition: color 150ms var(--ease-smooth); } /* >= 4.5:1 on surface-1 */
.rrow.checked .rrow-label { color: rgba(255, 255, 255, .85); }
.rrow-swatch { width: 10px; height: 10px; border-radius: 3px; flex: none; background: linear-gradient(135deg, rgb(var(--rc)), rgba(var(--rc), .87)); box-shadow: 0 0 6px rgba(var(--rc), .25); }
.rrow-count { font-size: 10.5px; color: rgba(255, 255, 255, .5); font-variant-numeric: tabular-nums; } /* >= 4.5:1 on surface-1 */
.rrow-box {
  width: 16px; height: 16px; flex: none;
  border-radius: 5px;
  background: rgba(255, 255, 255, .08);
  display: grid; place-items: center;
  color: #fff;
  transition: background-color 150ms var(--ease-smooth);
}
.rrow-box svg { width: 11px; height: 11px; opacity: 0; }
.rrow.checked .rrow-box { background: var(--accent); }
.rrow.checked .rrow-box svg { opacity: 1; }

.controls-footer { margin-top: auto; padding-bottom: 4px; }
.cf-divider { height: 1px; background: rgba(255, 255, 255, .05); margin-bottom: 10px; }
.reset-filters {
  width: 100%; height: 36px;
  border-radius: var(--radius-md);
  display: flex; align-items: center; justify-content: center; gap: 6px;
  font-size: 12px; font-weight: 500; letter-spacing: .025em;
  color: rgba(255, 255, 255, .6);
  background: rgba(255, 255, 255, .05);
  transition: all 200ms var(--ease-out-quad);
}
.reset-filters:hover { color: var(--foreground); background: rgba(255, 255, 255, .08); }

/* ---------- SEO band under the app screen ---------- */
.seo-band { background: #0f1219; padding: 64px clamp(24px, 8vw, 224px); }
.seo-inner { max-width: 1280px; margin: 0 auto; display: grid; gap: 40px; }
.seo-band h2 { font-size: 24px; font-weight: 600; margin-bottom: 20px; }
.seo-cols { display: grid; grid-template-columns: 1fr 1fr; gap: 40px; }
@media (max-width: 900px) { .seo-cols { grid-template-columns: 1fr; } }
.seo-cols h3 { font-size: 20px; font-weight: 600; margin-bottom: 12px; }
.seo-cols p { font-size: 15px; font-weight: 400; line-height: 1.7; color: var(--muted); margin: 0 0 12px; }
.seo-cols b { color: rgba(255, 255, 255, .85); font-weight: 600; }

/* ==========================================================================
   REDUCED MOTION — intentionally no animation kills. The owner wants the
   site fully animated for everyone (marquee, embers, glares included);
   OS-level reduce-motion is not honoured here by design.
   ========================================================================== */

/* ---------- swap item cards + picker + confirm summary ---------- */
.trade-item {
  position: relative;
  overflow: hidden;
  cursor: pointer;
  background: linear-gradient(180deg, rgba(10, 12, 20, .95) 0%, rgba(var(--rc, var(--rc-common)), .08) 100%);
  border-bottom: 2px solid rgb(var(--rc, var(--rc-common)));
  transition: transform 300ms var(--ease-out), box-shadow 300ms var(--ease-out);
  animation: pop-spring 300ms var(--ease-out-quart) both;
  will-change: transform;
}
.trade-item:hover { transform: scale(1.05); box-shadow: 0 25px 50px rgba(255, 255, 255, .05); z-index: 20; }
.trade-item img { position: absolute; inset: 14px 14px 38px; width: calc(100% - 28px); height: calc(100% - 52px); object-fit: contain; transition: transform 300ms var(--ease-out); }
.trade-item:hover img { transform: scale(1.04); }
/* two-line strip: name / price — text can never collide */
.trade-item .ti-strip {
  position: absolute; inset: auto 0 0 0;
  padding: 14px 6px 4px;
  background: linear-gradient(to top, rgba(0, 0, 0, .8), rgba(0, 0, 0, .45) 55%, transparent);
  display: flex; flex-direction: column; gap: 1px;
}
.trade-item .ti-name {
  font-size: 11px; font-weight: 600; color: rgba(255, 255, 255, .92);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.trade-item .ti-meta {
  display: inline-flex; align-items: center; gap: 3px;
  font-size: 10px; font-weight: 500; color: rgba(255, 255, 255, .65);
  font-variant-numeric: tabular-nums;
}
.trade-item .ti-meta .coin { width: 10px; height: 10px; }

.picker-results { display: grid; grid-template-columns: repeat(auto-fill, minmax(104px, 1fr)); grid-auto-rows: 132px; gap: 2px; max-height: 340px; overflow-y: auto; }
.picker-item {
  position: relative; overflow: hidden; cursor: pointer;
  background: linear-gradient(180deg, rgba(10, 12, 20, .95) 0%, rgba(var(--rc, var(--rc-common)), .08) 100%);
  border-bottom: 2px solid rgb(var(--rc, var(--rc-common)));
  transition: transform 200ms var(--ease-out);
}
.picker-item:hover { transform: scale(1.04); z-index: 5; box-shadow: 0 25px 50px rgba(255, 255, 255, .05); }
.picker-item img { position: absolute; inset: 12px 12px 34px; width: calc(100% - 24px); height: calc(100% - 46px); object-fit: contain; }
.picker-item span {
  position: absolute; inset: auto 0 0 0; padding: 8px 5px 3px;
  background: linear-gradient(to top, rgba(0, 0, 0, .75), transparent);
  font-size: 9px; font-weight: 600; color: rgba(255, 255, 255, .9);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}

.swap-summary { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; margin: 14px 0; }
@media (max-width: 480px) { .swap-summary { grid-template-columns: 1fr; } }
.swap-col { border-radius: var(--radius-lg); background: var(--surface); padding: 12px; min-height: 120px; min-width: 0; }
.swap-col h4 { font-size: 11px; font-weight: 600; text-transform: uppercase; letter-spacing: .05em; color: rgba(255, 255, 255, .45); margin-bottom: 8px; display: flex; justify-content: space-between; align-items: center; gap: 8px; }
.swap-col h4 b { color: var(--foreground); font-weight: 600; font-variant-numeric: tabular-nums; display: inline-flex; align-items: center; gap: 5px; }
.swap-col ul { list-style: none; margin: 0; padding: 0; display: grid; gap: 5px; max-height: 180px; overflow-y: auto; }
.swap-col li { display: flex; align-items: center; gap: 8px; font-size: 12.5px; font-weight: 400; color: rgba(255, 255, 255, .85); }
.swap-col li img { width: 24px; height: 24px; object-fit: contain; }
.swap-col li span { flex: 1; min-width: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.swap-col li em { font-style: normal; color: var(--muted); font-size: 11px; font-variant-numeric: tabular-nums; }

/* ---------- market-maker economics UI ---------- */
.net-row {
  display: flex; align-items: center; justify-content: space-between;
  padding: 8px 10px;
  border-radius: var(--radius-lg);
  background: rgba(255, 255, 255, .04);
  font-size: 12.5px; font-weight: 500;
}
.net-row .net-label { color: var(--muted); }
.net-pos { color: var(--success); font-weight: 700; font-variant-numeric: tabular-nums; }
.net-neg { color: var(--danger); font-weight: 700; font-variant-numeric: tabular-nums; }
.sum-row small { font-size: 10px; color: rgba(255, 255, 255, .35); font-weight: 400; }
.swap-note { margin: 8px 0 0; font-size: 10.5px; font-weight: 400; color: rgba(255, 255, 255, .35); text-align: right; }
.trade-item .ti-price {
  position: absolute; right: 6px; bottom: 6px;
  display: inline-flex; align-items: center; gap: 3px;
  font-size: 10px; font-weight: 500; color: rgba(255, 255, 255, .7);
  font-variant-numeric: tabular-nums;
}
.trade-item .ti-price .coin { width: 10px; height: 10px; }
.trade-item .qty-badge {
  position: absolute; top: 4px; right: 4px; z-index: 10;
  font-size: 10px; font-weight: 600;
  padding: 2px 7px; border-radius: 999px;
  background: rgba(0, 0, 0, .45); color: rgba(255, 255, 255, .8);
  transition: all 300ms var(--ease-out);
}
.trade-item.oos { cursor: not-allowed; }
.trade-item.oos img { filter: grayscale(.7) brightness(.6); }
.oos-overlay {
  position: absolute; inset: 0; z-index: 15;
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 5px;
  background: rgba(0, 0, 0, .65);
  animation: fade-in 200ms var(--ease-out) both;
}
.oos-overlay span {
  font-size: 9px; font-weight: 600; letter-spacing: .06em; text-transform: uppercase;
  color: rgba(255, 255, 255, .9);
  padding: 3px 9px; border-radius: 999px;
  background: rgba(255, 255, 255, .12);
}
.cart-chip .cc-price {
  position: absolute; right: 4px; bottom: 3px;
  font-size: 9px; font-weight: 600; color: var(--gold, #f8b74d);
  font-variant-numeric: tabular-nums;
}
.coins-chip {
  display: inline-flex; align-items: center; gap: 7px;
  height: 36px; padding: 0 12px;
  border-radius: 999px;
  font-size: 12px; font-weight: 600; color: rgba(255, 255, 255, .9);
  background: linear-gradient(to right, rgba(248, 183, 77, .22), rgba(248, 183, 77, .08));
  font-variant-numeric: tabular-nums;
  cursor: pointer;
}

/* ==========================================================================
   SWAP DESK v3 — selection states, coins cover, processing theatre,
   starter pack, and the login-modal styles that were missing from v2.
   ========================================================================== */

/* ---------- panel head counts ---------- */
.tpanel-count { font-size: 11px; font-weight: 500; color: rgba(255, 255, 255, .35); font-variant-numeric: tabular-nums; margin-right: 2px; }

/* ---------- selected card state (accent ring + check) ---------- */
.trade-item .ti-sel {
  position: absolute; top: 4px; left: 4px; z-index: 12;
  width: 18px; height: 18px; border-radius: 999px;
  display: grid; place-items: center;
  background: var(--accent); color: #fff;
  box-shadow: 0 0 10px rgba(139, 92, 246, .55);
  opacity: 0; transform: scale(.5);
  transition: opacity 180ms var(--ease-out-quad), transform 220ms var(--ease-out-quart);
}
.trade-item .ti-sel svg { width: 11px; height: 11px; }
.trade-item .ti-sel-count {
  position: absolute; top: 4px; left: 4px; z-index: 13;
  min-width: 18px; height: 18px; padding: 0 5px; border-radius: 999px;
  display: grid; place-items: center;
  background: var(--accent); color: #fff;
  font-size: 10px; font-weight: 700; font-variant-numeric: tabular-nums;
  box-shadow: 0 0 10px rgba(139, 92, 246, .55);
  animation: pop-spring 250ms var(--ease-out-quart) both;
}
.trade-item.selected { box-shadow: inset 0 0 0 2px var(--accent), 0 0 16px rgba(139, 92, 246, .25); }
.trade-item.selected .ti-sel { opacity: 1; transform: scale(1); }
.trade-item.selected img { filter: drop-shadow(0 0 10px rgba(var(--rc), .35)); }

/* ---------- trade-now button states ---------- */
.trade-now.is-ready::before { background: linear-gradient(to top left, #16a34a, #16a34a 50%, #4ade80); box-shadow: 0 4px 18px rgba(22, 163, 74, .45); }
.trade-now.is-ready::after { background: linear-gradient(94deg, #15803d, #22c55e); }
.trade-now:disabled { filter: saturate(.35) brightness(.7); cursor: not-allowed; }
.trade-now:disabled:active { transform: none; }

/* ---------- coins cover row (deficit paid from balance) ---------- */
.coins-cover {
  display: flex; align-items: center; gap: 8px;
  padding: 8px 10px; border-radius: var(--radius-md);
  background: rgba(248, 183, 77, .08);
  font-size: 12px; font-weight: 500; color: rgba(255, 255, 255, .85);
  cursor: pointer; user-select: none;
  transition: background-color 200ms var(--ease-out);
}
.coins-cover input { position: absolute; opacity: 0; pointer-events: none; }
.coins-cover .cc-box {
  width: 16px; height: 16px; flex: none; border-radius: 5px;
  background: rgba(248, 183, 77, .16);
  display: grid; place-items: center; color: #1a1206;
  transition: background-color 150ms var(--ease-smooth);
}
.coins-cover .cc-box svg { width: 11px; height: 11px; opacity: 0; transition: opacity 150ms var(--ease-smooth); }
.coins-cover input:checked + .cc-box { background: var(--warning); }
.coins-cover input:checked + .cc-box svg { opacity: 1; }
.coins-cover .cc-text b { color: var(--warning); font-variant-numeric: tabular-nums; }
.coins-cover:has(input:checked) { background: rgba(248, 183, 77, .14); }

/* ---------- price slider ---------- */
.price-slider {
  -webkit-appearance: none; appearance: none;
  width: 100%; height: 14px; margin: 2px 0 0;
  background: transparent; cursor: pointer;
}
.price-slider::-webkit-slider-runnable-track { height: 4px; border-radius: 2px; background: linear-gradient(to right, var(--accent) var(--fill, 100%), rgba(255, 255, 255, .1) var(--fill, 100%)); }
.price-slider::-webkit-slider-thumb {
  -webkit-appearance: none; width: 14px; height: 14px; margin-top: -5px;
  border-radius: 50%; background: var(--accent);
  box-shadow: 0 0 0 3px rgba(139, 92, 246, .25), 0 0 8px rgba(139, 92, 246, .5);
  transition: transform 150ms var(--ease-out-quad);
}
.price-slider::-webkit-slider-thumb:hover { transform: scale(1.15); }
.price-slider::-moz-range-track { height: 4px; border-radius: 2px; background: rgba(255, 255, 255, .1); }
.price-slider::-moz-range-progress { height: 4px; border-radius: 2px; background: var(--accent); }
.price-slider::-moz-range-thumb { width: 14px; height: 14px; border: none; border-radius: 50%; background: var(--accent); box-shadow: 0 0 0 3px rgba(139, 92, 246, .25); }

/* ---------- confirm modal net line ---------- */
.confirm-net { text-align: center; font-size: 13px; font-weight: 600; padding: 10px 0 14px; }

/* ---------- processing modal (swap theatre) ---------- */
.modal.processing { width: min(420px, 100%); text-align: center; }
.modal.processing.failed .proc-ring { animation: none; }
.proc-head { display: flex; flex-direction: column; align-items: center; gap: 14px; margin-bottom: 18px; }
.proc-ring { position: relative; width: 64px; height: 64px; }
.proc-ring svg { width: 100%; height: 100%; transform: rotate(-90deg); animation: spin 1.2s linear infinite; }
.proc-ring .ring-track { fill: none; stroke: rgba(255, 255, 255, .08); stroke-width: 4; }
.proc-ring .ring-run { fill: none; stroke: var(--accent); stroke-width: 4; stroke-linecap: round; stroke-dasharray: 80 20; }
.proc-ring.done svg { animation: none; }
.proc-ring.done::after {
  content: '✓';
  position: absolute; inset: 0; border-radius: 50%;
  display: grid; place-items: center;
  font-size: 30px; font-weight: 800; color: #fff;
  background: linear-gradient(135deg, #22c55e, #15803d);
  box-shadow: 0 0 24px rgba(34, 197, 94, .5);
  animation: pop-spring 350ms var(--ease-out-quart) both;
}
.modal.processing.failed .proc-ring::after {
  content: '✕'; background: linear-gradient(135deg, #ef4444, #b91c1c);
  box-shadow: 0 0 24px rgba(239, 68, 68, .4);
}
.proc-steps { list-style: none; margin: 0 0 6px; padding: 0; display: grid; gap: 4px; text-align: left; }
.proc-steps li {
  display: flex; align-items: center; gap: 10px;
  padding: 7px 10px; border-radius: var(--radius-md);
  font-size: 13px; font-weight: 500; color: rgba(255, 255, 255, .35);
  transition: color 200ms var(--ease-out), background-color 200ms var(--ease-out);
}
.proc-steps li .ps-dot {
  width: 18px; height: 18px; flex: none; border-radius: 50%;
  display: grid; place-items: center;
  background: rgba(255, 255, 255, .07);
  transition: background-color 200ms var(--ease-out);
}
.proc-steps li .ps-dot svg { width: 10px; height: 10px; opacity: 0; }
.proc-steps li.active { color: var(--foreground); background: rgba(139, 92, 246, .08); }
.proc-steps li.active .ps-dot { background: rgba(139, 92, 246, .25); box-shadow: 0 0 8px rgba(139, 92, 246, .4); animation: pulse 1.1s var(--ease-in-out) infinite; }
.proc-steps li.done { color: rgba(255, 255, 255, .65); }
.proc-steps li.done .ps-dot { background: var(--success); }
.proc-steps li.done .ps-dot svg { opacity: 1; }
.proc-result { animation: slide-fade-in 300ms var(--ease-out) both; }
.proc-pets { display: flex; flex-wrap: wrap; justify-content: center; gap: 6px; margin: 6px 0 12px; }
.proc-pets img {
  width: 52px; height: 52px; object-fit: contain; padding: 4px;
  border-radius: var(--radius-md);
  background: linear-gradient(180deg, rgba(10, 12, 20, .95), rgba(139, 92, 246, .1));
  animation: pop-spring 350ms var(--ease-out-quart) both;
}
.proc-pets img:nth-child(2) { animation-delay: 60ms; }
.proc-pets img:nth-child(3) { animation-delay: 120ms; }
.proc-pets img:nth-child(4) { animation-delay: 180ms; }
.proc-pets img:nth-child(5) { animation-delay: 240ms; }
.proc-pets img:nth-child(n+6) { animation-delay: 300ms; }
.proc-line { margin: 4px 0; font-size: 13.5px; font-weight: 500; color: rgba(255, 255, 255, .75); }
.proc-error { font-size: 13.5px; font-weight: 500; color: var(--danger); background: color-mix(in oklab, var(--danger) 10%, transparent); border-radius: var(--radius-md); padding: 10px 12px; margin: 0 0 14px; }

/* ---------- empty inventory art ---------- */
.empty-art {
  width: 64px; height: 64px; margin: 0 auto 16px;
  border-radius: var(--radius-2xl);
  display: grid; place-items: center;
  color: var(--muted);
  background: rgba(255, 255, 255, .05);
}
.empty-art svg { width: 30px; height: 30px; }

/* ---------- coins chip bump on balance change ---------- */
.coins-chip.bump { animation: coin-bump 500ms var(--ease-out-quart); }
@keyframes coin-bump {
  0% { transform: scale(1); } 35% { transform: scale(1.12); box-shadow: 0 0 18px rgba(248, 183, 77, .35); }
  100% { transform: scale(1); }
}

/* ---------- login modal (was missing from the v2 css rewrite) ---------- */
.phrase-row { position: relative; margin-bottom: 14px; }
.phrase-chips { display: flex; flex-wrap: wrap; gap: 6px; padding: 12px 46px 12px 14px; border-radius: var(--radius-xl); background: rgba(139, 92, 246, .09); animation: phrase-glow 2.6s var(--ease-in-out) infinite; }
.phrase-chip {
  display: inline-flex; align-items: center; height: 28px; padding: 0 13px;
  border-radius: 999px; font-size: 13px; font-weight: 600; letter-spacing: .02em;
  color: var(--accent-hover); background: rgba(139, 92, 246, .14);
  animation: chip-in 460ms var(--ease-out-quart) both;
  transition: transform 200ms var(--ease-out-quart), box-shadow 200ms var(--ease-out), background-color 150ms var(--ease-smooth);
}
.phrase-chip:hover { transform: translateY(-2px); background: rgba(139, 92, 246, .22); box-shadow: 0 4px 14px rgba(139, 92, 246, .3); }
.copy-fab {
  position: absolute; top: 50%; right: 8px; transform: translateY(-50%);
  width: 32px; height: 32px; border-radius: var(--radius-md);
  display: grid; place-items: center;
  color: var(--muted); background: rgba(255, 255, 255, .06);
  transition: all 150ms var(--ease-smooth);
}
.copy-fab:hover { color: var(--foreground); background: rgba(255, 255, 255, .12); }
.copy-fab.done { color: var(--success); background: rgba(34, 197, 94, .12); }
.auth-steps { margin: 0 0 14px; padding-left: 18px; display: grid; gap: 5px; font-size: 12.5px; font-weight: 400; color: var(--muted); line-height: 1.55; }
.poll-status { display: flex; align-items: center; justify-content: center; gap: 8px; min-height: 20px; margin-top: 12px; font-size: 12.5px; font-weight: 500; color: var(--muted); }
.spin { width: 13px; height: 13px; flex: none; border-radius: 50%; border: 2px solid rgba(255, 255, 255, .15); border-top-color: var(--accent); animation: spin 800ms linear infinite; }
.success-check {
  width: 64px; height: 64px; margin: 6px auto 16px; border-radius: 50%;
  display: grid; place-items: center;
  font-size: 30px; font-weight: 800; color: #fff;
  background: linear-gradient(135deg, #22c55e, #15803d);
  box-shadow: 0 0 24px rgba(34, 197, 94, .5);
  animation: pop-spring 400ms var(--ease-out-quart) both;
}

/* ==========================================================================
   MOTION PASS v4 — nothing is still. Staggered entrances, flashes, pulses,
   count-up helpers (JS), breathing CTAs, burst rings. All compositor-only
   where it matters; the global prefers-reduced-motion block kills all of it.
   ========================================================================== */

/* ---------- page switch ----------
   An instant swap (owner, Oct 21 2026: "change the animation so its not sliding, the only thing that should really
   have animation is the header, so it like increases in size or decreases in size depending on the page"): no
   cross-document view transition and no entrance — the content never slides, fades or moves on a switch, in any
   browser. The browser keeps the page being left on screen until the next one has its first frame (paint holding),
   and that frame comes composed: the header bar, footer and tab bar are in the HTML (server.js), so are the pages'
   placeholders, and app.js settleArrival finishes every entrance animation on arrival.
   The one motion is the header's size (rule 12: 64px everywhere, 56px on the swap desk): into or out of the desk the
   new page's header starts at the size and in the place the old page had it and grows or shrinks into its own in
   300 ms (--hm-dur, on --hm-ease); between two pages of one size nothing moves. public/js/arrive.js — a classic script
   in <head>, so it decides before the first paint in every browser, Firefox included — sets <html data-hdr-from="n|c">
   (the size of the page left: the note chrome.js leaves, ps:from), holds it at the start pose until the page's frames
   reach the screen on time (hm-hold, below) and takes it away when the wordmark's morph ends; the page's first load
   is built 200 ms into it (lib/api.js), so its first raster never freezes it mid-way.
   Transform only, so the compositor runs it whatever the arriving page's main thread is busy with, and the header's
   box is its new one from the first frame (it is fixed: nothing below it moves). From the old place to the new: every
   part of the bar by half the height difference (their vertical centre) and, on Market <-> Swap, sideways by the
   column difference (the desk's column is full width; 100cqw = the header's width, a container only while it morphs)
   — the wordmark scaled from its old size, its left edge in place; the nav also by the wordmark's width difference;
   Discord and the account chips (they end the column) the other way — and the scrolled bar's background (::before)
   scaled from the old height. Backwards fill only: once over, nothing has a transform. Reduced motion: none of it. */
/* --hm-ease: the browsers' own `ease` — it moves from its first frames (3 % by 15 ms) and its fastest refresh is an
   eighth of the way at 60 Hz; the standard curve (.4, 0, .2, 1) it replaces stood still for its first 33 ms, which
   added a frame or two of start pose to the hold (arrive.js) */
:root { --hm-dur: 300ms; --hm-ease: cubic-bezier(.25, .1, .25, 1); }
/* the page left: its bar height, wordmark width and column (the tokens at the top and body.swap-body's — change them
   together) and what its wordmark and bar measure against this page's (the page left always had the other size) */
:root[data-hdr-from=n] { --from-h: 64px; --from-logo-w: 137px; --from-con: 1280px; --from-gut: 20px; --from-logo-s: 1.181; --from-h-s: 1.143; }
:root[data-hdr-from=c] { --from-h: 56px; --from-logo-w: 116px; --from-con: 1848px; --from-gut: 16px; --from-logo-s: .847; --from-h-s: .875; }
@media (max-width: 640px) { :root[data-hdr-from=n] { --from-gut: 16px; } }
@media (min-width: 900.02px) and (max-width: 1180px) { :root[data-hdr-from=c] { --from-gut: 10px; } }
@media (max-width: 420px) {
  :root[data-hdr-from=n] { --from-logo-w: 116px; --from-logo-s: 1.16; }
  :root[data-hdr-from=c] { --from-logo-w: 100px; --from-logo-s: .862; }
}
:root[data-hdr-from] .site-header { container-type: inline-size; }
:root[data-hdr-from] .site-header .bar {
  --hm-dx: calc((min(var(--container), 100cqw - 2 * var(--gutter)) - min(var(--from-con), 100cqw - 2 * var(--from-gut))) / 2);
  --hm-dy: calc((var(--from-h) - var(--header-h)) / 2);
}
:root[data-hdr-from] .site-header .logo-word { animation: hm-logo var(--hm-dur) var(--hm-ease) backwards; transform-origin: 0 50%; }
:root[data-hdr-from] .site-header .main-nav { animation: hm-nav var(--hm-dur) var(--hm-ease) backwards; }
:root[data-hdr-from] .site-header .header-actions > * { animation: hm-end var(--hm-dur) var(--hm-ease) backwards; }
:root[data-hdr-from] .site-header::before { animation: hm-bg var(--hm-dur) var(--hm-ease) backwards; transform-origin: 50% 0; }
@keyframes hm-logo { from { transform: translate(var(--hm-dx), var(--hm-dy)) scale(var(--from-logo-s)); } }
@keyframes hm-nav { from { transform: translate(calc(var(--hm-dx) + var(--from-logo-w) - var(--logo-w)), var(--hm-dy)); } }
@keyframes hm-end { from { transform: translate(calc(-1 * var(--hm-dx)), var(--hm-dy)); } }
@keyframes hm-bg { from { transform: scaleY(var(--from-h-s)); } }
/* every arrival: held at the start pose until the page's frames reach the screen on time (after its first
   contentful paint, two frames in a row presented on time — arrive.js's dots; 600 ms after its first frame at the
   latest), then let go on the page's live clock — on a heavy first visit the GPU drew nothing for 100-170 ms after
   that paint, and a morph let go before it ran most of the way unseen (the header jumped 63-87 % at once) */
:root.hm-hold[data-hdr-from] .site-header :is(.logo-word, .main-nav, .header-actions > *), :root.hm-hold[data-hdr-from] .site-header::before { animation-play-state: paused; }
@media (prefers-reduced-motion: reduce) {
  :root[data-hdr-from] .site-header :is(.logo-word, .main-nav, .header-actions > *), :root[data-hdr-from] .site-header::before { animation: none; }
}
/* While the account slot is empty, its row (the Discord chip too) waits unseen, so nothing jumps sideways when the
   chips land: Firefox (and Safari before 18.2) paint the page before its script has filled the slot, and with a
   session cookie but no remembered account (ui/chrome.js) the slot waits for /api/me in every browser. Shown
   after 2.5 s regardless (no script, a failed load); app.js settleArrival never finishes late-show early. */
.header-actions:has(> .auth-slot:empty) { visibility: hidden; animation: late-show 0s 2.5s forwards; }
@keyframes late-show { to { visibility: visible; } }

/* ---------- nav underline slide ---------- */
.nav-link { position: relative; overflow: hidden; }
.nav-link::after {
  content: ''; position: absolute; left: 12px; right: 12px; bottom: 4px; height: 2px;
  border-radius: 2px; background: var(--accent);
  transform: scaleX(0); transform-origin: left;
  transition: transform 250ms var(--ease-out-fluid);
}
/* the hover underline only on a link that isn't the page's or the one just clicked: those carry the ink (shell.css) */
.nav-link:not(.active):not(.is-pending):hover::after { transform: scaleX(1); }

/* ---------- modal content stagger (login steps, confirm, processing) ---------- */
.modal > * { animation: slide-fade-in 380ms var(--ease-out) both; }
.modal > *:nth-child(1) { animation-delay: 30ms; }
.modal > *:nth-child(2) { animation-delay: 80ms; }
.modal > *:nth-child(3) { animation-delay: 130ms; }
.modal > *:nth-child(4) { animation-delay: 180ms; }
.modal > *:nth-child(5) { animation-delay: 230ms; }
.modal > *:nth-child(6) { animation-delay: 280ms; }
.login-body > * { animation: slide-fade-in 360ms var(--ease-out) both; }
.login-body > *:nth-child(1) { animation-delay: 60ms; }
.login-body > *:nth-child(2) { animation-delay: 120ms; }
.login-body > *:nth-child(3) { animation-delay: 180ms; }
.login-body > *:nth-child(4) { animation-delay: 240ms; }
.login-body > *:nth-child(5) { animation-delay: 300ms; }
.login-body > *:nth-child(6) { animation-delay: 360ms; }
.login-body > *:nth-child(7) { animation-delay: 420ms; }

/* ---------- login: passphrase panel ---------- */
.phrase-chips { animation: phrase-glow 2.6s var(--ease-in-out) infinite; }
@keyframes phrase-glow {
  0%, 100% { box-shadow: 0 0 0 rgba(139, 92, 246, 0); }
  50% { box-shadow: 0 0 22px rgba(139, 92, 246, .22); }
}
@keyframes chip-in {
  0% { opacity: 0; transform: translateY(10px) scale(.55); filter: blur(5px); }
  60% { opacity: 1; transform: translateY(-2px) scale(1.07); filter: blur(0); }
  100% { opacity: 1; transform: translateY(0) scale(1); }
}
.phrase-chip { transition: transform 200ms var(--ease-out-quart), box-shadow 200ms var(--ease-out); cursor: pointer; }
.phrase-chip:hover { transform: translateY(-2px); box-shadow: 0 4px 12px rgba(139, 92, 246, .3); }
.copy-fab { animation: fab-nudge 2.2s var(--ease-in-out) infinite; }
@keyframes fab-nudge {
  0%, 100% { transform: translateY(-50%) scale(1); box-shadow: 0 0 0 0 rgba(139, 92, 246, .35); }
  50% { transform: translateY(-50%) scale(1.07); box-shadow: 0 0 0 6px rgba(139, 92, 246, 0); }
}
.copy-fab.done { animation: none; transform: translateY(-50%) scale(1.12); }
.auth-steps li { animation: slide-fade-in 350ms var(--ease-out) both; }
.auth-steps li:nth-child(1) { animation-delay: 260ms; }
.auth-steps li:nth-child(2) { animation-delay: 340ms; }
.auth-steps li:nth-child(3) { animation-delay: 420ms; }
.welcome-bonus {
  display: inline-flex; align-items: center; gap: 7px;
  margin: 0 0 16px; padding: 8px 14px; border-radius: 999px;
  font-size: 12.5px; font-weight: 500; color: rgba(255, 255, 255, .85);
  background: rgba(248, 183, 77, .12);
  animation: pop-spring 400ms var(--ease-out-quart) 200ms both;
}
.welcome-bonus b { color: var(--warning); font-variant-numeric: tabular-nums; }

/* ---------- swap desk ---------- */
/* verdict pops when its state changes (JS re-adds .flash) */
.verdict.flash { animation: verdict-pop 340ms var(--ease-out-quart); }
@keyframes verdict-pop {
  0% { transform: scale(.94); opacity: .6; }
  60% { transform: scale(1.04); opacity: 1; }
  100% { transform: scale(1); }
}
/* ready CTA breathes */
.trade-now.is-ready { animation: ready-breathe 2.2s var(--ease-in-out) infinite; }
@keyframes ready-breathe {
  0%, 100% { filter: brightness(1) saturate(1); }
  50% { filter: brightness(1.12) saturate(1.15); }
}
/* grid entrances stagger via --rd (set per-index in JS) */
.trade-item { animation-delay: var(--rd, 0ms); }
/* selection flash (overrides entrance anim once selected) */
.trade-item.selected { animation: sel-flash 420ms var(--ease-out) both; }
@keyframes sel-flash {
  0% { filter: brightness(1.45) saturate(1.3); }
  100% { filter: brightness(1) saturate(1); }
}
/* cart chips lift on hover; remove button spins in */
.cart-chip { transition: transform 250ms var(--ease-out-quart), box-shadow 250ms var(--ease-out); }
.cart-chip:hover { transform: translateY(-4px) scale(1.03); box-shadow: 0 10px 24px rgba(0, 0, 0, .45); z-index: 5; }
.cart-chip .cc-x { transition: opacity 150ms var(--ease-smooth), transform 250ms var(--ease-out-quart), background-color 150ms var(--ease-smooth); }
.cart-chip .cc-x:hover { transform: rotate(90deg) scale(1.1); background: var(--danger); }
/* control column micro-motion */
.cacc-trigger { transition: color 150ms var(--ease-smooth); }
.cacc-trigger:hover { color: var(--foreground); }
.cacc-trigger:hover .cacc-chev { color: var(--accent); }
.rrow:hover .rrow-label { color: rgba(255, 255, 255, .78); transform: translateX(2px); }
.rrow-label { transition: color 150ms var(--ease-smooth), transform 200ms var(--ease-out-fluid); }
.rrow:hover .rrow-swatch { box-shadow: 0 0 10px rgba(var(--rc), .6); }
.rrow-swatch { transition: box-shadow 200ms var(--ease-out); }
.reset-filters:hover svg { transform: rotate(-180deg); }
.reset-filters svg { transition: transform 400ms var(--ease-out-fluid); }
/* processing modal */
.proc-ring::before {
  content: ''; position: absolute; inset: -6px; border-radius: 50%;
  background: radial-gradient(circle, rgba(139, 92, 246, .25), transparent 70%);
  animation: pulse 1.6s var(--ease-in-out) infinite;
}
.proc-ring.done::before { animation: burst-ring 700ms var(--ease-out) both; }
@keyframes burst-ring {
  0% { transform: scale(.5); opacity: .9; background: radial-gradient(circle, rgba(34, 197, 94, .4), transparent 70%); }
  100% { transform: scale(2.1); opacity: 0; background: radial-gradient(circle, rgba(34, 197, 94, 0), transparent 70%); }
}
.proc-steps li .ps-label { transition: transform 250ms var(--ease-out-fluid); }
.proc-steps li.active .ps-label { transform: translateX(3px); }

/* ---------- values table ---------- */
.vt-row { transition: background-color 150ms var(--ease-smooth), transform 250ms var(--ease-out-fluid); }
.vt-row:hover { transform: translateX(3px); }
.vt-row:hover .vt-thumb img { transform: scale(1.12) rotate(-2deg); }
.vt-thumb img { transition: transform 300ms var(--ease-out-quart); }
.vt-row:hover .vt-name { color: var(--accent-hover); }
.vt-name { transition: color 150ms var(--ease-smooth); }

/* ---------- FAQ accordions ---------- */
.faq-item[open] > .faq-a, .faq-item[open] > *:not(summary) { animation: slide-fade-in 300ms var(--ease-out) both; }
.faq-item summary { transition: color 150ms var(--ease-smooth); }
.faq-item summary:hover { color: var(--accent-hover); }
.faq-item[open] summary::after { transform: rotate(45deg); }
.faq-item { transition: background-color 200ms var(--ease-out-quad); }

/* ==========================================================================
   MOTION PASS v4.2 — modal spring, accordion reveal, loading states,
   cart exit, values staggers. Entrance fills use `backwards` so they never
   lock transform and block hover motion afterwards.
   ========================================================================== */

/* ---------- C1: overlay + modal spring entrance ---------- */
.overlay { animation: overlay-in 260ms var(--ease-out) both; }
@keyframes overlay-in { from { opacity: 0; } to { opacity: 1; } }
.modal { animation: modal-spring 420ms var(--ease-out-quart) both; }
@keyframes modal-spring {
  0% { opacity: 0; transform: scale(.92) translateY(16px); }
  60% { opacity: 1; transform: scale(1.008) translateY(-2px); }
  100% { opacity: 1; transform: scale(1) translateY(0); }
}

/* ---------- login step slide (re-triggered per step via .step-in) ---------- */
.login-body.step-in { animation: step-in 340ms var(--ease-out); }
@keyframes step-in { from { opacity: .35; transform: translateX(18px); } to { opacity: 1; transform: none; } }

/* ---------- C2: accordion height reveal ---------- */
.cacc-body { display: grid; grid-template-rows: 1fr; transition: grid-template-rows 300ms var(--ease-out-fluid); }
.cacc-fold { min-height: 0; overflow: hidden; }
.cacc-content { display: grid; gap: 8px; padding: 2px 2px 10px; }
.cacc[data-open="false"] .cacc-body { grid-template-rows: 0fr; }

/* ---------- C3: button loading spinner ---------- */
.btn.is-loading { pointer-events: none; color: transparent !important; }
.btn.is-loading::after {
  content: ''; position: absolute; top: 50%; left: 50%;
  width: 16px; height: 16px; margin: -8px 0 0 -8px;
  border-radius: 50%; border: 2px solid rgba(255, 255, 255, .25); border-top-color: #fff;
  animation: spin 700ms linear infinite;
}

/* ---------- C4: values rows stagger in, pages crossfade ---------- */
.vt-row { animation: row-in 340ms var(--ease-out) backwards; animation-delay: var(--rd, 0ms); }
@keyframes row-in { from { opacity: 0; transform: translateX(-10px); } to { opacity: 1; transform: none; } }
.vt-row.row-added { animation: row-added 550ms var(--ease-out); }
@keyframes row-added { 0% { background: rgba(139, 92, 246, .22); } 100% { background: transparent; } }
#v-body { transition: opacity 160ms var(--ease-out); }
#v-pager button { transition: transform 180ms var(--ease-out-quad), background-color 150ms var(--ease-smooth), color 150ms var(--ease-smooth); }
#v-pager button:hover:not(:disabled) { transform: translateY(-2px); background: rgba(255, 255, 255, .08); color: var(--foreground); }

/* ---------- C5: cart chip exit ---------- */
.cart-chip.chip-out { animation: chip-out 170ms var(--ease-out) both; pointer-events: none; }
@keyframes chip-out { to { opacity: 0; transform: scale(.7) translateY(8px); } }

/* ---------- C6: micro-motion ---------- */
.ptool-search svg { transition: color 200ms var(--ease-out); }
.ptool-search:focus-within svg { color: var(--accent); }
.ptool-sort { border-radius: 999px; transition: color 150ms var(--ease-smooth), background-color 150ms var(--ease-smooth), transform 200ms var(--ease-out-quart); }
.ptool-sort:hover { background: rgba(255, 255, 255, .06); transform: translateY(-1px); }
.modal-close { transition: all 200ms var(--ease-out-quart); }
.modal-close:hover { transform: rotate(90deg); }
.stat-card { transition: transform 300ms var(--ease-out-quart), background-color 200ms var(--ease-out-quad); }
.stat-card:hover { transform: translateY(-3px); }

/* entrance fills that must not block hover transforms */
.trade-item { animation-fill-mode: backwards; }
.cart-chip { animation-fill-mode: backwards; }
.reveal { animation-fill-mode: backwards; }
.card-in { animation-fill-mode: backwards; }

/* ==========================================================================
   v4.3 — page-level entrances so EVERY page animates on load, not just the
   swap desk. FAQ items cascade, values sections rise, swap panels rise.
   ========================================================================== */

/* ---------- FAQ: items cascade in ---------- */
.faq-item { animation: slide-fade-in 420ms var(--ease-out) backwards; }
.faq-item:nth-of-type(1) { animation-delay: 70ms; }
.faq-item:nth-of-type(2) { animation-delay: 115ms; }
.faq-item:nth-of-type(3) { animation-delay: 160ms; }
.faq-item:nth-of-type(4) { animation-delay: 205ms; }
.faq-item:nth-of-type(5) { animation-delay: 250ms; }
.faq-item:nth-of-type(6) { animation-delay: 295ms; }
.faq-item:nth-of-type(7) { animation-delay: 340ms; }
.faq-item:nth-of-type(8) { animation-delay: 385ms; }
.faq-item:nth-of-type(9) { animation-delay: 430ms; }
/* open body slides (replaces the earlier generic rule with a dedicated one) */
.faq-item[open] .faq-body { animation: faq-open 280ms var(--ease-out) both; }
@keyframes faq-open { from { opacity: 0; transform: translateY(-6px); } to { opacity: 1; transform: none; } }

/* ---------- swap desk: the three panels rise in on load ---------- */
.swap-grid > * { animation: panel-in 520ms var(--ease-out-quart) backwards; }
.swap-grid > *:nth-child(1) { animation-delay: 40ms; }
.swap-grid > *:nth-child(2) { animation-delay: 130ms; }
.swap-grid > *:nth-child(3) { animation-delay: 220ms; }
@keyframes panel-in {
  from { opacity: 0; transform: translateY(18px) scale(.99); }
  to { opacity: 1; transform: none; }
}
/* SEO band under the desk */
.seo-inner > * { animation: slide-fade-in 450ms var(--ease-out) backwards; }
.seo-inner > *:nth-child(2) { animation-delay: 90ms; }

/* ==========================================================================
   v4.4 — PROFILE PAGE + marquee upgrade + outline sweep round 2
   ========================================================================== */

/* ---------- profile shell ---------- */
.profile-page { padding-bottom: 48px; }
.profile-head { display: flex; align-items: center; gap: 16px; margin-bottom: 24px; flex-wrap: wrap; }
.ph-avatar img { width: 72px; height: 72px; border-radius: 20px; object-fit: cover; box-shadow: 0 0 24px rgba(139, 92, 246, .3); animation: pop-spring 420ms var(--ease-out-quart) backwards; }
.ph-id { flex: 1; min-width: 0; }
.ph-actions { display: flex; gap: 10px; align-items: center; flex-wrap: wrap; }

.profile-shell { display: grid; grid-template-columns: 230px minmax(0, 1fr); gap: 20px; align-items: start; }
.profile-nav { display: flex; flex-direction: column; gap: 2px; position: sticky; top: calc(var(--header-h) + 16px); }
.pnav-btn {
  position: relative;
  display: flex; align-items: center; gap: 10px;
  height: 42px; padding: 0 14px;
  border-radius: var(--radius-md);
  font-size: 14px; font-weight: 500; color: rgba(255, 255, 255, .55);
  text-align: left;
  transition: background-color 150ms var(--ease-smooth), color 150ms var(--ease-smooth);
}
.pnav-btn svg { width: 17px; height: 17px; flex: none; transition: color 150ms var(--ease-smooth); }
.pnav-btn:hover { background: rgba(255, 255, 255, .04); color: var(--foreground); }
.pnav-btn.on { color: var(--foreground); background: rgba(255, 255, 255, .04); }
.pnav-btn::before {
  content: ''; position: absolute; left: 0; top: 10px; bottom: 10px; width: 2px;
  border-radius: 2px; background: var(--accent);
  transform: scaleY(0); transform-origin: center;
  transition: transform 250ms var(--ease-out-fluid);
}
.pnav-btn.on::before { transform: scaleY(1); }
.pnav-btn.on svg { color: var(--accent); }

.profile-content { min-width: 0; }
.ptab { display: none; }
.ptab.on { display: block; }
.ptab.enter { animation: slide-fade-in 320ms var(--ease-out); }
.profile-sub { font-size: 15px; margin: 22px 0 12px; }

.profile-empty { text-align: center; padding: 44px 20px; }
.profile-empty h3 { font-size: 17px; margin-bottom: 4px; }
.profile-empty p { font-size: 13px; color: rgba(255, 255, 255, .6); margin: 0 0 16px; }

/* receipt rows */
.trade-row {
  display: grid; grid-template-columns: minmax(0, 1fr) auto minmax(0, 1fr) auto;
  gap: 12px; align-items: center;
  padding: 12px 14px; margin-bottom: 8px;
  border-radius: var(--radius-lg);
  background: var(--surface);
  animation: slide-fade-in 320ms var(--ease-out) backwards;
  transition: background-color 200ms var(--ease-out-quad);
}
.trade-row:hover { background: var(--surface-secondary); }
.tr-side { display: flex; gap: 4px; align-items: center; min-width: 0; flex-wrap: wrap; }
.tr-side img {
  width: 34px; height: 34px; object-fit: contain; padding: 3px;
  background: rgba(255, 255, 255, .04); border-radius: var(--radius-md);
}
.tr-more { font-size: 10px; font-weight: 600; color: var(--muted); }
.tr-arrow { width: 16px; height: 16px; color: rgba(255, 255, 255, .25); flex: none; }
.tr-meta { display: flex; flex-direction: column; align-items: flex-end; gap: 2px; font-size: 12px; font-weight: 500; }
.tr-time { color: var(--muted); font-weight: 400; }

/* inventory tab */
.inv-head { display: flex; justify-content: space-between; align-items: center; gap: 12px; margin-bottom: 12px; flex-wrap: wrap; }
.inv-item { cursor: pointer; }
.inv-item .inv-x {
  position: absolute; top: 4px; right: 4px; z-index: 12;
  width: 18px; height: 18px; border-radius: 999px;
  display: grid; place-items: center;
  background: rgba(219, 59, 62, .9); color: #fff;
  font-size: 10px; font-weight: 700;
  opacity: 0; transform: scale(.5);
  transition: opacity 160ms var(--ease-out-quad), transform 200ms var(--ease-out-quart);
}
.inv-item:hover .inv-x { opacity: 1; transform: scale(1); }

/* settings */
.settings-card { background: var(--surface); border-radius: var(--radius-lg); padding: 20px 22px; margin-bottom: 16px; animation: slide-fade-in 320ms var(--ease-out) backwards; }
.settings-card .profile-sub:first-child { margin-top: 0; }
.set-row { display: flex; justify-content: space-between; gap: 12px; padding: 11px 0; border-bottom: 1px solid var(--hairline); font-size: 14px; }
.set-row:last-of-type { border-bottom: none; }
.set-label { color: var(--muted); }
.set-value.mono { font-variant-numeric: tabular-nums; }
.set-actions { margin-top: 14px; display: flex; gap: 10px; }
.btn-danger { background: rgba(219, 59, 62, .12); color: #ff9092; }
.btn-danger:hover { background: rgba(219, 59, 62, .22); }
.btn-danger.is-loading::after { border-top-color: #ff9092; }

@media (max-width: 900px) {
  .profile-shell { grid-template-columns: 1fr; }
  .profile-nav {
    flex-direction: row; overflow-x: auto; position: static;
    gap: 4px; padding: 0 0 4px;
    scrollbar-width: none;
  }
  .profile-nav::-webkit-scrollbar { display: none; }
  .pnav-btn { flex: none; height: 38px; }
  .pnav-btn::before { left: 12px; right: 12px; top: auto; bottom: 0; width: auto; height: 2px; transform: scaleX(0); }
  .pnav-btn.on::before { transform: scaleX(1); }
}

/* ---------- marquee upgrade: bigger cards, breathing room, pop-in ---------- */
.marquee-item.pet-card { width: 150px; height: 184px; }
.marquee .marquee-item { animation: pop-spring 460ms var(--ease-out-quart) backwards; animation-delay: var(--rd, 0ms); }
.marquee { padding-bottom: 10px; }

/* ---------- outline sweep round 2 ---------- */
.sum-row { border-top: 1px solid var(--hairline); }

/* user chip opens the profile */
.user-chip { cursor: pointer; transition: background-color 150ms var(--ease-smooth), transform 200ms var(--ease-out-quart); }
.user-chip:hover { background: rgba(255, 255, 255, .09); transform: translateY(-1px); }

/* ---------- values pager (was unstyled bare buttons) ---------- */
.pager { display: flex; justify-content: center; align-items: center; gap: 6px; margin-top: 18px; flex-wrap: wrap; }
.pager button {
  min-width: 34px; height: 34px; padding: 0 11px;
  border-radius: 999px;
  font-size: 13px; font-weight: 500; color: rgba(255, 255, 255, .6);
  background: rgba(255, 255, 255, .05);
}
.pager button.on { background: var(--accent); color: #fff; box-shadow: 0 0 12px rgba(139, 92, 246, .35); }
.pager button:disabled { opacity: .35; cursor: default; }
.pager .dots { color: rgba(255, 255, 255, .3); font-size: 13px; }
