// App shell — router + nav + tweaks
{
const { LENSES } = window.PL_DATA;

const TWEAK_DEFAULTS = /*EDITMODE-BEGIN*/{
  "mode": "light",
  "accent": "#c2410c",
  "mapStyle": "tile",
  "showLabels": "always",
  "density": "comfy"
}/*EDITMODE-END*/;

function App() {
  // intro = cinematic landing screen; atlas = full-bleed map experience
  const [phase, setPhase] = React.useState(() => {
    // Skip intro on subsequent visits in the same session
    return sessionStorage.getItem("pl_introSeen") === "1" ? "atlas" : "intro";
  });
  const [page, setPage] = React.useState("landing");
  const [lensId, setLensId] = React.useState("reproductive");
  const [indexId, setIndexId] = React.useState("fascism");
  const [t, setTweak] = window.useTweaks(TWEAK_DEFAULTS);

  React.useEffect(() => {
    document.documentElement.setAttribute("data-mode", t.mode);
    document.documentElement.setAttribute("data-density", t.density);
    document.documentElement.style.setProperty("--accent", t.accent);
  }, [t.mode, t.density, t.accent]);

  const enterAtlas = () => {
    sessionStorage.setItem("pl_introSeen", "1");
    setPhase("atlas");
  };

  const go = (p) => { setPage(p); window.scrollTo({ top: 0, behavior: "instant" }); };

  // Intro is overlaid on top of the rendered atlas — that way when it fades
  // out, the (light-themed) atlas is already painted underneath. No jarring
  // theme flip.

  return (
    <React.Fragment>
      {phase === "intro" && <Intro enter={enterAtlas} />}
      <Nav page={page} go={go} />
      {page === "landing" && (
        <window.PL_Landing go={go} lensId={lensId} setLensId={setLensId}
          mapStyle={t.mapStyle} showLabels={t.showLabels} />
      )}
      {page === "state" && (
        <window.PL_StatePage go={go} setLensId={setLensId}
          mapStyle={t.mapStyle} showLabels={t.showLabels} />
      )}
      {page === "lens" && (
        <window.PL_LensPage go={go} lensId={lensId} setLensId={setLensId}
          mapStyle={t.mapStyle} showLabels={t.showLabels} />
      )}
      {page === "indices" && (
        <window.PL_IndicesPage go={go} indexId={indexId} setIndexId={setIndexId} />
      )}
      {page === "methodology" && <window.PL_Methodology go={go} />}
      {page === "specimen" && <window.PL_Specimen />}

      <Footer go={go} />

      <window.TweaksPanel title="Tweaks">
        <window.TweakSection title="Mode">
          <window.TweakRadio label="Theme" value={t.mode} onChange={v => setTweak("mode", v)}
            options={[{value:"light",label:"Light"},{value:"dark",label:"Dark"}]} />
          <window.TweakRadio label="Density" value={t.density} onChange={v => setTweak("density", v)}
            options={[{value:"comfy",label:"Comfy"},{value:"dense",label:"Dense"}]} />
        </window.TweakSection>
        <window.TweakSection title="Brand accent">
          <window.TweakColor label="Accent" value={t.accent} onChange={v => setTweak("accent", v)}
            options={["#c2410c", "#a87916", "#2a6b66", "#5e1e2c"]} />
        </window.TweakSection>
        <window.TweakSection title="Map">
          <window.TweakRadio label="State labels" value={t.showLabels} onChange={v => setTweak("showLabels", v)}
            options={[{value:"always",label:"Always"},{value:"hover",label:"Hover"},{value:"never",label:"Off"}]} />
        </window.TweakSection>
      </window.TweaksPanel>
    </React.Fragment>
  );
}

// --- Cinematic intro screen ----------------------------------------------
const ROTATING_WORDS = [
  "life", "work", "health", "voice", "freedom", "school",
  "home", "body", "vote", "harm", "hope", "choice",
];

function Intro({ enter }) {
  const [visible, setVisible] = React.useState(false);
  const [exiting, setExiting] = React.useState(false);
  const [wordIdx, setWordIdx] = React.useState(0);

  React.useEffect(() => {
    const t = setTimeout(() => setVisible(true), 60);
    return () => clearTimeout(t);
  }, []);

  // Cycle the rotating word slowly, after the intro has appeared
  React.useEffect(() => {
    if (!visible) return;
    const t = setInterval(() => setWordIdx(i => (i + 1) % ROTATING_WORDS.length), 2400);
    return () => clearInterval(t);
  }, [visible]);

  // Click anywhere or press any key to enter
  React.useEffect(() => {
    const onKey = (e) => { if (e.key) handleEnter(); };
    window.addEventListener("keydown", onKey);
    return () => window.removeEventListener("keydown", onKey);
  });

  const handleEnter = () => {
    if (exiting) return;
    setExiting(true);
    setTimeout(() => enter(), 480);
  };

  return (
    <div
      onClick={handleEnter}
      className="pl-intro"
      style={{
        position: "fixed", inset: 0, zIndex: 100,
        background: "var(--ink)", color: "var(--bg)",
        cursor: "pointer", overflow: "hidden",
        opacity: exiting ? 0 : (visible ? 1 : 0),
        transition: "opacity 380ms ease",
      }}
    >
      <div className="pl-intro-grid" />
      <div style={{
        position: "absolute", inset: 0,
        display: "flex", flexDirection: "column",
        alignItems: "flex-start", justifyContent: "center",
        padding: "clamp(32px, 6vw, 96px)",
        gap: 24,
      }}>
        <div className="eyebrow" style={{
          color: "var(--accent)", fontSize: 12,
          letterSpacing: "0.2em",
          opacity: visible ? 1 : 0,
          transform: visible ? "translateY(0)" : "translateY(8px)",
          transition: "all 700ms 60ms cubic-bezier(.2,.8,.2,1)",
        }}>
          POLICY LANDSCAPE · ATLAS OF LEGISLATIVE MOTION · 2025–26 SESSION
        </div>

        <h1 className="display" style={{
          fontSize: "clamp(64px, 9vw, 156px)", fontWeight: 600,
          letterSpacing: "-0.035em", lineHeight: 0.92, margin: 0,
          maxWidth: "16ch",
          opacity: visible ? 1 : 0,
          transform: visible ? "translateY(0)" : "translateY(20px)",
          transition: "all 900ms 240ms cubic-bezier(.2,.8,.2,1)",
        }}>
          How law<br/>shapes{" "}
          <span style={{
            color: "var(--accent)",
            display: "inline-block",
            position: "relative",
          }}>
            <span key={wordIdx} className="pl-rotating-word">
              {ROTATING_WORDS[wordIdx]}
            </span>
          </span>.
        </h1>

        <p style={{
          fontSize: "clamp(16px, 1.4vw, 20px)", lineHeight: 1.45,
          maxWidth: 580, color: "rgba(255,255,255,0.78)",
          margin: 0,
          opacity: visible ? 1 : 0,
          transform: visible ? "translateY(0)" : "translateY(20px)",
          transition: "all 900ms 480ms cubic-bezier(.2,.8,.2,1)",
        }}>
          State by state. Bill by bill. With the receipts.
          We score every U.S. legislature against an explicit framework of
          human rights, public health, and democratic norms — and show our work.
        </p>

        <div style={{
          marginTop: 12,
          display: "flex", alignItems: "center", gap: 16,
          opacity: visible ? 1 : 0,
          transform: visible ? "translateY(0)" : "translateY(20px)",
          transition: "all 900ms 720ms cubic-bezier(.2,.8,.2,1)",
        }}>
          <button onClick={(e) => { e.stopPropagation(); handleEnter(); }} className="btn btn-accent" style={{
            fontFamily: "var(--display)", fontSize: 18, fontWeight: 600,
            padding: "14px 28px",
            background: "var(--accent)", color: "#fff", border: "none", cursor: "pointer",
            letterSpacing: "-0.01em",
          }}>
            Enter the atlas →
          </button>
          <span className="mono" style={{ fontSize: 11, opacity: 0.55, letterSpacing: "0.12em" }}>
            CLICK ANYWHERE · OR PRESS ANY KEY
          </span>
        </div>
      </div>

      {/* footer marker */}
      <div style={{
        position: "absolute", bottom: 24, left: "clamp(32px, 6vw, 96px)",
        right: "clamp(32px, 6vw, 96px)",
        display: "flex", justifyContent: "space-between", alignItems: "center",
        opacity: visible ? 1 : 0,
        transition: "opacity 900ms 1100ms ease",
        fontFamily: "var(--mono)", fontSize: 10, letterSpacing: "0.2em",
        color: "rgba(255,255,255,0.4)",
      }}>
        <span>POLICYLANDSCAPE.COM</span>
        <span><span className="pl-pulse" style={{ background: "var(--accent)", marginRight: 8, display: "inline-block", width: 8, height: 8, borderRadius: "50%" }}></span>LIVE</span>
      </div>
    </div>
  );
}

function Nav({ page, go }) {
  const tabs = [
    ["landing", "Atlas"],
    ["lens", "Lens"],
    ["state", "State"],
    ["indices", "Indices"],
    ["methodology", "Method"],
    ["specimen", "Specimen"],
  ];
  return (
    <div className="pl-nav">
      <div className="pl-logo" onClick={() => go("landing")} style={{ cursor: "pointer" }}>
        <span className="dot"></span>
        Policy Landscape
      </div>
      <div className="pl-tabs">
        {tabs.map(([id, label]) => (
          <button key={id} className={`pl-tab ${page === id ? "active" : ""}`}
            onClick={() => go(id)}>{label}</button>
        ))}
      </div>
      <div className="pl-nav-meta">
        <span>2025–26 SESSION</span>
        <span className="pl-pulse"></span>
        <span>LIVE</span>
      </div>
    </div>
  );
}

// Set BUY_ME_A_COFFEE_URL to your buymeacoffee.com handle URL (e.g.,
// "https://buymeacoffee.com/your-handle") to activate the support link.
// Leave as empty string to hide the link entirely.
const BUY_ME_A_COFFEE_URL = "";

function Footer({ go }) {
  return (
    <footer className="pl-foot">
      <div>
        <h4>Policy Landscape</h4>
        <div>An editorial atlas of how state and federal legislation shapes life across 23 policy lenses and 8 editorial indices.</div>
        <div style={{ marginTop: 12 }}>policylandscape.com · v2.0.0</div>
        {BUY_ME_A_COFFEE_URL && (
          <div style={{ marginTop: 14 }}>
            <a href={BUY_ME_A_COFFEE_URL} target="_blank" rel="noopener noreferrer"
               style={{
                 display: "inline-block", padding: "6px 14px",
                 background: "var(--accent)", color: "#fff",
                 textDecoration: "none", fontSize: 13, fontWeight: 600,
                 borderRadius: 4, letterSpacing: "-0.005em",
               }}>
              Buy me a coffee →
            </a>
            <div style={{ marginTop: 8, fontSize: 11, color: "var(--ink-3)", maxWidth: 280 }}>
              Personally funded. If this atlas was useful to you, support keeps the next pull running.
            </div>
          </div>
        )}
      </div>
      <div>
        <h4>Pages</h4>
        <div style={{ display: "flex", flexDirection: "column", gap: 6 }}>
          <a onClick={() => go("landing")} style={{ cursor: "pointer" }}>Atlas / landing</a>
          <a onClick={() => go("state")} style={{ cursor: "pointer" }}>State detail</a>
          <a onClick={() => go("lens")} style={{ cursor: "pointer" }}>Lens detail</a>
          <a onClick={() => go("methodology")} style={{ cursor: "pointer" }}>Methodology</a>
          <a onClick={() => go("specimen")} style={{ cursor: "pointer" }}>Type & color specimen</a>
        </div>
      </div>
      <div>
        <h4>Sources</h4>
        <div style={{ display: "flex", flexDirection: "column", gap: 6 }}>
          <span>LegiScan · CC BY 4.0</span>
          <span>Anthropic Claude Haiku</span>
          <span>Calibration: Center for Reproductive Rights, MAP, Brennan Center, KFF, Sentencing Project,
          Giffords, ITUC, ALDF.</span>
          <span style={{ marginTop: 12 }}>Updated 2026-05-13 (v2 taxonomy)</span>
        </div>
      </div>
    </footer>
  );
}

// Show a brief loading state while live data loads from the dashboard API,
// then mount the app. Avoids rendering with placeholder neutral scores.
const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(
  <div style={{
    minHeight: "60vh", display: "flex", alignItems: "center", justifyContent: "center",
    fontFamily: "var(--mono)", fontSize: 11, letterSpacing: "0.14em",
    textTransform: "uppercase", color: "var(--ink-3)"
  }}>
    Loading policy landscape…
  </div>
);
window.PL_DATA.ready.then(({ live, scoredStateCount }) => {
  console.log(`[Policy Landscape] mounting (${live ? "live" : "stub"} data, ${scoredStateCount} states)`);
  root.render(<App />);
});

}
