// Chapter illustrations — frameless, edge-bleed, modyfi-style annotations.
// No surrounding box on any of them; they sit inside chapter-right naturally.

function useTime() {
  const [t, setT] = React.useState(0);
  React.useEffect(() => {
    let raf,start = performance.now();
    const tick = (now) => {setT((now - start) / 1000);raf = requestAnimationFrame(tick);};
    raf = requestAnimationFrame(tick);
    return () => cancelAnimationFrame(raf);
  }, []);
  return t;
}

const STAMP_STYLE = {
  fontFamily: 'var(--font-mono)',
  fontSize: 10.5,
  letterSpacing: '0.16em',
  textTransform: 'uppercase',
  color: 'rgba(250,250,247,0.5)'
};

// Frameless wrapper — annotations on the corners, no border around content
function Stage({ tag, footL, footR, children }) {
  return (
    <div style={{ width: '100%', height: '100%', minHeight: 480, position: 'relative', display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
      <div style={{ position: 'absolute', top: 0, left: 0, ...STAMP_STYLE, display: 'flex', alignItems: 'center', gap: 10 }}>
        <span style={{ width: 5, height: 5, borderRadius: '50%', background: '#10b981', boxShadow: '0 0 8px #10b981' }} />
        {tag}
      </div>
      <div style={{ position: 'absolute', top: 0, right: 0, ...STAMP_STYLE }}>live</div>
      {footL && <div style={{ position: 'absolute', bottom: 0, left: 0, ...STAMP_STYLE }}>{footL}</div>}
      {footR && <div style={{ position: 'absolute', bottom: 0, right: 0, ...STAMP_STYLE }}>{footR}</div>}
      {children}
    </div>);

}

// ─────────────────────────────────────────────────────────────
// 01 — Agent lattice
// ─────────────────────────────────────────────────────────────
function AgentGraph() {
  const t = useTime();
  const orch = { x: 50, y: 50 };
  const agents = [
  { id: 'sdr', x: 18, y: 22, label: 'sdr', task: 'reply' },
  { id: 'sup', x: 82, y: 22, label: 'support', task: 'triage' },
  { id: 'ana', x: 16, y: 78, label: 'analyst', task: 'report' },
  { id: 'ea', x: 84, y: 78, label: 'assistant', task: 'inbox' }];

  const tools = [
  { id: 'crm', x: 50, y: 8, label: 'crm' },
  { id: 'tg', x: 92, y: 50, label: 'tg' },
  { id: 'kb', x: 50, y: 92, label: 'kb' },
  { id: 'erp', x: 8, y: 50, label: 'erp' }];

  function curve(a, b, ctrlOffset = 10) {
    const mx = (a.x + b.x) / 2,my = (a.y + b.y) / 2;
    const dx = b.x - a.x,dy = b.y - a.y;
    const len = Math.sqrt(dx * dx + dy * dy) || 1;
    return { mx: mx + -dy / len * ctrlOffset, my: my + dx / len * ctrlOffset };
  }
  function pointOnCurve(a, c, b, T) {
    return {
      x: (1 - T) * (1 - T) * a.x + 2 * (1 - T) * T * c.mx + T * T * b.x,
      y: (1 - T) * (1 - T) * a.y + 2 * (1 - T) * T * c.my + T * T * b.y
    };
  }
  const edges = [
  ...agents.map((a) => ({ a: orch, b: a, key: 'o-' + a.id })),
  { a: agents[0], b: tools[0], key: 'sdr-crm' },
  { a: agents[1], b: tools[1], key: 'sup-tg' },
  { a: agents[2], b: tools[2], key: 'ana-kb' },
  { a: agents[3], b: tools[3], key: 'ea-erp' }];

  const states = ['plan', 'route', 'execute', 'verify', 'reply'];
  const stateIdx = Math.floor(t / 1.3) % states.length;

  return (
    <Stage tag="agent_lattice"
    footL={<span>orchestrator · {states[stateIdx]}</span>}
    footR={<span>{agents.length} agents · {tools.length} tools</span>}>
      <svg viewBox="0 0 100 100" preserveAspectRatio="xMidYMid meet" style={{ width: '94%', height: '94%' }}>
        <defs>
          <radialGradient id="ag-core" cx="50%" cy="50%" r="50%">
            <stop offset="0%" stopColor="#fafaf7" stopOpacity="0.6" />
            <stop offset="100%" stopColor="#fafaf7" stopOpacity="0" />
          </radialGradient>
        </defs>
        {edges.map((e, i) => {
          const c = curve(e.a, e.b, 8);
          const phase = (t * 0.32 + i * 0.27) % 1;
          const p = pointOnCurve(e.a, c, e.b, phase);
          const a = Math.sin(phase * Math.PI);
          return (
            <g key={e.key}>
              <path d={`M ${e.a.x} ${e.a.y} Q ${c.mx} ${c.my} ${e.b.x} ${e.b.y}`}
              fill="none" stroke="rgba(250,250,247,0.13)" strokeWidth="0.22" />
              <circle cx={p.x} cy={p.y} r="0.55" fill="#fafaf7" opacity={a} />
              <circle cx={p.x} cy={p.y} r="1.4" fill="#fafaf7" opacity={a * 0.18} />
            </g>);

        })}
        <g>
          <circle cx={orch.x} cy={orch.y} r={20} fill="url(#ag-core)" opacity={0.4 + 0.2 * Math.sin(t * 2)} />
          <circle cx={orch.x} cy={orch.y} r={6.5 + 0.4 * Math.sin(t * 2)} fill="#fafaf7" />
          <circle cx={orch.x} cy={orch.y} r={11.5} fill="none" stroke="rgba(250,250,247,0.3)" strokeWidth="0.2" strokeDasharray="0.5 1.2" style={{ transformOrigin: '50% 50%', transform: `rotate(${t * 16}deg)` }} />
        </g>
        {agents.map((a) => {
          const breathe = 1 + 0.08 * Math.sin(t * 1.3 + a.x);
          return (
            <g key={a.id}>
              <circle cx={a.x} cy={a.y} r={4.4 * breathe} fill="rgba(250,250,247,0.92)" />
              <circle cx={a.x} cy={a.y} r={5.6} fill="none" stroke="rgba(250,250,247,0.25)" strokeWidth="0.2" />
              <text x={a.x} y={a.y - 7.5} fontSize="2.4" textAnchor="middle"
              fill="rgba(250,250,247,0.62)" fontFamily="'JetBrains Mono', monospace" letterSpacing="0.06em">{a.label}</text>
              <text x={a.x} y={a.y + 9.5} fontSize="1.9" textAnchor="middle"
              fill="rgba(236,72,153,0.85)" fontFamily="'JetBrains Mono', monospace" letterSpacing="0.06em">{a.task}()</text>
            </g>);

        })}
        {tools.map((tl) =>
        <g key={tl.id}>
            <rect x={tl.x - 3} y={tl.y - 3} width="6" height="6" rx="0.6"
          fill="none" stroke="rgba(250,250,247,0.36)" strokeWidth="0.22" />
            <text x={tl.x} y={tl.y + 0.8} fontSize="1.8" textAnchor="middle"
          fill="rgba(250,250,247,0.55)" fontFamily="'JetBrains Mono', monospace" letterSpacing="0.05em">{tl.label}</text>
          </g>
        )}
      </svg>
    </Stage>);

}

// ─────────────────────────────────────────────────────────────
// 02 — Pipeline
// ─────────────────────────────────────────────────────────────
function Pipeline() {
  const t = useTime();
  const stages = [
  { x: 10, label: 'INTAKE', desc: 'webhook' },
  { x: 30, label: 'PARSE', desc: 'gpt-4o' },
  { x: 50, label: 'ENRICH', desc: 'crm-api' },
  { x: 70, label: 'ROUTE', desc: 'agent-mux' },
  { x: 90, label: 'OUT', desc: 'telegram' }];

  const tracks = [30, 46, 62];
  return (
    <Stage tag="pipeline_004"
    footL={<span>{(1240 + Math.floor(Math.sin(t * 0.7) * 80)).toLocaleString()} items/min</span>}
    footR={<span>latency · {120 + Math.floor(Math.sin(t * 1.4) * 30)}ms</span>}>
      <svg viewBox="0 0 100 100" preserveAspectRatio="xMidYMid meet" style={{ width: '96%', height: '96%' }}>
        <defs>
          <linearGradient id="flow-grad" x1="0" y1="0" x2="1" y2="0">
            <stop offset="0%" stopColor="#6366f1" /><stop offset="50%" stopColor="#ec4899" /><stop offset="100%" stopColor="#f59e0b" />
          </linearGradient>
        </defs>
        {tracks.map((y) =>
        <line key={y} x1="6" y1={y} x2="94" y2={y} stroke="rgba(250,250,247,0.08)" strokeWidth="0.18" strokeDasharray="0.4 1.0" />
        )}
        {stages.map((s) =>
        <g key={s.label}>
            <line x1={s.x} y1={22} x2={s.x} y2={70} stroke="rgba(250,250,247,0.18)" strokeWidth="0.22" />
            <text x={s.x} y="18" fontSize="2.4" textAnchor="middle" fill="rgba(250,250,247,0.62)" fontFamily="'JetBrains Mono', monospace" letterSpacing="0.12em">{s.label}</text>
            <text x={s.x} y="76" fontSize="1.8" textAnchor="middle" fill="rgba(250,250,247,0.4)" fontFamily="'JetBrains Mono', monospace" letterSpacing="0.06em">{s.desc}</text>
          </g>
        )}
        <path d="M 4 46 L 96 46" stroke="url(#flow-grad)" strokeWidth="0.14" opacity="0.4" />
        {Array.from({ length: 14 }, (_, idx) => {
          const speed = 6 + idx % 5 * 1.2;
          const phase = (t * speed + idx * 9) % 110 - 10;
          const y = tracks[idx % tracks.length];
          if (phase < 4 || phase > 94) return null;
          const inStage = stages.findIndex((s) => Math.abs(phase - s.x) < 4) >= 0;
          return (
            <g key={idx}>
              {inStage && <rect x={phase - 3} y={y - 3} width="6" height="6" fill="rgba(236,72,153,0.16)" />}
              <rect x={phase - 1.1} y={y - 1.1} width="2.2" height="2.2" fill="#fafaf7" />
              <rect x={phase - 4.4} y={y - 0.7} width="1.4" height="1.4" fill="rgba(250,250,247,0.32)" />
              <rect x={phase - 7.7} y={y - 0.5} width="1" height="1" fill="rgba(250,250,247,0.12)" />
            </g>);

        })}
        <g transform="translate(50 88)">
          <rect x="-22" y="-2" width="44" height="4" rx="2" fill="none" stroke="rgba(250,250,247,0.18)" strokeWidth="0.2" />
          <rect x="-22" y="-2" width={44 * (0.6 + 0.3 * Math.sin(t * 0.8))} height="4" rx="2" fill="url(#flow-grad)" opacity="0.85" />
        </g>
      </svg>
    </Stage>);

}

// ─────────────────────────────────────────────────────────────
// 03 — Vault
// ─────────────────────────────────────────────────────────────
function Vault() {
  const t = useTime();
  return (
    <Stage tag="air_gapped"
    footL={<span>qwen-3 · llama-3.3 · deepseek-r1</span>}
    footR={<span>2× a100 · soc-2</span>}>
      <svg viewBox="0 0 100 100" preserveAspectRatio="xMidYMid meet" style={{ width: '94%', height: '94%' }}>
        <defs>
          <linearGradient id="rackTop" x1="0" y1="0" x2="0" y2="1">
            <stop offset="0%" stopColor="rgba(250,250,247,0.18)" /><stop offset="100%" stopColor="rgba(250,250,247,0.04)" />
          </linearGradient>
          <linearGradient id="rackFront" x1="0" y1="0" x2="0" y2="1">
            <stop offset="0%" stopColor="rgba(250,250,247,0.10)" /><stop offset="100%" stopColor="rgba(0,0,0,0.6)" />
          </linearGradient>
        </defs>
        <ellipse cx="50" cy="86" rx="34" ry="2.6" fill="rgba(99,102,241,0.18)" />
        {[0, 1, 2, 3].map((i) => {
          const y = 76 - i * 12;
          return (
            <g key={i}>
              <path d={`M 30 ${y} L 50 ${y - 5} L 70 ${y} L 50 ${y + 5} Z`}
              fill="url(#rackTop)" stroke="rgba(250,250,247,0.5)" strokeWidth="0.22" />
              <path d={`M 30 ${y} L 50 ${y + 5} L 50 ${y + 10} L 30 ${y + 5} Z`}
              fill="url(#rackFront)" stroke="rgba(250,250,247,0.42)" strokeWidth="0.22" />
              <path d={`M 50 ${y + 5} L 70 ${y} L 70 ${y + 5} L 50 ${y + 10} Z`}
              fill="rgba(0,0,0,0.55)" stroke="rgba(250,250,247,0.42)" strokeWidth="0.22" />
              {[0, 1, 2, 3, 4].map((k) => {
                const phase = (t * 1.6 + i * 0.3 + k * 0.15) % 5;
                const lit = phase < 4.4;
                return (
                  <circle key={k} cx={34 + k * 3.6} cy={y + 7.2} r="0.55"
                  fill={lit ? '#4ade80' : 'rgba(74,222,128,0.18)'} />);

              })}
            </g>);

        })}
        <g transform="translate(50 22)">
          <rect x="-16" y="-7" width="32" height="11" rx="5.5" fill="rgba(0,0,0,0.85)" stroke="rgba(250,250,247,0.4)" strokeWidth="0.22" />
          <circle cx="-9" cy="-1.5" r="1.2" fill="#4ade80" />
          <text x="-3" y="1.2" fontSize="3.2" fill="#fafaf7" fontFamily="'JetBrains Mono', monospace" letterSpacing="0.14em">AIR-GAPPED</text>
        </g>
        {[0, 1, 2].map((i) =>
        <ellipse key={i} cx="50" cy="22" rx={18 + i * 6 + Math.sin(t * 1.5 + i) * 1.5}
        ry={5 + i * 1.5 + Math.sin(t * 1.5 + i) * 0.5}
        fill="none" stroke="rgba(99,102,241,0.18)" strokeWidth="0.18"
        opacity={0.7 - i * 0.2} />
        )}
      </svg>
    </Stage>);

}

// ─────────────────────────────────────────────────────────────
// 04 — Telegram bot conversation
// ─────────────────────────────────────────────────────────────
function TelegramMock() {
  const [step, setStep] = React.useState(0);
  React.useEffect(() => {
    const id = setInterval(() => setStep((s) => (s + 1) % 7), 1600);
    return () => clearInterval(id);
  }, []);
  const lines = [
  { side: 'in', text: 'Could you book me a haircut tomorrow evening?', time: '14:02' },
  { side: 'out', tools: ['catalog.barbers', 'schedule.find_slots'] },
  { side: 'out', text: 'Slots open tomorrow evening:\n· 6:00pm — Artem\n· 7:30pm — Mike\n· 8:30pm — Dennis\n\nWhich barber?', time: '14:02' },
  { side: 'in', text: 'Mike at 7:30pm', time: '14:03' },
  { side: 'out', tools: ['booking.create', 'sms.send'] },
  { side: 'out', text: 'Booked. Mike · tomorrow 7:30pm · 60 min.\n$32 · pay on arrival.\n\nSend a reminder 2h before?', time: '14:03', actions: ['Yes, remind me', 'No thanks'] },
  { side: 'in', text: 'Yes', time: '14:04', tail: 'seen' }];

  const visible = lines.slice(0, step + 1);
  const isTyping = step < 6;

  return (
    <Stage tag="telegram_bot"
    footL={<span>resolved · 96%</span>}
    footR={<span>avg · 28s · barbershop</span>}>
      <div style={{
        width: 'min(320px, 92%)', aspectRatio: '9 / 16',
        background: '#000', borderRadius: 30,
        border: '7px solid #0f0f0f',
        boxShadow: '0 30px 80px rgba(0,0,0,0.55), 0 0 0 1px rgba(250,250,247,0.06), inset 0 0 0 1px rgba(250,250,247,0.05)',
        display: 'flex', flexDirection: 'column', overflow: 'hidden',
        position: 'relative'
      }}>
        {/* Dynamic island */}
        <div style={{
          position: 'absolute', top: 8, left: '50%', transform: 'translateX(-50%)',
          width: 80, height: 22, borderRadius: 14, background: '#000', zIndex: 5
        }} />
        <div style={{
          padding: '32px 14px 10px',
          background: '#17212b',
          borderBottom: '1px solid rgba(250,250,247,0.04)',
          display: 'flex', alignItems: 'center', gap: 10
        }}>
          <div style={{
            width: 28, height: 28, borderRadius: 14,
            background: 'linear-gradient(135deg, #6366f1, #ec4899)',
            display: 'flex', alignItems: 'center', justifyContent: 'center',
            color: 'white', fontFamily: 'var(--font-display)', fontWeight: 800, fontSize: 13
          }}>A</div>
          <div style={{ flex: 1, minWidth: 0 }}>
            <div style={{ fontSize: 12, fontWeight: 500, color: '#fff', fontFamily: 'var(--font-body)' }}>Barbershop · bot</div>
            <div style={{ fontSize: 9, color: '#10b981', fontFamily: 'var(--font-mono)', letterSpacing: 0.5, textTransform: 'uppercase' }}>
              <span style={{ display: 'inline-block', width: 5, height: 5, borderRadius: 3, background: '#10b981', marginRight: 4, verticalAlign: 1 }} />
              online
            </div>
          </div>
        </div>
        <div style={{
          flex: 1, padding: '10px 10px 6px',
          background: '#0e1621',
          display: 'flex', flexDirection: 'column', gap: 5,
          overflow: 'hidden'
        }}>
          {visible.map((m, i) => {
            if (m.tools) {
              return (
                <div key={i} style={{
                  alignSelf: 'flex-end', maxWidth: '88%',
                  background: 'rgba(58, 135, 236, 0.12)',
                  border: '1px solid rgba(58, 135, 236, 0.25)',
                  borderRadius: 6, padding: '5px 8px',
                  fontFamily: 'var(--font-mono)', fontSize: 9,
                  color: 'rgba(255,255,255,0.7)', letterSpacing: 0.2
                }}>
                  {m.tools.map((tl, k) =>
                  <div key={k}><span style={{ color: '#60a5fa' }}>↳</span>{' '}{tl}</div>
                  )}
                </div>);

            }
            const isOut = m.side === 'out';
            return (
              <div key={i} style={{
                alignSelf: isOut ? 'flex-end' : 'flex-start',
                maxWidth: '82%',
                background: isOut ? '#2b5278' : '#182533',
                color: '#fff',
                padding: '6px 9px', borderRadius: 8,
                borderBottomRightRadius: isOut ? 3 : 8,
                borderBottomLeftRadius: isOut ? 8 : 3,
                fontSize: 11, lineHeight: 1.35, whiteSpace: 'pre-wrap',
                fontFamily: 'var(--font-body)'
              }}>
                {m.text}
                {m.actions &&
                <div style={{ marginTop: 6, display: 'flex', flexDirection: 'column', gap: 3 }}>
                    {m.actions.map((a, k) =>
                  <div key={k} style={{
                    padding: '5px 8px', background: 'rgba(255,255,255,0.08)',
                    borderRadius: 5, fontSize: 10, textAlign: 'center'
                  }}>{a}</div>
                  )}
                  </div>
                }
                <div style={{ fontSize: 8, opacity: 0.55, marginTop: 3, textAlign: 'right' }}>
                  {m.time}{m.tail === 'seen' && ' ✓✓'}
                </div>
              </div>);

          })}
          {isTyping &&
          <div className="typing" style={{ padding: '6px 9px', alignSelf: 'flex-start', background: '#182533', borderRadius: 8, borderBottomLeftRadius: 3 }}>
              <span /><span /><span />
            </div>
          }
        </div>
        <div style={{
          padding: 8, display: 'flex', gap: 6, alignItems: 'center',
          background: '#17212b', borderTop: '1px solid rgba(255,255,255,0.04)'
        }}>
          <div style={{ flex: 1, height: 22, borderRadius: 12, background: '#242f3d', fontSize: 10.5, color: 'rgba(255,255,255,0.4)', display: 'flex', alignItems: 'center', padding: '0 10px', fontFamily: 'var(--font-body)' }}>Message</div>
        </div>
      </div>
    </Stage>);

}

// ─────────────────────────────────────────────────────────────
// 05 — Fashion Mini App (showcase)
// Animated phone: TG chat → tap "Open store" → mini app slides up → app cycles
// Three distinct sneaker silhouettes drawn inline.
// ─────────────────────────────────────────────────────────────
const APP_PRODUCTS = [
  { id: 'nimbus',   name: 'Nimbus Lo',  sub: 'Lunar White', price: '$189', body: '#ede9df', accent: '#0a0a0a', colors: ['#ede9df','#0a0a0a','#3b3b3b','#d4a273'], model: 'nimbus' },
  { id: 'volta',    name: 'Volta 3',    sub: 'Carbon Mesh', price: '$224', body: '#141414', accent: '#ec4899', colors: ['#141414','#fafaf7','#5a4632','#3a4a55'], model: 'volta' },
  { id: 'meridian', name: 'Meridian',   sub: 'Bone Leather', price: '$156', body: '#d8d3c5', accent: '#0a0a0a', colors: ['#d8d3c5','#0a0a0a','#a0826d','#2e3a45'], model: 'meridian' },
];

// ── Sneaker silhouettes ──────────────────────────────────────
function SneakerNimbus({ body, accent }) {
  return (
    <svg viewBox="0 0 220 110" preserveAspectRatio="xMidYMid meet" style={{ width: '94%', filter: 'drop-shadow(0 12px 14px rgba(0,0,0,0.55))' }}>
      <defs>
        <linearGradient id="nb-body" x1="0" y1="0" x2="0" y2="1">
          <stop offset="0%" stopColor={body} stopOpacity="1"/>
          <stop offset="60%" stopColor={body} stopOpacity="0.92"/>
          <stop offset="100%" stopColor={body} stopOpacity="0.65"/>
        </linearGradient>
        <linearGradient id="nb-sole" x1="0" y1="0" x2="0" y2="1">
          <stop offset="0%" stopColor="#ffffff" stopOpacity="0.95"/>
          <stop offset="100%" stopColor="#b5b3ac" stopOpacity="1"/>
        </linearGradient>
      </defs>
      {/* Upper body */}
      <path d="M 14 80 Q 14 50 42 42 L 64 36 Q 90 30 116 36 L 152 46 Q 180 52 196 60 L 200 70 L 200 84 L 14 84 Z"
            fill="url(#nb-body)" stroke="rgba(0,0,0,0.18)" strokeWidth="0.6"/>
      {/* Heel counter */}
      <path d="M 154 52 L 162 30 Q 174 26 188 30 L 200 56 L 200 70 L 156 70 Z"
            fill={body} stroke="rgba(0,0,0,0.18)" strokeWidth="0.5" opacity="0.95"/>
      {/* Toe cap */}
      <path d="M 14 80 Q 14 64 28 60 L 50 60 L 56 82 L 14 82 Z"
            fill={body} stroke="rgba(0,0,0,0.12)" strokeWidth="0.4" opacity="0.7"/>
      {/* Tongue */}
      <path d="M 60 42 Q 64 22 86 22 L 110 24 Q 120 30 120 44 L 116 52 Q 92 52 64 52 Z"
            fill={body} stroke="rgba(0,0,0,0.14)" strokeWidth="0.4"/>
      {/* Tongue label */}
      <rect x="82" y="30" width="22" height="9" rx="1.5" fill={accent}/>
      <text x="93" y="36.5" fontSize="4.2" fill={body} textAnchor="middle" fontFamily="'JetBrains Mono', monospace" fontWeight="700" letterSpacing="0.06em">NORM</text>
      {/* Side swoosh */}
      <path d="M 36 76 Q 88 56 158 64 L 162 70 Q 92 70 38 80 Z"
            fill={accent} opacity="0.94"/>
      {/* Lace eyelets + Xs */}
      {[0,1,2,3].map(i => (
        <g key={i}>
          <line x1={68 + i*11} y1="32" x2={78 + i*11} y2="44" stroke="rgba(0,0,0,0.45)" strokeWidth="1"/>
          <line x1={78 + i*11} y1="32" x2={68 + i*11} y2="44" stroke="rgba(0,0,0,0.45)" strokeWidth="1"/>
          <circle cx={68 + i*11} cy="32" r="1.1" fill={accent}/>
          <circle cx={78 + i*11} cy="32" r="1.1" fill={accent}/>
        </g>
      ))}
      {/* Sole */}
      <path d="M 8 84 Q 6 96 18 100 L 196 100 Q 208 96 204 84 L 8 84 Z"
            fill="url(#nb-sole)" stroke="rgba(0,0,0,0.25)" strokeWidth="0.5"/>
      {/* Sole tread */}
      {[18, 44, 70, 96, 122, 148, 174, 196].map(x => (
        <line key={x} x1={x} y1="88" x2={x} y2="98" stroke="rgba(0,0,0,0.22)" strokeWidth="0.7"/>
      ))}
      {/* Perforations */}
      {[0,1,2,3].map(i => (
        <circle key={i} cx={36 + i*7} cy={68} r="0.9" fill="rgba(0,0,0,0.42)"/>
      ))}
      {/* Stitching */}
      <path d="M 14 78 Q 80 70 200 76" stroke="rgba(0,0,0,0.2)" strokeWidth="0.3" strokeDasharray="1.2 1.2" fill="none"/>
    </svg>
  );
}

function SneakerVolta({ body, accent }) {
  return (
    <svg viewBox="0 0 220 110" preserveAspectRatio="xMidYMid meet" style={{ width: '94%', filter: 'drop-shadow(0 12px 14px rgba(0,0,0,0.55))' }}>
      <defs>
        <linearGradient id="vt-body" x1="0" y1="0" x2="0" y2="1">
          <stop offset="0%" stopColor={body} stopOpacity="1"/>
          <stop offset="50%" stopColor={body} stopOpacity="0.85"/>
          <stop offset="100%" stopColor="#000" stopOpacity="0.95"/>
        </linearGradient>
        <radialGradient id="vt-air" cx="50%" cy="50%" r="50%">
          <stop offset="0%" stopColor="#ffffff" stopOpacity="0.35"/>
          <stop offset="100%" stopColor="#ffffff" stopOpacity="0"/>
        </radialGradient>
      </defs>
      {/* Sleek runner upper */}
      <path d="M 14 78 Q 16 50 50 44 L 78 38 Q 110 32 142 40 L 174 50 Q 196 56 204 66 L 204 78 L 14 78 Z"
            fill="url(#vt-body)" stroke={accent} strokeWidth="0.4" opacity="0.95"/>
      {/* Mesh panel */}
      <path d="M 50 60 Q 80 54 134 58 L 144 70 Q 96 72 50 72 Z"
            fill="rgba(255,255,255,0.06)" stroke="rgba(255,255,255,0.18)" strokeWidth="0.3"/>
      {/* Mesh dots */}
      {Array.from({length: 22}, (_, i) => (
        <circle key={i} cx={56 + (i % 11) * 8} cy={61 + Math.floor(i/11) * 6} r="0.5"
                fill="rgba(255,255,255,0.4)"/>
      ))}
      {/* Heel tab */}
      <path d="M 180 50 Q 196 44 206 50 L 206 68 L 184 68 Z"
            fill="#0a0a0a" stroke={accent} strokeWidth="0.4"/>
      <text x="194" y="62" fontSize="3.6" fill={accent} textAnchor="middle" fontFamily="'JetBrains Mono', monospace" fontWeight="700">V3</text>
      {/* Bold side stripe */}
      <path d="M 26 70 Q 78 50 152 56 L 158 62 Q 90 62 30 76 Z"
            fill={accent} opacity="0.92"/>
      {/* Brand check */}
      <path d="M 70 56 L 76 62 L 102 50" stroke="#fafaf7" strokeWidth="2" fill="none" strokeLinecap="round" strokeLinejoin="round" opacity="0.9"/>
      {/* Laces — flat black */}
      {[0,1,2].map(i => (
        <line key={i} x1={64 + i*14} y1="34" x2={82 + i*14} y2="46"
              stroke="#fafaf7" strokeWidth="1.2" opacity="0.8"/>
      ))}
      {/* Visible air-cushion midsole */}
      <path d="M 8 78 L 212 78 L 208 88 Q 196 92 16 92 Q 4 88 8 78 Z"
            fill="#0a0a0a" stroke={accent} strokeWidth="0.4"/>
      <ellipse cx="60" cy="85" rx="22" ry="2.5" fill="url(#vt-air)"/>
      <ellipse cx="140" cy="85" rx="32" ry="3" fill="url(#vt-air)"/>
      {/* Outsole */}
      <path d="M 12 92 Q 8 102 22 102 L 198 102 Q 214 100 208 92 L 12 92 Z"
            fill="#1a1a1a" stroke="rgba(255,255,255,0.1)" strokeWidth="0.3"/>
      {/* Tread chevrons */}
      {[24, 48, 72, 96, 120, 144, 168, 192].map(x => (
        <path key={x} d={`M ${x} 95 L ${x+4} 100 L ${x+8} 95`}
              stroke={accent} strokeWidth="0.8" fill="none" opacity="0.6"/>
      ))}
    </svg>
  );
}

function SneakerMeridian({ body, accent }) {
  return (
    <svg viewBox="0 0 220 110" preserveAspectRatio="xMidYMid meet" style={{ width: '94%', filter: 'drop-shadow(0 12px 14px rgba(0,0,0,0.55))' }}>
      <defs>
        <linearGradient id="md-body" x1="0" y1="0" x2="0" y2="1">
          <stop offset="0%" stopColor={body} stopOpacity="1"/>
          <stop offset="100%" stopColor={body} stopOpacity="0.78"/>
        </linearGradient>
      </defs>
      {/* Clean minimal upper */}
      <path d="M 18 82 Q 18 50 46 44 L 76 38 Q 108 34 138 40 L 168 48 Q 188 54 196 64 L 196 84 L 18 84 Z"
            fill="url(#md-body)" stroke="rgba(0,0,0,0.14)" strokeWidth="0.5"/>
      {/* Heel patch */}
      <path d="M 154 58 L 170 36 Q 184 32 192 40 L 196 60 L 196 70 L 156 70 Z"
            fill={accent} opacity="0.92"/>
      <text x="178" y="56" fontSize="4" fill={body} textAnchor="middle" fontFamily="'JetBrains Mono', monospace" fontWeight="700">M·</text>
      {/* Tongue */}
      <path d="M 64 46 Q 68 26 88 26 L 110 28 Q 120 34 120 46 L 116 54 Q 92 54 66 54 Z"
            fill={body} stroke="rgba(0,0,0,0.1)" strokeWidth="0.3" opacity="0.96"/>
      {/* Three perforation rows */}
      {[0,1,2].map(row => (
        Array.from({length: 5}, (_, i) => (
          <circle key={`p-${row}-${i}`}
                  cx={56 + i * 12 + row * 3}
                  cy={62 + row * 5}
                  r="0.9"
                  fill="rgba(0,0,0,0.42)"/>
        ))
      ))}
      {/* Slim brand stripe */}
      <line x1="38" y1="76" x2="160" y2="74" stroke={accent} strokeWidth="2.5" strokeLinecap="round" opacity="0.55"/>
      {/* Laces */}
      {[0,1,2,3].map(i => (
        <g key={i}>
          <line x1={70 + i*11} y1="34" x2={82 + i*11} y2="46" stroke="rgba(0,0,0,0.5)" strokeWidth="0.9"/>
          <circle cx={70 + i*11} cy="34" r="1" fill="rgba(0,0,0,0.7)"/>
          <circle cx={82 + i*11} cy="34" r="1" fill="rgba(0,0,0,0.7)"/>
        </g>
      ))}
      {/* Thin sole */}
      <path d="M 12 84 Q 10 94 20 96 L 196 96 Q 206 94 200 84 L 12 84 Z"
            fill="#fafaf7" stroke="rgba(0,0,0,0.2)" strokeWidth="0.4"/>
      <line x1="14" y1="89" x2="200" y2="89" stroke="rgba(0,0,0,0.18)" strokeWidth="0.3"/>
    </svg>
  );
}

function SneakerSVG({ model, body, accent }) {
  if (model === 'volta') return <SneakerVolta body={body} accent={accent} />;
  if (model === 'meridian') return <SneakerMeridian body={body} accent={accent} />;
  return <SneakerNimbus body={body} accent={accent} />;
}

// ── Easing ───────────────────────────────────────────────────
const easeOutCubic = (x) => 1 - Math.pow(1 - x, 3);
const easeInCubic = (x) => x * x * x;

function FashionMiniApp() {
  const t = useTime();
  const CYCLE = 12.5;
  const phase = t % CYCLE;

  // Phase machine
  // 0.0–1.8s: TG chat shown, idle (with last "Open store" button visible, slightly pulsing)
  // 1.8–2.3s: button tap effect (ripple)
  // 2.3–3.2s: app slides up (translateY 100% → 0%)
  // 3.2–10.0s: app fully visible, products cycle every ~2.0s
  // 10.0–11.0s: app slides down
  // 11.0–12.5s: settle on TG chat, loop
  let appProgress = 0;     // 0..1
  let buttonScale = 1;
  let rippleProgress = 0;  // 0..1

  if (phase < 1.8) {
    appProgress = 0;
    buttonScale = 1 + 0.04 * Math.sin(t * 5);
  } else if (phase < 2.3) {
    const lp = (phase - 1.8) / 0.5;
    buttonScale = 1 - 0.08 * Math.sin(lp * Math.PI);
    rippleProgress = lp;
    appProgress = 0;
  } else if (phase < 3.2) {
    appProgress = easeOutCubic((phase - 2.3) / 0.9);
    rippleProgress = 1;
  } else if (phase < 10.0) {
    appProgress = 1;
  } else if (phase < 11.0) {
    appProgress = 1 - easeInCubic((phase - 10.0) / 1.0);
  } else {
    appProgress = 0;
  }

  // Active product (during full-app phase)
  const appT = Math.max(0, phase - 3.2);
  const productIdx = Math.floor(appT / 2.0) % APP_PRODUCTS.length;
  const product = APP_PRODUCTS[productIdx];

  // Annotations only when app is fully open
  const annoActive = appProgress > 0.95;
  const annotations = [
    { label: 'catalog.grid(2)', side: 'left',  yPct: 14, targetXPct: 50, targetYPct: 30 },
    { label: 'motion.spring(0.42,0.8)', side: 'right', yPct: 36, targetXPct: 50, targetYPct: 78 },
    { label: 'tg.stars.pay()', side: 'right', yPct: 62, targetXPct: 50, targetYPct: 86 },
    { label: 'size.recommend(profile)', side: 'left', yPct: 56, targetXPct: 50, targetYPct: 60 },
  ];
  const annoIdx = annoActive ? Math.floor(appT * 0.62) % annotations.length : -1;
  const active = annotations[annoIdx >= 0 ? annoIdx : 0];

  // Status label shown at bottom
  const stateLabel = phase < 1.8 ? 'chat · idle'
    : phase < 2.3 ? 'webapp.launch()'
    : phase < 3.2 ? 'unfolding ↑'
    : phase < 10.0 ? `screen · ${String(productIdx + 1).padStart(2,'0')}/${APP_PRODUCTS.length} · ${product.id}`
    : 'closing ↓';

  return (
    <Stage tag="mini_app · norm"
           footL={<span>{stateLabel}</span>}
           footR={<span>react · ton · stars</span>}>
      <div style={{ position: 'relative', width: '100%', height: '100%', minHeight: 540, display: 'flex', alignItems: 'center', justifyContent: 'center' }}>

        {/* Annotation layer */}
        <svg viewBox="0 0 100 100" preserveAspectRatio="none"
             style={{ position: 'absolute', inset: 0, width: '100%', height: '100%', pointerEvents: 'none', zIndex: 1,
                      opacity: annoActive ? 1 : 0, transition: 'opacity 400ms' }}>
          <path
            key={'line-' + annoIdx}
            d={active.side === 'left'
              ? `M 12 ${active.yPct} L 30 ${active.yPct} L ${active.targetXPct} ${active.targetYPct}`
              : `M 88 ${active.yPct} L 70 ${active.yPct} L ${active.targetXPct} ${active.targetYPct}`}
            stroke="rgba(250,250,247,0.55)" strokeWidth="0.18" strokeDasharray="0.6 0.8" fill="none"
            style={{ animation: 'line-in 600ms ease-out' }} />
          <circle cx={active.targetXPct} cy={active.targetYPct} r="2"
                  fill="none" stroke="#ec4899" strokeWidth="0.25" opacity="0.9" />
          <circle cx={active.targetXPct} cy={active.targetYPct} r={3 + (t % 1) * 4}
                  fill="none" stroke="#ec4899" strokeWidth="0.18" opacity={1 - (t % 1)} />
        </svg>

        {annotations.map((a, i) => {
          const isActive = i === annoIdx && annoActive;
          return (
            <div key={a.label} style={{
              position: 'absolute',
              [a.side]: 6,
              top: a.yPct + '%',
              fontFamily: 'var(--font-mono)',
              fontSize: 11,
              letterSpacing: '0.04em',
              padding: '7px 11px',
              borderRadius: 999,
              background: isActive ? 'rgba(15, 15, 15, 0.95)' : 'rgba(15, 15, 15, 0.4)',
              border: '1px solid ' + (isActive ? 'rgba(250,250,247,0.32)' : 'rgba(250,250,247,0.08)'),
              color: isActive ? 'var(--fg)' : 'rgba(250,250,247,0.3)',
              transition: 'background 320ms, border-color 320ms, color 320ms, transform 320ms, opacity 320ms',
              transform: 'translateY(-50%) translateX(' + (isActive ? '0' : a.side === 'left' ? '-3px' : '3px') + ')',
              opacity: annoActive ? 1 : 0,
              zIndex: 3,
              whiteSpace: 'nowrap',
              display: 'inline-flex', alignItems: 'center', gap: 6,
            }}>
              <span style={{ color: isActive ? '#ec4899' : 'rgba(236,72,153,0.35)' }}>✦</span>
              {a.label}
            </div>
          );
        })}

        {/* Phone */}
        <div style={{
          position: 'relative',
          width: 'min(284px, 60%)', aspectRatio: '9 / 17',
          background: '#000', borderRadius: 36,
          border: '8px solid #0c0c0c',
          boxShadow: '0 40px 100px rgba(0,0,0,0.6), 0 0 0 1px rgba(250,250,247,0.06), inset 0 0 0 1px rgba(250,250,247,0.05)',
          overflow: 'hidden', zIndex: 2,
        }}>
          {/* Dynamic island */}
          <div style={{
            position: 'absolute', top: 10, left: '50%', transform: 'translateX(-50%)',
            width: 80, height: 22, borderRadius: 14, background: '#000', zIndex: 6,
          }} />

          {/* Status bar */}
          <div style={{
            display: 'flex', justifyContent: 'space-between', alignItems: 'center',
            padding: '12px 20px 0', fontFamily: 'var(--font-body)', fontSize: 11, fontWeight: 600,
            color: '#fff', position: 'relative', zIndex: 5,
          }}>
            <span>9:41</span><span style={{ width: 80 }} />
            <span style={{ display: 'flex', gap: 4, alignItems: 'center' }}>
              <svg viewBox="0 0 18 12" width="14" height="9"><path d="M1 9.5 L3 9.5 M5 7.5 L7 7.5 M9 5 L11 5 M13 2 L15 2" stroke="white" strokeWidth="1.5" /></svg>
            </span>
          </div>

          {/* ── TG chat layer ── */}
          <div style={{
            position: 'absolute', top: 40, left: 0, right: 0, bottom: 0,
            background: '#0e1621',
            display: 'flex', flexDirection: 'column',
            zIndex: 2,
          }}>
            {/* TG header */}
            <div style={{
              padding: '8px 14px', background: '#17212b',
              display: 'flex', alignItems: 'center', gap: 8,
              borderBottom: '1px solid rgba(255,255,255,0.04)',
            }}>
              <svg viewBox="0 0 10 10" width="9" height="9"><path d="M7 1 L3 5 L7 9" stroke="white" strokeWidth="1.3" fill="none" strokeLinecap="round" /></svg>
              <div style={{ width: 24, height: 24, borderRadius: 12, background: 'linear-gradient(135deg, #fafaf7, #d4d4d4)', display: 'flex', alignItems: 'center', justifyContent: 'center', color: '#0a0a0a', fontFamily: 'var(--font-display)', fontWeight: 800, fontSize: 10 }}>N</div>
              <div style={{ flex: 1 }}>
                <div style={{ fontSize: 11, fontWeight: 500, color: '#fff' }}>NORM∕ store</div>
                <div style={{ fontSize: 8.5, color: '#10b981', fontFamily: 'var(--font-mono)', letterSpacing: 0.4, textTransform: 'uppercase' }}>online</div>
              </div>
            </div>
            {/* Messages */}
            <div style={{ flex: 1, padding: '10px 10px 8px', display: 'flex', flexDirection: 'column', gap: 5, overflow: 'hidden' }}>
              <div style={{
                alignSelf: 'flex-end', maxWidth: '78%', background: '#2b5278',
                color: '#fff', padding: '6px 9px', borderRadius: 8, borderBottomRightRadius: 3,
                fontSize: 10.5, fontFamily: 'var(--font-body)', lineHeight: 1.35,
              }}>Looking for new low-tops<div style={{ fontSize: 7.5, opacity: 0.6, textAlign: 'right', marginTop: 3 }}>9:40 ✓✓</div></div>

              <div style={{
                alignSelf: 'flex-start', maxWidth: '84%', background: '#182533',
                color: '#fff', padding: '6px 9px', borderRadius: 8, borderBottomLeftRadius: 3,
                fontSize: 10.5, fontFamily: 'var(--font-body)', lineHeight: 1.35,
              }}>Got it. 47 fresh drops this week. Open the store — sizes match your profile.<div style={{ fontSize: 7.5, opacity: 0.55, textAlign: 'right', marginTop: 3 }}>9:41</div></div>

              {/* Tap-to-open button (TG inline keyboard style) */}
              <div style={{
                marginTop: 8,
                position: 'relative',
                padding: '10px 14px',
                background: 'linear-gradient(135deg, #6366f1, #ec4899, #f59e0b)',
                borderRadius: 8,
                fontFamily: 'var(--font-mono)',
                fontSize: 11,
                fontWeight: 600,
                color: '#fff',
                textAlign: 'center',
                letterSpacing: '0.06em',
                textTransform: 'uppercase',
                transform: `scale(${buttonScale})`,
                transformOrigin: 'center',
                transition: 'transform 120ms ease-out',
                overflow: 'hidden',
                boxShadow: phase < 1.8 ? '0 6px 18px rgba(236,72,153,0.32)' : 'none',
              }}>
                {/* Ripple */}
                {rippleProgress > 0 && rippleProgress < 1 && (
                  <span style={{
                    position: 'absolute', left: '50%', top: '50%',
                    width: rippleProgress * 200 + 'px', height: rippleProgress * 200 + 'px',
                    borderRadius: '50%',
                    background: 'rgba(255,255,255,' + (0.4 * (1 - rippleProgress)) + ')',
                    transform: 'translate(-50%, -50%)',
                    pointerEvents: 'none',
                  }}/>
                )}
                ▶ Open NORM∕ Store
              </div>
              <div style={{ textAlign: 'center', fontFamily: 'var(--font-mono)', fontSize: 8.5, color: 'rgba(255,255,255,0.35)', marginTop: 4, letterSpacing: 0.4 }}>powered by mini app · v3.2</div>
            </div>
            {/* TG input bar */}
            <div style={{
              padding: 7, display: 'flex', gap: 6, alignItems: 'center',
              background: '#17212b', borderTop: '1px solid rgba(255,255,255,0.04)',
            }}>
              <div style={{ flex: 1, height: 22, borderRadius: 12, background: '#242f3d',
                            fontSize: 10, color: 'rgba(255,255,255,0.4)',
                            display: 'flex', alignItems: 'center', padding: '0 10px',
                            fontFamily: 'var(--font-body)' }}>Message</div>
            </div>
          </div>

          {/* ── Mini App overlay (slides up over chat) ── */}
          <div style={{
            position: 'absolute', top: 40, left: 0, right: 0, bottom: 0,
            background: '#0a0a0a',
            padding: '14px 16px 16px',
            display: 'flex', flexDirection: 'column', gap: 12,
            color: '#fff',
            fontFamily: 'var(--font-body)',
            transform: `translateY(${(1 - appProgress) * 100}%)`,
            transition: 'transform 80ms linear',
            zIndex: 4,
            borderTopLeftRadius: 16, borderTopRightRadius: 16,
            boxShadow: appProgress < 1 ? '0 -20px 40px rgba(0,0,0,0.6)' : 'none',
          }}>
            {/* Drag handle on top edge (TG webapp style) */}
            <div style={{
              position: 'absolute', top: 6, left: '50%', transform: 'translateX(-50%)',
              width: 36, height: 4, borderRadius: 2, background: 'rgba(255,255,255,0.2)',
            }}/>

            {/* Top bar */}
            <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginTop: 6 }}>
              <div style={{ display: 'flex', alignItems: 'center', gap: 6 }}>
                <svg viewBox="0 0 10 10" width="9" height="9"><path d="M7 1 L3 5 L7 9" stroke="white" strokeWidth="1.3" fill="none" strokeLinecap="round" /></svg>
              </div>
              <div style={{ fontFamily: 'var(--font-display)', fontWeight: 800, letterSpacing: '0.05em', fontSize: 13 }}>NORM∕</div>
              <div style={{ display: 'flex', alignItems: 'center', gap: 4, fontFamily: 'var(--font-mono)', fontSize: 9, letterSpacing: '0.06em' }}>
                <span>BAG</span><span style={{
                  background: 'var(--fg)', color: 'var(--bg)', borderRadius: 999, padding: '1px 5px',
                  fontWeight: 600, fontSize: 8.5,
                }}>2</span>
              </div>
            </div>

            {/* Hero — sneaker silhouette */}
            <div key={'hero-' + product.id} style={{
              flex: '0 0 auto', height: 158, borderRadius: 14,
              background: 'radial-gradient(85% 80% at 50% 35%, #1a1a1a 0%, #050505 100%)',
              display: 'flex', alignItems: 'center', justifyContent: 'center',
              position: 'relative', overflow: 'hidden',
              animation: 'screen-in 460ms cubic-bezier(.2,.7,.3,1)',
            }}>
              <div style={{
                position: 'absolute', inset: '-10%',
                background: `radial-gradient(circle at 50% 60%, ${product.body}22 0%, transparent 60%)`,
              }}/>
              <SneakerSVG model={product.model} body={product.body} accent={product.accent} />
              <span style={{
                position: 'absolute', bottom: 8, left: 10,
                fontFamily: 'var(--font-mono)', fontSize: 8, letterSpacing: 0.6,
                color: 'rgba(255,255,255,0.45)', textTransform: 'uppercase',
              }}>{product.id} · 360°</span>
            </div>

            {/* Title + price */}
            <div key={'title-' + product.id} style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'flex-end', animation: 'screen-in 460ms cubic-bezier(.2,.7,.3,1) 80ms both' }}>
              <div>
                <div style={{ fontFamily: 'var(--font-mono)', fontSize: 9, letterSpacing: 0.6, color: 'rgba(255,255,255,0.5)', textTransform: 'uppercase' }}>SS-26 · DROP 04</div>
                <div style={{ fontFamily: 'var(--font-display)', fontWeight: 800, fontSize: 22, letterSpacing: '-0.03em', marginTop: 2 }}>{product.name}</div>
                <div style={{ fontFamily: 'var(--font-display)', fontWeight: 400, fontSize: 14, letterSpacing: '-0.02em', color: 'rgba(255,255,255,0.5)' }}>{product.sub}</div>
              </div>
              <div style={{ fontFamily: 'var(--font-display)', fontWeight: 700, fontSize: 22, letterSpacing: '-0.03em' }}>{product.price}</div>
            </div>

            {/* Color swatches */}
            <div style={{ display: 'flex', gap: 6, alignItems: 'center' }}>
              {product.colors.map((c, i) => (
                <div key={c + i} style={{
                  width: 22, height: 22, borderRadius: 11,
                  background: c,
                  border: '1px solid ' + (i === 0 ? 'rgba(255,255,255,0.6)' : 'rgba(255,255,255,0.15)'),
                  boxShadow: i === 0 ? '0 0 0 2px rgba(255,255,255,0.15)' : 'none',
                }}/>
              ))}
              <span style={{ marginLeft: 6, fontFamily: 'var(--font-mono)', fontSize: 9, color: 'rgba(255,255,255,0.5)' }}>4 colors</span>
            </div>

            {/* Size grid */}
            <div>
              <div style={{ display: 'flex', justifyContent: 'space-between', fontFamily: 'var(--font-mono)', fontSize: 9, letterSpacing: 0.4, color: 'rgba(255,255,255,0.5)', textTransform: 'uppercase', marginBottom: 6 }}>
                <span>US SIZE</span>
                <span style={{ color: '#ec4899' }}>● recommended 9.5</span>
              </div>
              <div style={{ display: 'grid', gridTemplateColumns: 'repeat(7, 1fr)', gap: 4 }}>
                {[7, 8, 9, '9.5', 10, 11, 12].map((sz, i) => (
                  <div key={sz} style={{
                    padding: '7px 0', textAlign: 'center',
                    borderRadius: 6, fontFamily: 'var(--font-mono)', fontSize: 10,
                    background: i === 3 ? 'var(--fg)' : 'rgba(255,255,255,0.05)',
                    color: i === 3 ? 'var(--bg)' : '#fff',
                    border: '1px solid ' + (i === 3 ? 'transparent' : 'rgba(255,255,255,0.08)'),
                    fontWeight: i === 3 ? 600 : 400,
                  }}>{sz}</div>
                ))}
              </div>
            </div>

            {/* CTA */}
            <div style={{
              marginTop: 'auto',
              padding: '13px 16px',
              borderRadius: 12,
              background: 'linear-gradient(135deg, #6366f1, #ec4899, #f59e0b)',
              color: '#fff',
              textAlign: 'center',
              fontFamily: 'var(--font-mono)',
              fontSize: 12,
              fontWeight: 600,
              letterSpacing: '0.08em',
              textTransform: 'uppercase',
              boxShadow: '0 14px 38px rgba(236,72,153,0.35)',
              display: 'flex', justifyContent: 'space-between', alignItems: 'center',
            }}>
              <span>Add to bag</span>
              <span>↗ {product.price}</span>
            </div>
            <div style={{ textAlign: 'center', fontFamily: 'var(--font-mono)', fontSize: 9, color: 'rgba(255,255,255,0.4)', letterSpacing: 0.5, marginTop: -4 }}>
              ★ Pay with Telegram Stars
            </div>
          </div>
        </div>
      </div>
      <style>{`
        @keyframes line-in {
          from { stroke-dashoffset: 30; opacity: 0; }
          to { stroke-dashoffset: 0; opacity: 1; }
        }
        @keyframes screen-in {
          from { opacity: 0; transform: translateY(8px); }
          to { opacity: 1; transform: translateY(0); }
        }
      `}</style>
    </Stage>
  );
}

window.ChapterIllustrations = { AgentGraph, Pipeline, Vault, TelegramMock, MiniAppScreens: FashionMiniApp };