// ── Design tokens ─────────────────────────────────────────────────────────────
const TOKENS = {
  fontBrand:    "'Hiyuga', serif",
  fontDisplay:  "'Koltav', serif",
  fontMono:     "'GC Vensca Mono', monospace",

  cardW: 360,
  cardH: 520,
  cardRadius: 18,

  // tier-independent surface colors
  surfaceDark:  '#0a0a10',
  surfaceDeep:  '#06060a',
};

// ── Archetype registry ────────────────────────────────────────────────────────
const ARCHETYPES = {
  slasher:         { name: "The Slasher",          hue: "#DC143C", short: "SLASH"  },
  pointGod:        { name: "Point God",            hue: "#7B2FBE", short: "PG"     },
  flamethrower:    { name: "Flamethrower",         hue: "#F4C20D", short: "FLAME"  },
  aerialArtist:    { name: "Aerial Artist",        hue: "#00B4D8", short: "AERIAL" },
  anchor:          { name: "The Anchor",           hue: "#708090", short: "ANCHOR" },
  ankletaker:      { name: "Ankletaker",           hue: "#00695C", short: "ANKLE"  },
  blur:            { name: "The Blur",             hue: "#ADFF2F", short: "BLUR"   },
  shadow:          { name: "The Shadow",           hue: "#0D1B2A", short: "SHADOW" },
  postBully:       { name: "Post Bully",           hue: "#1B4332", short: "POST"   },
  microwave:       { name: "Microwave",            hue: "#E63946", short: "MICRO"  },
  unicorn:         { name: "The Unicorn",          hue: "#9B59B6", short: "UNI"    },
  rimRunner:       { name: "Rim Runner",           hue: "#1565C0", short: "RIM"    },
  grandmaster:     { name: "Grandmaster",          hue: "#1A237E", short: "GM"     },
  giantSlayer:     { name: "Giant Slayer",         hue: "#8B0057", short: "SLAY"   },
  splasher:        { name: "Splasher",             hue: "#A8DADC", short: "SPLASH" },
  junkyardDog:     { name: "Junkyard Dog",         hue: "#C1440E", short: "DOG"    },
  finalForm:       { name: "Final Form",           hue: "#FFD700", short: "APEX"   },
  transitionHero:  { name: "Transition Hero",      hue: "#FF7F11", short: "TRANS"  },
  dreamShake:      { name: "Dream Shake",          hue: "#6A0572", short: "DREAM"  },
  wingIso:         { name: "Wing Iso",             hue: "#0F4C81", short: "WING"   },
  midrangeMaestro: { name: "Mid-range Maestro",    hue: "#B5651D", short: "MID"    },
  heliocentric:    { name: "Heliocentric Creator", hue: "#FFB347", short: "HELIO"  },
  bigFundamental:  { name: "Big Fundamental",      hue: "#2F4F2F", short: "FUND"   },
  ghost:           { name: "Ghost",                hue: "#D8E1E8", short: "GHOST"  },
};

const TIERS = {
  satin:       { name: "Satin Chroma",    short: "I"   },
  crystalline: { name: "Crystalline",     short: "II"  },
  prismatic:   { name: "Prismatic Surge", short: "III" },
  celestial:   { name: "Celestial Zenith",short: "IV"  },
};

// ── Color helpers ─────────────────────────────────────────────────────────────
function hexToRgb(hex) {
  const h = hex.replace('#', '');
  return {
    r: parseInt(h.slice(0, 2), 16),
    g: parseInt(h.slice(2, 4), 16),
    b: parseInt(h.slice(4, 6), 16),
  };
}
function darken(hex, amt) {
  const { r, g, b } = hexToRgb(hex);
  const f = 1 - amt;
  return `rgb(${Math.round(r*f)},${Math.round(g*f)},${Math.round(b*f)})`;
}
function lighten(hex, amt) {
  const { r, g, b } = hexToRgb(hex);
  return `rgb(${Math.round(r+(255-r)*amt)},${Math.round(g+(255-g)*amt)},${Math.round(b+(255-b)*amt)})`;
}

// ── CSS (injected once) ───────────────────────────────────────────────────────
const CARD_CSS = `
  .ssc-wrap {
    position: relative;
    width: 360px; height: 520px;
    transform-style: preserve-3d;
    transform: rotateX(var(--rx,0)) rotateY(var(--ry,0));
    transition: transform .08s linear;
    will-change: transform;
    cursor: pointer;
  }
  .ssc-inner {
    position: absolute; inset: 0;
    transform-style: preserve-3d;
    transition: transform .9s cubic-bezier(.2,.85,.3,1);
  }
  .ssc-wrap.flipped .ssc-inner { transform: rotateY(180deg); }

  .ssc-face {
    position: absolute; inset: 0;
    border-radius: 18px;
    overflow: hidden;
    backface-visibility: hidden;
    -webkit-backface-visibility: hidden;
    background: #0a0a10;
    box-shadow:
      0 30px 60px -20px rgba(0,0,0,.7),
      0 12px 24px -10px rgba(0,0,0,.5),
      inset 0 0 0 .5px rgba(255,255,255,.08);
  }
  .ssc-face-back {
    transform: rotateY(180deg);
    visibility: hidden;
    transition: visibility 0s linear .45s;
  }
  .ssc-wrap.flipped .ssc-face-back { visibility: visible; transition: visibility 0s linear .45s; }
  .ssc-wrap.flipped .ssc-face-front { visibility: hidden; transition: visibility 0s linear .45s; }

  .ssc-glow {
    position: absolute; inset: -6px;
    border-radius: 24px;
    background: radial-gradient(circle at var(--mxp,50%) var(--myp,50%),
      var(--hue-light) 0%, var(--hue) 25%, transparent 70%);
    filter: blur(calc(var(--glow-s) * 1px));
    opacity: calc(var(--glow-i) * (0.35 + var(--hover,0) * 0.65));
    transition: opacity .25s;
    z-index: -1;
    pointer-events: none;
  }
  .ssc-tier-celestial .ssc-glow {
    opacity: calc(var(--glow-i) * (0.7 + var(--hover,0) * 0.3));
  }

  .ssc-bg {
    position: absolute; inset: 0;
    background:
      radial-gradient(120% 90% at var(--mxp,50%) var(--myp,50%),
        var(--hue) 0%, var(--hue-dark) 55%, var(--hue-deep) 110%),
      linear-gradient(160deg, var(--hue-dark), var(--hue-deep));
    background-blend-mode: screen, normal;
  }
  .ssc-tier-satin .ssc-bg {
    background:
      radial-gradient(140% 100% at var(--mxp,50%) var(--myp,50%),
        var(--hue) 0%, var(--hue-dark) 50%, var(--hue-deep) 100%);
  }
  .ssc-tier-celestial .ssc-bg {
    background:
      radial-gradient(120% 90% at var(--mxp,50%) var(--myp,50%),
        var(--hue-dark) 0%, var(--hue-deep) 55%, #0a0a0f 110%);
  }

  .ssc-flow {
    position: absolute; inset: 0;
    background: linear-gradient(110deg,
      var(--hue-deep) 0%, var(--hue) 30%, var(--hue-light) 50%,
      var(--hue) 70%, var(--hue-deep) 100%);
    background-size: 300% 300%;
    animation: sscFlow 8s ease-in-out infinite;
    mix-blend-mode: screen;
    opacity: .85;
  }
  @keyframes sscFlow {
    0%   { background-position: 0% 50%; }
    50%  { background-position: 100% 50%; }
    100% { background-position: 0% 50%; }
  }

  .ssc-pattern {
    position: absolute; inset: 0;
    --d: calc(var(--pattern-d) * 1px + 6px);
    background-image:
      linear-gradient(60deg,  rgba(255,255,255,.05) 25%, transparent 25.5%, transparent 75%, rgba(255,255,255,.05) 75.5%),
      linear-gradient(-60deg, rgba(255,255,255,.05) 25%, transparent 25.5%, transparent 75%, rgba(255,255,255,.05) 75.5%);
    background-size: var(--d) calc(var(--d) * 1.732);
    opacity: .5;
    mix-blend-mode: screen;
    mask-image: radial-gradient(120% 120% at var(--mxp,50%) var(--myp,50%), black 30%, rgba(0,0,0,.3) 90%);
  }
  .ssc-tier-crystalline .ssc-pattern { opacity: .85; }
  .ssc-tier-crystalline .ssc-pattern::after {
    content: ""; position: absolute; inset: -20%;
    background: linear-gradient(115deg, transparent 35%,
      rgba(255,255,255,.4) 48%, rgba(255,255,255,.7) 50%,
      rgba(255,255,255,.4) 52%, transparent 65%);
    mix-blend-mode: screen;
    transform: translateX(-100%);
    animation: sscSweep 5s ease-in-out infinite;
  }
  @keyframes sscSweep {
    0%, 30%   { transform: translateX(-100%); }
    60%, 100% { transform: translateX(100%); }
  }

  .ssc-filigree {
    position: absolute; inset: 8px;
    border-radius: 14px;
    background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='80' height='80' viewBox='0 0 80 80'><g fill='none' stroke='%23FFD89A' stroke-width='.6' opacity='.85'><path d='M0 40 Q20 20 40 40 T80 40'/><path d='M40 0 Q20 20 40 40 T40 80'/><circle cx='40' cy='40' r='3'/><path d='M10 10 L30 30 M70 10 L50 30 M10 70 L30 50 M70 70 L50 50' stroke-width='.4'/></g></svg>");
    opacity: .6;
    mix-blend-mode: overlay;
  }

  .ssc-iri {
    position: absolute; inset: 0;
    background: conic-gradient(from var(--iri-angle, 0deg) at var(--mxp,50%) var(--myp,50%),
      hsl(0   100% 60%), hsl(60  100% 60%), hsl(120 100% 60%),
      hsl(180 100% 60%), hsl(240 100% 60%), hsl(300 100% 60%), hsl(360 100% 60%));
    filter: saturate(calc(var(--iri-sat) * 100%)) blur(8px);
    mix-blend-mode: var(--sheen-blend, color-dodge);
    -webkit-mask-image: radial-gradient(120% 90% at var(--mxp,50%) var(--myp,50%),
      rgba(0,0,0,.95) 0%, rgba(0,0,0,.4) 45%, rgba(0,0,0,0) 80%);
    mask-image: radial-gradient(120% 90% at var(--mxp,50%) var(--myp,50%),
      rgba(0,0,0,.95) 0%, rgba(0,0,0,.4) 45%, rgba(0,0,0,0) 80%);
    opacity: calc(0.55 + var(--hover,0) * 0.45);
    pointer-events: none;
  }
  .ssc-tier-satin    .ssc-iri { opacity: calc(0.25 + var(--hover,0) * 0.4); }
  .ssc-tier-prismatic .ssc-iri { opacity: calc(0.7  + var(--hover,0) * 0.3); }

  .ssc-spec {
    position: absolute; inset: 0;
    background: radial-gradient(circle calc(var(--spec-size) * 1px) at var(--mxp,50%) var(--myp,50%),
      rgba(255,255,255, calc(var(--spec-i) * 1)) 0%,
      rgba(255,255,255,.45) 18%, rgba(255,255,255,0) 60%);
    mix-blend-mode: screen;
    opacity: calc(0.35 + var(--hover,0) * 0.65);
    pointer-events: none;
  }

  .ssc-rim {
    position: absolute; inset: 0;
    border-radius: inherit;
    padding: 1.5px;
    background: linear-gradient(calc(var(--ry, 0deg) * 1 + 90deg),
      hsl(0   90% 70% / calc(var(--edge-refr) * 1)) 0%,
      hsl(60  90% 75% / calc(var(--edge-refr) * 1)) 25%,
      hsl(180 90% 75% / calc(var(--edge-refr) * 1)) 55%,
      hsl(280 90% 75% / calc(var(--edge-refr) * 1)) 80%,
      hsl(360 90% 70% / calc(var(--edge-refr) * 1)) 100%);
    -webkit-mask: linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0);
    -webkit-mask-composite: xor;
    mask-composite: exclude;
    pointer-events: none;
    mix-blend-mode: screen;
  }
  .ssc-tier-celestial .ssc-rim {
    background: linear-gradient(calc(var(--ry, 0deg) * 1 + 90deg),
      #FFD89A, #FFE9B2, #FFCB54, #FFD89A, #FFE9B2);
    opacity: calc(0.4 + var(--edge-refr) * 0.6);
  }

  .ssc-noise {
    position: absolute; inset: 0;
    background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='200' height='200'><filter id='n'><feTurbulence type='fractalNoise' baseFrequency='1.3' numOctaves='2' stitchTiles='stitch'/><feColorMatrix values='0 0 0 0 1  0 0 0 0 1  0 0 0 0 1  0 0 0 1 0'/></filter><rect width='100%' height='100%' filter='url(%23n)' opacity='1'/></svg>");
    background-size: 200px 200px;
    opacity: calc(var(--noise-a) * 1);
    mix-blend-mode: overlay;
    pointer-events: none;
  }

  .ssc-border {
    position: absolute; inset: 0;
    border-radius: inherit;
    box-shadow:
      inset 0 0 0 1px rgba(255,255,255,.08),
      inset 0 0 0 2px rgba(0,0,0,.4),
      inset 0 1px 0 rgba(255,255,255,.18);
    pointer-events: none;
  }
  .ssc-tier-celestial .ssc-border {
    box-shadow:
      inset 0 0 0 1.5px rgba(255,216,154,.55),
      inset 0 0 0 3px rgba(0,0,0,.5),
      inset 0 0 0 4.5px rgba(255,216,154,.35);
  }

  /* ── content ── */
  .ssc-cc {
    position: absolute; inset: 0;
    padding: 16px 18px;
    display: flex; flex-direction: column; gap: 12px;
    color: #fff;
    z-index: 5;
  }

  .ssc-header {
    text-align: center;
    padding: 2px 0 8px;
    border-bottom: 1px solid rgba(255,255,255,.18);
    transform: translateZ(20px);
  }
  .ssc-brand {
    font: 600 22px/1 'Hiyuga', serif;
    letter-spacing: .18em;
    color: #fff;
    text-transform: uppercase;
    text-shadow: 0 0 12px var(--hue), 0 1px 2px rgba(0,0,0,.6);
  }

  .ssc-top {
    display: grid;
    grid-template-columns: 110px 1fr;
    gap: 14px;
    align-items: stretch;
    transform: translateZ(20px);
  }

  .ssc-portrait {
    position: relative;
    height: 140px;
    border-radius: 10px;
    overflow: visible;
    color: rgba(255,255,255,.85);
    background: linear-gradient(180deg, rgba(255,255,255,.04), rgba(0,0,0,.3));
    box-shadow: inset 0 0 0 .5px rgba(255,255,255,.12);
  }
  .ssc-portrait-inner {
    position: absolute; inset: 0;
    transform: translate(var(--px,0), var(--py,0));
    transition: transform .15s ease-out;
    color: rgba(255,255,255,.92);
    filter: drop-shadow(0 6px 14px rgba(0,0,0,.4));
  }
  .ssc-tier-celestial .ssc-portrait-inner {
    inset: -12px -8px -8px -8px;
    z-index: 6;
  }

  .ssc-id-block {
    display: flex; flex-direction: column;
    justify-content: space-between;
    padding: 10px 12px;
    border-radius: 10px;
    background: linear-gradient(180deg, rgba(0,0,0,.55), rgba(0,0,0,.3));
    box-shadow: inset 0 0 0 .5px rgba(255,255,255,.18);
    backdrop-filter: blur(6px);
  }
  .ssc-field { display: flex; flex-direction: column; gap: 3px; }
  .ssc-field-label {
    font: 600 8px/1 'GC Vensca Mono', monospace;
    letter-spacing: .22em;
    color: rgba(255,255,255,.55);
    text-transform: uppercase;
  }
  .ssc-handle {
    font: 600 22px/1.05 'GC Vensca Mono', monospace;
    letter-spacing: .02em;
    color: var(--hue-bright);
    text-shadow: 0 0 10px var(--hue), 0 1px 2px rgba(0,0,0,.5);
  }
  .ssc-archetype-name {
    font: 400 18px/1.1 'Koltav', serif;
    letter-spacing: .02em;
    color: rgba(255,255,255,.95);
    text-transform: capitalize;
  }
  .ssc-xp { display: flex; align-items: center; gap: 8px; }
  .ssc-xp-track {
    flex: 1; height: 7px; border-radius: 6px;
    background: rgba(0,0,0,.55);
    box-shadow: inset 0 0 0 .5px rgba(255,255,255,.15);
    overflow: hidden;
  }
  .ssc-xp-fill {
    height: 100%; border-radius: 6px;
    background: linear-gradient(90deg, var(--hue), var(--hue-light));
    box-shadow: 0 0 8px var(--hue);
  }
  .ssc-xp-num {
    font: 600 14px/1 'Hiyuga', serif;
    letter-spacing: .04em;
    color: #fff;
    text-shadow: 0 0 8px var(--hue);
    font-variant-numeric: tabular-nums;
  }

  .ssc-divider {
    margin-top: auto;
    display: flex; align-items: center; gap: 8px;
    transform: translateZ(8px);
  }
  .ssc-divider span {
    flex: 1; height: 1px;
    background: linear-gradient(90deg, transparent, rgba(255,255,255,.25), transparent);
  }
  .ssc-divider b {
    font: 600 9px/1 'GC Vensca Mono', monospace;
    letter-spacing: .24em;
    color: rgba(255,255,255,.8);
  }

  .ssc-skills {
    display: grid; grid-template-columns: repeat(3, 1fr); gap: 6px;
    transform: translateZ(8px);
  }
  .ssc-skill {
    position: relative;
    aspect-ratio: 1.5 / 1;
    border-radius: 8px;
    display: grid; place-items: center;
    background: linear-gradient(180deg, rgba(255,255,255,.08), rgba(0,0,0,.35));
    box-shadow: inset 0 0 0 .5px rgba(255,255,255,.15);
    color: rgba(255,255,255,.9);
  }
  .ssc-skill svg { filter: drop-shadow(0 1px 2px rgba(0,0,0,.5)); }
  .ssc-skill b {
    position: absolute; right: 6px; bottom: 4px;
    font: 600 9px/1 'GC Vensca Mono', monospace;
    letter-spacing: .05em;
    color: var(--hue-bright);
    text-shadow: 0 0 8px var(--hue);
  }
  .ssc-skill-elite {
    box-shadow: inset 0 0 0 1px var(--hue-bright),
      0 0 12px rgba(var(--hue-r),var(--hue-g),var(--hue-b),.4);
  }

  .ssc-stats {
    display: grid; grid-template-columns: repeat(3,1fr); gap: 6px;
    transform: translateZ(10px);
  }
  .ssc-stat {
    padding: 8px 6px 6px; border-radius: 8px; text-align: center;
    background: linear-gradient(180deg, rgba(0,0,0,.45), rgba(0,0,0,.25));
    box-shadow: inset 0 0 0 .5px rgba(255,255,255,.12);
  }
  .ssc-stat-v {
    font: 400 26px/1 'Koltav', serif;
    letter-spacing: .01em; color: #fff;
    font-variant-numeric: tabular-nums;
  }
  .ssc-stat-l {
    font: 600 8.5px/1 'Hiyuga', serif;
    letter-spacing: .18em;
    margin-top: 5px;
    color: rgba(255,255,255,.7);
    text-transform: uppercase;
  }

  .ssc-tier-marker {
    margin-top: 6px;
    text-align: center;
    font: 500 8px/1 'GC Vensca Mono', monospace;
    letter-spacing: .24em;
    color: rgba(255,255,255,.65);
  }
  .ssc-tier-marker b { color: #fff; font-weight: 800; margin: 0 4px; }

  /* back face */
  .ssc-cc-back { padding: 22px 22px 18px; gap: 12px; justify-content: flex-start; }
  .ssc-back-eyebrow {
    font: 600 8px/1 'GC Vensca Mono', monospace;
    letter-spacing: .3em;
    text-align: center;
    color: rgba(255,255,255,.65);
    margin-bottom: 6px;
  }
  .ssc-back-block { display: flex; flex-direction: column; gap: 2px; }
  .ssc-back-label {
    font: 600 9px/1 'GC Vensca Mono', monospace;
    letter-spacing: .22em;
    color: rgba(255,255,255,.6);
  }
  .ssc-back-coin {
    font: 600 32px/1 'Hiyuga', serif;
    letter-spacing: .02em;
    color: #fff;
    text-shadow: 0 0 18px var(--hue);
  }
  .ssc-back-value {
    font: 400 20px/1.1 'Koltav', serif;
    letter-spacing: .01em;
    color: #fff;
  }
  .ssc-back-sub {
    font: 400 10px/1 'GC Vensca Mono', monospace;
    letter-spacing: .14em;
    color: rgba(255,255,255,.6);
  }
  .ssc-back-grid {
    display: flex; justify-content: space-between;
    font: 500 10px/1 'GC Vensca Mono', monospace;
    letter-spacing: .16em;
    color: rgba(255,255,255,.7);
    margin-top: 4px;
  }
  .ssc-back-grid b {
    display: block;
    font: 600 24px/1 'Hiyuga', serif;
    color: #fff;
    margin-top: 4px;
  }
  .ssc-rule {
    height: 1px;
    background: linear-gradient(90deg, transparent, rgba(255,255,255,.35), transparent);
    margin: 8px 0;
  }
  .ssc-back-watermark {
    margin-top: auto;
    font: 600 22px/1 'Hiyuga', serif;
    letter-spacing: .4em;
    color: rgba(255,255,255,.09);
    text-align: center;
    text-transform: uppercase;
  }

  /* non-flippable cards (carousel / hero / scatter) — no pointer affordance */
  .ssc-wrap.ssc-noflip { cursor: default; }

  /* fully static cards — no live tilt/RAF, no looping effect animations.
     Used for the carousel so 8 cards don't each run a rAF + infinite
     keyframe animation (big render win). */
  .ssc-wrap.ssc-static { transition: none; will-change: auto; }
  .ssc-wrap.ssc-static .ssc-flow,
  .ssc-wrap.ssc-static .ssc-pattern::after,
  .ssc-wrap.ssc-static .ssc-iri { animation: none !important; }

  /* ── Portrait: Y2K minimalist outline-only silhouette ── */
  .ssc-portrait-inner svg * {
    fill: none !important;
    stroke: currentColor;
    stroke-width: 1.6;
    stroke-linejoin: round;
    stroke-linecap: round;
    vector-effect: non-scaling-stroke;
  }
`;

let _cssInjected = false;
function injectCSS() {
  if (_cssInjected) return;
  const el = document.createElement('style');
  el.textContent = CARD_CSS;
  document.head.appendChild(el);
  _cssInjected = true;
}

// ── Effect layers ─────────────────────────────────────────────────────────────
function EffectLayers({ tier }) {
  return (
    <>
      <div className="ssc-bg" />
      <div className="ssc-pattern" />
      {tier === 'prismatic'  && <div className="ssc-flow" />}
      {tier === 'celestial'  && <div className="ssc-filigree" />}
      <div className="ssc-iri" />
      <div className="ssc-spec" />
      <div className="ssc-rim" />
      <div className="ssc-noise" />
      <div className="ssc-border" />
    </>
  );
}

// ── Silhouette SVG map ────────────────────────────────────────────────────────
const SILHOUETTES = {
  slasher: <path d="M70 38 c-9 0 -16 7 -16 16 c0 9 7 16 16 16 c5 0 9 -2 12 -5 l16 14 c-2 4 -3 8 -3 12 v18 l-22 32 c-3 4 -2 9 2 12 c4 3 9 2 12 -2 l24 -34 v44 c0 5 4 9 9 9 c5 0 9 -4 9 -9 v-78 c0 -3 -1 -6 -3 -8 l24 -10 c4 -2 6 -7 4 -11 c-2 -4 -7 -6 -11 -4 l-32 13 l-12 -10 c2 -3 3 -6 3 -10 c0 -9 -7 -16 -16 -16 z" fill="currentColor" />,
  pointGod: <g fill="currentColor"><circle cx="100" cy="48" r="14" /><path d="M86 64 h28 v44 l-12 90 h-12 l-4 -90 z M114 76 l24 -8 a4 4 0 1 1 2 8 l-26 12 z M86 76 l-22 -10 a4 4 0 1 0 -3 8 l25 14 z" /><circle cx="142" cy="68" r="6" stroke="currentColor" strokeWidth="2" fill="none" opacity=".6" /></g>,
  flamethrower: <g fill="currentColor"><circle cx="96" cy="44" r="13" /><path d="M82 58 h28 l4 50 l-8 86 h-12 l-4 -78 z M110 64 l30 -22 a5 5 0 0 1 6 8 l-26 28 z M82 70 l-18 18 a4 4 0 1 1 -6 -6 l16 -22 z" /><circle cx="146" cy="34" r="7" stroke="currentColor" strokeWidth="2.5" fill="none" /></g>,
  aerialArtist: <g fill="currentColor"><circle cx="104" cy="58" r="13" /><path d="M88 70 h32 l-4 56 h-26 z M120 80 l24 -16 a4 4 0 0 1 6 6 l-22 22 z M88 88 l-22 -8 a4 4 0 1 0 -2 8 l22 12 z M94 124 l-2 70 h12 l4 -70 z M112 124 l8 60 l10 -2 l-4 -62 z" /><circle cx="150" cy="58" r="6" fill="currentColor" /></g>,
  anchor: <g fill="currentColor"><circle cx="100" cy="46" r="14" /><path d="M86 60 h28 v60 h-28 z M86 70 l-12 -56 a4 4 0 0 1 8 -2 l8 54 z M114 70 l12 -56 a4 4 0 0 1 8 2 l-12 56 z M86 120 l-4 80 h12 l2 -80 z M114 120 l-2 80 h12 l-4 -80 z" /></g>,
  ankletaker: <g fill="currentColor"><circle cx="92" cy="64" r="13" /><path d="M78 78 l40 -8 l4 30 l-12 26 l8 70 h-14 l-6 -64 l-12 16 l-4 60 h-14 l4 -78 z M118 100 l24 32 a4 4 0 1 1 -6 4 l-22 -28 z" /><circle cx="152" cy="146" r="7" /></g>,
  blur: <g fill="currentColor"><circle cx="106" cy="50" r="12" /><path d="M92 64 l34 -2 l-2 56 l-12 80 h-12 l-2 -68 l-14 -8 z M126 72 l24 -4 a4 4 0 1 1 0 8 l-22 6 z" /><path d="M30 100 h36 M24 116 h44 M34 132 h30" stroke="currentColor" strokeWidth="3" opacity=".6" /></g>,
  shadow: <path d="M100 36 c14 0 22 12 20 26 c-2 12 -10 16 -10 24 c0 8 18 12 28 28 c12 18 14 44 8 64 c-6 18 -22 28 -46 28 c-24 0 -40 -10 -46 -28 c-6 -20 -4 -46 8 -64 c10 -16 28 -20 28 -28 c0 -8 -8 -12 -10 -24 c-2 -14 6 -26 20 -26 z" fill="currentColor" />,
  postBully: <g fill="currentColor"><circle cx="100" cy="44" r="14" /><path d="M70 60 h60 v58 h-60 z M70 72 l-14 14 a4 4 0 1 0 6 6 l12 -14 z M130 72 l14 14 a4 4 0 1 1 -6 6 l-12 -14 z M76 118 l-4 80 h16 l4 -80 z M124 118 l-4 80 h16 l4 -80 z" /></g>,
  microwave: <g fill="currentColor"><circle cx="100" cy="44" r="13" /><path d="M84 58 h32 l-4 60 h-26 z M116 70 l28 -8 a4 4 0 0 1 0 8 l-26 14 z M84 78 l-22 6 a4 4 0 0 1 -2 -8 l22 -10 z M88 122 l-4 78 h14 l4 -78 z M112 122 l4 78 h14 l-4 -78 z" /><path d="M150 36 l8 -12 M156 56 l16 -2 M168 70 l8 8" stroke="currentColor" strokeWidth="3" /></g>,
  unicorn: <g fill="currentColor"><circle cx="102" cy="36" r="11" /><path d="M90 48 h24 v50 l-6 50 h-12 l-6 -52 z M114 60 l24 -22 a4 4 0 0 1 6 6 l-22 26 z M90 70 l-18 -18 a4 4 0 1 1 6 -6 l18 18 z M96 148 l-4 50 h10 l2 -50 z M108 148 l8 50 l10 -2 l-6 -52 z" /></g>,
  rimRunner: <g fill="currentColor"><circle cx="98" cy="50" r="13" /><path d="M82 64 l32 -4 l4 58 l8 78 h-14 l-6 -66 l-14 14 l-4 60 h-14 l4 -82 z M118 70 l24 8 a4 4 0 1 1 -2 8 l-24 -8 z" /></g>,
  grandmaster: <g fill="currentColor"><circle cx="100" cy="44" r="13" /><path d="M84 58 h32 v58 h-32 z M116 64 l30 -4 a4 4 0 0 1 0 8 l-28 6 z M84 64 l-30 -4 a4 4 0 0 0 0 8 l28 6 z M86 116 l-4 80 h12 l4 -80 z M114 116 l-4 80 h12 l4 -80 z" /><circle cx="100" cy="100" r="14" stroke="currentColor" strokeWidth="2" fill="none" opacity=".6" /></g>,
  giantSlayer: <g fill="currentColor"><circle cx="86" cy="68" r="12" /><path d="M74 80 l44 -4 l4 36 l-10 30 l10 60 h-14 l-8 -54 l-12 14 l-4 50 h-14 l6 -70 z M118 116 l28 26 a4 4 0 1 1 -6 6 l-26 -22 z" /><circle cx="150" cy="148" r="6" /></g>,
  splasher: <g fill="currentColor"><circle cx="100" cy="46" r="13" /><path d="M86 60 h28 v52 h-28 z M114 66 l28 -28 a4 4 0 0 1 6 6 l-26 30 z M86 70 l-22 6 a4 4 0 0 1 -2 -8 l22 -10 z M88 112 l-4 86 h14 l4 -86 z M112 112 l4 86 h14 l-4 -86 z" /><circle cx="148" cy="32" r="6" stroke="currentColor" strokeWidth="2.5" fill="none" /></g>,
  junkyardDog: <g fill="currentColor"><circle cx="46" cy="124" r="12" /><path d="M58 116 l60 -8 l4 24 h-50 z M118 104 l40 -2 a4 4 0 0 1 0 8 l-38 4 z M120 132 l40 8 a4 4 0 1 1 -2 8 l-40 -8 z" /><circle cx="170" cy="100" r="6" /></g>,
  finalForm: <g fill="currentColor"><circle cx="100" cy="42" r="14" /><path d="M84 58 h32 v60 h-32 z M116 70 l40 -22 l-30 38 z M84 70 l-40 -22 l30 38 z M88 118 l-4 80 h12 l4 -80 z M112 118 l-4 80 h12 l4 -80 z" /><path d="M100 14 l4 22 l-4 8 l-4 -8 z" /></g>,
  transitionHero: <g fill="currentColor"><circle cx="96" cy="50" r="13" /><path d="M82 64 l34 -4 l4 50 l8 80 h-14 l-6 -66 l-14 14 l-4 60 h-14 l4 -82 z M120 70 l30 6 a4 4 0 1 1 -2 8 l-30 -6 z" /><path d="M20 110 h44 M14 130 h54 M28 150 h36" stroke="currentColor" strokeWidth="3" opacity=".55" /><circle cx="154" cy="80" r="6" /></g>,
  dreamShake: <g fill="currentColor"><circle cx="100" cy="46" r="14" /><path d="M82 60 h36 l-2 26 l-12 26 l8 80 h-14 l-6 -64 l-10 18 l-4 50 h-14 l6 -76 z M118 80 l28 -10 a4 4 0 1 1 2 8 l-26 14 z" /><path d="M70 110 q20 -8 40 0" fill="none" stroke="currentColor" strokeWidth="1.5" strokeDasharray="3 3" opacity=".5" /><circle cx="152" cy="74" r="6" /></g>,
  wingIso: <g fill="currentColor"><circle cx="100" cy="46" r="13" /><path d="M86 60 h28 v50 h-28 z M114 70 l24 8 a4 4 0 1 1 -2 8 l-24 -6 z M86 70 l-24 8 a4 4 0 1 0 2 8 l24 -6 z M88 110 l-4 86 h14 l4 -86 z M112 110 l4 86 h14 l-4 -86 z" /><circle cx="144" cy="86" r="6" /></g>,
  midrangeMaestro: <g fill="currentColor"><circle cx="100" cy="46" r="13" /><path d="M86 60 h28 v50 h-28 z M114 64 l30 -10 a4 4 0 0 1 4 8 l-28 14 z M86 70 l-22 -2 a4 4 0 0 0 0 8 l22 4 z M88 110 l-4 86 h14 l4 -86 z M112 110 l4 86 h14 l-4 -86 z" /><circle cx="154" cy="50" r="6" stroke="currentColor" strokeWidth="2.5" fill="none" /></g>,
  heliocentric: <g fill="currentColor"><circle cx="100" cy="50" r="14" /><path d="M84 64 h32 v52 h-32 z M116 70 l30 -8 a4 4 0 0 1 0 8 l-28 8 z M84 70 l-30 -8 a4 4 0 0 0 0 8 l28 8 z M86 116 l-4 80 h14 l4 -80 z M114 116 l-4 80 h14 l4 -80 z" /><g stroke="currentColor" strokeWidth="1.2" fill="none" opacity=".5"><circle cx="100" cy="90" r="42" /><circle cx="100" cy="90" r="58" /></g></g>,
  bigFundamental: <g fill="currentColor"><circle cx="100" cy="42" r="15" /><path d="M76 58 h48 v62 h-48 z M76 70 l-16 12 a4 4 0 1 0 6 6 l14 -14 z M124 70 l16 12 a4 4 0 1 1 -6 6 l-14 -14 z M82 120 l-4 80 h14 l4 -80 z M118 120 l-4 80 h14 l4 -80 z" /></g>,
  ghost: <g fill="currentColor" opacity=".7"><path d="M100 28 c20 0 34 16 34 38 v124 c0 6 -8 8 -12 2 l-8 -10 l-10 12 c-2 4 -8 4 -10 0 l-8 -12 l-10 10 c-4 6 -12 4 -12 -2 v-124 c0 -22 16 -38 36 -38 z" /><circle cx="90" cy="56" r="4" fill="#000" opacity=".4" /><circle cx="112" cy="56" r="4" fill="#000" opacity=".4" /></g>,
};

function Silhouette({ archetypeKey }) {
  const shape = SILHOUETTES[archetypeKey] || SILHOUETTES.slasher;
  return (
    <svg viewBox="0 0 200 220" preserveAspectRatio="xMidYMax meet"
         style={{ width: '100%', height: '100%' }}>
      <defs>
        <linearGradient id="sscSilg" x1="0" y1="0" x2="0" y2="1">
          <stop offset="0%"   stopColor="currentColor" stopOpacity=".95" />
          <stop offset="100%" stopColor="currentColor" stopOpacity=".55" />
        </linearGradient>
      </defs>
      <g style={{ color: 'url(#sscSilg)' }}>{shape}</g>
    </svg>
  );
}

const SKILL_ICONS = {
  ball:   <circle cx="12" cy="12" r="7" fill="none" stroke="currentColor" strokeWidth="1.5" />,
  bolt:   <path d="M13 3 L6 13 H11 L9 21 L18 11 H13 Z" fill="currentColor" />,
  target: <g fill="none" stroke="currentColor" strokeWidth="1.5"><circle cx="12" cy="12" r="7" /><circle cx="12" cy="12" r="3" /></g>,
  flame:  <path d="M12 3 c2 4 6 6 6 11 a6 6 0 0 1 -12 0 c0 -4 4 -7 4 -11 z" fill="currentColor" />,
  eye:    <g fill="none" stroke="currentColor" strokeWidth="1.5"><path d="M3 12 q9 -8 18 0 q-9 8 -18 0 z" /><circle cx="12" cy="12" r="2.2" /></g>,
  loop:   <path d="M5 9 a6 6 0 0 1 11 0 M19 15 a6 6 0 0 1 -11 0 M16 7 v3 h-3 M8 17 v-3 h3" fill="none" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" />,
};

function SkillBadge({ icon = 'ball', tier = 'I' }) {
  const isElite = tier === 'V' || tier === 'IV';
  return (
    <div className={`ssc-skill${isElite ? ' ssc-skill-elite' : ''}`}>
      <svg viewBox="0 0 24 24" width="22" height="22">{SKILL_ICONS[icon] || SKILL_ICONS.ball}</svg>
      <b>{tier}</b>
    </div>
  );
}

// ── Main component ────────────────────────────────────────────────────────────
/**
 * ShadowStepCard
 *
 * Renders a double-sided iridescent player card. Click to flip.
 * All effects respond to mouse position.
 */
function ShadowStepCard({
  // Identity
  playerName     = 'kingflexjr',
  archetype      = 'slasher',
  tier           = 'celestial',
  // Stats
  stats          = { record: '23-4', offRtg: '87.4', defRtg: '79.1' },
  // Progression
  xp             = 48240,
  xpProgress     = 0.62,
  // Back face
  drillCoins     = 3847,
  homeCourt      = 'Rucker Park',
  homeCourtSub   = 'Harlem · NY',
  squad          = 'The Grind Collective',
  seasonRecord   = { wins: 23, losses: 4, streak: 7 },
  // Skills (up to 6)
  skills         = [
    { icon: 'ball',   tier: 'I'   },
    { icon: 'bolt',   tier: 'III' },
    { icon: 'target', tier: 'II'  },
    { icon: 'flame',  tier: 'IV'  },
    { icon: 'eye',    tier: 'I'   },
    { icon: 'loop',   tier: 'II'  },
  ],
  // Effects
  showBack           = false,
  flippable          = true,
  staticRender       = false,
  tiltStrength       = 11,
  glowIntensity      = 70,
  glowSpread         = 90,
  iridescenceSat     = 0,
  iridescenceSpeed   = 48,
  specularSize       = 55,
  specularIntensity  = 80,
  noiseAmount        = 80,
  patternDensity     = 0,
  sheenBlend         = 'overlay',
  edgeRefraction     = 65,
  rotateOnIdle       = false,
  parallaxStrength   = 0,
}) {
  React.useEffect(() => { injectCSS(); }, []);

  // Resolve archetype — accepts a key string or a custom { name, hue, short } object
  const arch = typeof archetype === 'string'
    ? (ARCHETYPES[archetype] || ARCHETYPES.slasher)
    : archetype;

  const tierData = TIERS[tier] || TIERS.celestial;
  const hue = arch.hue;
  const { r, g, b } = hexToRgb(hue);

  const wrapRef  = React.useRef(null);
  const rafRef   = React.useRef(0);
  const targetRef  = React.useRef({ x: 0.5, y: 0.5, hover: 0 });
  const currentRef = React.useRef({ x: 0.5, y: 0.5, hover: 0 });
  const [flipped, setFlipped] = React.useState(showBack);

  React.useEffect(() => { setFlipped(showBack); }, [showBack]);

  React.useEffect(() => {
    const wrap = wrapRef.current;
    if (!wrap) return;
    if (staticRender) return; // static cards: no listeners, no rAF loop

    const onMove = (e) => {
      const rect = wrap.getBoundingClientRect();
      targetRef.current.x = (e.clientX - rect.left) / rect.width;
      targetRef.current.y = (e.clientY - rect.top)  / rect.height;
      targetRef.current.hover = 1;
    };
    const onLeave = () => {
      targetRef.current.hover = 0;
      targetRef.current.x = 0.5;
      targetRef.current.y = 0.5;
    };

    // Listen on the nearest positioned ancestor for a wider hit area
    const container = wrap.closest('#stage') || document.body;
    container.addEventListener('mousemove', onMove);
    container.addEventListener('mouseleave', onLeave);

    const tick = () => {
      const c = currentRef.current, tg = targetRef.current;
      c.x += (tg.x - c.x) * 0.12;
      c.y += (tg.y - c.y) * 0.12;
      c.hover += (tg.hover - c.hover) * 0.08;

      let rx, ry;
      if (rotateOnIdle && c.hover < 0.05) {
        const t = performance.now() / 2200;
        rx = Math.sin(t) * 6;
        ry = Math.cos(t * 0.7) * 10;
      } else {
        ry = (c.x - 0.5) * tiltStrength * 2;
        rx = -(c.y - 0.5) * tiltStrength * 2;
      }

      wrap.style.setProperty('--mx',    c.x);
      wrap.style.setProperty('--my',    c.y);
      wrap.style.setProperty('--mxp',   c.x * 100 + '%');
      wrap.style.setProperty('--myp',   c.y * 100 + '%');
      wrap.style.setProperty('--rx',    rx + 'deg');
      wrap.style.setProperty('--ry',    ry + 'deg');
      wrap.style.setProperty('--hover', c.hover);
      wrap.style.setProperty('--px',    (c.x - 0.5) * parallaxStrength + 'px');
      wrap.style.setProperty('--py',    (c.y - 0.5) * parallaxStrength + 'px');
      const ang = Math.atan2(c.y - 0.5, c.x - 0.5) * 180 / Math.PI;
      wrap.style.setProperty('--iri-angle', ang + iridescenceSpeed * 4 + 'deg');

      rafRef.current = requestAnimationFrame(tick);
    };
    rafRef.current = requestAnimationFrame(tick);

    return () => {
      cancelAnimationFrame(rafRef.current);
      container.removeEventListener('mousemove', onMove);
      container.removeEventListener('mouseleave', onLeave);
    };
  }, [tiltStrength, rotateOnIdle, iridescenceSpeed, parallaxStrength, staticRender]);

  const cssVars = {
    '--hue':        hue,
    '--hue-dark':   darken(hue, 0.55),
    '--hue-deep':   darken(hue, 0.78),
    '--hue-light':  lighten(hue, 0.35),
    '--hue-bright': lighten(hue, 0.55),
    '--hue-r':      r,
    '--hue-g':      g,
    '--hue-b':      b,
    '--glow-i':     glowIntensity / 100,
    '--glow-s':     glowSpread,
    '--iri-sat':    iridescenceSat / 100,
    '--spec-size':  specularSize,
    '--spec-i':     specularIntensity / 100,
    '--noise-a':    noiseAmount / 100,
    '--pattern-d':  patternDensity,
    '--sheen-blend':sheenBlend,
    '--edge-refr':  edgeRefraction / 100,
  };

  const archetypeDisplay = arch.name.replace(/^The\s+/, '');
  const xpFormatted = xp.toLocaleString();
  const coinsFormatted = drillCoins.toLocaleString();

  return (
    <div
      ref={wrapRef}
      className={`ssc-wrap ssc-tier-${tier}${flipped ? ' flipped' : ''}${flippable ? '' : ' ssc-noflip'}${staticRender ? ' ssc-static' : ''}`}
      style={cssVars}
      onClick={flippable ? () => setFlipped((f) => !f) : undefined}
      role={flippable ? 'button' : undefined}
      aria-label={flippable ? `${playerName} player card — click to flip` : `${playerName} player card`}
    >
      <div className="ssc-glow" />
      <div className="ssc-inner">

        {/* ── Front ── */}
        <div className="ssc-face ssc-face-front">
          <EffectLayers tier={tier} />
          <div className="ssc-cc">

            <div className="ssc-header">
              <div className="ssc-brand">SHADOW STEP</div>
            </div>

            <div className="ssc-top">
              <div className="ssc-portrait">
                <div className="ssc-portrait-inner">
                  <Silhouette archetypeKey={typeof archetype === 'string' ? archetype : 'slasher'} />
                </div>
              </div>

              <div className="ssc-id-block">
                <div className="ssc-field">
                  <div className="ssc-field-label">USERNAME</div>
                  <div className="ssc-handle">{playerName}</div>
                </div>
                <div className="ssc-field">
                  <div className="ssc-field-label">ARCHETYPE</div>
                  <div className="ssc-archetype-name">{archetypeDisplay}</div>
                </div>
                <div className="ssc-field">
                  <div className="ssc-field-label">TOTAL XP</div>
                  <div className="ssc-xp">
                    <div className="ssc-xp-track">
                      <div className="ssc-xp-fill" style={{ width: `${Math.round(xpProgress * 100)}%` }} />
                    </div>
                    <div className="ssc-xp-num">{xpFormatted}</div>
                  </div>
                </div>
              </div>
            </div>

            <div className="ssc-divider"><span /><b></b><span /></div>

            <div className="ssc-skills">
              {skills.slice(0, 6).map((s, i) => (
                <SkillBadge key={i} icon={s.icon} tier={s.tier} />
              ))}
            </div>

            <div className="ssc-stats">
              <div className="ssc-stat">
                <div className="ssc-stat-v">{stats.record}</div>
                <div className="ssc-stat-l">1v1 REC</div>
              </div>
              <div className="ssc-stat">
                <div className="ssc-stat-v">{stats.offRtg}</div>
                <div className="ssc-stat-l">OFF RTG</div>
              </div>
              <div className="ssc-stat">
                <div className="ssc-stat-v">{stats.defRtg}</div>
                <div className="ssc-stat-l">DEF RTG</div>
              </div>
            </div>

            <div className="ssc-tier-marker">
              <span>TIER</span>{' '}
              <b>{tierData.short}</b>{' '}
              <span>· {archetypeDisplay.toUpperCase()}</span>
            </div>

          </div>
        </div>

        {/* ── Back (only rendered when the card can flip — saves the
            second iridescent render stack on static cards) ── */}
        {flippable && (
        <div className="ssc-face ssc-face-back">
          <EffectLayers tier={tier} />
          <div className="ssc-cc ssc-cc-back">

            <div className="ssc-back-eyebrow">— SHADOW STEP / PLAYER ARCHIVE —</div>

            <div className="ssc-back-block">
              <div className="ssc-back-label">DRILL COINS</div>
              <div className="ssc-back-coin">◈ {coinsFormatted}</div>
            </div>
            <div className="ssc-rule" />

            <div className="ssc-back-block">
              <div className="ssc-back-label">HOME COURT</div>
              <div className="ssc-back-value">{homeCourt}</div>
              {homeCourtSub && <div className="ssc-back-sub">{homeCourtSub}</div>}
            </div>
            <div className="ssc-rule" />

            <div className="ssc-back-block">
              <div className="ssc-back-label">SQUAD</div>
              <div className="ssc-back-value">{squad}</div>
            </div>
            <div className="ssc-rule" />

            <div className="ssc-back-block">
              <div className="ssc-back-label">SEASON RECORD</div>
              <div className="ssc-back-grid">
                <span>WIN <b>{seasonRecord.wins}</b></span>
                <span>LOSS <b>{seasonRecord.losses}</b></span>
                <span>STREAK <b>{seasonRecord.streak}</b></span>
              </div>
            </div>

            <div className="ssc-back-watermark">SHADOW STEP</div>

          </div>
        </div>
        )}

      </div>
    </div>
  );
}

// ── Mount helper: render a card into any DOM node ──────────────────────────────
window.ShadowStepCard = ShadowStepCard;
window.ARCHETYPES = ARCHETYPES;
window.TIERS = TIERS;
window.__cardRoots = window.__cardRoots || new WeakMap();
window.mountCard = function(el, props){
  if(!el) return null;
  injectCSS();
  let root = window.__cardRoots.get(el);
  if(!root){ root = ReactDOM.createRoot(el); window.__cardRoots.set(el, root); }
  root.render(React.createElement(ShadowStepCard, props || {}));
  return root;
};
