// Shared site chrome + unified tweak store for interior pages.
// The interior pages render their own <SiteHeader> (sibling to the tweaks panel),
// so header and panel share state through a small module-level store (CRCStore)
// rather than React context. Defaults here are kept identical to the homepage.

const CRC_BODY_FONTS = {
  sourceSerif: '"Source Serif 4", Georgia, serif',
  plexSerif:   '"IBM Plex Serif", Georgia, serif',
  inter:       '"Inter", "Helvetica Neue", sans-serif'
};

const CRC_DEFAULTS = {
  bodyFont: "sourceSerif",
  headerStyle: "minimal",
  teal: "balanced",
  bgShade: "warm",
  density: 90,
  uiText: "large",
  brandSide: "left",
  brandOrder: "crcFirst",
  brandText: "none",      // default: logo only
  dsNavStyle: "dropdown",
  navFit: "roomy",
  dsNavBg: false,
  dsMenu: "flat",
  graphFit: "margins",
  methodText: "wide",
  brandMatch: "logo",
  dsLabel: "above",       // default: "Datasets" row above
  dsSubAlign: "center",
  dsEyebrow: true,
  arxivStyle: "underline",
  linkPos: "top",
  endLinks: "plain",      // bottom-of-page repeat links style
  applyBig: true,         // default: larger apply button on
  pageRules: false,
  contributors: "off",       // dataset-page contributor line placement
  consExample: "rows",        // ConCoRD constraint-example layout
  symMargins: true,
  snugMargins: false
};

const NAV_DATASETS = [
  { label: "LMCA",        href: "lmca.html",        name: "Reward Model",    desc: "Rating model critiques of conceptual arguments against expert judgement." },
  { label: "ConCoRD", href: "consistency.html", name: "ConCoRD",     desc: "Whether a model's positions stay stable across reframings of a question." },
  { label: "DTBench",     href: "dtbench.html",     name: "Decision Theory", desc: "Original decision-theoretic scenarios scored on reasoning structure." }
];

// ---- unified store ----------------------------------------------------------
const CRCStore = (() => {
  const subs = new Set();
  let contentMode = "center";

  const readBool = (k, dflt) => {
    const v = localStorage.getItem("crc:" + k);
    if (v === null) return dflt;
    return v === "on";
  };
  const read = () => {
    const g = (k, d) => { const v = localStorage.getItem("crc:" + k); return v === null ? d : v; };
    const eb = localStorage.getItem("crc:dsEyebrow");
    return {
      bodyFont:   g("bodyFont",   CRC_DEFAULTS.bodyFont),
      headerStyle:g("headerStyle",CRC_DEFAULTS.headerStyle),
      teal:       g("teal",       CRC_DEFAULTS.teal),
      bgShade:    g("bgShade",    CRC_DEFAULTS.bgShade),
      density:    parseFloat(g("density", CRC_DEFAULTS.density)) || CRC_DEFAULTS.density,
      uiText:     g("uiText", "") === "regular" ? "regular" : "large",
      brandSide:  g("brandSide",  CRC_DEFAULTS.brandSide),
      brandOrder: g("brandOrder", CRC_DEFAULTS.brandOrder),
      brandText:  g("brandText",  CRC_DEFAULTS.brandText),
      dsNavStyle: g("dsNavStyle", CRC_DEFAULTS.dsNavStyle),
      navFit:     g("navFit",     CRC_DEFAULTS.navFit),
      dsNavBg:    readBool("dsNavBg", CRC_DEFAULTS.dsNavBg),
      dsMenu:     g("dsMenu",     CRC_DEFAULTS.dsMenu),
      graphFit:   g("graphFit",   CRC_DEFAULTS.graphFit),
      methodText: g("methodText", CRC_DEFAULTS.methodText),
      brandMatch: g("brandMatch", CRC_DEFAULTS.brandMatch),
      dsLabel:    g("dsLabel",    CRC_DEFAULTS.dsLabel),
      dsSubAlign: g("dsSubAlign", CRC_DEFAULTS.dsSubAlign),
      dsEyebrow:  eb === null ? CRC_DEFAULTS.dsEyebrow : eb !== "off",
      arxivStyle: g("arxivStyle", CRC_DEFAULTS.arxivStyle),
      linkPos:    g("linkPos",    CRC_DEFAULTS.linkPos),
      endLinks:   g("endLinks",   CRC_DEFAULTS.endLinks),
      applyBig:   readBool("applyBig", CRC_DEFAULTS.applyBig),
      pageRules:  readBool("pageRules", CRC_DEFAULTS.pageRules),
      contributors: g("contributors", CRC_DEFAULTS.contributors),
      consExample: g("consExample", CRC_DEFAULTS.consExample),
      symMargins: g("contentAlign", "") !== "wide",
      snugMargins:readBool("contentSnug", CRC_DEFAULTS.snugMargins)
    };
  };

  let state = read();

  const TEAL = { medium: "#4a6e6e", balancedLt: "#5a8885", balancedMid: "#498581", balanced: "#367370" };
  const TEAL_COOL = { medium: "#356f76", balancedLt: "#4a8b90", balancedMid: "#3a878d", balanced: "#297479" };
  const WARM_RAMP = { ink: "#1c1a17", ink2: "#3a3730", ink3: "#6b665c", inkDim: "#9a948a", rule: "#d9d2c4", ruleStrong: "#b8b0a0" };
  const COOL_RAMP = { ink: "#17191c", ink2: "#383c42", ink3: "#5e646c", inkDim: "#969ba2", rule: "#e4e5e7", ruleStrong: "#c5c8cd" };
  const BG = {
    warm:  { bg: "#f5f1ea", bg2: "#efeadf", ...WARM_RAMP },
    soft:  { bg: "#f7f4ee", bg2: "#f1ece1", ...WARM_RAMP },
    light: { bg: "#f9f6f1", bg2: "#f2ede3", ...WARM_RAMP },
    white: { bg: "#ffffff", bg2: "#f4f5f6", ...COOL_RAMP }
  };

  const apply = () => {
    const t = state;
    const root = document.documentElement;
    const tealMap = t.bgShade === "white" ? TEAL_COOL : TEAL;
    const REDWOOD_GREEN = "#2a6750";
    const REDWOOD_LOGO = "#1d4b38";
    const isGreen = t.brandMatch === "highlight";
    const highlight = isGreen ? REDWOOD_GREEN : (tealMap[t.teal] || tealMap.medium);
    root.style.setProperty("--teal", highlight);
    root.style.setProperty("--redwood-ink", isGreen ? REDWOOD_LOGO : highlight);
    const bg = BG[t.bgShade] || BG.soft;
    root.style.setProperty("--bg", bg.bg);
    root.style.setProperty("--bg-2", bg.bg2);
    root.style.setProperty("--ink", bg.ink);
    root.style.setProperty("--ink-2", bg.ink2);
    root.style.setProperty("--ink-3", bg.ink3);
    root.style.setProperty("--ink-dim", bg.inkDim);
    root.style.setProperty("--rule", bg.rule);
    root.style.setProperty("--rule-strong", bg.ruleStrong);
    root.style.setProperty("--font-display", '"EB Garamond", Georgia, serif');
    root.style.setProperty("--font-body", CRC_BODY_FONTS[t.bodyFont] || CRC_BODY_FONTS.sourceSerif);
    root.style.setProperty("--display-weight", 500);
    root.style.setProperty("--display-tracking", "-0.01em");
    root.style.setProperty("--hero-size", "48px");
    root.style.setProperty("--hero-gap", "48px");
    root.style.setProperty("--brand-flow", t.brandSide === "right" ? "row-reverse" : "row");
    root.style.setProperty("--brand-order", t.brandOrder === "redwoodFirst" ? "row-reverse" : "row");
    root.style.zoom = String((t.density ?? 90) / 100);
    root.dataset.uiText = t.uiText === "regular" ? "regular" : "large";
    root.dataset.dsEyebrow = t.dsEyebrow === false ? "off" : "on";
    root.dataset.arxivStyle = t.arxivStyle || "underline";
    root.dataset.linkPos = t.linkPos || "top";
    root.dataset.endLinks = t.endLinks || "plain";
    root.dataset.pageRules = t.pageRules ? "on" : "off";
    root.dataset.applyBig = t.applyBig ? "on" : "off";
    root.dataset.contributors = t.contributors || "off";
    root.dataset.consExample = t.consExample || "rows";
    const centered = t.symMargins !== false;
    root.dataset.content = contentMode === "wide" ? "wide" : (centered ? "center" : "wide");
    root.dataset.contentSnug = (contentMode !== "wide" && centered && t.snugMargins) ? "on" : "off";
    // data-ds-label drives the header label spacing (lives on the .site element)
    const site = document.querySelector(".site");
    if (site) site.setAttribute("data-ds-label", t.dsLabel || "inline");
    root.setAttribute("data-header", t.headerStyle || "minimal");
    root.dataset.dsNav = t.dsNavStyle || "plain";
    root.dataset.navFit = t.navFit || "roomy";
    root.dataset.dsNavBg = t.dsNavBg ? "on" : "off";
    root.dataset.dsMenu = t.dsMenu || "flat";
    root.dataset.graphFit = t.graphFit || "margins";
    root.dataset.methodText = t.methodText || "wide";
  };

  const persist = (k, v) => {
    const map = {
      contentAlign: () => localStorage.setItem("crc:contentAlign", state.symMargins ? "center" : "wide"),
    };
    // store raw value under crc:<key> with boolean/text normalization
    const set = (key, val) => localStorage.setItem("crc:" + key, val);
    set("bodyFont", state.bodyFont);
    set("headerStyle", state.headerStyle);
    set("teal", state.teal);
    set("bgShade", state.bgShade);
    set("density", String(state.density));
    set("uiText", state.uiText);
    set("brandSide", state.brandSide);
    set("brandOrder", state.brandOrder);
    set("brandText", state.brandText);
    set("dsNavStyle", state.dsNavStyle);
    set("navFit", state.navFit);
    set("dsNavBg", state.dsNavBg ? "on" : "off");
    set("dsMenu", state.dsMenu);
    set("graphFit", state.graphFit);
    set("methodText", state.methodText);
    set("brandMatch", state.brandMatch);
    set("dsLabel", state.dsLabel);
    set("dsSubAlign", state.dsSubAlign);
    set("dsEyebrow", state.dsEyebrow ? "on" : "off");
    set("arxivStyle", state.arxivStyle);
    set("linkPos", state.linkPos);
    set("endLinks", state.endLinks);
    set("applyBig", state.applyBig ? "on" : "off");
    set("pageRules", state.pageRules ? "on" : "off");
    set("contributors", state.contributors);
    set("consExample", state.consExample);
    set("contentAlign", state.symMargins ? "center" : "wide");
    set("contentSnug", state.snugMargins ? "on" : "off");
  };

  return {
    get: () => state,
    set: (k, v) => {
      state = { ...state, [k]: v };
      try { persist(); } catch (e) {}
      apply();
      subs.forEach((f) => f());
    },
    subscribe: (f) => { subs.add(f); return () => subs.delete(f); },
    apply,
    setContentMode: (m) => { contentMode = m; apply(); subs.forEach((f) => f()); },
    refresh: () => { state = read(); apply(); subs.forEach((f) => f()); }
  };
})();

function useCRCTweaks() {
  const [, force] = React.useReducer((x) => x + 1, 0);
  React.useEffect(() => CRCStore.subscribe(force), []);
  return [CRCStore.get(), CRCStore.set];
}

// Pre-React paint (and re-sync each load from localStorage) to avoid a flash.
function applyDefaultTokens() {
  CRCStore.refresh();
}

// Dataset-page contributor line. Rendered in three candidate slots per page
// (eyebrow / title / lede); CSS shows exactly the one matching the active
// `data-contributors` tweak. `slot` identifies which placement this instance is.
function CRCContributors({ names, slot }) {
  const list = (names || []).filter(Boolean);
  if (!list.length) return null;
  return (
    <div className={"contributors contributors--" + slot}>
      <span className="contributors-label">Contributors</span>
      <span className="contributors-names">{list.join(", ")}</span>
    </div>
  );
}

// ---- header -----------------------------------------------------------------
function CRCBrandLockup({ brandText, accent }) {
  const label = brandText === "full" ? "Conceptual reasoning capabilities team" : "CRC";
  return (
    <span className={"brand-lockup" + (brandText === "none" ? " brand-lockup--logo-only" : "")}>
      {brandText !== "none" && (accent ? (
        <a href="index.html" className={"wordmark wordmark--accent" + (brandText === "full" ? " wordmark--full" : "")}>
          <span className="wm-dot" />
          <span>{label}</span>
        </a>
      ) : (
        <a href="index.html" className={"wordmark" + (brandText === "full" ? " wordmark--full" : "")}>{label}</a>
      ))}
      {brandText !== "none" && <span className="brand-divider" />}
      <a href="index.html" aria-label="Redwood Research"><span className="redwood-logo" role="img" aria-label="Redwood Research" /></a>
    </span>
  );
}

function CRCNav({ current, t }) {
  const [menuOpen, setMenuOpen] = React.useState(false);
  const [ddOpen, setDdOpen] = React.useState(false);
  const ddRef = React.useRef(null);
  React.useEffect(() => {
    document.documentElement.classList.toggle("nav-locked", menuOpen);
    const onResize = () => { if (window.innerWidth > 680) setMenuOpen(false); };
    window.addEventListener("resize", onResize);
    return () => window.removeEventListener("resize", onResize);
  }, [menuOpen]);
  React.useEffect(() => {
    if (!ddOpen) return;
    const onDown = (e) => { if (ddRef.current && !ddRef.current.contains(e.target)) setDdOpen(false); };
    const onKey = (e) => { if (e.key === "Escape") setDdOpen(false); };
    document.addEventListener("mousedown", onDown);
    document.addEventListener("keydown", onKey);
    return () => { document.removeEventListener("mousedown", onDown); document.removeEventListener("keydown", onKey); };
  }, [ddOpen]);
  const stacked = t.dsNavStyle === "sublabel";
  const isDropdown = t.dsNavStyle === "dropdown";
  const DS_DROPDOWN = [
    { name: "Argument evaluation (LMCA)", href: "lmca.html", key: "LMCA" },
    { name: "Consistency (ConCoRD)", href: "consistency.html", key: "ConCoRD" },
    { name: "Decision theory (DTBench)", href: "dtbench.html", key: "DTBench" }
  ];
  const dsActive = DS_DROPDOWN.some((d) => d.key === current);
  const dsLinks = NAV_DATASETS.map((d) => (
    <a key={d.label} href={d.href}
       className={"nav-link nav-ds-link" + (stacked ? " nav-link--stack" : "") + (d.label === current ? " is-active" : "")}>
      {t.dsNavStyle === "dot" && <span className="nav-ds-dot" aria-hidden="true"></span>}
      <span className="nav-ds-label">{d.label}</span>
      {stacked && <span className="nav-link-sub">dataset</span>}
    </a>
  ));
  return (
    <React.Fragment>
      <button
        className="nav-toggle"
        aria-label="Open menu"
        aria-expanded={menuOpen}
        onClick={() => setMenuOpen(true)}>
        <span></span><span></span><span></span>
      </button>
      <div
        className={"nav-backdrop" + (menuOpen ? " is-open" : "")}
        onClick={() => setMenuOpen(false)}
        aria-hidden="true"></div>
    <nav
      className={"nav" + (menuOpen ? " nav--open" : "") + (stacked && t.dsSubAlign === "top" ? " nav--ds-baseline" : "")}
      onClick={(e) => { if (e.target.closest("a")) setMenuOpen(false); }}>
      <button className="nav-drawer-close" aria-label="Close menu" onClick={() => setMenuOpen(false)}>×</button>
      <a href="index.html#leaderboard" className={"nav-link" + (current === "Leaderboard" ? " is-active" : "")}>Leaderboard</a>
      <a href="methodology.html" className={"nav-link" + (current === "Methodology" ? " is-active" : "")}>Methodology</a>
      <a href="about.html" className={"nav-link" + (current === "About" ? " is-active" : "")}>About</a>
      {t.dsLabel === "inline" && !isDropdown && <span className="nav-ds-kicker nav-ds-kicker--inline" aria-hidden="true">Datasets</span>}
      {isDropdown ? (
        <div className={"nav-dd" + (ddOpen ? " is-open" : "") + (dsActive ? " is-active" : "")} ref={ddRef}>
          <button className="nav-dd-trigger" aria-expanded={ddOpen} aria-haspopup="true"
            onClick={(e) => { e.preventDefault(); setDdOpen((o) => !o); }}>
            Datasets <span className="nav-dd-caret" aria-hidden="true">▾</span>
          </button>
          <div className="nav-dd-menu nav-dd-menu--compact">
            {DS_DROPDOWN.map((d) => (
              <a key={d.href} href={d.href} className={"nav-dd-item" + (d.key === current ? " is-active" : "")}>
                <span className="nav-dd-name">{d.name}</span>
              </a>
            ))}
          </div>
        </div>
      ) : (t.dsLabel === "above" || t.dsLabel === "below") ? (
        <span className={"nav-ds-group nav-ds-group--" + t.dsNavStyle + " nav-ds-group--labelled nav-ds-group--label-" + t.dsLabel}>
          <span className="nav-ds-kicker nav-ds-kicker--stacked" aria-hidden="true">Datasets</span>
          {dsLinks}
        </span>
      ) : (
        <span className={"nav-ds-group nav-ds-group--" + t.dsNavStyle}>{dsLinks}</span>
      )}
    </nav>
    </React.Fragment>
  );
}

function SiteHeader({ current }) {
  const [t] = useCRCTweaks();
  const style = t.headerStyle || "minimal";

  if (style === "tealbar") {
    return (
      <header className="site-header header--tealbar">
        <div className="tealbar">
          <div className="container tealbar-inner mono-small">
            <span>Conceptual Reasoning Index · A research project</span>
            <span className="tealbar-cta">Latest: DTBench v2 released →</span>
          </div>
        </div>
        <div className="container header-inner">
          <CRCBrandLockup brandText={t.brandText} />
          <CRCNav current={current} t={t} />
        </div>
      </header>
    );
  }
  if (style === "accent") {
    return (
      <header className="site-header header--accent">
        <div className="container header-inner">
          <CRCBrandLockup brandText={t.brandText} accent />
          <CRCNav current={current} t={t} />
        </div>
      </header>
    );
  }
  if (style === "inverted") {
    return (
      <header className="site-header header--inverted">
        <div className="container header-inner">
          <CRCBrandLockup brandText={t.brandText} />
          <CRCNav current={current} t={t} />
        </div>
      </header>
    );
  }
  return (
    <header className="site-header">
      <div className="container header-inner">
        <CRCBrandLockup brandText={t.brandText} />
        <CRCNav current={current} t={t} />
      </div>
    </header>
  );
}

function PageHero({ eyebrow, title, lede }) {
  return (
    <section className="page-hero">
      <div className="container">
        {eyebrow && <div className="eyebrow">{eyebrow}</div>}
        <h1 className="subhero-title">{title}</h1>
        {lede && <p className="subhero-lede">{lede}</p>}
      </div>
    </section>
  );
}

function SiteFooter() {
  return (
    <footer className="site-footer">
      <div className="container footer-inner">
        <div className="footer-copy mono-small dim">© 2026</div>
      </div>
    </footer>
  );
}

Object.assign(window, {
  applyDefaultTokens, SiteHeader, PageHero, SiteFooter,
  CRCStore, useCRCTweaks, CRC_BODY_FONTS, CRC_DEFAULTS, CRCContributors
});
