/* ──────────────────────────────────────────────────────────────────
   potionpost — SVG potion renderer
   Mirrors petalpost's /shared/bouquet.jsx in role:
     - export <Potion> for the live preview
     - export window.INGREDIENT_VOCAB and window.VESSEL_VOCAB for the
       design panel's pickers (single source of truth for names + glyphs).
   ────────────────────────────────────────────────────────────────── */

// Seeded RNG (mulberry32) — deterministic per-card placement so the live
// preview matches the printed card front, but each card looks different.
function rng(seed){
  let s = seed | 0;
  return () => { s |= 0; s = (s + 0x6D2B79F5) | 0;
    let t = s;
    t = Math.imul(t ^ (t >>> 15), 1 | t);
    t = (t + Math.imul(t ^ (t >>> 7), 61 | t)) ^ t;
    return ((t ^ (t >>> 14)) >>> 0) / 4294967296;
  };
}

// ──────────────────────────────────────────────────────────────────
// VESSELS — each defines its outer silhouette, the inner liquid clip,
// and how it sits in the 320x420 viewBox. cx,cy are the *liquid surface*
// center so we can place floating ingredients consistently.
// ──────────────────────────────────────────────────────────────────

const VESSELS = {
  cauldron: {
    name: 'cauldron',
    lt: 'cast iron',
    // liquid surface ellipse: cx 160, cy 245, rx 92, ry 14
    surface: { cx: 160, cy: 245, rx: 92, ry: 14 },
    // inside polygon (for ingredient clipping)
    inside: 'M68,245 Q60,300 92,335 Q160,365 228,335 Q260,300 252,245 Z',
    // height of liquid column for the gradient
    body: { top: 230, bottom: 350 },
    // picker glyph: simplified
    glyph: (
      <g fill="none" stroke="currentColor" strokeWidth="1.6" strokeLinecap="round" strokeLinejoin="round">
        <path d="M5 12 L31 12" />
        <path d="M8 12 Q6 26 14 30 Q18 31 22 30 Q30 26 28 12" />
        <path d="M3 14 L7 14" />
        <path d="M29 14 L33 14" />
      </g>
    ),
    // SVG: back layer (behind liquid) + front layer (rim, handles)
    back: (
      <g>
        {/* base shadow on ground */}
        <ellipse cx="160" cy="360" rx="115" ry="9" fill="#000" opacity=".35" />
        {/* legs / feet */}
        <path d="M88,330 q-8,18 -2,28 l8,0 q-6,-10 0,-22 z" fill="#0d0911" />
        <path d="M232,330 q8,18 2,28 l-8,0 q6,-10 0,-22 z" fill="#0d0911" />
        {/* body (back curve, behind liquid) */}
        <path d="M68,245 Q60,310 92,338 Q160,366 228,338 Q260,310 252,245 Z"
              fill="#161118" stroke="#3a2e1a" strokeWidth="1.4" />
        {/* inner shadow at rim */}
        <ellipse cx="160" cy="245" rx="92" ry="14" fill="#0a0710" />
      </g>
    ),
    front: (
      <g>
        {/* rim ellipse — outer */}
        <ellipse cx="160" cy="245" rx="98" ry="16" fill="none" stroke="#3a2e1a" strokeWidth="2.2" />
        {/* rim band */}
        <path d="M62,245 Q62,236 70,232 Q160,224 250,232 Q258,236 258,245" fill="#1d1620" stroke="#3a2e1a" strokeWidth="1.4" />
        {/* handles */}
        <path d="M65,253 q-14,2 -16,12 q-1,8 8,10" fill="none" stroke="#2a2128" strokeWidth="3" strokeLinecap="round" />
        <path d="M255,253 q14,2 16,12 q1,8 -8,10" fill="none" stroke="#2a2128" strokeWidth="3" strokeLinecap="round" />
        {/* subtle highlight on body */}
        <path d="M78,260 Q72,300 90,328" stroke="rgba(255,238,200,.04)" strokeWidth="3" fill="none" strokeLinecap="round" />
      </g>
    ),
  },

  flask: {
    name: 'flask',
    lt: 'erlenmeyer',
    // ~70% full: the liquid surface sits down in the wide cone, and its top
    // corners ride the actual glass walls (138→96 left, 182→224 right over
    // y 238→335) so the brew never bulges past the slanted shoulders.
    surface: { cx: 160, cy: 272, rx: 36, ry: 7 },
    inside: 'M124,272 L96,335 Q120,354 160,354 Q200,354 224,335 L196,272 Z',
    body: { top: 260, bottom: 350 },
    glyph: (
      <g fill="none" stroke="currentColor" strokeWidth="1.6" strokeLinecap="round" strokeLinejoin="round">
        <path d="M14 6 L14 14 L7 29 Q7 32 11 32 L25 32 Q29 32 29 29 L22 14 L22 6 Z" />
        <path d="M12 6 L24 6" />
      </g>
    ),
    back: (
      <g>
        <ellipse cx="160" cy="362" rx="78" ry="6" fill="#000" opacity=".32" />
        {/* glass body — solid back fill */}
        <path d="M138,150 L138,238 L96,335 Q120,358 160,358 Q200,358 224,335 L182,238 L182,150 Z"
              fill="rgba(240,226,193,.04)" stroke="none" />
        {/* surface ellipse (behind liquid) — matches the lowered liquid level */}
        <ellipse cx="160" cy="272" rx="36" ry="7" fill="rgba(0,0,0,.25)" />
      </g>
    ),
    front: (
      <g>
        {/* glass outline */}
        <path d="M138,150 L138,238 L96,335 Q120,358 160,358 Q200,358 224,335 L182,238 L182,150"
              fill="none" stroke="#d6be8a" strokeOpacity=".55" strokeWidth="1.6" strokeLinejoin="round" />
        {/* neck rim */}
        <path d="M136,150 L184,150" stroke="#d6be8a" strokeOpacity=".55" strokeWidth="2.2" strokeLinecap="round" />
        <path d="M134,148 L186,148 L186,154 L134,154 Z" fill="#322a40" stroke="#d6be8a" strokeOpacity=".55" strokeWidth="1.2" />
        {/* glass shine */}
        <path d="M146,260 L116,330" stroke="rgba(255,255,255,.16)" strokeWidth="2" strokeLinecap="round" fill="none" />
        <path d="M178,170 L178,210" stroke="rgba(255,255,255,.1)" strokeWidth="1.4" strokeLinecap="round" />
      </g>
    ),
  },

  vial: {
    name: 'vial',
    lt: 'test tube',
    surface: { cx: 160, cy: 220, rx: 22, ry: 5 },
    inside: 'M138,220 L138,330 Q138,348 160,348 Q182,348 182,330 L182,220 Z',
    body: { top: 200, bottom: 348 },
    glyph: (
      <g fill="none" stroke="currentColor" strokeWidth="1.6" strokeLinecap="round" strokeLinejoin="round">
        <rect x="14" y="3" width="8" height="6" rx="1.5" />
        <path d="M13 9 L13 26 Q13 31 18 31 Q23 31 23 26 L23 9 Z" />
        <path d="M13 13 L23 13" />
      </g>
    ),
    back: (
      <g>
        <ellipse cx="160" cy="354" rx="40" ry="4" fill="#000" opacity=".32" />
        <path d="M138,160 L138,330 Q138,348 160,348 Q182,348 182,330 L182,160 Z"
              fill="rgba(240,226,193,.04)" />
        <ellipse cx="160" cy="220" rx="22" ry="5" fill="rgba(0,0,0,.25)" />
      </g>
    ),
    front: (
      <g>
        <path d="M138,160 L138,330 Q138,348 160,348 Q182,348 182,330 L182,160"
              fill="none" stroke="#d6be8a" strokeOpacity=".55" strokeWidth="1.6" />
        {/* cork stopper */}
        <rect x="134" y="148" width="52" height="14" rx="3" fill="#6e4a2a" stroke="#3a2412" strokeWidth="1" />
        <path d="M138,150 L182,150" stroke="rgba(255,238,200,.18)" strokeWidth="1" />
        <ellipse cx="160" cy="148" rx="26" ry="3.5" fill="#8a5e36" stroke="#3a2412" strokeWidth=".8" />
        {/* string tie around neck */}
        <path d="M134,166 L186,166" stroke="#9d4a5c" strokeWidth="1.4" />
        <circle cx="186" cy="166" r="1.8" fill="#9d4a5c" />
        {/* shine */}
        <path d="M144,230 L144,310" stroke="rgba(255,255,255,.15)" strokeWidth="2" strokeLinecap="round" />
      </g>
    ),
  },

  gourd: {
    name: 'gourd',
    lt: 'calabash',
    surface: { cx: 160, cy: 250, rx: 38, ry: 7 },
    inside: 'M122,250 Q104,300 124,340 Q160,360 196,340 Q216,300 198,250 Z',
    body: { top: 240, bottom: 355 },
    glyph: (
      <g fill="none" stroke="currentColor" strokeWidth="1.6" strokeLinecap="round" strokeLinejoin="round">
        <rect x="14" y="4" width="8" height="4" rx="1" />
        <path d="M15 8 Q14 16 12 18 Q6 22 6 26 Q6 32 18 32 Q30 32 30 26 Q30 22 24 18 Q22 16 21 8 Z" />
      </g>
    ),
    back: (
      <g>
        <ellipse cx="160" cy="360" rx="60" ry="5" fill="#000" opacity=".32" />
        {/* gourd body */}
        <path d="M122,250 Q104,300 124,344 Q160,362 196,344 Q216,300 198,250 Z"
              fill="#5a3a24" stroke="#3a2412" strokeWidth="1.4" />
        {/* upper bulb */}
        <path d="M148,225 Q142,240 122,250 Q120,254 124,256 Q160,262 196,256 Q200,254 198,250 Q178,240 172,225 Z"
              fill="#5a3a24" stroke="#3a2412" strokeWidth="1.2" />
        {/* tie line */}
        <path d="M138,238 Q160,244 182,238" stroke="#3a2412" strokeWidth="1" fill="none" />
        <ellipse cx="160" cy="250" rx="38" ry="7" fill="rgba(0,0,0,.5)" />
      </g>
    ),
    front: (
      <g>
        {/* cork */}
        <rect x="152" y="200" width="16" height="22" rx="2" fill="#4a3018" stroke="#2a1808" strokeWidth="1" />
        <ellipse cx="160" cy="200" rx="8" ry="3" fill="#7a5430" stroke="#2a1808" strokeWidth=".8" />
        {/* leather strap */}
        <path d="M124,240 Q160,234 196,240" stroke="#9d4a5c" strokeWidth="1.6" fill="none" />
        {/* highlight */}
        <path d="M134,290 Q132,320 152,344" stroke="rgba(255,238,200,.08)" strokeWidth="3" fill="none" strokeLinecap="round" />
      </g>
    ),
  },

  jar: {
    name: 'jar',
    lt: 'apothecary',
    surface: { cx: 160, cy: 240, rx: 56, ry: 8 },
    inside: 'M104,240 L104,330 Q104,348 122,350 L198,350 Q216,348 216,330 L216,240 Z',
    body: { top: 230, bottom: 350 },
    glyph: (
      <g fill="none" stroke="currentColor" strokeWidth="1.6" strokeLinecap="round" strokeLinejoin="round">
        <rect x="10" y="3" width="16" height="5" rx="1" />
        <path d="M9 8 L27 8 L27 11 L9 11 Z" />
        <path d="M10 11 L10 30 Q10 32 13 32 L23 32 Q26 32 26 30 L26 11" />
        <path d="M9 18 L27 18" />
      </g>
    ),
    back: (
      <g>
        <ellipse cx="160" cy="356" rx="78" ry="6" fill="#000" opacity=".32" />
        {/* jar body */}
        <path d="M104,180 L104,330 Q104,348 122,350 L198,350 Q216,348 216,330 L216,180 Z"
              fill="rgba(240,226,193,.05)" />
        <ellipse cx="160" cy="240" rx="56" ry="8" fill="rgba(0,0,0,.25)" />
      </g>
    ),
    front: (
      <g>
        <path d="M104,180 L104,330 Q104,348 122,350 L198,350 Q216,348 216,330 L216,180"
              fill="none" stroke="#d6be8a" strokeOpacity=".55" strokeWidth="1.6" />
        {/* lid */}
        <rect x="100" y="166" width="120" height="16" rx="3" fill="#2a2128" stroke="#d6be8a" strokeOpacity=".55" strokeWidth="1.4" />
        <rect x="94" y="160" width="132" height="10" rx="2" fill="#1a1620" stroke="#d6be8a" strokeOpacity=".55" strokeWidth="1.2" />
        {/* label */}
        <rect x="118" y="260" width="84" height="40" rx="2" fill="#f0e2c1" stroke="#8a7c5c" strokeWidth=".8" opacity=".9" />
        <text x="160" y="278" textAnchor="middle" fontFamily="IM Fell English, serif" fontStyle="italic" fontSize="11" fill="#3a2412">tincture</text>
        <text x="160" y="293" textAnchor="middle" fontFamily="JetBrains Mono, monospace" fontSize="6.5" letterSpacing="1" fill="#8a7c5c">№ vii</text>
        {/* shine */}
        <path d="M114,200 L114,260" stroke="rgba(255,255,255,.12)" strokeWidth="2" strokeLinecap="round" />
      </g>
    ),
  },
};

// ──────────────────────────────────────────────────────────────────
// BREW colors. The "tint" is the body color; we derive a lighter top
// for the meniscus and a darker bottom for depth.
// ──────────────────────────────────────────────────────────────────

const BREWS = {
  emerald:  { name: 'emerald',  top: '#6ec27a', mid: '#2f7a45', bot: '#0f3a26', glow: '#8de58d' },
  violet:   { name: 'violet',   top: '#a884d6', mid: '#5e3a96', bot: '#291848', glow: '#c5a4ec' },
  crimson:  { name: 'crimson',  top: '#d4506e', mid: '#9a2840', bot: '#3e0c1c', glow: '#f08aa4' },
  midnight: { name: 'midnight', top: '#5870a8', mid: '#2a3a6a', bot: '#0c1230', glow: '#8aa0d4' },
  gilded:   { name: 'gilded',   top: '#f1c970', mid: '#c08a26', bot: '#5a3a0c', glow: '#ffe2a0' },
  pearl:    { name: 'pearl',    top: '#f4eedf', mid: '#d6c8a6', bot: '#8a7c5c', glow: '#ffffff' },
};

// ──────────────────────────────────────────────────────────────────
// INGREDIENTS — small SVG glyphs (~30×30 in their local coords).
// Each renders as a <g> centered on (0,0); the renderer translates +
// rotates them when placing inside or above the vessel.
// ──────────────────────────────────────────────────────────────────

const ING = {
  mandrake: {
    name: 'mandrake', lt: 'root',
    glyph: (
      <g>
        {/* gnarled root with two legs */}
        <path d="M0,-12 Q-4,-6 -2,0 Q-8,4 -10,12 Q-8,16 -4,14" fill="#a07a4a" stroke="#3a2412" strokeWidth="1.1" />
        <path d="M0,-12 Q4,-6 2,0 Q8,4 10,12 Q8,16 4,14" fill="#a07a4a" stroke="#3a2412" strokeWidth="1.1" />
        <path d="M-2,-12 Q-4,-16 -2,-18 Q0,-20 2,-18 Q4,-16 2,-12" fill="#a07a4a" stroke="#3a2412" strokeWidth="1.1" />
        {/* leaf top */}
        <path d="M-1,-19 Q-6,-24 -8,-22 M-1,-19 Q-2,-26 0,-26 M1,-19 Q6,-24 8,-22" stroke="#6a8254" strokeWidth="1.4" fill="none" strokeLinecap="round" />
        {/* face */}
        <circle cx="-2" cy="-2" r=".8" fill="#3a2412" />
        <circle cx="2" cy="-2" r=".8" fill="#3a2412" />
      </g>
    ),
  },
  toadstool: {
    name: 'toadstool', lt: 'fly-cap',
    glyph: (
      <g>
        {/* stem */}
        <path d="M-3,-2 L-3,12 Q-3,14 0,14 Q3,14 3,12 L3,-2 Z" fill="#f0e2c1" stroke="#3a2412" strokeWidth=".9" />
        {/* cap */}
        <path d="M-13,-2 Q-13,-14 0,-14 Q13,-14 13,-2 Z" fill="#c44a3a" stroke="#3a2412" strokeWidth="1.1" />
        {/* spots */}
        <circle cx="-7" cy="-8" r="1.6" fill="#f0e2c1" />
        <circle cx="6" cy="-9" r="1.4" fill="#f0e2c1" />
        <circle cx="0" cy="-5" r="1.5" fill="#f0e2c1" />
        <circle cx="-3" cy="-11" r="1" fill="#f0e2c1" />
      </g>
    ),
  },
  moonflower: {
    name: 'moonflower', lt: 'midnight bloom',
    glyph: (
      <g>
        {/* 5 petals */}
        {[0,72,144,216,288].map(a => (
          <ellipse key={a} cx="0" cy="-8" rx="4" ry="7" fill="#f0e2f8" stroke="#9d4a5c" strokeOpacity=".4" strokeWidth=".7" transform={`rotate(${a})`} />
        ))}
        <circle cx="0" cy="0" r="2.5" fill="#f1c970" stroke="#3a2412" strokeWidth=".7" />
      </g>
    ),
  },
  feather: {
    name: 'feather', lt: 'raven',
    glyph: (
      <g transform="rotate(-20)">
        <path d="M0,-14 Q-5,-4 -4,6 Q-2,12 0,14 Q2,12 4,6 Q5,-4 0,-14 Z" fill="#2a2128" stroke="#5a4632" strokeWidth=".9" />
        <path d="M0,-12 L0,12" stroke="#5a4632" strokeWidth=".7" />
        {/* barbs */}
        <path d="M0,-8 L-3,-6 M0,-4 L-4,-2 M0,0 L-4,2 M0,4 L-3,6 M0,-8 L3,-6 M0,-4 L4,-2 M0,0 L4,2 M0,4 L3,6" stroke="#5a4632" strokeWidth=".6" fill="none" />
      </g>
    ),
  },
  scale: {
    name: 'dragon scale', lt: 'iridescent',
    glyph: (
      <g>
        <path d="M0,-10 L8,0 L0,10 L-8,0 Z" fill="url(#scaleGrad)" stroke="#3a2412" strokeWidth=".9" />
        <path d="M0,-10 L8,0 L0,2 Z" fill="rgba(255,255,255,.18)" />
      </g>
    ),
  },
  crystal: {
    name: 'crystal', lt: 'quartz shard',
    glyph: (
      <g>
        <path d="M0,-12 L6,-4 L4,10 L-4,10 L-6,-4 Z" fill="#c5b4e6" stroke="#3a2412" strokeWidth=".9" opacity=".88" />
        <path d="M0,-12 L6,-4 L0,-3 Z" fill="rgba(255,255,255,.3)" />
        <path d="M-6,-4 L0,-3 L-4,10 Z" fill="rgba(0,0,0,.15)" />
      </g>
    ),
  },
  eye: {
    name: 'owl eye', lt: 'observing',
    glyph: (
      <g>
        <ellipse cx="0" cy="0" rx="11" ry="7" fill="#f0e2c1" stroke="#3a2412" strokeWidth="1.1" />
        <circle cx="0" cy="0" r="5" fill="#c08a26" stroke="#3a2412" strokeWidth=".8" />
        <circle cx="0" cy="0" r="2.5" fill="#1a1010" />
        <circle cx="1" cy="-1" r=".8" fill="#fff" />
      </g>
    ),
  },
  acorn: {
    name: 'acorn', lt: 'oak seed',
    glyph: (
      <g>
        {/* nut */}
        <path d="M-5,-2 Q-5,8 0,10 Q5,8 5,-2 Z" fill="#b58a52" stroke="#3a2412" strokeWidth="1" />
        {/* cap */}
        <path d="M-7,-4 Q-7,-9 0,-9 Q7,-9 7,-4 Q7,-2 5,-2 L-5,-2 Q-7,-2 -7,-4 Z" fill="#5a3a24" stroke="#3a2412" strokeWidth="1" />
        {/* stem */}
        <path d="M0,-9 L0,-12" stroke="#3a2412" strokeWidth="1.2" strokeLinecap="round" />
        {/* cap dots */}
        <circle cx="-3" cy="-6" r=".7" fill="#3a2412" />
        <circle cx="3" cy="-6" r=".7" fill="#3a2412" />
        <circle cx="0" cy="-4" r=".7" fill="#3a2412" />
      </g>
    ),
  },
  bone: {
    name: 'bone', lt: 'small',
    glyph: (
      <g transform="rotate(35)">
        <path d="M-12,-3 q-3,0 -3,3 q0,3 3,3 q1,0 2,-1 l16,0 q1,1 2,1 q3,0 3,-3 q0,-3 -3,-3 q-1,0 -2,1 l-16,0 q-1,-1 -2,-1 z"
              fill="#f0e2c1" stroke="#3a2412" strokeWidth="1" />
      </g>
    ),
  },
  bay: {
    name: 'bay leaf', lt: 'laurel',
    glyph: (
      <g transform="rotate(35)">
        <path d="M-10,0 Q-6,-7 0,-8 Q8,-6 10,0 Q6,7 0,8 Q-6,6 -10,0 Z" fill="#6a8254" stroke="#3a2412" strokeWidth="1" />
        <path d="M-10,0 L10,0" stroke="#3a2412" strokeWidth=".8" />
        <path d="M-6,-3 L-2,-1 M-4,-5 L0,-2 M-2,-6 L2,-2 M2,-4 L5,-1 M4,-2 L7,0" stroke="#3a2412" strokeWidth=".5" opacity=".5" />
      </g>
    ),
  },
  starshard: {
    name: 'starshard', lt: 'fallen',
    glyph: (
      <g>
        <path d="M0,-12 L3,-3 L12,0 L3,3 L0,12 L-3,3 L-12,0 L-3,-3 Z" fill="#f1c970" stroke="#3a2412" strokeWidth=".9" />
        <path d="M0,-12 L3,-3 L0,0 Z" fill="rgba(255,255,255,.4)" />
      </g>
    ),
  },
  nightshade: {
    name: 'nightshade', lt: 'belladonna',
    glyph: (
      <g>
        {/* berries cluster */}
        <circle cx="-4" cy="2" r="4" fill="#3a1830" stroke="#1a0816" strokeWidth=".7" />
        <circle cx="3" cy="0" r="4.5" fill="#3a1830" stroke="#1a0816" strokeWidth=".7" />
        <circle cx="-1" cy="7" r="3.5" fill="#3a1830" stroke="#1a0816" strokeWidth=".7" />
        {/* highlights */}
        <circle cx="-5" cy="1" r="1" fill="rgba(255,255,255,.4)" />
        <circle cx="2" cy="-1" r="1.2" fill="rgba(255,255,255,.4)" />
        {/* stem & leaves */}
        <path d="M0,-2 L0,-9" stroke="#6a8254" strokeWidth="1.2" />
        <path d="M0,-7 Q-5,-9 -7,-6 Q-4,-5 0,-7" fill="#6a8254" stroke="#3a2412" strokeWidth=".6" />
        <path d="M0,-9 Q5,-11 7,-8 Q4,-7 0,-9" fill="#6a8254" stroke="#3a2412" strokeWidth=".6" />
      </g>
    ),
  },
  spiral: {
    name: 'newt tail', lt: 'twisted',
    glyph: (
      <g>
        <path d="M-8,8 Q-8,-2 0,-4 Q8,-2 6,5 Q4,9 0,8 Q-2,7 -1,4 Q0,2 2,3" fill="none" stroke="#6a4a2a" strokeWidth="2" strokeLinecap="round" />
      </g>
    ),
  },
  petal: {
    name: 'rose petal', lt: 'pressed',
    glyph: (
      <g transform="rotate(-30)">
        <path d="M0,-10 Q-7,-4 -6,4 Q-3,10 0,10 Q3,10 6,4 Q7,-4 0,-10 Z" fill="#9d4a5c" stroke="#3a2412" strokeWidth=".9" />
        <path d="M0,-9 L0,9" stroke="#3a2412" strokeWidth=".5" opacity=".5" />
      </g>
    ),
  },
  wax: {
    name: 'wax seal', lt: 'pressed',
    glyph: (
      <g>
        <circle cx="0" cy="0" r="10" fill="#9d4a5c" stroke="#3a2412" strokeWidth="1" />
        <circle cx="0" cy="0" r="8" fill="none" stroke="rgba(0,0,0,.25)" strokeWidth=".7" />
        <text x="0" y="3.5" textAnchor="middle" fontFamily="IM Fell English, serif" fontStyle="italic" fontSize="11" fill="#3a1620">p</text>
        {/* drips */}
        <path d="M-8,7 Q-9,11 -7,12 Q-5,11 -6,8" fill="#9d4a5c" stroke="#3a2412" strokeWidth=".7" />
      </g>
    ),
  },
};

// ──────────────────────────────────────────────────────────────────
// ATMOSPHERE — decorations layered around the vessel.
// id → { name, render(ctx) } where ctx carries the seed + vessel info.
// ──────────────────────────────────────────────────────────────────

const ATMOS = {
  steam: {
    name: 'steam', lt: 'curling',
    render: (rand, vessel) => {
      const { cx, cy } = vessel.surface;
      const wisps = [];
      const n = 3;
      for (let i = 0; i < n; i++) {
        const x = cx - 30 + i * 30 + (rand() - .5) * 16;
        const top = cy - 70 - rand() * 30;
        const sway = (rand() - .5) * 20;
        wisps.push(
          <path key={i}
                d={`M${x},${cy - 6} Q${x + sway / 2},${cy - 30} ${x + sway},${cy - 50} Q${x + sway - 10},${top} ${x + sway + 6},${top - 14}`}
                stroke="rgba(240,226,193,.32)"
                strokeWidth="2.4"
                strokeLinecap="round"
                fill="none" />
        );
      }
      return <g key="steam">{wisps}</g>;
    },
    glyph: (
      <g fill="none" stroke="currentColor" strokeWidth="1.6" strokeLinecap="round">
        <path d="M9 22 Q7 16 11 12 Q9 8 13 4" />
        <path d="M16 22 Q14 16 18 12 Q16 8 20 4" />
        <path d="M23 22 Q21 16 25 12 Q23 8 27 4" />
      </g>
    ),
  },
  sparks: {
    name: 'sparks', lt: 'embered',
    render: (rand, vessel) => {
      const { cx, cy } = vessel.surface;
      const dots = [];
      for (let i = 0; i < 18; i++) {
        const angle = rand() * Math.PI * 2;
        const r = 60 + rand() * 80;
        const x = cx + Math.cos(angle) * r * (rand() > .5 ? 1 : .6);
        const y = cy - 30 + Math.sin(angle) * r * .6 - rand() * 30;
        const s = .8 + rand() * 1.6;
        dots.push(<circle key={i} cx={x} cy={y} r={s} fill="#f1c970" opacity={.4 + rand() * .5} />);
      }
      return <g key="sparks">{dots}</g>;
    },
    glyph: (
      <g fill="currentColor">
        <circle cx="9" cy="10" r="1.4" /><circle cx="18" cy="6" r="1" />
        <circle cx="24" cy="14" r="1.6" /><circle cx="14" cy="20" r="1.2" />
        <circle cx="22" cy="24" r="1" /><circle cx="8" cy="22" r=".9" />
      </g>
    ),
  },
  moth: {
    name: 'moth', lt: 'fluttering',
    render: (rand, vessel) => {
      const { cx, cy } = vessel.surface;
      const x = cx + (rand() > .5 ? 1 : -1) * (80 + rand() * 30);
      const y = cy - 50 - rand() * 30;
      return (
        <g key="moth" transform={`translate(${x},${y})`}>
          <ellipse cx="0" cy="0" rx="2" ry="6" fill="#3a2128" />
          <path d="M0,-2 Q-9,-6 -10,2 Q-8,6 -2,4 Z" fill="#5a4632" stroke="#3a2128" strokeWidth=".6" />
          <path d="M0,-2 Q9,-6 10,2 Q8,6 2,4 Z" fill="#5a4632" stroke="#3a2128" strokeWidth=".6" />
          <circle cx="-6" cy="-1" r="1" fill="#f0e2c1" opacity=".7" />
          <circle cx="6" cy="-1" r="1" fill="#f0e2c1" opacity=".7" />
          <path d="M-1,-5 L-3,-9 M1,-5 L3,-9" stroke="#3a2128" strokeWidth=".6" />
        </g>
      );
    },
    glyph: (
      <g fill="none" stroke="currentColor" strokeWidth="1.4" strokeLinecap="round">
        <ellipse cx="18" cy="18" rx="1.4" ry="5" fill="currentColor" />
        <path d="M18 16 Q10 12 9 20 Q12 24 17 22" />
        <path d="M18 16 Q26 12 27 20 Q24 24 19 22" />
      </g>
    ),
  },
  candle: {
    name: 'candle', lt: 'lit',
    render: (rand, vessel) => {
      const side = rand() > .5 ? 1 : -1;
      const baseX = vessel.surface.cx + side * 130;
      const baseY = 358;
      return (
        <g key="candle">
          <ellipse cx={baseX} cy={baseY + 4} rx="12" ry="2.5" fill="#000" opacity=".4" />
          <rect x={baseX - 10} y={baseY - 2} width="20" height="6" rx="1.5" fill="#3a2128" stroke="#1a1010" strokeWidth=".8" />
          <rect x={baseX - 6} y={baseY - 30} width="12" height="28" fill="#f0e2c1" stroke="#8a7c5c" strokeWidth=".9" />
          {/* drips */}
          <path d={`M${baseX - 6},${baseY - 14} q-2,4 0,8 q3,1 3,-3`} fill="#f0e2c1" stroke="#8a7c5c" strokeWidth=".7" />
          {/* wick */}
          <path d={`M${baseX},${baseY - 30} L${baseX},${baseY - 34}`} stroke="#3a2128" strokeWidth="1" />
          {/* flame */}
          <path d={`M${baseX},${baseY - 34} q-4,-3 -3,-8 q2,-4 3,-5 q1,1 3,5 q1,5 -3,8 z`} fill="#f1c970" />
          <path d={`M${baseX},${baseY - 36} q-2,-2 -2,-5 q2,-3 2,-3 q0,0 2,3 q0,3 -2,5 z`} fill="#c44a3a" opacity=".7" />
          {/* glow */}
          <circle cx={baseX} cy={baseY - 36} r="22" fill="url(#flameGlow)" />
        </g>
      );
    },
    glyph: (
      <g fill="none" stroke="currentColor" strokeWidth="1.4" strokeLinecap="round">
        <rect x="14" y="14" width="8" height="14" rx="1" />
        <path d="M18 14 L18 11 M18 11 Q15 9 17 6 Q18 5 18 5 Q18 5 19 6 Q21 9 18 11" />
      </g>
    ),
  },
  bats: {
    name: 'bats', lt: 'silhouettes',
    render: (rand) => {
      const items = [];
      for (let i = 0; i < 3; i++) {
        const x = 30 + rand() * 260;
        const y = 30 + rand() * 80;
        const s = .6 + rand() * .6;
        items.push(
          <g key={i} transform={`translate(${x},${y}) scale(${s})`}>
            <path d="M0,0 q-3,-3 -8,0 q2,-5 -3,-6 q4,2 6,-2 q2,4 5,4 q3,0 5,-4 q2,4 6,2 q-5,1 -3,6 q-5,-3 -8,0 z" fill="#0a0610" stroke="#3a2128" strokeWidth=".6" />
          </g>
        );
      }
      return <g key="bats">{items}</g>;
    },
    glyph: (
      <g fill="currentColor">
        <path d="M18 16 q-3,-3 -8,0 q2,-5 -3,-6 q4,2 6,-2 q2,4 5,4 q3,0 5,-4 q2,4 6,-2 q-5,1 -3,6 q-5,-3 -8,0 z" />
      </g>
    ),
  },
  raven: {
    name: 'raven', lt: 'perched',
    render: (rand, vessel) => {
      const side = rand() > .5 ? 1 : -1;
      const x = vessel.surface.cx + side * 140;
      const y = 100;
      return (
        <g key="raven" transform={`translate(${x},${y}) scale(${side === 1 ? -1 : 1},1)`}>
          {/* body */}
          <ellipse cx="0" cy="0" rx="12" ry="8" fill="#0a0610" stroke="#2a2128" strokeWidth=".7" />
          {/* head */}
          <circle cx="9" cy="-6" r="5" fill="#0a0610" stroke="#2a2128" strokeWidth=".7" />
          {/* beak */}
          <path d="M14,-7 L19,-6 L14,-4 Z" fill="#1a1010" />
          {/* eye */}
          <circle cx="11" cy="-7" r=".8" fill="#f1c970" />
          {/* tail */}
          <path d="M-12,2 L-22,4 L-12,6 Z" fill="#0a0610" />
          {/* wing */}
          <path d="M-2,-3 Q4,-6 8,-2 Q4,4 -4,2 Z" fill="#1a1010" stroke="#3a2128" strokeWidth=".5" />
          {/* legs */}
          <path d="M0,8 L-2,14 M4,8 L4,14" stroke="#3a2128" strokeWidth="1" />
        </g>
      );
    },
    glyph: (
      <g fill="currentColor">
        <ellipse cx="14" cy="20" rx="8" ry="5" />
        <circle cx="22" cy="14" r="4" />
        <path d="M26 13 L30 14 L26 16 Z" />
      </g>
    ),
  },
  moon: {
    name: 'crescent', lt: 'waxing',
    render: (rand) => {
      const side = rand() > .5 ? 1 : -1;
      const x = side === 1 ? 270 : 50;
      const y = 60;
      return (
        <g key="moon" transform={`translate(${x},${y})`}>
          <circle cx="0" cy="0" r="22" fill="#f0e2c1" opacity=".15" />
          <circle cx="0" cy="0" r="16" fill="#f0e2c1" />
          <circle cx="5" cy="-3" r="14" fill="#18141f" />
          {/* craters */}
          <circle cx="-7" cy="3" r="1.4" fill="#c4b690" />
          <circle cx="-3" cy="7" r="1" fill="#c4b690" />
          <circle cx="-9" cy="-2" r=".8" fill="#c4b690" />
        </g>
      );
    },
    glyph: (
      <g fill="currentColor">
        <circle cx="18" cy="18" r="11" />
        <circle cx="22" cy="14" r="9" fill="#18141f" />
      </g>
    ),
  },
};

// ──────────────────────────────────────────────────────────────────
// Public vocab — picker reads these (name, lt, glyph) for swatches.
// ──────────────────────────────────────────────────────────────────

window.INGREDIENT_VOCAB = Object.entries(ING).map(([type, v]) => ({ type, name: v.name, lt: v.lt, glyph: v.glyph }));
window.VESSEL_VOCAB = Object.entries(VESSELS).map(([id, v]) => ({ id, name: v.name, lt: v.lt, glyph: v.glyph }));
window.BREW_VOCAB = Object.entries(BREWS).map(([id, v]) => ({ id, name: v.name, top: v.top, mid: v.mid, bot: v.bot }));
window.ATMOS_VOCAB = Object.entries(ATMOS).map(([id, v]) => ({ id, name: v.name, lt: v.lt, glyph: v.glyph }));

// ──────────────────────────────────────────────────────────────────
// <Potion> — the live preview / print art.
// Props:
//   vessel:      id from VESSELS
//   brew:        id from BREWS
//   ingredients: array of { id, type, isNew? } where type is an ING key
//   atmosphere:  array of ATMOS keys
//   accentSeed:  number — drives random placement (deterministic per card)
// ──────────────────────────────────────────────────────────────────

function Potion({ vessel, brew, ingredients, atmosphere, accentSeed }){
  const V = VESSELS[vessel] || VESSELS.cauldron;
  const B = BREWS[brew] || BREWS.emerald;
  const ings = ingredients || [];
  const atm = atmosphere || [];
  const seed = (accentSeed | 0) || 1;

  // Ingredient placements. Every ingredient lives INSIDE the liquid (the group
  // below is clipped to V.inside), so a reshuffle re-rolls the arrangement but can
  // never fling one outside the brew. They spread down the liquid column (surface →
  // floor) and across a central band scaled to the vessel's surface width.
  // Computed once per (seed, vessel, ings.length) so positions are stable per card.
  const rand = rng(seed);
  const floor = (V.body && V.body.bottom) || (V.surface.cy + 90);
  const n = ings.length;
  const placements = ings.map((ing, i) => {
    const { cx, cy, rx } = V.surface;
    const top = cy + 14, bot = floor - 18;
    const halfW = Math.max(rx * 0.6, 14);
    const t = n <= 1 ? 0.5 : (i + 0.5) / n;            // index → horizontal slot
    const x = cx + (t - 0.5) * 2 * halfW + (rand() - 0.5) * halfW * 0.5;
    const y = top + (bot - top) * rand();              // seeded depth in the column
    const rot = (rand() - 0.5) * 50;
    const sc = 0.7 + rand() * 0.22;
    return { ...ing, x, y, rot, sc };
  });

  // Liquid is a vertical gradient from top→bot using brew colors.
  // Always render the liquid so empty-ingredient vessels still feel filled.
  return (
    <svg viewBox="0 0 320 420" xmlns="http://www.w3.org/2000/svg" style={{display:'block'}}>
      <defs>
        <linearGradient id="brewGrad" x1="0" x2="0" y1="0" y2="1">
          <stop offset="0%" stopColor={B.top} stopOpacity=".95" />
          <stop offset="55%" stopColor={B.mid} />
          <stop offset="100%" stopColor={B.bot} />
        </linearGradient>
        <linearGradient id="scaleGrad" x1="0" x2="1" y1="0" y2="1">
          <stop offset="0%" stopColor="#6a8254" />
          <stop offset="100%" stopColor="#2a4030" />
        </linearGradient>
        <radialGradient id="flameGlow" cx=".5" cy=".5" r=".5">
          <stop offset="0%" stopColor="#f1c970" stopOpacity=".55" />
          <stop offset="60%" stopColor="#c44a3a" stopOpacity=".18" />
          <stop offset="100%" stopColor="#c44a3a" stopOpacity="0" />
        </radialGradient>
        <radialGradient id="brewGlow" cx=".5" cy=".5" r=".5">
          <stop offset="0%" stopColor={B.glow} stopOpacity=".35" />
          <stop offset="60%" stopColor={B.glow} stopOpacity=".06" />
          <stop offset="100%" stopColor={B.glow} stopOpacity="0" />
        </radialGradient>
        <clipPath id={"insideClip_" + vessel}>
          <path d={V.inside} />
        </clipPath>
      </defs>

      {/* atmosphere — back layer (moon, bats, raven all sit behind the vessel) */}
      {atm.includes('moon') && ATMOS.moon.render(rng(seed + 1))}
      {atm.includes('bats') && ATMOS.bats.render(rng(seed + 2))}
      {atm.includes('raven') && ATMOS.raven.render(rng(seed + 3), V)}

      {/* glow halo around vessel */}
      <ellipse cx={V.surface.cx} cy={V.surface.cy + 30} rx="130" ry="80" fill="url(#brewGlow)" />

      {/* vessel back (the body that contains the liquid) */}
      {V.back}

      {/* liquid */}
      <g clipPath={`url(#insideClip_${vessel})`}>
        <path d={V.inside} fill="url(#brewGrad)" />
        {/* tiny bubbles */}
        {Array.from({ length: 7 }).map((_, i) => {
          const r2 = rng(seed * 7 + i + 11);
          const x = V.surface.cx + (r2() - .5) * V.surface.rx * 1.5;
          const y = V.surface.cy + 10 + r2() * 60;
          const s = .6 + r2() * 1.4;
          return <circle key={i} cx={x} cy={y} r={s} fill={B.top} opacity={.4 + r2() * .35} />;
        })}
        {/* ingredients — all rendered here, clipped to the liquid so none escape */}
        {placements.map(p => (
          <g key={p.id} transform={`translate(${p.x},${p.y}) rotate(${p.rot}) scale(${p.sc})`} opacity=".92">
            {ING[p.type] && ING[p.type].glyph}
          </g>
        ))}
      </g>

      {/* liquid surface — meniscus ellipse on top */}
      <ellipse cx={V.surface.cx} cy={V.surface.cy} rx={V.surface.rx} ry={V.surface.ry} fill={B.top} opacity=".95" />
      <ellipse cx={V.surface.cx} cy={V.surface.cy - 1} rx={V.surface.rx - 4} ry={Math.max(V.surface.ry - 2, 2)} fill={B.glow} opacity=".4" />

      {/* vessel front (rim, handles, label, glass highlights) */}
      {V.front}

      {/* atmosphere — top layer (steam, sparks, moth) */}
      {atm.includes('candle') && ATMOS.candle.render(rng(seed + 4), V)}
      {atm.includes('steam')  && ATMOS.steam.render(rng(seed + 5), V)}
      {atm.includes('sparks') && ATMOS.sparks.render(rng(seed + 6), V)}
      {atm.includes('moth')   && ATMOS.moth.render(rng(seed + 7), V)}
    </svg>
  );
}

// expose for the other scripts
window.Potion = Potion;
