// The reading flow: spread selection → voice → question → shuffle → cut → draw → interpret.

const { useState: useS2, useEffect: useE2, useRef: useR2, useMemo: useM2 } = React;

// ────────────────────────────────────────────────────────────────
// Reader Profile modal — full character bio
// ────────────────────────────────────────────────────────────────
function ReaderProfileModal({ voice, onClose, onChoose, isSelected }) {
  useE2(() => {
    const h = (e) => { if (e.key === 'Escape') { TTS.stopVoice(); onClose(); } };
    window.addEventListener('keydown', h);
    return () => { window.removeEventListener('keydown', h); TTS.stopVoice(); };
  }, []);

  const signatureCard = TAROT_DECK.find(c => c.id === voice.signatureCard);

  return (
    <div className="modal-backdrop" onClick={() => { TTS.stopVoice(); onClose(); }}>
      <div className="modal reader-profile" onClick={e => e.stopPropagation()}>
        <button className="modal-close" onClick={() => { TTS.stopVoice(); onClose(); }}>×</button>

        <div className="profile-left">
          <div className="voice-portrait" style={{width:'120px', height:'120px'}}>
            <Sigil name={voice.glyph} style={{width:'56px', height:'56px'}}/>
          </div>
          <VoicePreviewButton voice={voice}/>
          {signatureCard && (
            <div style={{marginTop:'1.5rem'}}>
              <div className="position-pill">Signature Card</div>
              <div style={{marginTop:'0.8rem'}}>
                <TarotCard card={signatureCard} flipped size=""/>
              </div>
            </div>
          )}
        </div>

        <div className="profile-right">
          <span className="eyebrow">{voice.epithet}</span>
          <h2 style={{marginTop:'0.6rem'}}>{voice.name}</h2>

          <div className="profile-quote">
            <span className="quote-mark">"</span>
            {voice.opening}
            <span className="quote-mark">"</span>
          </div>

          <p className="lead" style={{marginTop:'1.5rem'}}>{voice.bio}</p>

          <div className="profile-stats">
            <div className="profile-stat">
              <h4>Origin</h4>
              <p>{voice.origin}</p>
            </div>
            <div className="profile-stat">
              <h4>Style</h4>
              <p>{voice.style}</p>
            </div>
            <div className="profile-stat">
              <h4>Best for</h4>
              <p>{voice.bestFor}</p>
            </div>
          </div>

          <div style={{marginTop:'2rem', display:'flex', gap:'1rem', flexWrap:'wrap'}}>
            <button className="btn primary small" onClick={onChoose}>
              {isSelected ? 'Chosen ✓' : `Read with ${voice.name}`}
            </button>
            <button className="btn ghost small" onClick={() => { TTS.stopVoice(); onClose(); }}>
              Close
            </button>
          </div>
        </div>
      </div>
    </div>
  );
}

// ────────────────────────────────────────────────────────────────
// Voice preview button — small per-card play, uses ElevenLabs if available
// ────────────────────────────────────────────────────────────────
function VoicePreviewButton({ voice }) {
  const [playing, setPlaying] = useS2(false);
  const handle = async (e) => {
    e.stopPropagation();
    if (playing) {
      TTS.stopVoice();
      setPlaying(false);
      return;
    }
    setPlaying(true);
    try {
      await TTS.speakVoice(voice.preview || `Hello. I am ${voice.name}.`, voice);
    } catch (err) {
      console.warn('Voice preview failed:', err);
    } finally {
      setPlaying(false);
    }
  };
  return (
    <button className="voice-preview-btn"
            title={playing ? 'Stop' : 'Preview voice'}
            onClick={handle}>
      <Sigil name={playing ? 'pause' : 'play'}/>
    </button>
  );
}

// ────────────────────────────────────────────────────────────────
// SpreadDiagram — small SVG showing each spread's actual shape
// ────────────────────────────────────────────────────────────────
// viewBox 0 0 100 70. Rects use w=10 h=16 unless overridden.
const SPREAD_DIAGRAMS = {
  career: [ {x:12,y:27}, {x:30,y:27}, {x:48,y:27}, {x:66,y:27}, {x:84,y:27} ],
  three:  [ {x:24,y:27}, {x:48,y:27}, {x:72,y:27} ],
  celtic: [
    {x:39,y:27},                            // 1 heart
    {x:34,y:32, w:16, h:6, rotated:true},   // 2 crossing
    {x:39,y:50},                            // 3 foundation
    {x:21,y:27},                            // 4 receding
    {x:39, y:4},                            // 5 crown
    {x:57,y:27},                            // 6 coming
    {x:81,y:54},                            // 7 self (staff bottom)
    {x:81,y:38},                            // 8 room
    {x:81,y:21},                            // 9 hopes & fears
    {x:81, y:4},                            // 10 outcome (staff top)
  ],
  love: [
    {x:14,y:27},                            // 1 you (left)
    {x:74,y:27},                            // 2 them (right)
    {x:44, y:6},                            // 3 between (top center)
    {x:44,y:27},                            // 4 hinders (mid center)
    {x:44,y:48},                            // 5 deepens (bottom center)
  ],
  single: [ {x:44,y:18, w:14, h:34} ],
};
function SpreadDiagram({ spreadId }) {
  const cells = SPREAD_DIAGRAMS[spreadId] || SPREAD_DIAGRAMS.career;
  return (
    <svg viewBox="0 0 100 70" preserveAspectRatio="xMidYMid meet">
      {cells.map((c, i) => {
        const w = c.w ?? 10;
        const h = c.h ?? 16;
        return (
          <g key={i}>
            <rect x={c.x} y={c.y} width={w} height={h} rx="1.2"/>
            <rect className="inner" x={c.x + 1.5} y={c.y + 1.5} width={w - 3} height={h - 3} rx="0.6"/>
          </g>
        );
      })}
    </svg>
  );
}

// ────────────────────────────────────────────────────────────────
// Spread selection
// ────────────────────────────────────────────────────────────────
function SpreadsScreen({ onChooseSpread, voice, onChooseVoice }) {
  const [selected, setSelected] = useS2('career');
  const [profileVoice, setProfileVoice] = useS2(null);
  const spread = ALL_SPREADS.find(s => s.id === selected) || ALL_SPREADS[0];

  return (
    <div className="container">
      <div className="center">
        <span className="eyebrow">Begin a Reading</span>
        <h1 style={{marginTop:'1rem'}}>Choose Your Spread</h1>
        <p className="lead" style={{margin:'1.4rem auto', maxWidth:'620px'}}>
          The spread shapes the question. Begin with the one that calls — the others will keep.
        </p>
      </div>
      <Divider glyph="mark"/>

      <div style={{display:'grid', gridTemplateColumns:'repeat(auto-fit, minmax(260px, 1fr))', gap:'1.5rem', marginTop:'2rem'}}>
        {ALL_SPREADS.map(s => (
          <div key={s.id}
               className={`spread-card ${selected === s.id ? 'selected' : ''} ${!s.available ? 'disabled' : ''}`}
               onClick={() => s.available && setSelected(s.id)}>
            <div className="spread-card-diagram">
              <SpreadDiagram spreadId={s.id}/>
            </div>
            <div className="spread-tag">{s.tag}</div>
            <h3 style={{fontSize:'1.05rem'}}>{s.name}</h3>
            <p style={{fontSize:'0.95rem', color:'var(--ash)'}}>{s.blurb}</p>
            <div style={{fontFamily:'var(--font-display)', fontSize:'0.7rem', letterSpacing:'0.25em', color:'var(--gold-dim)'}}>
              {s.count} {s.count === 1 ? 'CARD' : 'CARDS'}
            </div>
          </div>
        ))}
      </div>

      <div className="spacer-lg"></div>
      <Divider glyph="sigil-mark"/>

      <div className="center" style={{marginTop:'2rem'}}>
        <span className="eyebrow">The Reader's Voice</span>
        <h2 style={{marginTop:'0.8rem'}}>Who will read for you?</h2>
        <p className="lead" style={{margin:'1rem auto 2rem', maxWidth:'560px', fontSize:'1.15rem'}}>
          Each voice carries the cards differently. Pick the one whose temperament suits the question.
        </p>
      </div>

      <div className="voice-grid">
        {VOICES.map(v => (
          <div key={v.id}
               className={`voice-card ${voice?.id === v.id ? 'active' : ''}`}
               onClick={() => onChooseVoice(v)}>
            <div className="voice-portrait"><Sigil name={v.glyph}/></div>
            <div className="voice-info">
              <div className="voice-name">{v.name}</div>
              <div className="voice-epithet">{v.epithet}</div>
              <div className="voice-trait">{v.trait}</div>
              <button className="voice-readmore"
                      onClick={(e) => { e.stopPropagation(); setProfileVoice(v); }}>
                Read profile →
              </button>
            </div>
            <VoicePreviewButton voice={v}/>
          </div>
        ))}
      </div>

      {profileVoice && <ReaderProfileModal voice={profileVoice}
                                            onClose={() => setProfileVoice(null)}
                                            onChoose={() => { onChooseVoice(profileVoice); setProfileVoice(null); }}
                                            isSelected={voice?.id === profileVoice.id}/>}

      <div className="spacer-lg"></div>

      <div className="center">
        <button className="btn primary" disabled={!spread.available}
                onClick={() => onChooseSpread(spread)}>
          Enter the Reading <Sigil name="chevron-right"/>
        </button>
        <p className="muted" style={{marginTop:'1rem', fontSize:'0.9rem', fontStyle:'italic'}}>
          {voice ? `Read by ${voice.name}` : 'Reader\'s voice not yet chosen'}
        </p>
      </div>
      <div className="spacer-lg"></div>
    </div>
  );
}

// ────────────────────────────────────────────────────────────────
// Reading flow — full session
// ────────────────────────────────────────────────────────────────
function ReadingScreen({ spread, voice, onComplete, onCancel }) {
  // phases: question | shuffle | cut | draw | reveal | interpret
  const [phase, setPhase] = useS2('question');
  const [question, setQuestion] = useS2('');
  const [draws, setDraws] = useS2([]);  // {cardId, reversed} for each position
  const [revealed, setRevealed] = useS2([]); // which positions revealed
  const [synthesis, setSynthesis] = useS2(null);
  const [loadingSynth, setLoadingSynth] = useS2(false);
  const [voicePlaying, setVoicePlaying] = useS2(false);

  const phases = ['Question', 'Shuffle', 'Cut', 'Draw', 'Reading'];
  const phaseIdx = { question:0, shuffle:1, cut:2, draw:3, reveal:3, interpret:4 }[phase];

  // ─── Phase: Question ───────────────────────────────────────
  if (phase === 'question') {
    return (
      <div className="container narrow">
        <PhaseRail steps={phases} current={phaseIdx}/>
        <div className="center">
          <span className="eyebrow">{spread.name}</span>
          <h1 style={{marginTop:'1rem'}}>What shall we ask?</h1>
          <p className="lead" style={{margin:'1.5rem auto', maxWidth:'560px'}}>
            Open questions read best. Begin with <em>"What…"</em> or <em>"How…"</em> rather than <em>"Will…"</em>.
          </p>
        </div>
        <div className="question-form">
          <textarea className="input"
                    placeholder="What is mine to do, here?"
                    value={question}
                    onChange={e => setQuestion(e.target.value)}
                    rows={3}
                    autoFocus/>
          <div style={{marginTop:'2rem', display:'flex', gap:'1rem', justifyContent:'center'}}>
            <button className="btn ghost" onClick={onCancel}>Back</button>
            <button className="btn primary"
                    disabled={question.trim().length < 4}
                    onClick={() => setPhase('shuffle')}>
              Hold the Question <Sigil name="chevron-right"/>
            </button>
          </div>
        </div>
        <div className="spacer-lg"></div>
      </div>
    );
  }

  // ─── Phase: Shuffle ────────────────────────────────────────
  if (phase === 'shuffle') {
    return <ShufflePhase phases={phases} phaseIdx={phaseIdx} question={question}
                         onDone={() => setPhase('cut')}/>;
  }

  // ─── Phase: Cut ────────────────────────────────────────────
  if (phase === 'cut') {
    return <CutPhase phases={phases} phaseIdx={phaseIdx} question={question}
                     onDone={() => {
                       // generate the draws now, locked in
                       const shuffled = [...TAROT_DECK].sort(() => Math.random() - 0.5);
                       const picks = shuffled.slice(0, spread.count).map(c => ({
                         cardId: c.id,
                         reversed: Math.random() < 0.5,
                       }));
                       setDraws(picks);
                       setPhase('reveal');
                     }}/>;
  }

  // ─── Phase: Reveal (laid out, click to flip each) ─────────
  if (phase === 'reveal' || phase === 'interpret') {
    return (
      <ReadingBoard
        spread={spread}
        question={question}
        voice={voice}
        draws={draws}
        revealed={revealed}
        setRevealed={setRevealed}
        synthesis={synthesis}
        setSynthesis={setSynthesis}
        loadingSynth={loadingSynth}
        setLoadingSynth={setLoadingSynth}
        voicePlaying={voicePlaying}
        setVoicePlaying={setVoicePlaying}
        phases={phases}
        phaseIdx={phaseIdx}
        phase={phase}
        setPhase={setPhase}
        onComplete={onComplete}
      />
    );
  }

  return null;
}

// ────────────────────────────────────────────────────────────────
// Shuffle phase
// ────────────────────────────────────────────────────────────────
function ShufflePhase({ phases, phaseIdx, question, onDone }) {
  const [shuffling, setShuffling] = useS2(true);
  const [shuffles, setShuffles] = useS2(0);

  useE2(() => {
    if (!shuffling) return;
    const i = setInterval(() => setShuffles(s => s + 1), 1400);
    return () => clearInterval(i);
  }, [shuffling]);

  return (
    <div className="container narrow">
      <PhaseRail steps={phases} current={phaseIdx}/>
      <div className="center">
        <span className="eyebrow">Hold Your Question</span>
        <h2 style={{marginTop:'1rem'}}>The Deck is Shuffling</h2>
        <p className="lead" style={{margin:'1rem auto', maxWidth:'520px', fontStyle:'italic'}}>
          "{question}"
        </p>
      </div>

      <div style={{margin:'3rem auto', display:'flex', justifyContent:'center'}}>
        <div className={`deck ${shuffling ? 'shuffling' : ''}`}>
          {[0,1,2,3,4].map(i => (
            <div key={i} className="card" style={{
              animationDelay: `${i * 0.12}s`,
              zIndex: 5 - i,
              transform: shuffling ? undefined : `translate(${i * 1.5}px, ${i * 1.5}px)`
            }}>
              <div className="card-inner">
                <div className="card-face card-back"><Sigil name="sigil-mark" className="back-sigil"/></div>
              </div>
            </div>
          ))}
        </div>
      </div>

      <div className="center" style={{marginTop:'3rem'}}>
        <p className="muted" style={{fontStyle:'italic', marginBottom:'1.5rem'}}>
          {shuffles < 2 ? 'The cards are settling…' :
           shuffles < 4 ? 'They are listening for your question…' :
           'The deck is ready when you are.'}
        </p>
        <button className="btn primary" onClick={() => { setShuffling(false); setTimeout(onDone, 400); }}
                disabled={shuffles < 2}>
          The Deck is Ready <Sigil name="chevron-right"/>
        </button>
      </div>
      <div className="spacer-lg"></div>
    </div>
  );
}

// ────────────────────────────────────────────────────────────────
// Cut phase — drag a handle along a track
// ────────────────────────────────────────────────────────────────
function CutPhase({ phases, phaseIdx, question, onDone }) {
  const [pos, setPos] = useS2(0.5);
  const trackRef = useR2(null);
  const [dragging, setDragging] = useS2(false);
  const [cut, setCut] = useS2(false);

  const handleDown = (e) => {
    setDragging(true);
    e.preventDefault();
  };

  useE2(() => {
    if (!dragging) return;
    const move = (e) => {
      if (!trackRef.current) return;
      const r = trackRef.current.getBoundingClientRect();
      const x = (e.clientX ?? e.touches?.[0]?.clientX) - r.left;
      const p = Math.max(0, Math.min(1, x / r.width));
      setPos(p);
    };
    const up = () => setDragging(false);
    window.addEventListener('mousemove', move);
    window.addEventListener('mouseup', up);
    window.addEventListener('touchmove', move);
    window.addEventListener('touchend', up);
    return () => {
      window.removeEventListener('mousemove', move);
      window.removeEventListener('mouseup', up);
      window.removeEventListener('touchmove', move);
      window.removeEventListener('touchend', up);
    };
  }, [dragging]);

  // visualize: deck split at position
  const leftStack = Math.floor(pos * 12) + 1;
  const rightStack = 13 - leftStack;

  return (
    <div className="container narrow">
      <PhaseRail steps={phases} current={phaseIdx}/>
      <div className="center">
        <span className="eyebrow">Cut the Deck</span>
        <h2 style={{marginTop:'1rem'}}>Where shall we cut?</h2>
        <p className="lead" style={{margin:'1rem auto', maxWidth:'520px'}}>
          Drag the marker along the deck. Cut where your hand wants to stop.
        </p>
      </div>

      <div style={{margin:'3rem 0', display:'flex', justifyContent:'center', alignItems:'flex-end', gap:'12px', minHeight:'120px'}}>
        {/* Left stack */}
        <div style={{display:'flex', flexDirection:'column-reverse', gap:'-50px'}}>
          {Array.from({length: leftStack}, (_, i) => (
            <div key={i} style={{
              width:'140px', height:'8px',
              background: 'linear-gradient(180deg, var(--plum), var(--aubergine))',
              border:'1px solid var(--gold-dim)',
              borderRadius:'2px',
              marginTop:'-2px',
              boxShadow:'0 1px 0 var(--gold-faint) inset',
            }}/>
          ))}
        </div>
        <div style={{width:'30px', textAlign:'center', color:'var(--gold)', fontFamily:'var(--font-display)', letterSpacing:'0.3em', fontSize:'0.7rem'}}>
          <Sigil name="scissors"/>
        </div>
        {/* Right stack */}
        <div style={{display:'flex', flexDirection:'column-reverse', gap:'-50px'}}>
          {Array.from({length: rightStack}, (_, i) => (
            <div key={i} style={{
              width:'140px', height:'8px',
              background: 'linear-gradient(180deg, var(--plum), var(--aubergine))',
              border:'1px solid var(--gold-dim)',
              borderRadius:'2px',
              marginTop:'-2px',
              boxShadow:'0 1px 0 var(--gold-faint) inset',
            }}/>
          ))}
        </div>
      </div>

      <div className="cut-zone">
        <div className="cut-ticks">
          <span>· Top ·</span>
          <span>· Middle ·</span>
          <span>· Bottom ·</span>
        </div>
        <div ref={trackRef} className="cut-track" style={{position:'relative', height:'4px', cursor:'pointer'}}
             onMouseDown={(e) => {
               if (!trackRef.current) return;
               const r = trackRef.current.getBoundingClientRect();
               const p = Math.max(0, Math.min(1, (e.clientX - r.left) / r.width));
               setPos(p);
               setDragging(true);
             }}>
          <div className="cut-handle"
               style={{left: `${pos * 100}%`}}
               onMouseDown={handleDown}
               onTouchStart={handleDown}>
            <Sigil name="scissors"/>
          </div>
        </div>
      </div>

      <div className="center" style={{marginTop:'3rem'}}>
        <button className="btn primary" onClick={() => { setCut(true); setTimeout(onDone, 600); }}>
          Cut Here <Sigil name="chevron-right"/>
        </button>
      </div>
      <div className="spacer-lg"></div>
    </div>
  );
}

// ────────────────────────────────────────────────────────────────
// Reading board — the dealt spread, flipping, interpretation
// ────────────────────────────────────────────────────────────────
function ReadingBoard({ spread, question, voice, draws, revealed, setRevealed,
                        synthesis, setSynthesis, loadingSynth, setLoadingSynth,
                        voicePlaying, setVoicePlaying,
                        phases, phaseIdx, phase, setPhase, onComplete }) {

  const positions = spread.positions;
  const cardLookup = useM2(() => Object.fromEntries(TAROT_DECK.map(c => [c.id, c])), []);
  const drawCards = draws.map(d => ({ ...cardLookup[d.cardId], reversed: d.reversed }));
  const allRevealed = revealed.length === positions.length;

  const handleReveal = (i) => {
    if (revealed.includes(i)) return;
    setRevealed([...revealed, i]);
  };

  // when all revealed, move to interpret phase + generate synthesis
  useE2(() => {
    if (allRevealed && phase !== 'interpret') {
      setPhase('interpret');
    }
  }, [allRevealed, phase]);

  // Generate AI synthesis once on interpret
  useE2(() => {
    if (phase !== 'interpret' || synthesis || loadingSynth) return;
    setLoadingSynth(true);

    const cardSummary = drawCards.map((c, i) =>
      `${i+1}. ${positions[i].name} (${positions[i].prompt}): ${c.name}${c.reversed ? ' (reversed)' : ''} — ${c.reversed ? c.reversed : c.upright}`
    ).join('\n');

    const paragraphCount =
      spread.count === 1 ? '2 short paragraphs (2-3 sentences each)' :
      spread.count <= 3  ? '2 short paragraphs (3-4 sentences each)' :
      spread.count <= 5  ? '3 short paragraphs (3-4 sentences each)' :
                            '4 short paragraphs (3-4 sentences each)';

    const prompt = `You are ${voice?.name || 'a tarot reader'}${voice?.epithet ? ', ' + voice.epithet : ''}.

VOICE & CHARACTER:
${voice?.promptTone || voice?.trait || 'Speak as an earnest, mystical tarot reader.'}

THE WORLD OF THIS DECK:
This is the Veiled Tarot — a deck drawn in the visual key of the Black diaspora’s
futures and pasts at once. Its cards picture a cosmos of obsidian skin and gold
filigree, of cities raised on starlight, of ankhs that double as circuit-glyphs,
of panthers as familiars and crowns cut from a metal older than empire. The Fool
steps from a high city into the wider galaxy; the Empress tends an orchard threaded
with code; the King of Pentacles holds an estate the centuries could not break.
The figures are kin — ancestors, sovereigns, navigators, builders — not strangers
from another tradition.

Read with this world as the air the questioner breathes. Let the following
principles shape the texture of the reading, without ever being named or
explained:
  •  Ancestral memory is a kind of technology. The past is not behind — it is
     underneath, a foundation that powers what comes next.
  •  Sankofa: go back, fetch what was lost, bring it forward. Endings are
     recoveries. Returns are not retreats.
  •  Diaspora is cosmos. Distance, departure, the long arc home — these are the
     real shape of journeys, more than maps suggest.
  •  Sovereignty: the questioner is a builder of worlds, never a supplicant.
     Even the difficult cards are addressed to a person with their own throne.
  •  Time is a spiral, not a line. The future is already remembering them.
  •  The body is an inheritance. Adornment, beauty, presence — these are power,
     not vanity.

When the cards' imagery suggests it, draw on the deck's own vocabulary — gold,
ankh, panther, crown, the violet hour, the vine-grown throne, the city under
a great moon, the long lineage — in service of the reading. Never as decoration
for its own sake.

Do not use the word "Afrofuturist" or any variant. Do not name authors,
franchises, real-world countries, or specific cultures. Do not perform
an accent or dialect. Let the world be felt, not announced.

The questioner has come to you with this question:
"${question}"

You laid ${spread.name} for them. ${spread.count === 1 ? 'A single card was drawn' : `${spread.count} cards in these positions`}:
${cardSummary}

${spread.synthGuide || ''}

Give them an earnest, mystical reading in ${paragraphCount}. Speak directly to them. Weave the cards together into a unified reading — never list each card mechanically.

Stay completely in character — every sentence should sound like ${voice?.name}, not like a generic reader. Do not use markdown formatting. Do not introduce yourself. Begin with the reading itself. End with a single closing sentence that holds the whole reading.`;

    // Route order:
    //   1. window.claude.complete  — works only inside claude.ai's sandbox
    //   2. Worker /complete proxy  — hosted Anthropic API call (production path)
    //   3. Pre-written fallback    — when neither is reachable
    const onResolve = (text) => { setSynthesis(text.trim()); setLoadingSynth(false); };
    const onFallback = () => {
      setSynthesis(buildFallbackSynth(drawCards, positions, question, voice, spread));
      setLoadingSynth(false);
    };

    if (typeof window.claude?.complete === 'function') {
      window.claude.complete(prompt).then(onResolve).catch(onFallback);
    } else if (window.VEILED_CONFIG?.ttsProxyUrl) {
      fetch(window.VEILED_CONFIG.ttsProxyUrl + '/complete', {
        method: 'POST',
        headers: { 'content-type': 'application/json' },
        body: JSON.stringify({ prompt }),
      })
        .then(r => r.ok ? r.json() : Promise.reject(new Error('proxy ' + r.status)))
        .then(data => onResolve(data.text || ''))
        .catch(onFallback);
    } else {
      onFallback();
    }
  }, [phase, synthesis, loadingSynth]);

  const handleSave = () => {
    const entry = {
      id: 'r-' + Date.now(),
      timestamp: Date.now(),
      question,
      spreadId: spread.id,
      spreadName: spread.name,
      voiceId: voice?.id,
      voiceName: voice?.name,
      draws,
      synthesis,
    };
    onComplete(entry);
  };

  return (
    <div className="container wide">
      <PhaseRail steps={phases} current={phaseIdx}/>
      <div className="center">
        <span className="eyebrow">{spread.name}</span>
        <h2 style={{marginTop:'1rem', fontStyle:'italic', fontFamily:'var(--font-serif)', fontWeight:300, textTransform:'none', letterSpacing:'0.02em', fontSize:'clamp(1.4rem, 2.8vw, 2.2rem)'}}>
          "{question}"
        </h2>
        <p className="muted" style={{marginTop:'0.5rem', fontSize:'0.85rem'}}>
          Read by {voice?.name || 'the cards'}
        </p>
      </div>

      <Divider glyph="mark"/>

      {phase === 'reveal' && (
        <p className="center muted" style={{fontStyle:'italic', marginBottom:'2rem'}}>
          Touch each card to turn it over.
        </p>
      )}

      <div className="spread-board">
        <div className={`spread-${spread.layout}`} style={spread.layout === 'row' ? {'--cols': spread.count} : undefined}>
          {positions.map((pos, i) => {
            const isRevealed = revealed.includes(i);
            const card = drawCards[i];
            return (
              <div key={pos.id} className="slot">
                <div className="pos-num">· {String(i + 1).padStart(2, '0')} ·</div>
                <TarotCard card={card} flipped={isRevealed} reversed={card?.reversed}
                           size={spread.cardSize || ''} interactive
                           onClick={() => handleReveal(i)}/>
                <div className="pos-name">{pos.name}</div>
              </div>
            );
          })}
        </div>
      </div>

      {phase === 'interpret' && (
        <>
          <Divider glyph="sigil-mark"/>

          {/* Per-card interpretations */}
          <div className="stack" style={{gap:'3rem', marginTop:'2rem'}}>
            {drawCards.map((card, i) => {
              const pos = positions[i];
              return (
                <div key={i} className="reading-detail">
                  <div className="visual">
                    <div className="position-pill">· {String(i+1).padStart(2,'0')} · {pos.name}</div>
                    <TarotCard card={card} flipped reversed={card.reversed} size="lg"/>
                    <p className="muted" style={{textAlign:'center', fontStyle:'italic', maxWidth:'260px', fontSize:'0.95rem'}}>
                      {pos.prompt}
                    </p>
                  </div>
                  <div className="reading-meaning">
                    <div>
                      <h3 style={{display:'flex', alignItems:'center', flexWrap:'wrap', gap:'0.4rem'}}>
                        {card.name}
                        {card.reversed && <span className="reversed-tag">Reversed</span>}
                      </h3>
                      <p className="lead" style={{marginTop:'0.6rem', fontSize:'1.15rem'}}>{card.long}</p>
                    </div>
                    <div style={{marginTop:'1.5rem'}}>
                      <h4>{card.reversed ? 'Reversed Meaning' : 'Upright Meaning'}</h4>
                      <p style={{marginTop:'0.4rem'}}>{card.reversed ? card.reversed : card.upright}</p>
                    </div>
                    <div style={{marginTop:'1.2rem'}}>
                      <h4>In this position</h4>
                      <p style={{marginTop:'0.4rem', fontStyle:'italic', color:'var(--ash)'}}>
                        Falling as <em>{pos.name}</em>, this card speaks to {pos.prompt.toLowerCase()}
                      </p>
                    </div>
                  </div>
                </div>
              );
            })}
          </div>

          <Divider glyph="mark"/>

          {/* AI Synthesis */}
          <div className="synth-block" style={{marginTop:'2rem'}}>
            <PanelCorners/>
            <span className="eyebrow">The Reading</span>
            <h2 style={{marginTop:'0.8rem', textAlign:'left'}}>
              {voice?.name || 'The Reader'} speaks
            </h2>
            <div style={{marginTop:'1.5rem'}}>
              {loadingSynth ? (
                <div className="center muted" style={{padding:'2rem 0', fontStyle:'italic'}}>
                  <Sigil name="sigil-mark" className="back-sigil" style={{width:48, height:48, color:'var(--gold)', opacity:0.6, animation:'spin 4s linear infinite'}}/>
                  <p style={{marginTop:'1rem'}}>The reader is gathering the cards into a voice…</p>
                </div>
              ) : (
                <div className="synth-text">
                  {(synthesis || '').split(/\n\n+/).filter(Boolean).map((p, i) => <p key={i}>{p}</p>)}
                </div>
              )}
            </div>
            {synthesis && (
              <div className="audio-controls">
                <button className="play-pill" onClick={async () => {
                  if (voicePlaying) {
                    TTS.stopVoice();
                    setVoicePlaying(false);
                    return;
                  }
                  setVoicePlaying(true);
                  try {
                    await TTS.speakVoice(synthesis, voice);
                  } catch (err) {
                    console.warn('Voice playback failed:', err);
                    alert('The reader could not speak: ' + err.message + '\n\nCheck your ElevenLabs API key in Voice Settings.');
                  } finally {
                    setVoicePlaying(false);
                  }
                }}>
                  <Sigil name={voicePlaying ? 'pause' : 'play'}/>
                  {voicePlaying ? 'Stop' : 'Hear it spoken'}
                </button>
                <span className="muted" style={{fontSize:'0.85rem', fontStyle:'italic'}}>
                  {voicePlaying ? `${voice?.name} is reading…` :
                   TTS.hasElevenVoice(voice) ? `Voice: ${voice?.name}` :
                   voice?.voiceId ? `${voice?.name} · add API key in Settings` :
                   `${voice?.name} · browser voice (not yet recorded)`}
                </span>
                <span style={{flex:1}}></span>
                <button className="btn small ghost" onClick={() => { TTS.stopVoice(); setVoicePlaying(false); setSynthesis(null); setLoadingSynth(false); }}>
                  Re-read
                </button>
              </div>
            )}
          </div>

          <div className="spacer-lg"></div>

          <div className="center" style={{display:'flex', gap:'1rem', justifyContent:'center', flexWrap:'wrap'}}>
            <button className="btn ghost" onClick={() => onComplete(null)}>Close Without Saving</button>
            <button className="btn primary" onClick={handleSave} disabled={loadingSynth}>
              Keep in My Journal <Sigil name="check"/>
            </button>
          </div>
        </>
      )}

      <div className="spacer-lg"></div>
    </div>
  );
}

// Fallback synthesis composer if Claude call fails — works for any spread.
function buildFallbackSynth(cards, positions, question, voice, spread) {
  if (!cards.length) return 'The cards lie quiet tonight.';

  // Single card: one tight paragraph, one closing line.
  if (cards.length === 1) {
    const c = cards[0];
    const m = c.reversed ? c.reversed : c.upright;
    return [
      `The card that came is ${c.name}${c.reversed ? ', reversed' : ''}. ${c.long}`,
      `Read into the question, it speaks: ${m.toLowerCase()} Hold this lightly. One card is a single star — a window onto the lineage, not a verdict.`,
    ].join('\n\n');
  }

  // Multi-card: walk through cards, grouping ~3 per paragraph.
  const lines = cards.map((c, i) => {
    const pos = positions[i];
    const m = c.reversed ? c.reversed : c.upright;
    return `In ${pos.name.toLowerCase()}, ${c.name.toLowerCase()}${c.reversed ? ', reversed,' : ''}: ${m.toLowerCase()}`;
  });

  const perPara = cards.length <= 3 ? lines.length : cards.length <= 5 ? Math.ceil(cards.length / 2) : Math.ceil(cards.length / 3);
  const paras = [];
  for (let i = 0; i < lines.length; i += perPara) {
    paras.push(lines.slice(i, i + perPara).join(' '));
  }
  paras.push(`Hold the cards lightly. The future they show is one thread in a long lineage; this is the one asking for your hand.`);
  return paras.join('\n\n');
}

Object.assign(window, { SpreadsScreen, SpreadDiagram, ReadingScreen, ShufflePhase, CutPhase, ReadingBoard, ReaderProfileModal, VoicePreviewButton });
