// Shared design tokens + layout primitives for all four parts.
// All scenes use the <Scene> slot-based layout to support portrait AND landscape.

const theme = {
  colors: {
    cream:   '#f5ecd9',
    paper:   '#faf3e3',
    ink:     '#2a2420',
    inkSoft: '#574b42',
    pencil:  '#8a7a6b',
    rule:    '#c7b99c',
    tomato:  '#d9543a',
    mustard: '#e0a43a',
    teal:    '#2f6d68',
    sage:    '#8ca87a',
    rose:    '#c87b7b',
    shadow:  'rgba(58, 42, 30, 0.15)',
  },
  fonts: {
    title: '"Noto Serif SC", "Source Han Serif SC", ui-serif, serif',
    body:  '"Noto Sans SC", "Source Han Sans SC", "PingFang SC", sans-serif',
    mono:  '"JetBrains Mono", "Menlo", ui-monospace, monospace',
    hand:  '"Noto Sans SC", "Source Han Sans SC", sans-serif',
  },
};

// ── Orientation context ─────────────────────────────────────────────────────
const OrientationContext = React.createContext('portrait');
const useOrientation = () => React.useContext(OrientationContext);
const isLandscape = () => React.useContext(OrientationContext) === 'landscape';

// ── Paper background ────────────────────────────────────────────────────────
function PaperBg({ dark = false }) {
  if (dark) {
    return <div style={{ position:'absolute', inset:0, background: theme.colors.ink }}/>;
  }
  return (
    <div style={{ position: 'absolute', inset: 0, background: theme.colors.cream, overflow:'hidden' }}>
      <div style={{
        position: 'absolute', inset: 0,
        backgroundImage: 'radial-gradient(rgba(120,90,50,0.06) 1px, transparent 1px)',
        backgroundSize: '3px 3px', opacity: 0.8,
      }}/>
      <div style={{
        position: 'absolute', inset: 0,
        backgroundImage: `
          linear-gradient(to right, rgba(139,117,86,0.08) 1px, transparent 1px),
          linear-gradient(to bottom, rgba(139,117,86,0.08) 1px, transparent 1px)`,
        backgroundSize: '48px 48px',
      }}/>
      <div style={{
        position: 'absolute', inset: 0,
        background: 'radial-gradient(ellipse at center, transparent 40%, rgba(58,42,30,0.08) 100%)',
      }}/>
    </div>
  );
}

// ── ChapterBar: responsive ──────────────────────────────────────────────────
function ChapterBar({ chapter, section, color = theme.colors.tomato }) {
  const orient = useOrientation();
  const pad = orient === 'landscape' ? 30 : 40;
  return (
    <div style={{
      position: 'absolute',
      top: pad, left: pad, right: pad,
      display: 'flex', alignItems: 'center', gap: 14,
      fontFamily: theme.fonts.body,
      zIndex: 5,
    }}>
      <div style={{ width: 10, height: 10, borderRadius: 5, background: color, flexShrink: 0 }}/>
      <div style={{ fontSize: orient === 'landscape' ? 18 : 22, fontWeight: 600, color: theme.colors.ink, letterSpacing: '0.08em' }}>
        {chapter}
      </div>
      <div style={{ flex: 1, height: 1, background: theme.colors.rule }}/>
      <div style={{ fontSize: orient === 'landscape' ? 16 : 20, color: theme.colors.pencil, fontFamily: theme.fonts.mono }}>
        {section}
      </div>
    </div>
  );
}

// ── Subtitle bar ────────────────────────────────────────────────────────────
function Subtitle({ text }) {
  const orient = useOrientation();
  const bottom = orient === 'landscape' ? 40 : 100;
  const fontSize = orient === 'landscape' ? 26 : 34;
  const pad = orient === 'landscape' ? '16px 24px' : '22px 30px';
  const lr = orient === 'landscape' ? 60 : 60;
  return (
    <div style={{
      position: 'absolute', left: lr, right: lr, bottom,
      padding: pad,
      background: 'rgba(42,36,32,0.92)',
      color: theme.colors.cream,
      borderRadius: 14,
      fontFamily: theme.fonts.body,
      fontSize, lineHeight: 1.45, fontWeight: 400,
      boxShadow: `0 10px 40px ${theme.colors.shadow}`,
      zIndex: 6,
    }}>{text}</div>
  );
}

// ── Scene: slot-based layout that auto-adapts to orientation ────────────────
// Slots: titleSlot, mainSlot (rendered differently per orientation).
// Portrait: title at top ~140, main below ~540-1800
// Landscape: title left column, main right column
function Scene({ title, main, sub, chapter, section, color, orient: orientOverride }) {
  const orient = orientOverride || useOrientation();

  if (orient === 'landscape') {
    return (
      <>
        <PaperBg />
        {chapter && <ChapterBar chapter={chapter} section={section} color={color}/>}
        <div style={{
          position: 'absolute', left: 60, top: 110, width: 620, bottom: 120,
          display: 'flex', flexDirection: 'column', justifyContent: 'flex-start',
        }}>
          {title}
        </div>
        <div style={{
          position: 'absolute', left: 720, top: 110, right: 60, bottom: 120,
          display: 'flex', flexDirection: 'column', justifyContent: 'center',
          overflow: 'hidden',
        }}>
          {main}
        </div>
        {sub && <Subtitle text={sub}/>}
      </>
    );
  }

  // Portrait
  return (
    <>
      <PaperBg />
      {chapter && <ChapterBar chapter={chapter} section={section} color={color}/>}
      <div style={{
        position: 'absolute', left: 60, top: 130, right: 60,
      }}>
        {title}
      </div>
      <div style={{
        position: 'absolute', left: 60, top: 560, right: 60, bottom: 220,
        display: 'flex', flexDirection: 'column', justifyContent: 'flex-start',
      }}>
        {main}
      </div>
      {sub && <Subtitle text={sub}/>}
    </>
  );
}

// ── MethodTitleBlock: standard title slot content ───────────────────────────
function MethodTitleBlock({ number, chinese, english, color = theme.colors.tomato, localTime = 1 }) {
  const orient = useOrientation();
  const op = clamp(localTime/0.4, 0, 1);
  const titleSize = orient === 'landscape' ? 86 : 100;
  return (
    <div style={{ opacity: op }}>
      <div style={{
        fontFamily: theme.fonts.mono, fontSize: orient === 'landscape' ? 22 : 26,
        color, letterSpacing: '0.2em',
      }}>METHOD {number}</div>
      <div style={{
        fontFamily: theme.fonts.title, fontSize: titleSize, fontWeight: 900,
        color: theme.colors.ink, marginTop: 12, lineHeight: 1.05,
        wordBreak: 'keep-all',
      }}>{chinese}</div>
      {english && (
        <div style={{
          fontFamily: theme.fonts.body, fontSize: orient === 'landscape' ? 22 : 26,
          color: theme.colors.pencil, marginTop: 16, letterSpacing: '0.04em',
        }}>{english}</div>
      )}
    </div>
  );
}

// ── Opening scene shell (dark bg, big number in corner) ─────────────────────
function OpeningShell({ partNumber, title, subtitle, chips, localTime }) {
  const orient = useOrientation();

  if (orient === 'landscape') {
    return (
      <>
        <PaperBg dark/>
        <div style={{
          position:'absolute', top: 60, right: 60,
          fontFamily: theme.fonts.mono, fontSize: 220, fontWeight: 900,
          color: 'rgba(224,164,58,0.18)', lineHeight: 0.9,
        }}>{partNumber}</div>
        <div style={{
          position: 'absolute', left: 80, top: 140, width: 1400,
          opacity: clamp(localTime/0.5, 0, 1),
        }}>
          <div style={{ fontFamily: theme.fonts.mono, fontSize: 26, color: theme.colors.mustard, letterSpacing: '0.3em', marginBottom: 24 }}>
            PART {partNumber} / 04
          </div>
          <div style={{ fontFamily: theme.fonts.title, fontSize: 130, fontWeight: 900, color: theme.colors.cream, lineHeight: 1.05, wordBreak:'keep-all' }}>
            {title}
          </div>
          <div style={{ fontFamily: theme.fonts.body, fontSize: 32, color: theme.colors.rule, marginTop: 30, fontWeight: 300 }}>
            {subtitle}
          </div>
          <div style={{ marginTop: 40, display: 'flex', gap: 12, flexWrap: 'wrap', maxWidth: 1600 }}>
            {chips.map((n, i) => (
              <span key={i} style={{
                padding: '8px 18px', border: `1.5px solid ${theme.colors.mustard}`, borderRadius: 999,
                color: theme.colors.mustard, fontFamily: theme.fonts.body, fontSize: 22,
                opacity: clamp((localTime - 0.8 - i*0.08)/0.3, 0, 1),
              }}>{n}</span>
            ))}
          </div>
        </div>
      </>
    );
  }

  // Portrait
  return (
    <>
      <PaperBg dark/>
      <div style={{
        position:'absolute', top: 120, right: 80,
        fontFamily: theme.fonts.mono, fontSize: 260, fontWeight: 900,
        color: 'rgba(224,164,58,0.18)', lineHeight: 0.9,
      }}>{partNumber}</div>
      <div style={{
        position: 'absolute', left: 80, right: 80, top: 680,
        opacity: clamp(localTime/0.5, 0, 1),
      }}>
        <div style={{ fontFamily: theme.fonts.mono, fontSize: 28, color: theme.colors.mustard, letterSpacing: '0.3em', marginBottom: 40 }}>
          PART {partNumber} / 04
        </div>
        <div style={{ fontFamily: theme.fonts.title, fontSize: 140, fontWeight: 900, color: theme.colors.cream, lineHeight: 1.05, wordBreak:'keep-all' }}>
          {title}
        </div>
        <div style={{ fontFamily: theme.fonts.body, fontSize: 36, color: theme.colors.rule, marginTop: 40, fontWeight: 300 }}>
          {subtitle}
        </div>
        <div style={{ marginTop: 50, display: 'flex', gap: 14, flexWrap: 'wrap' }}>
          {chips.map((n, i) => (
            <span key={i} style={{
              padding: '10px 18px', border: `1.5px solid ${theme.colors.mustard}`, borderRadius: 999,
              color: theme.colors.mustard, fontFamily: theme.fonts.body, fontSize: 22,
              opacity: clamp((localTime - 0.8 - i*0.08)/0.3, 0, 1),
            }}>{n}</span>
          ))}
        </div>
      </div>
    </>
  );
}

// ── LocalSprite (same as before) ────────────────────────────────────────────
function LocalSprite({ start = 0, end = Infinity, children }) {
  const parent = useSprite();
  const lt = parent.localTime;
  const visible = lt >= start && lt <= end;
  if (!visible) return null;
  const duration = end - start;
  const localTime = Math.max(0, lt - start);
  const progress = duration > 0 && isFinite(duration) ? Math.min(1, Math.max(0, localTime / duration)) : 0;
  const value = { localTime, progress, duration, visible };
  return (
    <SpriteContext.Provider value={value}>
      {typeof children === 'function' ? children(value) : children}
    </SpriteContext.Provider>
  );
}

// ── ChapterComparison: summary panel (dark bg, list of methods) ─────────────
function ChapterComparison({ heading, items, footer, localTime }) {
  const orient = useOrientation();

  if (orient === 'landscape') {
    return (
      <>
        <PaperBg dark/>
        <div style={{
          position: 'absolute', left: 60, top: 80, width: 700,
          opacity: clamp(localTime/0.4, 0, 1),
        }}>
          <div style={{ fontFamily: theme.fonts.mono, fontSize: 22, color: theme.colors.mustard, letterSpacing: '0.2em' }}>CHAPTER SUMMARY</div>
          <div style={{ fontFamily: theme.fonts.title, fontSize: 70, fontWeight: 900, color: theme.colors.cream, marginTop: 12, lineHeight: 1.05 }}>
            {heading}
          </div>
          {footer && (
            <div style={{
              marginTop: 40, padding: 24, background: theme.colors.mustard, color: theme.colors.ink,
              borderRadius: 14, fontFamily: theme.fonts.body, fontSize: 22, fontWeight: 600,
              textAlign: 'center', lineHeight: 1.5,
              opacity: clamp((localTime - 2.5)/0.5, 0, 1),
            }}>{footer}</div>
          )}
        </div>
        <div style={{ position: 'absolute', right: 60, top: 80, width: 1040, bottom: 80,
          display: 'flex', flexDirection: 'column', justifyContent: 'center', gap: 14 }}>
          {items.map((m, i) => {
            const show = clamp((localTime - 0.5 - i*0.25)/0.4, 0, 1);
            return (
              <div key={i} style={{
                padding: 20, background: 'rgba(250,243,227,0.06)',
                border: `2px solid ${m.color}`, borderRadius: 14,
                opacity: show, transform: `translateX(${(1-show)*-30}px)`,
              }}>
                <div style={{ fontFamily: theme.fonts.body, fontSize: 26, fontWeight: 700, color: theme.colors.cream }}>{m.name}</div>
                <div style={{ fontFamily: theme.fonts.body, fontSize: 20, color: m.color, marginTop: 6 }}>→ {m.use}</div>
              </div>
            );
          })}
        </div>
      </>
    );
  }

  // Portrait
  return (
    <>
      <PaperBg dark/>
      <div style={{ position: 'absolute', left: 60, top: 80, opacity: clamp(localTime/0.4, 0, 1) }}>
        <div style={{ fontFamily: theme.fonts.mono, fontSize: 24, color: theme.colors.mustard, letterSpacing: '0.2em' }}>CHAPTER SUMMARY</div>
        <div style={{ fontFamily: theme.fonts.title, fontSize: 84, fontWeight: 900, color: theme.colors.cream, marginTop: 12, lineHeight: 1.05 }}>
          {heading}
        </div>
      </div>
      <div style={{ position: 'absolute', left: 60, right: 60, top: 420 }}>
        {items.map((m, i) => {
          const show = clamp((localTime - 0.5 - i*0.3)/0.4, 0, 1);
          return (
            <div key={i} style={{
              marginBottom: 20, padding: 22,
              background: 'rgba(250,243,227,0.06)',
              border: `2px solid ${m.color}`, borderRadius: 14,
              opacity: show, transform: `translateX(${(1-show)*-30}px)`,
            }}>
              <div style={{ fontFamily: theme.fonts.body, fontSize: 28, fontWeight: 700, color: theme.colors.cream }}>{m.name}</div>
              <div style={{ fontFamily: theme.fonts.body, fontSize: 22, color: m.color, marginTop: 6 }}>→ {m.use}</div>
            </div>
          );
        })}
      </div>
      {footer && (
        <div style={{
          position: 'absolute', left: 60, right: 60, bottom: 200,
          padding: 24, background: theme.colors.mustard, color: theme.colors.ink,
          borderRadius: 14, fontFamily: theme.fonts.body, fontSize: 26, fontWeight: 600,
          textAlign: 'center', lineHeight: 1.5,
          opacity: clamp((localTime - 2.5)/0.5, 0, 1),
        }}>{footer}</div>
      )}
    </>
  );
}

// ── OrientationSwitch button (rendered by each HTML host) ───────────────────
function OrientationSwitch({ current, onToggle }) {
  return (
    <button
      onClick={onToggle}
      style={{
        position: 'fixed', top: 16, right: 16, zIndex: 9999,
        padding: '10px 16px',
        background: 'rgba(42,36,32,0.92)', color: '#f5ecd9',
        border: `1.5px solid ${theme.colors.mustard}`,
        borderRadius: 999, cursor: 'pointer',
        fontFamily: theme.fonts.body, fontSize: 14, fontWeight: 600,
        letterSpacing: '0.05em',
        boxShadow: '0 4px 20px rgba(0,0,0,0.3)',
      }}
    >
      {current === 'portrait' ? '🔄 切换横屏' : '🔄 切换竖屏'}
    </button>
  );
}

// ── OrientedStage: wraps Stage and persists orientation ─────────────────────
function OrientedStage({ duration, persistKey, children }) {
  const [orient, setOrient] = React.useState(() => {
    try { return localStorage.getItem(persistKey + ':orient') || 'portrait'; }
    catch { return 'portrait'; }
  });
  const toggle = () => {
    const next = orient === 'portrait' ? 'landscape' : 'portrait';
    setOrient(next);
    try { localStorage.setItem(persistKey + ':orient', next); } catch {}
  };
  const w = orient === 'portrait' ? 1080 : 1920;
  const h = orient === 'portrait' ? 1920 : 1080;
  return (
    <>
      <OrientationSwitch current={orient} onToggle={toggle}/>
      <OrientationContext.Provider value={orient}>
        <Stage key={orient} width={w} height={h} duration={duration} background="#f5ecd9" persistKey={persistKey + ':' + orient}>
          {children}
        </Stage>
      </OrientationContext.Provider>
    </>
  );
}

Object.assign(window, {
  theme,
  useOrientation, isLandscape, OrientationContext,
  PaperBg, ChapterBar, Subtitle,
  Scene, MethodTitleBlock, OpeningShell, ChapterComparison,
  LocalSprite,
  OrientedStage,
});
