/* global React, ReactDOM, FairDieDemo, LoadedDieDemo, CasinoSection, TemperatureSection, HallucinationGrid, TakeawaysSection, IntrospectionDemo, AlwaysHallucinatingReframe, GloveIllustration, FitGuide, ScaffoldingDemo, TweaksPanel, useTweaks, TweakSection, TweakColor, TweakRadio, TweakToggle */
const { useState, useEffect } = React;

const DEFAULTS = /*EDITMODE-BEGIN*/{
  "accentColor": "#B4351C",
  "background": "warm-paper",
  "mastheadTag": "THE GLASS BOX · EXHIBIT 03",
  "showTOC": true
} /*EDITMODE-END*/;

function App() {
  const [t, setTweak] = useTweaks(DEFAULTS);

  // Apply tweakable color + background as CSS variable overrides on <html>.
  useEffect(() => {
    document.documentElement.style.setProperty("--vermilion", t.accentColor);
    const bgMap = {
      "warm-paper": { paper: "#F2EDE3", paper2: "#E8E2D2" },
      "cool-paper": { paper: "#EEEFE8", paper2: "#E2E4DA" },
      "bone": { paper: "#F7F2E8", paper2: "#EDE6D2" }
    };
    const bg = bgMap[t.background] || bgMap["warm-paper"];
    document.documentElement.style.setProperty("--paper", bg.paper);
    document.documentElement.style.setProperty("--paper-2", bg.paper2);
  }, [t.accentColor, t.background]);

  // Scroll-spy for the table of contents on the left rail.
  const [activeSection, setActiveSection] = useState("hero");
  useEffect(() => {
    const sections = document.querySelectorAll("section[data-toc]");
    const observer = new IntersectionObserver(
      (entries) => {
        entries.forEach((e) => {
          if (e.isIntersecting) setActiveSection(e.target.dataset.toc);
        });
      },
      { rootMargin: "-40% 0px -55% 0px" }
    );
    sections.forEach((s) => observer.observe(s));
    return () => observer.disconnect();
  }, []);

  const tocItems = [
  { id: "hero", lbl: "Cold open" },
  { id: "fair", lbl: "01 · Standard die" },
  { id: "loaded", lbl: "02 · Loaded die" },
  { id: "casino", lbl: "03 · Rigged casino" },
  { id: "temp", lbl: "04 · Temperature" },
  { id: "hallu", lbl: "05 · Wrong rolls" },
  { id: "glove", lbl: "06 · Empty glove" },
  { id: "fit", lbl: "07 · Why use it" },
  { id: "take", lbl: "08 · Takeaways" },
  { id: "refs", lbl: "09 · Works cited" }];


  return (
    <div>
      <div className="page">
        <div className="masthead">
          <div className="brand"><b>◆</b> {t.mastheadTag}{window.__OFFLINE ? " \u00b7 OFFLINE EDITION" : ""}</div>
          <div>THE LOADED DIE · A DISCOURSE DEPOT ARTIFACT · 2026</div>
        </div>
      </div>

      {t.showTOC &&
      <nav className="toc">
          {tocItems.map((item) =>
        <a
          key={item.id}
          href={`#${item.id}`}
          className={activeSection === item.id ? "active" : ""}
          onClick={(e) => {
            e.preventDefault();
            document.getElementById(item.id)?.scrollIntoView({ behavior: "smooth", block: "start" });
          }}>
          
              <span className="dot" />
              <span className="lbl">{item.lbl}</span>
            </a>
        )}
        </nav>
      }

      <div className="page">
        {/* ----- HERO ----- */}
        <section id="hero" data-toc="hero" data-screen-label="00 Hero" className="hero">
          <div className="eyebrow"><span className="num">№ 03</span> An exhibit on probabilistic language</div>
          <h1>
            With an LLM, you are rolling a die — but not a standard one.<br />
            You are rolling a <span className="italic">loaded</span> one.
          </h1>
          <p className="lede">
            People hear "dice roll" and picture six faces, equal odds, pure
            chance. That metaphor is why the magic of language models
            survives, because a fair die would only ever produce gibberish. To see
            the machinery as it actually is, you have to upgrade the die.
          </p>
          <div className="hero-meta">
            <div><b>Exhibit</b>The Loaded Die</div>
            <div><b>Reading time</b>~9 minutes</div>
            <div><b>Format</b>Interactive · scroll</div>
            <div><b>Companion</b>
              <a href="Poster.html">Placard ↗</a>
            </div>
          </div>
        </section>

        <hr className="rule-thick" />

        {/* ----- SECTION 1 — FAIR DIE ----- */}
        <section id="fair" data-toc="fair" data-screen-label="01 Standard die">
          <div className="section-head">
            <div className="meta"><span className="num">№ 01</span>Standard Die</div>
            <h2>A die with equal faces produces equal <span className="italic">nonsense.</span></h2>
          </div>
          <p className="col-narrow">
            A six-sided die is uniform: each face has the same 16.6%
            chance of landing up. A 100,000-sided fair die, one face
            per word in the vocabulary, would simply emit a random word
            from the dictionary every time. The result is pure noise.
            Language requires the weighting.
          </p>
          <FairDieDemo />
        </section>

        <hr className="rule" />

        {/* ----- SECTION 2 — LOADED DIE ----- */}
        <section id="loaded" data-toc="loaded" data-screen-label="02 Loaded die">
          <div className="section-head">
            <div className="meta"><span className="num">№ 02</span>Loaded Die</div>
            <h2>The center of gravity shifts with every <span className="italic">preceding word.</span></h2>
          </div>
          <p className="col-narrow">
            Imagine a die with 100,000 sides — one for every token the
            model can emit. The die is magically weighted, and the
            weighting changes in real time based on the words that came
            before. Given <code>“The capital of France is”</code>, the
            face for <i>Paris</i> carries almost all the mass. The face
            for <i>banana</i> still exists; it just weighs nearly
            nothing.
          </p>
          <p className="pull" style={{ margin: "32px 0 56px" }}>
            What you are watching is the die <span className="italic">obeying gravity.</span>
          </p>
          <LoadedDieDemo />
        </section>

        {/* ----- SECTION 3 — CASINO ----- */}
        <section id="casino" data-toc="casino" data-screen-label="03 Rigged casino" style={{ padding: 0 }}>
          <CasinoSection />
        </section>

        {/* ----- SECTION 4 — TEMPERATURE ----- */}
        <section id="temp" data-toc="temp" data-screen-label="04 Temperature">
          <div className="section-head">
            <div className="meta"><span className="num">№ 04</span>Temperature</div>
            <h2>One knob decides how often the die <span className="italic">obeys gravity.</span></h2>
          </div>
          <p className="col-narrow">
            "Temperature" is a single number that re-shapes the
            distribution before the roll. Turn it down and the model
            always picks the heaviest weight: safe, repeatable, a touch
            robotic. Turn it up and the lighter weights get a chance.
            Turn it up far enough and the long tail, the off-script
            tokens, starts to land.
          </p>
          <div style={{ marginTop: 48 }}>
            <TemperatureSection />
          </div>
        </section>

        <hr className="rule" />

        {/* ----- SECTION 5 — HALLUCINATION ----- */}
        <section id="hallu" data-toc="hallu" data-screen-label="05 Wrong rolls">
          <div className="section-head">
            <div className="meta"><span className="num">№ 05</span>The "Wrong" Answer</div>
            <h2>A hallucination is just a die roll that <span className="italic">landed light.</span></h2>
          </div>
          <p className="col-narrow">
            If the loaded die lands on <i>Paris</i> 97 times out of 100,
            we call the system a genius. But on the 98th roll, the 1.5%
            face lands up and the output is <i>London</i>. To you, that's
            a lie. To the machine, the math worked exactly as designed.
          </p>
          <div style={{ marginTop: 56 }}>
            <HallucinationGrid />
          </div>
        </section>

        {/* ----- SECTION 6 — EMPTY GLOVE ----- */}
        <section id="glove" data-toc="glove" data-screen-label="06 Empty glove">
          <div className="section-head">
            <div className="meta"><span className="num">№ 06</span>The Empty Glove</div>
            <h2>But push <span className="italic">harder.</span> The reframe gets <span className="italic">worse.</span></h2>
          </div>
          <p className="col-narrow">
            We just said: <i>some</i> rolls land light, and those are
            hallucinations. That's the comfortable version of the story.
            The hard version goes further, and once you see it, you
            cannot unsee it.
          </p>

          <div style={{ marginTop: 48 }}>
            <AlwaysHallucinatingReframe />
          </div>

          <p className="col-narrow">
            The machine has no causal model of the world. No filing
            cabinet of facts. No internal stage where it consults
            reality before speaking. It only has weights and
            probabilities. When it says <i>Paris,</i> it is outputting
            a high-probability token sequence. No fact is being
            accessed. When it says <i>banana,</i> it is doing the
            exact same thing. We call one of these accuracy and the
            other a hallucination. The mechanical process is
            <b> identical.</b> It is always hallucinating. Sometimes
            the hallucination happens to align with consensus reality,
            and we reward the machine for it.
          </p>

          <p className="pull" style={{ margin: "48px 0" }}>
            The AI <span className="italic">never sees</span> reality. It only calculates the proximity of tokens.
          </p>

          {/* The introspection trap — a live demo. */}
          <div className="mono" style={{ fontSize: 11, letterSpacing: "0.18em", textTransform: "uppercase", color: "var(--muted)", marginBottom: 14 }}>
            And here is where it gets dangerous
          </div>
          <h3 style={{ marginBottom: 16, maxWidth: "22ch" }}>
            Asking the die to <span className="italic">explain itself</span> is just another roll.
          </h3>
          <p className="col-narrow" style={{ marginBottom: 32 }}>
            When you ask the model <i>“How do you work?”</i> it does
            not run a diagnostic on its own math. It cannot — there
            is no internal mirror to consult. It does what it always
            does: predicts the most plausible next tokens. Because
            its training data is saturated with articles, blog posts,
            and transcripts about how AIs work, the output sounds
            exactly like an engineer explaining an AI. It is a
            <i> simulation of an explanation.</i> Try it:
          </p>

          <IntrospectionDemo />

          {/* The Empty Glove. */}
          <div className="glove-block">
            <div className="glove-svg-wrap">
              <GloveIllustration />
            </div>
            <div>
              <div className="mono" style={{ fontSize: 10, letterSpacing: "0.2em", textTransform: "uppercase", color: "var(--muted)", marginBottom: 14 }}>
                The metaphor
              </div>
              <div className="glove-line">
                Human language is a glove stretched by the movements
                of living hands. When the LLM speaks, you are watching
                the glove move on its <i>own,</i> controlled entirely
                by statistics. Because the glove moves in familiar,
                human-shaped ways, you instinctively assume there is a
                living hand inside.
                <br /><br />
                <span style={{ color: "var(--vermilion)", fontStyle: "italic" }}>There is no hand. There is only the shape we left behind.</span>
                <span className="glove-cite">After Durt, Froese &amp; Fuchs · 2023</span>
              </div>
            </div>
          </div>

          {/* The hard rule. */}
          <div className="rule-stamp">
            <p className="rule-text">
              This is why it doesn't make sense to ask an LLM to <i>explain itself.</i><br />
              It cannot introspect. It can only predict what introspection <i>sounds like.</i>
            </p>
            <p className="rule-sub">
              Any explanation the model gives for its own behavior is
              a post-hoc rationalization. The bureaucrat persona steps
              in after the fact to write a polite, plausible memo
              about a process it has no access to. Treat it as
              confabulation.
            </p>
          </div>
        </section>

        {/* ----- SECTION 7 — FORM, NOT FACTS ----- */}
        <section id="fit" data-toc="fit" data-screen-label="07 Why use it">
          <div className="section-head">
            <div className="meta"><span className="num">№ 07</span>Form, Not Facts</div>
            <h2>If it's always hallucinating, why <span className="italic">use one at all?</span></h2>
          </div>
          <p className="col-narrow">
            The Empty Glove can sound like a verdict: <i>therefore,
            never use the tool.</i> That's the wrong reading. The right
            reading is more useful and more honest.
          </p>
          <p className="pull" style={{ margin: "32px 0 56px" }}>
            Hallucination is the <span className="italic">engine.</span>
          </p>
          <p className="col-narrow">
            And many tasks <i>want</i> a probability engine. They want
            plausible structure, fluent shape, a draft to react to.
            The trick is matching the task to the tool. Three buckets:
          </p>

          <div style={{ marginTop: 48 }}>
            <FitGuide />
          </div>

          {/* The Latent Scaffolding moment. */}
          <div style={{ marginTop: 80 }}>
            <div className="mono" style={{ fontSize: 11, letterSpacing: "0.18em", textTransform: "uppercase", color: "var(--muted)", marginBottom: 14 }}>
              The brainstorming case
            </div>
            <h3 style={{ marginBottom: 16, maxWidth: "24ch" }}>
              Latent <span className="italic">scaffolding.</span>
            </h3>
            <div className="two-up" style={{ alignItems: "start" }}>
              <div>
                <p style={{ marginBottom: 0 }}>
                  As a brainstorming partner, the model's tendency to
                  invent plausible structures is its <i>greatest</i>
                  feature. Ask it for ten possible angles on a problem.
                  Three are bad, two are obvious, five are useful. You
                  cut what you don't want and keep what you do.
                </p>
                <p style={{ marginTop: 14 }}>
                  You'd rather start with seven good ideas you didn't
                  have to generate than spend twenty minutes staring at
                  a blank page. The hallucination is scaffolding you
                  didn't have to build.
                </p>
              </div>
              <ScaffoldingDemo />
            </div>
          </div>

          {/* The closing rule — visual rhyme with the Empty Glove rule. */}
          <div className="rule-stamp" style={{ marginTop: 80 }}>
            <p className="rule-text">
              <i>Verification</i> as the default.<br />
              The machine is your <i>drafter.</i> Every output is a <i>draft.</i>
            </p>
            <p className="rule-sub">
              Every draft must be checked against ground truth before
              you stake anything on it. The model produces a shape.
              You bring it into contact with the world. That seam,
              between what the die generated and what is actually so,
              is where the human has to stand.
            </p>
          </div>
        </section>

        {/* ----- SECTION 8 — TAKEAWAYS ----- */}
        <section id="take" data-toc="take" data-screen-label="08 Takeaways">
          <div className="section-head">
            <div className="meta"><span className="num">№ 08</span>The Glass Box</div>
            <h2>What this metaphor lets you say <span className="italic">without anthropomorphizing.</span></h2>
          </div>
          <p className="col-narrow">
            The loaded die is a complete mechanical vocabulary. It lets
            you describe what the machine is doing, why it usually
            works, and why it sometimes fails, with no reference to
            understanding, intention, or mind. Three questions, three
            cleaner answers:
          </p>
          <TakeawaysSection />

          <div style={{ marginTop: 80, padding: "40px 48px", background: "var(--ink)", color: "var(--paper)", borderRadius: 2 }}>
            <div className="mono" style={{ fontSize: 10, letterSpacing: "0.2em", textTransform: "uppercase", color: "rgba(242,237,227,0.6)", marginBottom: 14 }}>
              For the curriculum
            </div>
            <div style={{ fontFamily: "var(--serif-display)", fontSize: 32, lineHeight: 1.2, maxWidth: "30ch", marginBottom: 18 }}>
              A complete <span style={{ color: "var(--gold)", fontStyle: "italic" }}>mechanical vocabulary</span> for the Glass Box.
            </div>
            <p style={{ color: "rgba(242,237,227,0.78)", maxWidth: "52ch" }}>
              Where the weights come from, what they are, and how
              they get cast. There is no magic and no mind here, only
              a casino that has been rigged for so long it has
              started to look like an oracle. Pair this exhibit with
              the other Glass Box presentations on AI literacy.
            </p>
          </div>
        </section>

        {/* ----- SECTION 9 — WORKS CITED ----- */}
        <section id="refs" data-toc="refs" data-screen-label="09 Works cited" style={{ paddingTop: 80, paddingBottom: 40 }}>
          <div className="section-head">
            <div className="meta"><span className="num">№ 09</span>Works Cited</div>
            <h2>Sources behind <span className="italic">the metaphor.</span></h2>
          </div>
          <ol className="works-cited">
            <li>
              <span className="wc-num">01</span>
              <span className="wc-body">
                <span className="wc-authors">Spennemann, D. H.</span>
                <span className="wc-year">2026</span>
                <span className="wc-title">How unique are hallucinated citations offered by generative Artificial Intelligence models?</span>
                <span className="wc-src">arXiv preprint arXiv:2604.16407.</span>
              </span>
            </li>
            <li>
              <span className="wc-num">02</span>
              <span className="wc-body">
                <span className="wc-authors">Durt, C., Froese, T., &amp; Fuchs, T.</span>
                <span className="wc-year">2023</span>
                <span className="wc-title">Against AI understanding and sentience: large language models, meaning, and the patterns of human language use.</span>
                <span className="wc-src">Preprint.</span>
              </span>
            </li>
            <li>
              <span className="wc-num">03</span>
              <span className="wc-body">
                <span className="wc-authors">Yampolskiy, R. V.</span>
                <span className="wc-year">2019</span>
                <span className="wc-title">Unexplainability and incomprehensibility of artificial intelligence.</span>
                <span className="wc-src">arXiv preprint arXiv:1907.03869.</span>
              </span>
            </li>
          </ol>
        </section>

        <footer className="colophon">
          <div>The Glass Box · Exhibit № 03 · The Loaded Die</div>
          <div>Curriculum Edition · A Discourse Depot artifact</div>
        </footer>
      </div>

      {/* ----- TWEAKS PANEL ----- */}
      <TweaksPanel title="Tweaks">
        <TweakSection label="Visual">
          <TweakColor
            label="Accent color"
            value={t.accentColor}
            onChange={(v) => setTweak("accentColor", v)}
            options={["#B4351C", "#7A2E2E", "#2C4A6B", "#385A3F", "#1A1815"]} />
          
          <TweakRadio
            label="Background"
            value={t.background}
            onChange={(v) => setTweak("background", v)}
            options={[
            { value: "warm-paper", label: "Warm" },
            { value: "cool-paper", label: "Cool" },
            { value: "bone", label: "Bone" }]
            } />
          
        </TweakSection>
        <TweakSection label="Chrome">
          <TweakToggle
            label="Show table of contents"
            value={t.showTOC}
            onChange={(v) => setTweak("showTOC", v)} />
          
        </TweakSection>
      </TweaksPanel>
    </div>);

}

ReactDOM.createRoot(document.getElementById("root")).render(<App />);