// atelier-screens-b.jsx — Lesson, Puzzle/Study, Hero piece, Tension screens.

const { useState: useSB, useEffect: useEB, useMemo: useMB, useRef: useRB } = React;

// Local copy of glyph map (atelier-board.jsx exports window.B_GLYPH but we copy here for safety)
const SB_GLYPH = {
  wK:'♔',wQ:'♕',wR:'♖',wB:'♗',wN:'♘',wP:'♙',
  bK:'♚',bQ:'♛',bR:'♜',bB:'♝',bN:'♞',bP:'♟',
};

const PIECE_NAMES = {
  wK:'White king', wQ:'White queen', wR:'White rook', wB:'White bishop', wN:'White knight', wP:'White pawn',
  bK:'Black king', bQ:'Black queen', bR:'Black rook', bB:'Black bishop', bN:'Black knight', bP:'Black pawn',
};

// === 3. LESSON SEQUENCE — interactive 4-phase quiz ============================
function LessonScreen({ palette, tweaks, lessonId, setRoute }) {
  const C = palette;
  const { isMobile, isTablet } = window.useBreakpoint();

  // All hooks must come before any early return.
  const activeLessonId = lessonId || (window.LESSON && window.LESSON.id);

  // Phase: 'look' | 'heatmap' | 'hero' | 'tension' | 'done'
  const [phase, setPhase] = useSB('look');

  // Heatmap quiz state
  const [heatmapAnswered, setHeatmapAnswered] = useSB(false);
  const [heatmapChoice, setHeatmapChoice] = useSB(null);

  // Hero move state
  const [heroSelected, setHeroSelected] = useSB(false);
  const [heroMoveResult, setHeroMoveResult] = useSB(null); // null | 'correct' | 'wrong-dest' | 'memory' | 'revealed'
  const [wrongPieceFeedback, setWrongPieceFeedback] = useSB(false);
  const [wrongDestStrikes, setWrongDestStrikes] = useSB(0);
  const [memoryCountdown, setMemoryCountdown] = useSB(5);
  const [memoryPhase, setMemoryPhase] = useSB('idle'); // 'idle' | 'showing' | 'hidden' | 'answered'
  // attemptedMove: the user's pending or accepted move, used to override the
  // rendered position so the piece actually slides to where they dropped it.
  const [attemptedMove, setAttemptedMove] = useSB(null); // { from, to } | null
  const countdownRef = useRB(null);
  const snapBackRef = useRB(null);

  // Tension quiz state
  const [tensionAnswered, setTensionAnswered] = useSB(false);
  const [tensionChoice, setTensionChoice] = useSB(null);

  // Board hover
  const [hovered, setHovered] = useSB(null);

  // Unlock-able layer chips (off by default, toggled by the user once unlocked)
  const [unlockedLayers, setUnlockedLayers] = useSB({ heatmap: false, hero: false, trajectory: false, tension: false });
  const [layerToggles, setLayerToggles] = useSB({ heatmap: false, hero: false, trajectory: false, tension: false });

  // Reset everything when lesson changes.
  useEB(() => {
    setPhase('look');
    setHeatmapAnswered(false); setHeatmapChoice(null);
    setHeroSelected(false); setHeroMoveResult(null);
    setWrongPieceFeedback(false); setWrongDestStrikes(0);
    setMemoryCountdown(5); setMemoryPhase('idle');
    setAttemptedMove(null);
    if (snapBackRef.current) { clearTimeout(snapBackRef.current); snapBackRef.current = null; }
    setTensionAnswered(false); setTensionChoice(null);
    setUnlockedLayers({ heatmap: false, hero: false, trajectory: false, tension: false });
    setLayerToggles({ heatmap: false, hero: false, trajectory: false, tension: false });
  }, [activeLessonId]);

  // Countdown timer for memory mode.
  useEB(() => {
    if (memoryPhase === 'showing') {
      countdownRef.current = setInterval(() => {
        setMemoryCountdown((prev) => {
          if (prev <= 1) {
            clearInterval(countdownRef.current);
            setMemoryPhase('hidden');
            return 0;
          }
          return prev - 1;
        });
      }, 1000);
    }
    return () => { if (countdownRef.current) clearInterval(countdownRef.current); };
  }, [memoryPhase]);

  const boardPalette = useMB(() => ({
    ...C,
    squareLight: '#E7E5E0',
    squareDark:  '#B7B4AD',
    boneDeep:    '#DEDCD7',
    sienna:      '#8E8378',
    siennaSoft:  '#B4ABA2',
    terracotta:  '#6D6359',
    celadon:     '#B8BBC2',
    celadonSoft: '#D2D5DA',
    sage:        '#9498A0',
  }), [C]);

  // Heatmap quiz options — computed before any guard so hooks order is stable.
  // sideToMove is derived below from LESSON; we read it directly here for the memo dep.
  const _sideToMove = (window.LESSON && window.LESSON.meta && window.LESSON.meta.sideToMove) || 'white';
  const heatmapOptions = useMB(() => {
    const influence = window.A_INFLUENCE_BOARD || {};
    const position = window.A_POSITION || {};
    const side = (window.LESSON && window.LESSON.meta && window.LESSON.meta.sideToMove) || 'white';
    const entries = Object.entries(influence).filter(([sq]) => !position[sq]);
    if (!entries.length) return [];
    entries.sort((a, b) => side === 'white' ? b[1] - a[1] : a[1] - b[1]);
    const correct = entries[0][0];
    const seed0 = activeLessonId ? activeLessonId.charCodeAt(activeLessonId.length - 1) : 0;
    const pool = entries.slice(1).filter(([, v]) => Math.abs(v) > 0.05);
    const d1 = pool[seed0 % Math.max(pool.length, 1)]?.[0] || entries[1]?.[0];
    const d2 = pool[(seed0 + 3) % Math.max(pool.length, 1)]?.[0] || entries[2]?.[0];
    const opts = [correct, d1, d2].filter(Boolean);
    const shift = (seed0 % 3);
    const shuffled = [opts[shift % opts.length], opts[(shift + 1) % opts.length], opts[(shift + 2) % opts.length]];
    return shuffled.map((sq, i) => ({ sq, label: String.fromCharCode(65 + i) }));
  }, [activeLessonId, _sideToMove]);

  // Tension quiz options.
  const tensionOptions = useMB(() => {
    const tensions = window.A_TENSIONS || [];
    if (!tensions.length) return [];
    const correct = tensions[0].defender;
    const position = window.A_POSITION || {};
    const allPieceSqs = Object.keys(position).filter((sq) => sq !== correct);
    const seed0 = activeLessonId ? activeLessonId.charCodeAt(0) : 0;
    const d1 = allPieceSqs[seed0 % Math.max(allPieceSqs.length, 1)];
    const d2 = allPieceSqs[(seed0 + 5) % Math.max(allPieceSqs.length, 1)] || allPieceSqs[0];
    const opts = [correct, d1, d2].filter(Boolean);
    const shift = (seed0 % 3);
    const shuffled = [opts[shift % opts.length], opts[(shift + 1) % opts.length], opts[(shift + 2) % opts.length]];
    return shuffled.map((sq, i) => ({ sq, label: String.fromCharCode(65 + i) }));
  }, [activeLessonId]);

  // Hidden pieces for memory mode — must be before any guard return.
  const hiddenPieces = useMB(() => {
    const position = window.A_POSITION || {};
    const hero = window.A_HERO;
    if (memoryPhase === 'hidden' || memoryPhase === 'answered') {
      // Blank board: hide everything
      return new Set(Object.keys(position));
    }
    if (memoryPhase === 'showing') {
      // Show only the hero piece; ghost all others
      return new Set(Object.keys(position).filter(sq => sq !== hero));
    }
    return null;
  }, [memoryPhase]);

  // Guard: lesson data not ready.
  if (!window.LESSON || !window.LESSON.meta) return null;

  const meta = window.LESSON.meta;
  const sideToMove = meta.sideToMove || 'white';
  const sideLabel = sideToMove === 'white' ? 'White' : 'Black';
  const heroSq = window.A_HERO;
  const heroCode = heroSq && window.A_POSITION && window.A_POSITION[heroSq];
  const heroName = heroCode ? PIECE_NAMES[heroCode] : 'the key piece';
  const heroTarget = (window.A_TRAJECTORIES && heroSq && (window.A_TRAJECTORIES[heroSq] || []))[1] || null;

  const heatmapCorrectSq = heatmapOptions.length > 0
    ? (() => {
        const influence = window.A_INFLUENCE_BOARD || {};
        const position = window.A_POSITION || {};
        const entries = Object.entries(influence).filter(([sq]) => !position[sq]);
        if (!entries.length) return heatmapOptions[0].sq;
        entries.sort((a, b) => sideToMove === 'white' ? b[1] - a[1] : a[1] - b[1]);
        return entries[0][0];
      })()
    : null;

  const tensionCorrectSq = window.A_TENSIONS && window.A_TENSIONS.length ? window.A_TENSIONS[0].defender : null;

  // Hero phase: free-move flow. Click any piece, then any destination square or
  // another piece (capture). We validate once both halves are in.
  function attemptHeroMove(from, to) {
    if (from === to) return;
    // Slide the piece on the board so the user sees their move land.
    setAttemptedMove({ from, to });
    const correctPiece = from === heroSq;
    const correctDest  = !heroTarget || to === heroTarget;
    if (correctPiece && correctDest) {
      setHeroMoveResult('correct');
      return;
    }
    // Wrong move: leave the piece on the dropped square for a moment so the
    // user sees what they did, then snap it back and show feedback.
    const strikes = wrongDestStrikes + 1;
    setWrongDestStrikes(strikes);
    if (snapBackRef.current) clearTimeout(snapBackRef.current);
    snapBackRef.current = setTimeout(() => {
      setAttemptedMove(null);
      setHeroSelected(false);
      setWrongPieceFeedback(true);
      setTimeout(() => setWrongPieceFeedback(false), 2400);
      if (strikes >= 2) {
        setMemoryCountdown(5);
        setMemoryPhase('showing');
      }
    }, 900);
  }

  function handleHeroPieceSelect(sq) {
    if (heroMoveResult) return;
    if (memoryPhase !== 'idle') return;
    if (attemptedMove) return; // mid snap-back; ignore clicks
    if (!sq) { setHeroSelected(false); return; } // board passed null = deselect
    if (!heroSelected) {
      setHeroSelected(sq);
      setWrongPieceFeedback(false);
      return;
    }
    if (sq === heroSelected) {
      setHeroSelected(false);
      return;
    }
    // Different piece clicked while one is selected: treat as capture move.
    attemptHeroMove(heroSelected, sq);
  }

  function handleHeroSquareClick(sq) {
    if (heroMoveResult) return;
    if (attemptedMove) return; // mid snap-back; ignore clicks
    if (memoryPhase === 'hidden') {
      // Memory mode: blank board, clicking lands the hero piece.
      if (!heroTarget || sq === heroTarget) {
        setHeroMoveResult('correct');
      } else {
        setHeroMoveResult('wrong-dest');
      }
      setMemoryPhase('answered');
      return;
    }
    if (heroSelected) attemptHeroMove(heroSelected, sq);
  }

  // Tension phase: click any piece on the board to answer.
  function handleTensionPieceSelect(sq) {
    if (tensionAnswered) return;
    const code = window.A_POSITION && window.A_POSITION[sq];
    if (!code) return; // only piece clicks count
    setTensionChoice(sq);
    setTensionAnswered(true);
  }

  // Board layers — each phase decides what's forced on, then we merge in
  // anything the user has manually toggled via an unlocked chip.
  const forcedLayers = (() => {
    switch (phase) {
      case 'look':    return { heatmap: false, hero: false, trajectory: false, tension: false };
      case 'heatmap': return { heatmap: heatmapAnswered, hero: false, trajectory: false, tension: false };
      case 'hero':    return { heatmap: false, hero: heroMoveResult === 'correct', trajectory: heroMoveResult === 'correct', tension: false };
      case 'tension': return { heatmap: false, hero: false, trajectory: false, tension: tensionAnswered };
      case 'done':    return { heatmap: false, hero: false, trajectory: false, tension: false };
      default:        return { heatmap: false, hero: false, trajectory: false, tension: false };
    }
  })();
  const activeLayers = {
    heatmap:    forcedLayers.heatmap    || (unlockedLayers.heatmap    && layerToggles.heatmap),
    hero:       forcedLayers.hero       || (unlockedLayers.hero       && layerToggles.hero),
    trajectory: forcedLayers.trajectory || (unlockedLayers.trajectory && layerToggles.trajectory),
    tension:    forcedLayers.tension    || (unlockedLayers.tension    && layerToggles.tension),
  };

  // Board special props per phase.
  const activeMarkedSquares = (phase === 'heatmap' && !heatmapAnswered) ? heatmapOptions : null;
  const markedSquaresProp = activeMarkedSquares || null;

  const highlightSquareProp = null;
  // (We intentionally don't show a hint for the destination to keep it challenging.)

  const boardSize = isMobile ? Math.min(320, window.innerWidth - 48) : 520;

  // Phase step numbers.
  const PHASE_ORDER = ['look', 'heatmap', 'hero', 'tension'];
  const phaseNum = PHASE_ORDER.indexOf(phase) + 1;
  const phaseKicker = phase === 'done' ? 'Complete' : `Step ${phaseNum} of 4`;

  // Board interaction handlers by phase.
  let onSelectProp = null;
  if (phase === 'hero') onSelectProp = handleHeroPieceSelect;
  else if (phase === 'tension' && !tensionAnswered) onSelectProp = handleTensionPieceSelect;

  const onSquareClickProp = phase === 'hero' ? handleHeroSquareClick : null;

  // Selected square for highlight ring.
  let selectedProp = null;
  if (phase === 'hero' && heroSelected) selectedProp = heroSelected;
  else if (phase === 'tension' && tensionAnswered && tensionChoice) selectedProp = tensionChoice;

  // Focus square for tension phase — spotlight the correct piece after answer.
  const focusProp = phase === 'tension' && tensionAnswered && tensionCorrectSq ? tensionCorrectSq : null;

  // Position override: when the user has tried (or just made) a move in the
  // hero phase, render the board with that piece moved. Anything sitting on
  // the destination is captured (removed).
  let positionOverrideProp = null;
  if (attemptedMove && window.A_POSITION) {
    const base = window.A_POSITION;
    const piece = base[attemptedMove.from];
    if (piece) {
      const next = { ...base };
      delete next[attemptedMove.from];
      next[attemptedMove.to] = piece;
      positionOverrideProp = next;
    }
  }

  return (
    <div style={{ flex: 1, height: '100%', overflow: 'hidden', display: 'flex', flexDirection: 'column', background: C.bone }}>
      {/* Phase strip */}
      <div style={{
        padding: isMobile ? '12px 16px' : '14px 40px',
        borderBottom: `0.6px solid ${C.umberHair}`,
        display: 'flex', alignItems: 'center', gap: isMobile ? 12 : 20,
      }}>
        <div style={{
          fontFamily: window.ATELIER_TYPE.ui, fontSize: 10, letterSpacing: 3,
          textTransform: 'uppercase', color: C.umberFaint, flexShrink: 0,
        }}>{phaseKicker}</div>
        <div style={{ flex: 1, display: 'flex', gap: 5 }}>
          {PHASE_ORDER.map((p, i) => {
            const done = PHASE_ORDER.indexOf(phase) > i || phase === 'done';
            const active = phase === p;
            return (
              <div key={p} style={{
                flex: active ? 2 : 1, height: 4, borderRadius: 99,
                background: done ? C.brassDeep : (active ? C.brass : C.umberHair),
                transition: 'all 280ms ' + window.ATELIER_EASE,
              }} />
            );
          })}
        </div>
        <div style={{
          fontFamily: window.ATELIER_TYPE.ui, fontSize: 11,
          color: C.umberFaint, flexShrink: 0,
        }}>{window.creativeTitle ? window.creativeTitle(activeLessonId) : meta.title}</div>
      </div>

      {/* Body */}
      <div style={{
        flex: 1, overflow: isTablet ? 'auto' : 'hidden',
        display: 'grid',
        gridTemplateColumns: isTablet ? '1fr' : 'minmax(0, 1fr) 380px',
        gap: 0,
      }}>
        {/* Board column */}
        <div style={{
          display: 'flex', alignItems: 'center', justifyContent: 'center',
          flexDirection: 'column', gap: 14,
          padding: isMobile ? 16 : 32,
          background: `radial-gradient(120% 80% at 50% -10%, ${window.withAlpha(C.brassLight, 0.35)}, transparent 60%)`,
          overflow: 'auto',
        }}>
          <div style={{
            background: boardPalette.boneDeep, padding: isMobile ? 8 : 14, borderRadius: 8,
            boxShadow: '0 30px 50px -28px rgba(42,34,27,0.45)',
          }}>
            <window.AtelierBoard
              palette={boardPalette}
              layers={activeLayers}
              heatmapStyle={tweaks.heatmapStyle}
              heatmapIntensity={tweaks.heatmapIntensity}
              trajectoryStyle={tweaks.trajectoryStyle}
              hovered={hovered}
              onHover={setHovered}
              selected={selectedProp}
              onSelect={onSelectProp}
              onSquareClick={onSquareClickProp}
              markedSquares={markedSquaresProp}
              hiddenPieces={hiddenPieces}
              highlightSquare={highlightSquareProp}
              focus={focusProp}
              size={boardSize}
              noTrajectoryOnSelect={true}
              positionOverride={positionOverrideProp}
            />
          </div>
          <UnlockedLayerChips
            palette={C}
            unlocked={unlockedLayers}
            toggles={layerToggles}
            setToggles={setLayerToggles}
          />
        </div>

        {/* Sidebar */}
        <aside style={{
          background: C.cream,
          borderLeft: isTablet ? 'none' : `0.6px solid ${C.umberHair}`,
          borderTop: isTablet ? `0.6px solid ${C.umberHair}` : 'none',
          padding: isMobile ? '24px 20px' : '36px 32px',
          display: 'flex', flexDirection: 'column', gap: 20,
          overflow: 'auto',
        }}>
          {phase === 'look' && (
            <LookPhase
              C={C} sideLabel={sideLabel}
              onContinue={() => setPhase('heatmap')}
              isMobile={isMobile}
            />
          )}
          {phase === 'heatmap' && (
            <HeatmapPhase
              C={C} sideLabel={sideLabel}
              options={heatmapOptions}
              correctSq={heatmapCorrectSq}
              answered={heatmapAnswered}
              choice={heatmapChoice}
              onChoose={(sq) => { setHeatmapChoice(sq); setHeatmapAnswered(true); }}
              onContinue={() => {
                setUnlockedLayers((prev) => ({ ...prev, heatmap: true }));
                setPhase('hero');
              }}
            />
          )}
          {phase === 'hero' && (
            <HeroPhase
              C={C}
              heroSq={heroSq}
              heroName={heroName}
              heroTarget={heroTarget}
              heroSelected={heroSelected}
              heroMoveResult={heroMoveResult}
              wrongPieceFeedback={wrongPieceFeedback}
              wrongDestStrikes={wrongDestStrikes}
              memoryPhase={memoryPhase}
              memoryCountdown={memoryCountdown}
              onContinue={() => {
                setUnlockedLayers((prev) => ({ ...prev, hero: true, trajectory: true }));
                setPhase('tension');
                setHeroSelected(false);
                setMemoryPhase('idle');
                setAttemptedMove(null);
              }}
              lesson={window.LESSON}
            />
          )}
          {phase === 'tension' && (
            <TensionPhase
              C={C}
              correctSq={tensionCorrectSq}
              answered={tensionAnswered}
              choice={tensionChoice}
              onContinue={() => {
                setUnlockedLayers((prev) => ({ ...prev, tension: true }));
                setPhase('done');
              }}
              onStudy={() => {
                if (typeof setRoute === 'function') setRoute('puzzle');
              }}
              lesson={window.LESSON}
            />
          )}
          {phase === 'done' && (
            <DonePhase
              C={C}
              onNext={() => {
                const idx = window.LESSON_INDEX;
                const list = (idx && idx.lessons) || [];
                const others = list.filter((l) => l.id !== activeLessonId);
                if (!others.length || typeof setRoute !== 'function') return;
                const next = others[Math.floor(Math.random() * others.length)];
                setRoute('lesson:' + next.id);
              }}
              onStudy={() => {
                if (typeof setRoute === 'function') setRoute('puzzle');
              }}
              onPlay={() => {
                if (typeof setRoute === 'function') setRoute('play');
              }}
            />
          )}
        </aside>
      </div>
    </div>
  );
}

// === Lesson sub-phase components =============================================

function LookPhase({ C, sideLabel, onContinue, isMobile }) {
  return (
    <>
      <div style={{
        fontFamily: window.ATELIER_TYPE.ui, fontSize: 10, letterSpacing: 3.5,
        textTransform: 'uppercase', color: C.umberFaint,
      }}>Read the position</div>
      <h2 style={{
        margin: 0,
        fontFamily: window.ATELIER_TYPE.display, fontWeight: 300, fontStyle: 'italic',
        fontSize: isMobile ? 28 : 36, lineHeight: 1.1, color: C.umber, letterSpacing: -0.3,
      }}>Read the position</h2>
      <p style={{
        margin: 0,
        fontFamily: window.ATELIER_TYPE.display, fontSize: 17, lineHeight: 1.6, color: C.umberSoft,
      }}>{sideLabel} to move. Take a moment before continuing.</p>
      <div style={{ flex: 1 }} />
      <button style={window.primaryBtn(C)} onClick={onContinue}>Continue</button>
    </>
  );
}

function HeatmapPhase({ C, sideLabel, options, correctSq, answered, choice, onChoose, onContinue }) {
  const correct = choice === correctSq;
  return (
    <>
      <div style={{
        fontFamily: window.ATELIER_TYPE.ui, fontSize: 10, letterSpacing: 3.5,
        textTransform: 'uppercase', color: C.umberFaint,
      }}>Step 2 of 4</div>
      <h2 style={{
        margin: 0,
        fontFamily: window.ATELIER_TYPE.display, fontWeight: 300, fontStyle: 'italic',
        fontSize: 32, lineHeight: 1.1, color: C.umber,
      }}>Which square does {sideLabel} control most?</h2>
      {!answered && (
        <div style={{ display: 'flex', flexDirection: 'column', gap: 10, marginTop: 8 }}>
          {options.map(({ sq, label }) => (
            <button key={sq} onClick={() => onChoose(sq)}
              style={{
                ...window.ghostBtn(C),
                textAlign: 'left',
                padding: '12px 18px',
                borderRadius: 10,
                display: 'flex', alignItems: 'center', gap: 14,
              }}>
              <span style={{
                fontFamily: window.ATELIER_TYPE.ui, fontSize: 13, fontWeight: 700,
                color: C.brassDeep, minWidth: 20,
              }}>{label}</span>
              <span style={{
                fontFamily: window.ATELIER_TYPE.display, fontStyle: 'italic',
                fontSize: 18, color: C.umber,
              }}>{sq.toUpperCase()}</span>
            </button>
          ))}
        </div>
      )}
      {answered && (
        <>
          <div style={{
            padding: '16px 18px', borderRadius: 12,
            background: correct ? window.withAlpha(C.brass, 0.12) : window.withAlpha(C.sienna, 0.10),
            border: `0.6px solid ${correct ? C.brass : C.sienna}`,
          }}>
            <div style={{
              fontFamily: window.ATELIER_TYPE.display, fontStyle: 'italic',
              fontSize: 17, lineHeight: 1.5, color: C.umber,
            }}>
              {correct
                ? `Yes. ${correctSq.toUpperCase()} is deep in ${sideLabel}'s territory.`
                : `Not quite. ${correctSq.toUpperCase()} is where ${sideLabel} has the most reach.`}
            </div>
          </div>
          <div style={{ flex: 1 }} />
          <button style={window.primaryBtn(C)} onClick={onContinue}>Continue</button>
        </>
      )}
    </>
  );
}

function HeroPhase({ C, heroSq, heroName, heroTarget, heroSelected, heroMoveResult, wrongPieceFeedback, wrongDestStrikes, memoryPhase, memoryCountdown, onContinue, lesson }) {
  const coaching = lesson && lesson.coaching && lesson.coaching.find((c) => c.anchor === heroSq);
  const explanation = coaching ? coaching.text : null;

  return (
    <>
      <div style={{
        fontFamily: window.ATELIER_TYPE.ui, fontSize: 10, letterSpacing: 3.5,
        textTransform: 'uppercase', color: C.umberFaint,
      }}>Step 3 of 4</div>
      <h2 style={{
        margin: 0,
        fontFamily: window.ATELIER_TYPE.display, fontWeight: 300, fontStyle: 'italic',
        fontSize: 32, lineHeight: 1.1, color: C.umber,
      }}>Find the key piece and make its best move.</h2>

      {/* Instruction state */}
      {!heroMoveResult && memoryPhase === 'idle' && !wrongPieceFeedback && (
        <p style={{ margin: 0, fontFamily: window.ATELIER_TYPE.display, fontSize: 16, lineHeight: 1.55, color: C.umberSoft }}>
          {!heroSelected
            ? 'Pick the piece you think should move, then click where it goes.'
            : 'Now click where this piece should go.'}
        </p>
      )}

      {/* Wrong attempt feedback (covers both wrong piece and wrong destination) */}
      {wrongPieceFeedback && (
        <div style={{
          padding: '12px 16px', borderRadius: 10,
          background: window.withAlpha(C.sienna, 0.10),
          border: `0.6px solid ${C.sienna}`,
          fontFamily: window.ATELIER_TYPE.display, fontStyle: 'italic',
          fontSize: 15, color: C.sienna,
        }}>
          Not that move. Try a different piece or square.
        </div>
      )}

      {/* Memory mode: showing */}
      {memoryPhase === 'showing' && (
        <div style={{
          padding: '14px 18px', borderRadius: 12,
          background: window.withAlpha(C.brassDeep, 0.12),
          border: `0.6px solid ${C.brassDeep}`,
          fontFamily: window.ATELIER_TYPE.display, fontStyle: 'italic',
          fontSize: 16, color: C.umber,
        }}>
          Remember this piece. ({memoryCountdown})
        </div>
      )}

      {/* Memory mode: hidden */}
      {(memoryPhase === 'hidden' || memoryPhase === 'answered') && !heroMoveResult && (
        <div style={{
          padding: '14px 18px', borderRadius: 12,
          background: window.withAlpha(C.brassDeep, 0.12),
          border: `0.6px solid ${C.brassDeep}`,
          fontFamily: window.ATELIER_TYPE.display, fontStyle: 'italic',
          fontSize: 16, color: C.umber,
        }}>
          Now click where it should go.
        </div>
      )}

      {/* Result */}
      {heroMoveResult && (
        <>
          <div style={{
            padding: '16px 18px', borderRadius: 12,
            background: heroMoveResult === 'correct'
              ? window.withAlpha(C.brass, 0.12)
              : window.withAlpha(C.sienna, 0.10),
            border: `0.6px solid ${heroMoveResult === 'correct' ? C.brass : C.sienna}`,
          }}>
            <div style={{
              fontFamily: window.ATELIER_TYPE.display, fontStyle: 'italic',
              fontSize: 17, lineHeight: 1.5, color: C.umber,
            }}>
              {heroMoveResult === 'correct'
                ? `Yes! ${heroName} moves to ${heroTarget ? heroTarget.toUpperCase() : 'its best square'}.`
                : `The best square was ${heroTarget ? heroTarget.toUpperCase() : 'unknown'}.`}
            </div>
            {explanation && (
              <div style={{
                marginTop: 10,
                fontFamily: window.ATELIER_TYPE.display, fontSize: 15, lineHeight: 1.55, color: C.umberSoft,
              }}>{explanation}</div>
            )}
          </div>
          <div style={{ flex: 1 }} />
          <button style={window.primaryBtn(C)} onClick={onContinue}>Continue</button>
        </>
      )}
    </>
  );
}

function TensionPhase({ C, correctSq, answered, choice, onContinue, onStudy, lesson }) {
  const tensions = window.A_TENSIONS || [];
  const correctTension = tensions.find((t) => t.defender === correctSq);
  const correct = choice === correctSq;
  const coaching = lesson && lesson.coaching && lesson.coaching.find((c) => c.anchor === correctSq);
  const explanation = coaching ? coaching.text : (correctTension ? correctTension.note : null);
  const chosenCode = choice && window.A_POSITION && window.A_POSITION[choice];
  const correctCode = correctSq && window.A_POSITION && window.A_POSITION[correctSq];

  return (
    <>
      <div style={{
        fontFamily: window.ATELIER_TYPE.ui, fontSize: 10, letterSpacing: 3.5,
        textTransform: 'uppercase', color: C.umberFaint,
      }}>Step 4 of 4</div>
      <h2 style={{
        margin: 0,
        fontFamily: window.ATELIER_TYPE.display, fontWeight: 300, fontStyle: 'italic',
        fontSize: 32, lineHeight: 1.1, color: C.umber,
      }}>Which piece is under the most pressure?</h2>

      {!answered && (
        <p style={{ margin: 0, fontFamily: window.ATELIER_TYPE.display, fontSize: 16, lineHeight: 1.55, color: C.umberSoft }}>
          Click any piece on the board. We'll tell you whether it's the most strained one.
        </p>
      )}

      {answered && (
        <>
          <div style={{
            padding: '16px 18px', borderRadius: 12,
            background: correct ? window.withAlpha(C.brass, 0.12) : window.withAlpha(C.sienna, 0.10),
            border: `0.6px solid ${correct ? C.brass : C.sienna}`,
          }}>
            <div style={{
              fontFamily: window.ATELIER_TYPE.display, fontStyle: 'italic',
              fontSize: 17, lineHeight: 1.5, color: C.umber,
            }}>
              {correct
                ? `Yes. ${PIECE_NAMES[correctCode] || 'That piece'} on ${correctSq.toUpperCase()} is defending ${correctTension ? correctTension.load : '?'} attackers with only ${correctTension ? correctTension.support : '?'} supporters.`
                : `Not quite. You picked ${PIECE_NAMES[chosenCode] || 'that piece'} on ${choice ? choice.toUpperCase() : '?'}. The overloaded one is ${PIECE_NAMES[correctCode] || 'the piece'} on ${correctSq ? correctSq.toUpperCase() : '?'}.`}
            </div>
            {explanation && (
              <div style={{
                marginTop: 10,
                fontFamily: window.ATELIER_TYPE.display, fontSize: 15, lineHeight: 1.55, color: C.umberSoft,
              }}>{explanation}</div>
            )}
          </div>
          <div style={{ flex: 1 }} />
          <div style={{ display: 'flex', gap: 10 }}>
            <button style={window.ghostBtn(C)} onClick={onContinue}>Continue</button>
            <button style={window.primaryBtn(C)} onClick={onStudy}>Study this position</button>
          </div>
        </>
      )}
    </>
  );
}

function DonePhase({ C, onNext, onStudy, onPlay }) {
  return (
    <>
      <div style={{
        fontFamily: window.ATELIER_TYPE.ui, fontSize: 10, letterSpacing: 3.5,
        textTransform: 'uppercase', color: C.umberFaint,
      }}>Complete</div>
      <h2 style={{
        margin: 0,
        fontFamily: window.ATELIER_TYPE.display, fontWeight: 300, fontStyle: 'italic',
        fontSize: 36, lineHeight: 1.1, color: C.umber,
      }}>Lesson complete.</h2>
      <p style={{
        margin: 0,
        fontFamily: window.ATELIER_TYPE.display, fontSize: 17, lineHeight: 1.6, color: C.umberSoft,
      }}>
        Want to play it out against Stockfish, pick a new position, or study this one in detail?
      </p>
      <div style={{ flex: 1 }} />
      <div style={{ display: 'flex', flexDirection: 'column', gap: 10 }}>
        <button style={window.primaryBtn(C)} onClick={onPlay}>Continue playing vs Stockfish</button>
        <div style={{ display: 'flex', gap: 10 }}>
          <button style={{ ...window.ghostBtn(C), flex: 1 }} onClick={onStudy}>Study this position</button>
          <button style={{ ...window.ghostBtn(C), flex: 1 }} onClick={onNext}>Next puzzle</button>
        </div>
      </div>
    </>
  );
}

// Chips below the lesson board: each unlocked layer can be toggled on/off.
function UnlockedLayerChips({ palette, unlocked, toggles, setToggles }) {
  const C = palette;
  const L = window.COPY.layers;
  const items = [
    { key: 'heatmap',    label: L.heatmap    },
    { key: 'hero',       label: L.hero       },
    { key: 'trajectory', label: L.trajectory },
    { key: 'tension',    label: L.tension    },
  ];
  const anyUnlocked = items.some((it) => unlocked[it.key]);
  if (!anyUnlocked) return null;
  return (
    <div style={{ display: 'flex', gap: 6, flexWrap: 'wrap', justifyContent: 'center' }}>
      {items.map((it) => {
        if (!unlocked[it.key]) return null;
        const on = !!toggles[it.key];
        return (
          <button key={it.key}
            onClick={() => setToggles({ ...toggles, [it.key]: !on })}
            style={{
              appearance: 'none', cursor: 'pointer',
              padding: '7px 12px', borderRadius: 99,
              border: `0.6px solid ${on ? C.umber : C.umberHair}`,
              background: on ? C.umber : C.cream,
              color: on ? C.cream : C.umberSoft,
              fontFamily: window.ATELIER_TYPE.ui,
              fontSize: 10, letterSpacing: 2, textTransform: 'uppercase',
              transition: 'all 180ms ' + window.ATELIER_EASE,
              display: 'inline-flex', alignItems: 'center', gap: 7,
            }}>
            <span style={{
              width: 6, height: 6, borderRadius: 99,
              background: on ? C.brassLight : 'transparent',
              border: `0.6px solid ${on ? C.brassLight : C.umberFaint}`,
            }} />
            {it.label}
          </button>
        );
      })}
    </div>
  );
}

// === 4. PUZZLE / STUDY — tabbed screen ========================================
function PuzzleScreen({ palette, tweaks }) {
  const C = palette;
  const { isMobile, isTablet } = window.useBreakpoint();
  const [tab, setTab] = useSB('board'); // 'board' | 'heatmap' | 'hero' | 'tension'

  // Board tab state
  const [hovered, setHovered] = useSB(null);
  const [selected, setSelected] = useSB(null);
  const [layers, setLayers] = useSB({ heatmap: true, hero: true, trajectory: false, tension: false });
  const [openAnnot, setOpenAnnot] = useSB(0);

  const lesson = window.LESSON;
  const meta = lesson && lesson.meta;
  const coaching = (lesson && lesson.coaching) || window.COPY.puzzle.commentary;

  // Hero tab data
  const heroSq = window.A_HERO;
  const heroCode = heroSq && window.A_POSITION && window.A_POSITION[heroSq];
  const heroShap = heroSq && window.A_SHAP ? (window.A_SHAP[heroSq] || 0) : 0;
  const heroFactors = (heroSq && window.A_SHAP_FACTORS && window.A_SHAP_FACTORS[heroSq]) || [];
  const heroInfluence = (heroSq && window.A_INFLUENCE_BY_PIECE && window.A_INFLUENCE_BY_PIECE[heroSq]) || {};
  const heroTrajectory = (heroSq && window.A_TRAJECTORIES && window.A_TRAJECTORIES[heroSq]) || null;

  // Tension tab data
  const tensions = window.A_TENSIONS || [];
  const [tensionIdx, setTensionIdx] = useSB(0);

  // Top 5 influence squares for hero tab.
  const topInfluenceSqs = useMB(() => {
    const entries = Object.entries(heroInfluence);
    entries.sort((a, b) => Math.abs(b[1]) - Math.abs(a[1]));
    return entries.slice(0, 5);
  }, [heroSq]);

  // Tab button style helper.
  function tabStyle(id) {
    const active = tab === id;
    return {
      appearance: 'none', cursor: 'pointer',
      border: 'none',
      borderBottom: `2px solid ${active ? C.brassDeep : 'transparent'}`,
      background: 'transparent',
      padding: '12px 20px',
      fontFamily: window.ATELIER_TYPE.display,
      fontStyle: active ? 'italic' : 'normal',
      fontSize: 17,
      color: active ? C.umber : C.umberFaint,
      transition: 'all 180ms ' + window.ATELIER_EASE,
    };
  }

  const title = (lesson && window.creativeTitle) ? window.creativeTitle(lesson.id) : ((meta && meta.title) || window.COPY.puzzle.topbarTitle);
  const kicker = (meta && meta.theme && window.creativeSubtitle) ? window.creativeSubtitle(meta.theme) : ((meta && meta.subtitle) || window.COPY.puzzle.topbarKicker);
  const sideLabel = (meta && meta.sideToMove) ? (meta.sideToMove === 'white' ? 'White to move' : 'Black to move') : window.COPY.puzzle.sideToMove;

  return (
    <div style={{ flex: 1, height: '100%', overflow: 'hidden', display: 'flex', flexDirection: 'column', background: C.bone }}>
      {/* Topbar */}
      <window.Topbar palette={C} kicker={kicker} title={title}
        rightSlot={
          <span style={{
            fontFamily: window.ATELIER_TYPE.ui, fontSize: 11, letterSpacing: 2,
            textTransform: 'uppercase', color: C.umberFaint, padding: '8px 12px',
          }}>{sideLabel}</span>
        }
      />
      {/* Tab bar */}
      <div style={{
        borderBottom: `0.6px solid ${C.umberHair}`,
        display: 'flex', paddingLeft: isMobile ? 12 : 32,
        background: C.cream,
      }}>
        <button style={tabStyle('board')} onClick={() => setTab('board')}>Board</button>
        <button style={tabStyle('heatmap')} onClick={() => setTab('heatmap')}>Heatmap</button>
        <button style={tabStyle('hero')} onClick={() => setTab('hero')}>Hero</button>
        <button style={tabStyle('tension')} onClick={() => setTab('tension')}>Tension</button>
      </div>

      {/* Tab content */}
      <div style={{ flex: 1, overflow: isTablet ? 'auto' : 'hidden' }}>
        {tab === 'board' && (
          <div style={{
            height: '100%', display: 'grid',
            gridTemplateColumns: isTablet ? '1fr' : 'minmax(0, 1fr) 380px',
          }}>
            <div style={{ overflow: 'auto', display: 'flex', flexDirection: 'column' }}>
              <div style={{
                flex: 1, display: 'flex', alignItems: 'center', justifyContent: 'center',
                padding: 24,
                background: `radial-gradient(120% 80% at 50% -10%, ${window.withAlpha(C.brassLight, 0.35)}, transparent 60%)`,
              }}>
                <div style={{
                  background: C.boneDeep, padding: 14, borderRadius: 8,
                  boxShadow: '0 30px 50px -28px rgba(42,34,27,0.45)',
                }}>
                  <window.AtelierBoard
                    palette={C}
                    layers={layers}
                    heatmapStyle={tweaks.heatmapStyle}
                    heatmapIntensity={tweaks.heatmapIntensity}
                    trajectoryStyle={tweaks.trajectoryStyle}
                    hovered={hovered}
                    selected={selected}
                    onHover={setHovered}
                    onSelect={setSelected}
                    size={isMobile ? Math.min(320, window.innerWidth - 48) : 560}
                  />
                </div>
              </div>
              <div style={{ padding: '14px 40px 22px', borderTop: `0.6px solid ${C.umberHair}`, display: 'flex', gap: 24, alignItems: 'center', background: C.bone }}>
                <window.LayerToggle palette={C} layers={layers} setLayers={setLayers} />
                <div style={{ flex: 1 }} />
                {selected ? (
                  <SelectionInfo palette={C} square={selected} clear={() => setSelected(null)} />
                ) : (
                  <div style={{
                    fontFamily: window.ATELIER_TYPE.display, fontStyle: 'italic',
                    fontSize: 14, color: C.umberFaint,
                  }}>
                    {coaching && coaching.length > 0 ? window.COPY.puzzle.selectionHint : 'Click any piece to read its influence.'}
                  </div>
                )}
              </div>
            </div>
            <aside style={{
              background: C.cream,
              borderLeft: isTablet ? 'none' : `0.6px solid ${C.umberHair}`,
              borderTop: isTablet ? `0.6px solid ${C.umberHair}` : 'none',
              padding: isMobile ? '20px 16px' : '28px 28px',
              display: 'flex', flexDirection: 'column', gap: 16,
              overflow: 'auto',
            }}>
              <window.SectionHeading palette={C} kicker={window.COPY.puzzle.coachKicker} title={window.COPY.puzzle.coachTitle} small />
              <div style={{ display: 'flex', flexDirection: 'column', gap: 12 }}>
                {coaching.map((c, i) => {
                  const open = i === openAnnot;
                  return (
                    <button key={i}
                      onClick={() => { setOpenAnnot(i); setSelected(c.anchor); }}
                      onMouseEnter={() => setHovered(c.anchor)}
                      onMouseLeave={() => setHovered(null)}
                      style={{
                        appearance: 'none', textAlign: 'left', cursor: 'pointer',
                        border: `0.6px solid ${open ? C.umber : C.umberHair}`,
                        background: open ? C.bone : 'transparent',
                        borderRadius: 12, padding: '14px 16px',
                        display: 'flex', flexDirection: 'column', gap: 8,
                        transition: 'all 220ms ' + window.ATELIER_EASE,
                      }}>
                      <div style={{ display: 'flex', alignItems: 'center', gap: 8, justifyContent: 'space-between' }}>
                        <div style={{
                          fontFamily: window.ATELIER_TYPE.ui, fontSize: 10, letterSpacing: 2.5,
                          textTransform: 'uppercase', color: C.umberFaint,
                        }}>
                          {i + 1} · {c.mood} · {c.anchor.toUpperCase()}
                        </div>
                        <MoodMark palette={C} mood={c.mood} />
                      </div>
                      {open && (
                        <p style={{
                          margin: 0,
                          fontFamily: window.ATELIER_TYPE.display, fontSize: 15.5, lineHeight: 1.55,
                          color: C.umber,
                          animation: 'atelier-fade 360ms ' + window.ATELIER_EASE + ' both',
                        }}>{c.text}</p>
                      )}
                      {!open && (
                        <div style={{
                          fontFamily: window.ATELIER_TYPE.display, fontSize: 13, lineHeight: 1.45,
                          color: C.umberFaint,
                          overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap',
                        }}>{c.text}</div>
                      )}
                    </button>
                  );
                })}
              </div>
              <div style={{ flex: 1 }} />
              <Card palette={C} padding={16}>
                <div style={{
                  fontFamily: window.ATELIER_TYPE.ui, fontSize: 9, letterSpacing: 3,
                  textTransform: 'uppercase', color: C.umberFaint, marginBottom: 6,
                }}>{window.COPY.puzzle.evalLabel}</div>
                <div style={{ display: 'flex', alignItems: 'baseline', gap: 8 }}>
                  <div style={{
                    fontFamily: window.ATELIER_TYPE.display, fontWeight: 300, fontStyle: 'italic',
                    fontSize: 30, color: C.umber,
                  }}>{window.COPY.puzzle.evalValue}</div>
                  <div style={{ fontFamily: window.ATELIER_TYPE.ui, fontSize: 11, letterSpacing: 1, color: C.umberFaint }}>
                    {window.COPY.puzzle.evalSub}
                  </div>
                </div>
                <EvalBar palette={C} value={0.72} />
              </Card>
            </aside>
          </div>
        )}

        {tab === 'heatmap' && (
          <div style={{
            height: '100%', display: 'grid',
            gridTemplateColumns: isTablet ? '1fr' : 'minmax(0, 1fr) 380px',
            overflow: isTablet ? 'auto' : 'hidden',
          }}>
            <div style={{
              display: 'flex', alignItems: 'center', justifyContent: 'center',
              padding: 24,
              background: `radial-gradient(120% 80% at 50% -10%, ${window.withAlpha(C.brassLight, 0.35)}, transparent 60%)`,
              overflow: 'auto',
            }}>
              <div style={{
                background: C.boneDeep, padding: 14, borderRadius: 8,
                boxShadow: '0 30px 50px -28px rgba(42,34,27,0.45)',
              }}>
                <window.AtelierBoard
                  palette={C}
                  layers={{ heatmap: true, hero: false, trajectory: false, tension: false }}
                  heatmapStyle={tweaks.heatmapStyle}
                  heatmapIntensity={tweaks.heatmapIntensity}
                  trajectoryStyle={tweaks.trajectoryStyle}
                  size={isMobile ? Math.min(320, window.innerWidth - 48) : 560}
                  noTrajectoryOnSelect={true}
                />
              </div>
            </div>
            <aside style={{
              background: C.cream,
              borderLeft: isTablet ? 'none' : `0.6px solid ${C.umberHair}`,
              borderTop: isTablet ? `0.6px solid ${C.umberHair}` : 'none',
              padding: isMobile ? '20px 16px' : '28px 28px',
              display: 'flex', flexDirection: 'column', gap: 16,
              overflow: 'auto',
            }}>
              <window.SectionHeading palette={C} kicker="Heatmap" title="How to read the colors" small />
              <p style={{ margin: 0, fontFamily: window.ATELIER_TYPE.display, fontSize: 15, lineHeight: 1.55, color: C.umberSoft }}>
                The board shows where each side has the most reach. Warm tones are White's influence; cool tones are Black's. The deeper the wash, the more pieces are looking at that square.
              </p>
              <div style={{ display: 'flex', gap: 10 }}>
                <div style={{
                  flex: 1, padding: '12px 14px', borderRadius: 10,
                  background: window.withAlpha(C.sienna, 0.12),
                  border: `0.6px solid ${C.sienna}`,
                }}>
                  <div style={{
                    fontFamily: window.ATELIER_TYPE.ui, fontSize: 9, letterSpacing: 3,
                    textTransform: 'uppercase', color: C.sienna, marginBottom: 4,
                  }}>White</div>
                  <div style={{
                    fontFamily: window.ATELIER_TYPE.display, fontStyle: 'italic',
                    fontSize: 14, color: C.umber,
                  }}>warm wash</div>
                </div>
                <div style={{
                  flex: 1, padding: '12px 14px', borderRadius: 10,
                  background: window.withAlpha(C.celadon, 0.18),
                  border: `0.6px solid ${C.celadon}`,
                }}>
                  <div style={{
                    fontFamily: window.ATELIER_TYPE.ui, fontSize: 9, letterSpacing: 3,
                    textTransform: 'uppercase', color: C.sage, marginBottom: 4,
                  }}>Black</div>
                  <div style={{
                    fontFamily: window.ATELIER_TYPE.display, fontStyle: 'italic',
                    fontSize: 14, color: C.umber,
                  }}>cool wash</div>
                </div>
              </div>
              <div style={{
                padding: '14px 16px', borderRadius: 12,
                background: C.bone, border: `0.6px solid ${C.umberHair}`,
              }}>
                <div style={{
                  fontFamily: window.ATELIER_TYPE.ui, fontSize: 9, letterSpacing: 3,
                  textTransform: 'uppercase', color: C.umberFaint, marginBottom: 8,
                }}>What to look for</div>
                <p style={{ margin: 0, fontFamily: window.ATELIER_TYPE.display, fontSize: 14, lineHeight: 1.55, color: C.umberSoft }}>
                  Squares where one color dominates are safer for that side. Squares where colors clash are contested — that's where the real chess happens.
                </p>
              </div>
              {coaching && coaching.length > 0 && (
                <div style={{
                  padding: '14px 16px', borderRadius: 12,
                  background: C.bone, border: `0.6px solid ${C.umberHair}`,
                }}>
                  <div style={{
                    fontFamily: window.ATELIER_TYPE.ui, fontSize: 9, letterSpacing: 3,
                    textTransform: 'uppercase', color: C.umberFaint, marginBottom: 8,
                  }}>In this position</div>
                  <p style={{ margin: 0, fontFamily: window.ATELIER_TYPE.display, fontSize: 14, lineHeight: 1.55, color: C.umberSoft }}>
                    {coaching[0].text}
                  </p>
                </div>
              )}
            </aside>
          </div>
        )}

        {tab === 'hero' && (
          <div style={{
            height: '100%', display: 'grid',
            gridTemplateColumns: isTablet ? '1fr' : 'minmax(0, 1fr) 380px',
            overflow: isTablet ? 'auto' : 'hidden',
          }}>
            {/* Board with hero + trajectory layers on */}
            <div style={{
              display: 'flex', alignItems: 'center', justifyContent: 'center',
              padding: 24,
              background: `radial-gradient(120% 80% at 50% -10%, ${window.withAlpha(C.brassLight, 0.35)}, transparent 60%)`,
              overflow: 'auto',
            }}>
              <div style={{
                background: C.boneDeep, padding: 14, borderRadius: 8,
                boxShadow: '0 30px 50px -28px rgba(42,34,27,0.45)',
              }}>
                <window.AtelierBoard
                  palette={C}
                  layers={{ heatmap: false, hero: true, trajectory: true, tension: false }}
                  heatmapStyle={tweaks.heatmapStyle}
                  heatmapIntensity={tweaks.heatmapIntensity}
                  trajectoryStyle={tweaks.trajectoryStyle}
                  size={isMobile ? Math.min(320, window.innerWidth - 48) : 560}
                  noTrajectoryOnSelect={true}
                />
              </div>
            </div>
            {/* Side: compact hero card + factors */}
            <aside style={{
              background: C.cream,
              borderLeft: isTablet ? 'none' : `0.6px solid ${C.umberHair}`,
              borderTop: isTablet ? `0.6px solid ${C.umberHair}` : 'none',
              padding: isMobile ? '20px 16px' : '28px 28px',
              display: 'flex', flexDirection: 'column', gap: 16,
              overflow: 'auto',
            }}>
              {/* Compact hero plinth */}
              <div style={{
                position: 'relative', background: C.boneDeep, borderRadius: 14,
                padding: '18px 18px 20px', border: `0.6px solid ${C.umberHair}`,
                overflow: 'hidden',
                display: 'flex', alignItems: 'center', gap: 16,
              }}>
                <div style={{
                  position: 'absolute', inset: 0,
                  background: `radial-gradient(80% 100% at 0% 50%, ${window.withAlpha(C.brassLight, 0.7)}, transparent 65%)`,
                  pointerEvents: 'none',
                }} />
                <div style={{
                  fontFamily: '"Noto Sans Symbols 2","Segoe UI Symbol",sans-serif',
                  fontSize: 64, lineHeight: 1, color: C.umber, position: 'relative',
                  filter: `drop-shadow(0 4px 6px rgba(42,34,27,0.25))`,
                }}>{heroCode ? SB_GLYPH[heroCode] : '?'}</div>
                <div style={{ position: 'relative', display: 'flex', flexDirection: 'column', gap: 4 }}>
                  <div style={{
                    fontFamily: window.ATELIER_TYPE.ui, fontSize: 9, letterSpacing: 3,
                    textTransform: 'uppercase', color: C.umberFaint,
                  }}>Hero piece · {heroSq ? heroSq.toUpperCase() : ''}</div>
                  <div style={{
                    fontFamily: window.ATELIER_TYPE.display, fontStyle: 'italic', fontWeight: 300,
                    fontSize: 30, color: C.umber, lineHeight: 1,
                  }}>{heroShap >= 0 ? '+' : ''}{heroShap.toFixed(2)}</div>
                  {heroTrajectory && heroTrajectory.length > 1 && (
                    <div style={{
                      fontFamily: window.ATELIER_TYPE.display, fontStyle: 'italic',
                      fontSize: 13, color: C.umberSoft,
                    }}>{heroTrajectory.join(' → ')}</div>
                  )}
                </div>
              </div>

              {/* Top influence squares */}
              {topInfluenceSqs.length > 0 && (
                <div>
                  <div style={{
                    fontFamily: window.ATELIER_TYPE.ui, fontSize: 9, letterSpacing: 3,
                    textTransform: 'uppercase', color: C.umberFaint, marginBottom: 8,
                  }}>Top influence squares</div>
                  <div style={{ display: 'flex', flexDirection: 'column', gap: 6 }}>
                    {topInfluenceSqs.map(([sq, v]) => (
                      <div key={sq} style={{
                        display: 'flex', alignItems: 'center', gap: 10,
                        padding: '6px 10px', borderRadius: 8,
                        background: C.bone, border: `0.6px solid ${C.umberHair}`,
                      }}>
                        <span style={{
                          fontFamily: window.ATELIER_TYPE.ui, fontSize: 11, letterSpacing: 2,
                          textTransform: 'uppercase', color: C.umberFaint, minWidth: 28,
                        }}>{sq.toUpperCase()}</span>
                        <div style={{
                          flex: 1, height: 3, borderRadius: 99,
                          background: C.umberHair, overflow: 'hidden', position: 'relative',
                        }}>
                          <div style={{
                            position: 'absolute', left: 0, top: 0, height: '100%',
                            width: `${Math.min(100, Math.abs(v) * 100)}%`,
                            background: v >= 0 ? C.sienna : C.celadon,
                          }} />
                        </div>
                        <span style={{
                          fontFamily: window.ATELIER_TYPE.display, fontStyle: 'italic',
                          fontSize: 13, color: v >= 0 ? C.sienna : C.celadon, minWidth: 40, textAlign: 'right',
                        }}>{v >= 0 ? '+' : ''}{v.toFixed(2)}</span>
                      </div>
                    ))}
                  </div>
                </div>
              )}

              {/* Factors */}
              <div>
                <div style={{
                  fontFamily: window.ATELIER_TYPE.ui, fontSize: 9, letterSpacing: 3,
                  textTransform: 'uppercase', color: C.umberFaint, marginBottom: 10,
                }}>Why this piece matters</div>
                <div style={{ display: 'flex', flexDirection: 'column', gap: 10 }}>
                  {heroFactors.length > 0
                    ? heroFactors.map((f, i) => <FactorCard key={i} palette={C} num={i + 1} {...f} />)
                    : (
                      <div style={{
                        padding: '14px', borderRadius: 12,
                        background: C.bone, border: `0.6px dashed ${C.umberHair}`,
                        fontFamily: window.ATELIER_TYPE.display, fontStyle: 'italic',
                        fontSize: 14, color: C.umberFaint,
                      }}>Engine analysis not yet run for this position.</div>
                    )}
                </div>
              </div>
            </aside>
          </div>
        )}

        {tab === 'tension' && (
          <div style={{
            height: '100%', display: 'grid',
            gridTemplateColumns: isTablet ? '1fr' : 'minmax(0, 1fr) 380px',
            overflow: isTablet ? 'auto' : 'hidden',
          }}>
            {/* Left: board with tension arrows */}
            <div style={{
              display: 'flex', alignItems: 'center', justifyContent: 'center',
              padding: 24,
              background: `radial-gradient(120% 80% at 50% -10%, ${window.withAlpha(C.brassLight, 0.35)}, transparent 60%)`,
              overflow: 'auto',
            }}>
              <div style={{
                background: C.boneDeep, padding: 14, borderRadius: 8,
                boxShadow: '0 30px 50px -28px rgba(42,34,27,0.45)',
              }}>
                <window.AtelierBoard
                  palette={C}
                  layers={{ heatmap: false, hero: false, trajectory: false, tension: true }}
                  heatmapStyle={tweaks.heatmapStyle}
                  heatmapIntensity={tweaks.heatmapIntensity}
                  trajectoryStyle={tweaks.trajectoryStyle}
                  focus={tensions[tensionIdx] ? tensions[tensionIdx].defender : (tensions[0] && tensions[0].defender)}
                  size={isMobile ? Math.min(320, window.innerWidth - 48) : 560}
                  noTrajectoryOnSelect={true}
                />
              </div>
            </div>
            {/* Right: tension list + detail merged */}
            <aside style={{
              background: C.cream,
              borderLeft: isTablet ? 'none' : `0.6px solid ${C.umberHair}`,
              borderTop: isTablet ? `0.6px solid ${C.umberHair}` : 'none',
              padding: isMobile ? '20px 16px' : '28px 28px',
              display: 'flex', flexDirection: 'column', gap: 14,
              overflow: 'auto',
            }}>
              <window.SectionHeading palette={C} kicker="Tension" title="Pressure points" small />
              {tensions.length === 0 && (
                <div style={{ fontFamily: window.ATELIER_TYPE.display, fontStyle: 'italic', fontSize: 14, color: C.umberFaint }}>
                  No tensions found in this position.
                </div>
              )}
              {tensions.map((t, i) => {
                const active = i === tensionIdx;
                const overloaded = t.load > t.support;
                const code = window.A_POSITION && window.A_POSITION[t.defender];
                return (
                  <button key={i} onClick={() => setTensionIdx(i)}
                    style={{
                      appearance: 'none', textAlign: 'left', cursor: 'pointer',
                      background: active ? C.bone : 'transparent',
                      border: `0.6px solid ${active ? (overloaded ? C.sienna : C.celadon) : C.umberHair}`,
                      borderRadius: 12, padding: '12px 14px',
                      display: 'flex', flexDirection: 'column', gap: 6,
                      transition: 'all 220ms ' + window.ATELIER_EASE,
                    }}>
                    <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between' }}>
                      <div style={{
                        fontFamily: window.ATELIER_TYPE.ui, fontSize: 10, letterSpacing: 3,
                        textTransform: 'uppercase', color: C.umberFaint,
                      }}>
                        {code ? SB_GLYPH[code] : ''} {t.defender.toUpperCase()}
                      </div>
                      <window.Pill palette={C} tone={overloaded ? 'sienna' : 'celadon'}>
                        {t.load}/{t.support}
                      </window.Pill>
                    </div>
                    <div style={{
                      fontFamily: window.ATELIER_TYPE.display, fontStyle: 'italic',
                      fontSize: 14, color: C.umber,
                    }}>{overloaded ? 'Overloaded' : 'Balanced'}</div>
                    {active && (
                      <div style={{
                        fontFamily: window.ATELIER_TYPE.display, fontSize: 13,
                        color: C.umberSoft, lineHeight: 1.45,
                      }}>{t.note}</div>
                    )}
                  </button>
                );
              })}
              {tensions.length > 0 && (() => {
                const cur = tensions[tensionIdx] || tensions[0];
                const overloaded = cur.load > cur.support;
                return (
                  <>
                    <div style={{
                      padding: '12px 14px', background: C.bone, borderRadius: 12,
                      border: `0.6px solid ${C.umberHair}`,
                    }}>
                      <div style={{
                        fontFamily: window.ATELIER_TYPE.ui, fontSize: 9, letterSpacing: 3,
                        textTransform: 'uppercase', color: C.umberFaint, marginBottom: 6,
                      }}>Attackers ({cur.load})</div>
                      <ul style={{ margin: 0, padding: 0, listStyle: 'none', display: 'flex', flexDirection: 'column', gap: 4 }}>
                        {cur.attackers.map((a, i) => (
                          <li key={i} style={{ display: 'flex', alignItems: 'baseline', gap: 8, fontFamily: window.ATELIER_TYPE.display, fontSize: 13, color: C.umber }}>
                            <span style={{ fontFamily: window.ATELIER_TYPE.ui, fontSize: 10, letterSpacing: 2, color: C.umberFaint, minWidth: 28 }}>{a.from.toUpperCase()}</span>
                            <span style={{ fontStyle: 'italic' }}>{a.kind}</span>
                          </li>
                        ))}
                      </ul>
                    </div>
                    <div style={{
                      padding: '12px 14px', background: C.bone, borderRadius: 12,
                      border: `0.6px solid ${C.umberHair}`,
                    }}>
                      <div style={{
                        fontFamily: window.ATELIER_TYPE.ui, fontSize: 9, letterSpacing: 3,
                        textTransform: 'uppercase', color: C.umberFaint, marginBottom: 6,
                      }}>Supporters ({cur.support})</div>
                      <ul style={{ margin: 0, padding: 0, listStyle: 'none', display: 'flex', flexDirection: 'column', gap: 4 }}>
                        {cur.supporters.map((a, i) => (
                          <li key={i} style={{ display: 'flex', alignItems: 'baseline', gap: 8, fontFamily: window.ATELIER_TYPE.display, fontSize: 13, color: C.umber }}>
                            <span style={{ fontFamily: window.ATELIER_TYPE.ui, fontSize: 10, letterSpacing: 2, color: C.umberFaint, minWidth: 28 }}>{a.from.toUpperCase()}</span>
                            <span style={{ fontStyle: 'italic' }}>{a.kind}</span>
                          </li>
                        ))}
                      </ul>
                    </div>
                    <div style={{
                      padding: '14px 16px', borderRadius: 12,
                      background: overloaded ? window.withAlpha(C.sienna, 0.10) : window.withAlpha(C.celadon, 0.12),
                      border: `0.6px solid ${overloaded ? C.sienna : C.celadon}`,
                    }}>
                      <div style={{
                        fontFamily: window.ATELIER_TYPE.ui, fontSize: 9, letterSpacing: 3,
                        textTransform: 'uppercase', color: overloaded ? C.sienna : C.sage, marginBottom: 6,
                      }}>Load vs support</div>
                      <div style={{
                        fontFamily: window.ATELIER_TYPE.display, fontStyle: 'italic', fontWeight: 300,
                        fontSize: 24, color: overloaded ? C.sienna : C.sage, lineHeight: 1,
                      }}>{cur.load} / {cur.support}</div>
                    </div>
                  </>
                );
              })()}
            </aside>
          </div>
        )}
      </div>
    </div>
  );
}

// === Helper components ========================================================

function EvalBar({ palette, value }) {
  const C = palette;
  const w = Math.max(0, Math.min(1, value));
  return (
    <div style={{
      marginTop: 10,
      height: 6, borderRadius: 99,
      background: C.celadonSoft,
      overflow: 'hidden',
      position: 'relative',
    }}>
      <div style={{
        position: 'absolute', left: 0, top: 0,
        height: '100%', width: `${w * 100}%`,
        background: `linear-gradient(90deg, ${C.brass}, ${C.sienna})`,
        transition: 'width 320ms ' + window.ATELIER_EASE,
      }} />
      <div style={{ position: 'absolute', left: '50%', top: -2, bottom: -2, width: 1, background: C.umberHair }} />
    </div>
  );
}

function MoodMark({ palette, mood }) {
  const C = palette;
  const mark = {
    curious: { glyph: '·', color: C.brass },
    warning: { glyph: '!', color: C.sienna },
    discovery: { glyph: '✦', color: C.brassDeep },
  }[mood] || { glyph: '·', color: C.brass };
  return (
    <span style={{
      width: 22, height: 22, borderRadius: 99,
      display: 'inline-flex', alignItems: 'center', justifyContent: 'center',
      background: window.withAlpha(mark.color, 0.18),
      color: mark.color,
      fontFamily: window.ATELIER_TYPE.display,
      fontSize: 13,
    }}>{mark.glyph}</span>
  );
}

function SelectionInfo({ palette, square, clear }) {
  const C = palette;
  const code = window.A_POSITION[square];
  if (!code) return null;
  const shap = window.A_SHAP[square] || 0;
  const trajectory = window.A_TRAJECTORIES[square];
  return (
    <div style={{
      display: 'flex', alignItems: 'center', gap: 14,
      background: C.cream, border: `0.6px solid ${C.umberHair}`,
      borderRadius: 99, padding: '6px 8px 6px 14px',
    }}>
      <div style={{
        fontFamily: '"Noto Sans Symbols 2","Segoe UI Symbol",sans-serif',
        fontSize: 22, color: C.umber, lineHeight: 1,
      }}>{window.B_GLYPH[code]}</div>
      <div style={{
        fontFamily: window.ATELIER_TYPE.ui, fontSize: 11, letterSpacing: 1.5,
        textTransform: 'uppercase', color: C.umberFaint,
      }}>{square.toUpperCase()}</div>
      <div style={{
        fontFamily: window.ATELIER_TYPE.display, fontStyle: 'italic',
        fontSize: 16, color: shap >= 0 ? C.sienna : C.celadon,
      }}>score {shap >= 0 ? '+' : ''}{shap.toFixed(2)}</div>
      {trajectory && (
        <div style={{
          fontFamily: window.ATELIER_TYPE.ui, fontSize: 11, letterSpacing: 1,
          color: C.umberSoft,
        }}>route: {trajectory.join(' → ')}</div>
      )}
      <button onClick={clear} style={{
        appearance: 'none', cursor: 'pointer',
        border: 'none', background: C.umber, color: C.cream,
        width: 24, height: 24, borderRadius: 99, marginLeft: 4,
        fontFamily: window.ATELIER_TYPE.ui, fontSize: 12,
      }}>×</button>
    </div>
  );
}

// === 5. HERO PIECE DEEP-DIVE (legacy standalone screen) =======================
function HeroPieceScreen({ palette, tweaks }) {
  const C = palette;
  const { isMobile, isTablet } = window.useBreakpoint();
  const piece = window.A_HERO;
  const factors = window.A_SHAP_FACTORS[piece] || [];
  const total = window.A_SHAP[piece];

  return (
    <div style={{ flex: 1, height: '100%', overflow: 'auto', background: C.bone }}>
      <window.Topbar palette={C} kicker={window.COPY.hero.topbarKicker} title={window.COPY.hero.topbarTitle}
        rightSlot={<window.Pill palette={C} tone="brass">{window.COPY.hero.badge}</window.Pill>}
      />
      <div className="atelier-hero-grid" style={{
        padding: isMobile ? '20px 16px 40px' : '40px 48px 56px',
        display: 'grid',
        gridTemplateColumns: isTablet ? '1fr' : '420px 1fr',
        gap: 36,
      }}>
        <div>
          <div style={{
            position: 'relative',
            background: C.boneDeep,
            borderRadius: 14,
            padding: '40px 24px 56px',
            border: `0.6px solid ${C.umberHair}`,
            overflow: 'hidden',
            minHeight: 460,
          }}>
            <div style={{
              position: 'absolute', inset: 0,
              background: `radial-gradient(80% 50% at 50% 0%, ${window.withAlpha(C.brassLight, 0.7)}, transparent 65%)`,
              pointerEvents: 'none',
            }} />
            <div style={{ position: 'relative', display: 'flex', flexDirection: 'column', alignItems: 'center', gap: 12 }}>
              <div style={{
                fontFamily: window.ATELIER_TYPE.ui, fontSize: 10, letterSpacing: 3.5,
                textTransform: 'uppercase', color: C.umberFaint,
              }}>{window.COPY.hero.pieceLabel}</div>
              <div style={{
                fontFamily: '"Noto Sans Symbols 2","Segoe UI Symbol",sans-serif',
                fontSize: 220, lineHeight: 1, color: C.umber,
                filter: `drop-shadow(0 8px 8px rgba(42,34,27,0.25)) drop-shadow(0 0 2px ${C.brassLight})`,
              }}>{SB_GLYPH[window.A_POSITION && window.A_POSITION[piece]] || '♞'}</div>
              <div style={{
                fontFamily: window.ATELIER_TYPE.display, fontStyle: 'italic', fontWeight: 300,
                fontSize: 56, color: C.umber, lineHeight: 1,
              }}>{total >= 0 ? '+' : ''}{(total || 0).toFixed(2)}</div>
              <div style={{
                fontFamily: window.ATELIER_TYPE.ui, fontSize: 11, letterSpacing: 2,
                textTransform: 'uppercase', color: C.umberFaint,
              }}>{window.COPY.hero.shapLabel}</div>
              <div style={{
                marginTop: 18, padding: '10px 18px',
                background: C.cream, border: `0.6px solid ${C.brass}`,
                borderRadius: 99,
                fontFamily: window.ATELIER_TYPE.display, fontStyle: 'italic',
                fontSize: 13, color: C.umberSoft,
              }}>{window.COPY.hero.quote}</div>
            </div>
          </div>
          <div style={{
            marginTop: 14,
            display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 10,
          }}>
            {Object.values(window.COPY.hero.stats).map((s) => (
              <MiniStat key={s.label} palette={C} label={s.label} value={s.value} />
            ))}
          </div>
        </div>
        <div>
          <window.SectionHeading palette={C} kicker={window.COPY.hero.factorsSectionKicker}
            title={window.COPY.hero.factorsSectionTitle}
          />
          <div style={{ marginTop: 20, display: 'flex', flexDirection: 'column', gap: 12 }}>
            {factors.length > 0
              ? factors.map((f, i) => <FactorCard key={i} palette={C} num={i + 1} {...f} />)
              : (
                <div style={{
                  padding: '20px', borderRadius: 12,
                  background: C.cream, border: `0.6px dashed ${C.umberHair}`,
                  fontFamily: window.ATELIER_TYPE.display, fontStyle: 'italic',
                  fontSize: 15, color: C.umberFaint,
                }}>Engine analysis not yet run for this position.</div>
              )}
            {factors.length > 0 && (
              <div style={{
                marginTop: 6,
                display: 'flex', alignItems: 'center', justifyContent: 'space-between',
                padding: '14px 18px',
                borderTop: `0.6px dashed ${C.umberHair}`,
              }}>
                <div style={{
                  fontFamily: window.ATELIER_TYPE.ui, fontSize: 10, letterSpacing: 3,
                  textTransform: 'uppercase', color: C.umberFaint,
                }}>{window.COPY.hero.sumLabel}</div>
                <div style={{
                  fontFamily: window.ATELIER_TYPE.display, fontStyle: 'italic',
                  fontSize: 26, color: C.sienna,
                }}>{total >= 0 ? '+' : ''}{(total || 0).toFixed(2)}</div>
              </div>
            )}
          </div>
        </div>
      </div>
    </div>
  );
}

function MiniStat({ palette, label, value }) {
  const C = palette;
  return (
    <div style={{
      padding: '12px 14px', background: C.cream, borderRadius: 10,
      border: `0.6px solid ${C.umberHair}`,
    }}>
      <div style={{
        fontFamily: window.ATELIER_TYPE.ui, fontSize: 9, letterSpacing: 2.5,
        textTransform: 'uppercase', color: C.umberFaint,
      }}>{label}</div>
      <div style={{
        marginTop: 4,
        fontFamily: window.ATELIER_TYPE.display, fontWeight: 400,
        fontSize: 18, color: C.umber,
      }}>{value}</div>
    </div>
  );
}

function FactorCard({ palette, num, label, value }) {
  const C = palette;
  const v = Math.abs(value);
  const positive = value >= 0;
  const width = Math.min(100, v * 100);
  return (
    <div style={{
      padding: '16px 20px',
      background: C.cream, borderRadius: 12,
      border: `0.6px solid ${C.umberHair}`,
      display: 'grid', gridTemplateColumns: '24px 1fr 80px', alignItems: 'center', gap: 14,
    }}>
      <div style={{
        fontFamily: window.ATELIER_TYPE.ui, fontSize: 11, letterSpacing: 1,
        color: C.umberFaint,
      }}>{String(num).padStart(2, '0')}</div>
      <div>
        <div style={{
          fontFamily: window.ATELIER_TYPE.display, fontStyle: 'italic',
          fontSize: 17, color: C.umber, marginBottom: 8,
        }}>{label}</div>
        <div style={{
          height: 3, borderRadius: 99,
          background: C.umberHair, position: 'relative', overflow: 'hidden',
        }}>
          <div style={{
            position: 'absolute', left: 0, top: 0, height: '100%',
            width: `${width}%`,
            background: positive ? C.sienna : C.celadon,
          }} />
        </div>
      </div>
      <div style={{
        textAlign: 'right',
        fontFamily: window.ATELIER_TYPE.display, fontStyle: 'italic',
        fontSize: 20,
        color: positive ? C.sienna : C.celadon,
      }}>{positive ? '+' : ''}{value.toFixed(2)}</div>
    </div>
  );
}

// === 6. TENSION EXPLORER (legacy standalone screen) ==========================
function TensionScreen({ palette, tweaks }) {
  const C = palette;
  const { isMobile, isTablet } = window.useBreakpoint();
  const tensions = window.A_TENSIONS;
  const [selectedIdx, setSelectedIdx] = useSB(0);
  const cur = tensions[selectedIdx];

  return (
    <div className="atelier-layout-three-col" style={{ flex: 1, height: isTablet ? 'auto' : '100%', overflow: isTablet ? 'auto' : 'hidden', display: 'grid',
      gridTemplateColumns: isTablet ? '1fr' : '340px minmax(0, 1fr) 340px',
      background: C.bone,
    }}>
      <aside style={{
        padding: isMobile ? '20px 16px' : '28px 24px',
        borderRight: isTablet ? 'none' : `0.6px solid ${C.umberHair}`,
        borderBottom: isTablet ? `0.6px solid ${C.umberHair}` : 'none',
        background: C.bone,
        overflow: 'auto',
        display: 'flex', flexDirection: 'column', gap: 18,
      }}>
        <window.SectionHeading palette={C} kicker={window.COPY.tension.listSectionKicker} title={window.COPY.tension.listSectionTitle} small />
        <div style={{ display: 'flex', flexDirection: 'column', gap: 10 }}>
          {tensions.map((t, i) => {
            const active = i === selectedIdx;
            const overloaded = t.load > t.support;
            return (
              <button key={i} onClick={() => setSelectedIdx(i)}
                style={{
                  appearance: 'none', textAlign: 'left', cursor: 'pointer',
                  background: active ? C.cream : 'transparent',
                  border: `0.6px solid ${active ? (overloaded ? C.sienna : C.celadon) : C.umberHair}`,
                  borderRadius: 12, padding: '14px 16px',
                  display: 'flex', flexDirection: 'column', gap: 8,
                  transition: 'all 220ms ' + window.ATELIER_EASE,
                }}>
                <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between' }}>
                  <div style={{
                    fontFamily: window.ATELIER_TYPE.ui, fontSize: 10, letterSpacing: 3,
                    textTransform: 'uppercase', color: C.umberFaint,
                  }}>{window.COPY.tension.defenderLabel(t.defender)}</div>
                  <window.Pill palette={C} tone={overloaded ? 'sienna' : 'celadon'}>
                    {t.load}/{t.support}
                  </window.Pill>
                </div>
                <div style={{
                  fontFamily: window.ATELIER_TYPE.display, fontStyle: 'italic',
                  fontSize: 17, color: C.umber,
                }}>{overloaded ? window.COPY.tension.overloadedLabel : window.COPY.tension.balancedLabel}</div>
                <div style={{
                  fontFamily: window.ATELIER_TYPE.display, fontSize: 13,
                  color: C.umberSoft, lineHeight: 1.45,
                  display: '-webkit-box', WebkitLineClamp: 2, WebkitBoxOrient: 'vertical',
                  overflow: 'hidden',
                }}>{t.note}</div>
              </button>
            );
          })}
        </div>
        <div style={{
          padding: '16px',
          background: C.cream, borderRadius: 12,
          border: `0.6px dashed ${C.umberHair}`,
        }}>
          <div style={{
            fontFamily: window.ATELIER_TYPE.ui, fontSize: 9, letterSpacing: 3,
            textTransform: 'uppercase', color: C.umberFaint, marginBottom: 8,
          }}>{window.COPY.tension.howToReadTitle}</div>
          <p style={{ margin: 0, fontFamily: window.ATELIER_TYPE.display, fontSize: 13, lineHeight: 1.55, color: C.umberSoft }}>
            {window.COPY.tension.howToReadBody}
          </p>
        </div>
      </aside>
      <div style={{ display: 'flex', flexDirection: 'column' }}>
        <window.Topbar palette={C} kicker={window.COPY.tension.topbarKicker} title={window.COPY.tension.topbarTitle} rightSlot={null} />
        <div style={{
          flex: 1, display: 'flex', alignItems: 'center', justifyContent: 'center',
          padding: 24,
          background: `radial-gradient(120% 80% at 50% -10%, ${window.withAlpha(C.brassLight, 0.35)}, transparent 60%)`,
        }}>
          <div style={{
            background: C.boneDeep, padding: 14, borderRadius: 8,
            boxShadow: '0 30px 50px -28px rgba(42,34,27,0.45)',
          }}>
            <window.AtelierBoard
              palette={C}
              layers={{ heatmap: false, hero: false, trajectory: false, tension: true }}
              heatmapStyle={tweaks.heatmapStyle}
              heatmapIntensity={tweaks.heatmapIntensity}
              trajectoryStyle={tweaks.trajectoryStyle}
              focus={cur && cur.defender}
              size={isMobile ? Math.min(320, window.innerWidth - 48) : 480}
            />
          </div>
        </div>
      </div>
      <aside style={{
        padding: isMobile ? '20px 16px' : '28px 24px',
        borderLeft: isTablet ? 'none' : `0.6px solid ${C.umberHair}`,
        borderTop: isTablet ? `0.6px solid ${C.umberHair}` : 'none',
        background: C.cream,
        overflow: 'auto',
        display: 'flex', flexDirection: 'column', gap: 16,
      }}>
        <window.SectionHeading palette={C} kicker={window.COPY.tension.defenderLabel(cur.defender)} title={cur.load > cur.support ? window.COPY.tension.breakdownTitleOverloaded(cur.defender) : window.COPY.tension.breakdownTitleBalanced} small />
        <p style={{ margin: 0, fontFamily: window.ATELIER_TYPE.display, fontSize: 16, lineHeight: 1.55, color: C.umberSoft }}>{cur.note}</p>
        <div style={{ padding: '14px 16px', background: C.bone, borderRadius: 12, border: `0.6px solid ${C.umberHair}` }}>
          <div style={{
            fontFamily: window.ATELIER_TYPE.ui, fontSize: 9, letterSpacing: 3,
            textTransform: 'uppercase', color: C.umberFaint, marginBottom: 8,
          }}>{window.COPY.tension.attackersLabel(cur.load)}</div>
          <ul style={{ margin: 0, padding: 0, listStyle: 'none', display: 'flex', flexDirection: 'column', gap: 6 }}>
            {cur.attackers.map((a, i) => (
              <li key={i} style={{ display: 'flex', alignItems: 'baseline', gap: 8, fontFamily: window.ATELIER_TYPE.display, fontSize: 15, color: C.umber }}>
                <span style={{ fontFamily: window.ATELIER_TYPE.ui, fontSize: 10, letterSpacing: 2, color: C.umberFaint, minWidth: 28 }}>{a.from.toUpperCase()}</span>
                <span style={{ fontStyle: 'italic' }}>{a.kind}</span>
              </li>
            ))}
          </ul>
        </div>
        <div style={{ padding: '14px 16px', background: C.bone, borderRadius: 12, border: `0.6px solid ${C.umberHair}` }}>
          <div style={{
            fontFamily: window.ATELIER_TYPE.ui, fontSize: 9, letterSpacing: 3,
            textTransform: 'uppercase', color: C.umberFaint, marginBottom: 8,
          }}>{window.COPY.tension.supportersLabel(cur.support)}</div>
          <ul style={{ margin: 0, padding: 0, listStyle: 'none', display: 'flex', flexDirection: 'column', gap: 6 }}>
            {cur.supporters.map((a, i) => (
              <li key={i} style={{ display: 'flex', alignItems: 'baseline', gap: 8, fontFamily: window.ATELIER_TYPE.display, fontSize: 15, color: C.umber }}>
                <span style={{ fontFamily: window.ATELIER_TYPE.ui, fontSize: 10, letterSpacing: 2, color: C.umberFaint, minWidth: 28 }}>{a.from.toUpperCase()}</span>
                <span style={{ fontStyle: 'italic' }}>{a.kind}</span>
              </li>
            ))}
          </ul>
        </div>
        <div style={{
          padding: '16px', borderRadius: 12,
          background: cur.load > cur.support ? window.withAlpha(C.sienna, 0.10) : window.withAlpha(C.celadon, 0.12),
          border: `0.6px solid ${cur.load > cur.support ? C.sienna : C.celadon}`,
        }}>
          <div style={{
            fontFamily: window.ATELIER_TYPE.ui, fontSize: 9, letterSpacing: 3,
            textTransform: 'uppercase', color: cur.load > cur.support ? C.sienna : C.sage, marginBottom: 8,
          }}>{window.COPY.tension.strainLabel}</div>
          <div style={{
            fontFamily: window.ATELIER_TYPE.display, fontStyle: 'italic', fontWeight: 300,
            fontSize: 30, color: cur.load > cur.support ? C.sienna : C.sage, lineHeight: 1,
          }}>{cur.load} / {cur.support}</div>
          <div style={{ marginTop: 8, fontFamily: window.ATELIER_TYPE.display, fontSize: 14, color: C.umberSoft }}>
            {cur.load > cur.support ? window.COPY.tension.strainOverloaded : window.COPY.tension.strainBalanced}
          </div>
        </div>
      </aside>
    </div>
  );
}

Object.assign(window, {
  LessonScreen, PuzzleScreen, HeroPieceScreen, TensionScreen,
  EvalBar, MoodMark, SelectionInfo, MiniStat, FactorCard,
});
