// Panel chrome — comic-strip frame with thick black border, hard drop shadow,
// optional caption box at top, optional sticker stamp at corner.

function Panel({
  x, y, w, h,
  rotate = 0,
  bg = '#0B1410',
  caption,
  captionBg = '#F5EBD8',
  number,
  children,
  show = true,
  entryProgress = 1, // 0..1
}) {
  const t = Math.max(0, Math.min(1, entryProgress));
  const scale = 0.92 + 0.08 * t;
  const opacity = t;

  return (
    <div style={{
      position: 'absolute',
      left: x, top: y, width: w, height: h,
      transform: `rotate(${rotate}deg) scale(${scale})`,
      opacity,
      background: bg,
      border: '5px solid #0A0A0A',
      boxShadow: '10px 10px 0 #0A0A0A',
      borderRadius: 4,
      overflow: 'hidden',
      transformOrigin: 'center',
    }}>
      {/* Inner stage for content */}
      <div style={{ position: 'absolute', inset: 0, overflow: 'hidden' }}>
        {children}
      </div>

      {/* Caption box — letter-pressed at top-left */}
      {caption && (
        <div style={{
          position: 'absolute',
          left: 16, top: 16,
          background: captionBg,
          border: '3px solid #0A0A0A',
          padding: '6px 12px',
          fontFamily: 'Akira Expanded, "Cocogoose Pro", sans-serif',
          fontSize: 14,
          fontWeight: 900,
          letterSpacing: '0.06em',
          textTransform: 'uppercase',
          color: '#0A0F0A',
          boxShadow: '3px 3px 0 #0A0A0A',
          zIndex: 5,
        }}>
          {caption}
        </div>
      )}

      {/* Panel number sticker — bottom-right */}
      {number != null && (
        <div style={{
          position: 'absolute',
          right: 12, bottom: 12,
          width: 38, height: 38,
          borderRadius: '50%',
          background: '#FF6B35',
          border: '3px solid #0A0A0A',
          color: '#0A0A0A',
          fontFamily: 'Akira Expanded, sans-serif',
          fontWeight: 900,
          fontSize: 18,
          display: 'flex', alignItems: 'center', justifyContent: 'center',
          boxShadow: '3px 3px 0 #0A0A0A',
          transform: 'rotate(-6deg)',
          zIndex: 5,
        }}>{number}</div>
      )}
    </div>
  );
}

// Halftone overlay
function Halftone({ color = 'rgba(0,0,0,0.18)', size = 6, opacity = 1 }) {
  return (
    <div style={{
      position: 'absolute', inset: 0,
      backgroundImage: `radial-gradient(circle, ${color} 1px, transparent 1.5px)`,
      backgroundSize: `${size}px ${size}px`,
      opacity,
      pointerEvents: 'none',
    }}/>
  );
}

// Sunburst conic gradient
function Sunburst({ x = '50%', y = '50%', size = 800, color = 'var(--accent-ember)', opacity = 0.18, rotate = 0 }) {
  const segs = Array.from({length: 24}, (_, i) =>
    `${color} ${i*15}deg ${i*15 + 7.5}deg, transparent ${i*15 + 7.5}deg ${(i+1)*15}deg`
  ).join(', ');
  return (
    <div style={{
      position: 'absolute',
      left: x, top: y,
      width: size, height: size,
      transform: `translate(-50%,-50%) rotate(${rotate}deg)`,
      background: `conic-gradient(from 0deg, ${segs})`,
      opacity, pointerEvents: 'none',
      borderRadius: '50%',
    }}/>
  );
}

// 3D perspective floor grid (lab/grounds)
function GridFloor({ color = 'rgba(255,107,53,0.32)', y = '60%' }) {
  return (
    <div style={{
      position: 'absolute',
      left: '50%', bottom: '-20%',
      width: '180%', height: '90%',
      transform: 'translateX(-50%) rotateX(68deg)',
      transformOrigin: '50% 100%',
      backgroundImage: `linear-gradient(${color} 1px, transparent 1px), linear-gradient(90deg, ${color} 1px, transparent 1px)`,
      backgroundSize: '40px 40px',
      maskImage: 'linear-gradient(180deg, transparent 0%, #000 35%, #000 100%)',
      WebkitMaskImage: 'linear-gradient(180deg, transparent 0%, #000 35%, #000 100%)',
      pointerEvents: 'none',
    }}/>
  );
}

// Floating ember orb
function Ember({ x, y, size = 14, color = '#FF6B35', glow = 1, drift = 0 }) {
  return (
    <div style={{
      position: 'absolute',
      left: x, top: y,
      width: size, height: size,
      borderRadius: '50%',
      background: `radial-gradient(circle at 30% 30%, #FFE0B0, ${color} 55%, #5A1A0A)`,
      boxShadow: `0 0 ${size*1.5}px ${color}${Math.floor(glow*180).toString(16).padStart(2,'0')}, inset -2px -3px 5px rgba(0,0,0,0.4)`,
      transform: `translate(-50%,-50%) translateY(${drift}px)`,
      pointerEvents: 'none',
    }}/>
  );
}

// Star/spark glyph
function Spark({ x, y, size = 16, color = '#FFD93D', rotate = 0, opacity = 1 }) {
  return (
    <svg style={{
      position: 'absolute',
      left: x, top: y,
      transform: `translate(-50%,-50%) rotate(${rotate}deg)`,
      opacity,
      pointerEvents: 'none',
    }} width={size*2} height={size*2} viewBox="-10 -10 20 20">
      <path d="M 0 -10 L 2 -2 L 10 0 L 2 2 L 0 10 L -2 2 L -10 0 L -2 -2 Z"
            fill={color} stroke="#0A0A0A" strokeWidth="1.5"/>
    </svg>
  );
}

// Bunting pennants strung across top of a panel
function Bunting({ y = 12, count = 9, w, colors }) {
  const cs = colors || ['#FF6B35', '#F2A93B', '#A8FFB0', '#00F0FF', '#FF1493'];
  const span = w - 24;
  return (
    <svg style={{ position: 'absolute', left: 12, top: y, width: span, height: 28, pointerEvents: 'none' }}>
      <path d={`M 0 4 Q ${span/2} 18 ${span} 4`} stroke="#0A0A0A" strokeWidth="2" fill="none"/>
      {Array.from({ length: count }).map((_, i) => {
        const t = i / (count - 1);
        const cx = t * span;
        // sag follows arc
        const cy = 4 + Math.sin(t * Math.PI) * 14;
        return (
          <g key={i} transform={`translate(${cx} ${cy})`}>
            <polygon points="-7,0 7,0 0,16" fill={cs[i % cs.length]} stroke="#0A0A0A" strokeWidth="1.5"/>
          </g>
        );
      })}
    </svg>
  );
}

// Scout patch
function ScoutPatch({ x, y, size = 80, label = 'FIRE', color = '#FF6B35', glyph = '★', rotate = -8, progress = 1 }) {
  const t = Math.max(0, Math.min(1, progress));
  const s = t < 0.4 ? Easing.easeOutBack(t/0.4) : 1;
  const opacity = t;
  return (
    <div style={{
      position: 'absolute', left: x, top: y,
      transform: `translate(-50%,-50%) rotate(${rotate}deg) scale(${s})`,
      opacity, pointerEvents: 'none',
    }}>
      <svg width={size} height={size} viewBox="-50 -50 100 100" style={{overflow:'visible'}}>
        {/* outer scalloped ring */}
        {Array.from({length: 16}).map((_, i) => {
          const a = (i/16) * Math.PI * 2;
          return <circle key={i} cx={Math.cos(a)*42} cy={Math.sin(a)*42} r="6" fill="#F5EBD8" stroke="#0A0A0A" strokeWidth="2"/>;
        })}
        <circle r="38" fill={color} stroke="#0A0A0A" strokeWidth="3"/>
        <circle r="30" fill="none" stroke="#0A0A0A" strokeWidth="2" strokeDasharray="3 3"/>
        <text x="0" y="-2" textAnchor="middle" fontFamily="Akira Expanded" fontSize="22" fontWeight="900" fill="#0A0A0A">{glyph}</text>
        <text x="0" y="20" textAnchor="middle" fontFamily="Akira Expanded" fontSize="10" fontWeight="900" fill="#0A0A0A" letterSpacing="1">{label}</text>
      </svg>
    </div>
  );
}

// Camp gate / sign — wooden plank with rope
function CampSign({ x, y, w = 320, text = 'carl.camp', sub = 'pop. 1', rotate = 1, progress = 1 }) {
  const t = Math.max(0, Math.min(1, progress));
  const scale = t < 0.4 ? Easing.easeOutBack(t/0.4) : 1;
  return (
    <div style={{
      position: 'absolute', left: x, top: y,
      transform: `translate(-50%,-50%) rotate(${rotate}deg) scale(${scale})`,
      opacity: t,
      pointerEvents: 'none',
    }}>
      {/* rope */}
      <svg width="20" height="40" style={{position:'absolute', left:'50%', top:-30, transform:'translateX(-50%)'}}>
        <line x1="10" y1="0" x2="10" y2="40" stroke="#0A0A0A" strokeWidth="3" strokeDasharray="2 2"/>
      </svg>
      <div style={{
        background: '#C8A776',
        border: '4px solid #0A0A0A',
        borderRadius: 6,
        padding: '14px 22px',
        boxShadow: '6px 6px 0 #0A0A0A',
        textAlign: 'center',
        minWidth: w,
        position: 'relative',
      }}>
        {/* wood grain */}
        <div style={{position:'absolute', inset:0, background:'repeating-linear-gradient(180deg, transparent 0 8px, rgba(60,30,10,0.18) 8px 9px)', pointerEvents:'none'}}/>
        <div style={{
          fontFamily: 'Nirakolu, system-ui, sans-serif',
          fontSize: 38, fontWeight: 900,
          color: '#2A1F14', letterSpacing: '-0.01em', position:'relative',
        }}>{text}</div>
        {sub && <div style={{
          fontFamily: 'Special Elite, monospace',
          fontSize: 13, color: '#2A1F14', marginTop: 4, position:'relative',
        }}>{sub}</div>}
      </div>
    </div>
  );
}

// Terminal window (lab)
function LabTerminal({ x, y, w = 360, h = 200, lines = [], progress = 1 }) {
  const t = Math.max(0, Math.min(1, progress));
  // reveal lines progressively
  const visibleCount = Math.floor(t * lines.length);
  const partialChars = ((t * lines.length) - visibleCount);

  return (
    <div style={{
      position: 'absolute', left: x, top: y,
      width: w, height: h,
      transform: 'translate(-50%,-50%)',
      background: '#0B1410',
      border: '3px solid #00F0FF',
      borderRadius: 8,
      boxShadow: '0 0 30px rgba(0,240,255,0.35), 6px 6px 0 #0A0A0A',
      overflow: 'hidden',
      opacity: t < 0.1 ? t/0.1 : 1,
    }}>
      {/* titlebar */}
      <div style={{
        height: 22,
        background: '#131F18',
        borderBottom: '1px solid rgba(0,240,255,0.3)',
        display: 'flex', alignItems: 'center', gap: 6, padding: '0 8px',
      }}>
        <div style={{ width: 8, height: 8, borderRadius: 4, background: '#FF1493' }}/>
        <div style={{ width: 8, height: 8, borderRadius: 4, background: '#FFFF33' }}/>
        <div style={{ width: 8, height: 8, borderRadius: 4, background: '#39FF14' }}/>
        <div style={{ marginLeft: 8, fontFamily: 'JetBrains Mono, monospace', fontSize: 10, color: '#00F0FF', letterSpacing: '0.15em' }}>LAB · CARL@LOCAL</div>
      </div>
      {/* content */}
      <div style={{ padding: 12, fontFamily: 'JetBrains Mono, monospace', fontSize: 13, color: '#A8FFB0', lineHeight: 1.6 }}>
        {lines.map((line, i) => {
          if (i < visibleCount) {
            return <div key={i} style={{ color: line.color || '#A8FFB0' }}>{line.text}</div>;
          } else if (i === visibleCount) {
            const reveal = line.text.slice(0, Math.floor(partialChars * line.text.length));
            return <div key={i} style={{ color: line.color || '#A8FFB0' }}>{reveal}<span style={{ color: '#00F0FF' }}>▊</span></div>;
          }
          return null;
        })}
      </div>
    </div>
  );
}

// Campfire — animated with flickering ember stack
function Campfire({ x, y, scale = 1, time = 0 }) {
  const flick1 = Math.sin(time * 12) * 3;
  const flick2 = Math.cos(time * 14 + 1) * 4;
  return (
    <div style={{
      position: 'absolute', left: x, top: y,
      transform: `translate(-50%,-50%) scale(${scale})`,
      pointerEvents: 'none',
    }}>
      <svg width="120" height="160" viewBox="-60 -100 120 160">
        {/* glow */}
        <ellipse cx="0" cy="0" rx="70" ry="40" fill="rgba(255,107,53,0.25)" filter="blur(2px)"/>
        {/* logs */}
        <ellipse cx="-22" cy="38" rx="34" ry="8" fill="#5A3A1A" stroke="#0A0A0A" strokeWidth="2.5" transform="rotate(-15 -22 38)"/>
        <ellipse cx="22" cy="36" rx="34" ry="8" fill="#7A4A2A" stroke="#0A0A0A" strokeWidth="2.5" transform="rotate(18 22 36)"/>
        <circle cx="-50" cy="34" r="6" fill="#3A2010" stroke="#0A0A0A" strokeWidth="2"/>
        <circle cx="50" cy="32" r="6" fill="#3A2010" stroke="#0A0A0A" strokeWidth="2"/>

        {/* flame outer */}
        <path d={`M -28 30 Q -36 ${-30+flick1} -10 ${-50+flick2} Q 0 ${-86+flick1} 12 ${-58+flick2} Q 38 ${-26+flick2} 28 32 Z`}
              fill="#FF6B35" stroke="#0A0A0A" strokeWidth="3"/>
        {/* flame mid */}
        <path d={`M -18 28 Q -22 ${-10+flick1} -4 ${-32+flick2} Q 4 ${-62+flick1} 14 ${-30+flick2} Q 24 -4 18 30 Z`}
              fill="#F2A93B"/>
        {/* flame core */}
        <path d={`M -8 26 Q -10 0 0 -16 Q 8 -42 12 -10 Q 14 14 10 28 Z`}
              fill="#FFD93D"/>
      </svg>
    </div>
  );
}

// Cabin (tiny illustrated cabin)
function Cabin({ x, y, scale = 1, glow = false }) {
  return (
    <div style={{ position:'absolute', left:x, top:y,
      transform: `translate(-50%,-50%) scale(${scale})`,
      filter: glow ? 'drop-shadow(0 0 24px rgba(127,255,0,0.5))' : 'none',
      pointerEvents:'none',
    }}>
      <svg width="180" height="160" viewBox="0 0 180 160">
        {/* roof */}
        <polygon points="90,12 22,72 158,72" fill="#5A3A1A" stroke="#0A0A0A" strokeWidth="3.5"/>
        <polygon points="90,12 158,72 144,72 90,26" fill="#3A2010"/>
        {/* body */}
        <rect x="32" y="72" width="116" height="74" fill="#7A4A2A" stroke="#0A0A0A" strokeWidth="3.5"/>
        {/* logs */}
        {[82,96,110,124,138].map((y, i) => (
          <line key={i} x1="32" y1={y} x2="148" y2={y} stroke="#0A0A0A" strokeWidth="1.5" opacity="0.5"/>
        ))}
        {/* door */}
        <rect x="76" y="100" width="28" height="46" fill="#3A2010" stroke="#0A0A0A" strokeWidth="3"/>
        <circle cx="98" cy="124" r="2" fill="#FFD93D"/>
        {/* windows */}
        <rect x="42" y="86" width="22" height="20" fill={glow ? '#A8FFB0' : '#F2A93B'} stroke="#0A0A0A" strokeWidth="2.5"/>
        <rect x="116" y="86" width="22" height="20" fill={glow ? '#A8FFB0' : '#F2A93B'} stroke="#0A0A0A" strokeWidth="2.5"/>
        <line x1="53" y1="86" x2="53" y2="106" stroke="#0A0A0A" strokeWidth="1.5"/>
        <line x1="42" y1="96" x2="64" y2="96" stroke="#0A0A0A" strokeWidth="1.5"/>
        <line x1="127" y1="86" x2="127" y2="106" stroke="#0A0A0A" strokeWidth="1.5"/>
        <line x1="116" y1="96" x2="138" y2="96" stroke="#0A0A0A" strokeWidth="1.5"/>
        {/* chimney + smoke */}
        <rect x="120" y="32" width="14" height="22" fill="#5A3A1A" stroke="#0A0A0A" strokeWidth="2.5"/>
      </svg>
    </div>
  );
}

// Human silhouette/partner — abstract head + shoulders
function HumanPartner({ x, y, scale = 1, progress = 1 }) {
  const t = Math.max(0, Math.min(1, progress));
  return (
    <div style={{ position: 'absolute', left: x, top: y, transform: `translate(-50%,-50%) scale(${scale})`, opacity: t, pointerEvents: 'none' }}>
      <svg width="200" height="240" viewBox="0 0 200 240">
        {/* body */}
        <path d="M 30 240 Q 30 160 100 160 Q 170 160 170 240 Z" fill="#1E3A8A" stroke="#0A0A0A" strokeWidth="4"/>
        {/* neck */}
        <rect x="86" y="130" width="28" height="34" fill="#ECE7DC" stroke="#0A0A0A" strokeWidth="3"/>
        {/* head */}
        <ellipse cx="100" cy="100" rx="42" ry="48" fill="#ECE7DC" stroke="#0A0A0A" strokeWidth="4"/>
        {/* hair */}
        <path d="M 60 88 Q 58 50 100 48 Q 142 50 140 88 Q 138 70 100 68 Q 62 70 60 88 Z" fill="#2A1F14" stroke="#0A0A0A" strokeWidth="3"/>
        {/* eyes */}
        <circle cx="84" cy="104" r="3" fill="#0A0A0A"/>
        <circle cx="116" cy="104" r="3" fill="#0A0A0A"/>
        {/* smile */}
        <path d="M 84 122 Q 100 132 116 122" stroke="#0A0A0A" strokeWidth="3" fill="none" strokeLinecap="round"/>
        {/* arm reaching out */}
        <path d="M 30 200 Q -10 200 -30 180" stroke="#ECE7DC" strokeWidth="22" fill="none" strokeLinecap="round"/>
        <path d="M 30 200 Q -10 200 -30 180" stroke="#0A0A0A" strokeWidth="3" fill="none" strokeLinecap="round"/>
        {/* hand/fist */}
        <circle cx="-30" cy="180" r="14" fill="#ECE7DC" stroke="#0A0A0A" strokeWidth="3"/>
      </svg>
    </div>
  );
}

Object.assign(window, { Panel, Halftone, Sunburst, GridFloor, Ember, Spark, Bunting, ScoutPatch, CampSign, LabTerminal, Campfire, Cabin, HumanPartner });
