// screens-b.jsx — Objects, Events, Writing (screens 04-06) /* ════════════════════════════════════════════════════════════ 04 · OBJECTS — clues stitch a case back together ════════════════════════════════════════════════════════════ */ function ObjectGlyph({ kind }) { // Tiny ink-style sketches for each object kind. Loose, monochrome. const map = { "半截竹杖": ( ), "血染袖口": ( ), "旧信": ( ), "铜令牌": ( ), "油纸包": ( ), }; return map[kind] || null; } function Screen04Objects({ copy }) { const s = copy.screens.objects; return ( }>
{s.winTitle}
{s.cards.map((c, i) => (
{c.name}
{c.level}线索
持有人
{c.holder}
首次出现
{c.firstAt}
当前状态
{c.state}
关联人物
{c.related}
剧情作用
{c.role}
线索状态 {c.clue}
))}
{s.traceHead}
{s.traceFrom} {s.traceFromHint}
{s.traceArrow}
{s.traceTo} {s.traceToHint}
); } /* ════════════════════════════════════════════════════════════ 05 · EVENTS — turn fragments into events and foreshadowing ════════════════════════════════════════════════════════════ */ function Screen05Events({ copy }) { const s = copy.screens.events; return ( }>

{s.winTitle}

{s.viewLabel}
{s.views.map((v, i) => ( ))}
{s.tlHead}

{s.tlSub}

{s.timeline.map((e, i) => (
{e.n} {e.h}

{e.p}

{e.ch}
))}
{s.foreshadowHead}

{s.foreshadowSub}

    {s.foreshadows.map((f, i) => (
  • {f.t} {f.ch}
  • ))}
{s.causalHead}

{s.causalSub}

{s.causal.map((row, i) => (
{row.map((node, j) => ( {node} {j < row.length - 1 && } ))}
))}
{s.indexHead}

{s.indexSub}

    {s.index.map((c, i) =>
  • {c}
  • )}
); } /* ════════════════════════════════════════════════════════════ 06 · WRITING — all the structure exists so you can write ════════════════════════════════════════════════════════════ */ function Screen06Writing({ copy }) { const s = copy.screens.writing; return ( } className="bw-frame--wide">
{/* Left: book + chapter list */} {/* Middle: prose */}

{s.proseTitle}

{s.proseWords}
{s.proseParas.map((p, i) => (

{p}{i === s.proseParas.length - 1 && }

))}
{s.statusBar.words} {s.statusBar.speed} · {s.statusBar.today} {s.statusBar.saved} {s.statusBar.auto}
{/* Right: quick references */}

{s.endHead}

{s.endCtaPrimary} {s.endCtaSecondary}

{s.endNote}

); } function ScreenFAQItem({ item, index, isOpen, onToggle }) { const buttonId = `faq-trigger-${index}`; const panelId = `faq-panel-${index}`; return (
{item.a}
); } Object.assign(window, { Screen04Objects, Screen05Events, Screen06Writing, ObjectGlyph, ScreenFAQItem, Screen08FAQ, }); /* 07 FAQ - same shell, FAQ grid as body. */ function Screen08FAQ({ copy }) { const s = copy.screens.faq; const [openIndex, setOpenIndex] = React.useState(null); const toggle = (index) => setOpenIndex((current) => current === index ? null : index); return (
{[0, 1].map((column) => (
{copy.faq.items.map((item, index) => ( index % 2 === column && ( toggle(index)} /> ) ))}
))}
); }