// tweaks-app.jsx — Typography tweaks for TNLG Landing

const TWEAK_DEFAULTS = /*EDITMODE-BEGIN*/{
  "displayFont": "Gambarino",
  "brandFont": "Clash Display",
  "bodyFont": "Satoshi",
  "displayWeight": 400,
  "brandWeight": 600,
  "bodyWeight": 400,
  "headingSize": 100,
  "bodySize": 100,
  "letterSpacing": 0,
  "italicAccent": true,
  "constructionNotice": "console"
}/*EDITMODE-END*/;

// Font catalog — grouped by role. Each entry: {label, stack, googleFamily, italic?, defaultWeights}
const DISPLAY_FONTS = [
  { label: "Gambarino",        stack: "'Gambarino', serif",                  src: "fontshare", family: "gambarino", weights: "400" },
  { label: "Playfair Display", stack: "'Playfair Display', serif",           src: "google",    family: "Playfair+Display:ital,wght@0,400;0,600;0,700;1,400;1,600" },
  { label: "Cormorant Garamond", stack: "'Cormorant Garamond', serif",       src: "google",    family: "Cormorant+Garamond:ital,wght@0,400;0,500;0,600;0,700;1,400;1,500" },
  { label: "EB Garamond",      stack: "'EB Garamond', serif",                src: "google",    family: "EB+Garamond:ital,wght@0,400;0,500;0,600;0,700;1,400;1,500" },
  { label: "Editorial New",    stack: "'Gambarino', 'Times New Roman', serif", src: "fontshare", family: "gambarino", weights: "400", note: "fallback" },
  { label: "Instrument Serif", stack: "'Instrument Serif', serif",           src: "google",    family: "Instrument+Serif:ital@0;1" },
  { label: "DM Serif Display", stack: "'DM Serif Display', serif",           src: "google",    family: "DM+Serif+Display:ital@0;1" },
  { label: "Libre Caslon",     stack: "'Libre Caslon Text', serif",          src: "google",    family: "Libre+Caslon+Text:ital,wght@0,400;0,700;1,400" },
];

const BRAND_FONTS = [
  { label: "JetBrains Mono", stack: "'JetBrains Mono', ui-monospace, monospace", src: "google", family: "JetBrains+Mono:wght@400;500;600;700;800" },
  { label: "IBM Plex Mono",  stack: "'IBM Plex Mono', ui-monospace, monospace", src: "google",    family: "IBM+Plex+Mono:wght@400;500;600;700" },
  { label: "Clash Display", stack: "'Clash Display', sans-serif",            src: "fontshare", family: "clash-display", weights: "500,600,700" },
  { label: "Switzer",       stack: "'Switzer', sans-serif",                  src: "fontshare", family: "switzer",       weights: "400,500,600,700,900" },
  { label: "General Sans",  stack: "'General Sans', sans-serif",             src: "fontshare", family: "general-sans",  weights: "400,500,600,700" },
  { label: "Neue Haas Grotesk", stack: "'Space Grotesk', sans-serif",        src: "google",    family: "Space+Grotesk:wght@400;500;600;700" },
  { label: "Archivo",       stack: "'Archivo', sans-serif",                  src: "google",    family: "Archivo:wght@400;500;600;700;800;900" },
  { label: "Sora",          stack: "'Sora', sans-serif",                     src: "google",    family: "Sora:wght@300;400;500;600;700;800" },
  { label: "Bricolage Grotesque", stack: "'Bricolage Grotesque', sans-serif", src: "google",   family: "Bricolage+Grotesque:opsz,wght@12..96,400;12..96,500;12..96,600;12..96,700" },
  { label: "Manrope",       stack: "'Manrope', sans-serif",                  src: "google",    family: "Manrope:wght@400;500;600;700;800" },
];

const BODY_FONTS = [
  { label: "Satoshi",       stack: "'Satoshi', sans-serif",                  src: "fontshare", family: "satoshi", weights: "400,500,700,900" },
  { label: "Inter",         stack: "'Inter', sans-serif",                    src: "google",    family: "Inter:wght@400;500;600;700" },
  { label: "Söhne",         stack: "'Supreme', sans-serif",                  src: "fontshare", family: "supreme", weights: "400,500,700" },
  { label: "Geist",         stack: "'Geist', sans-serif",                    src: "google",    family: "Geist:wght@300;400;500;600;700" },
  { label: "IBM Plex Sans", stack: "'IBM Plex Sans', sans-serif",            src: "google",    family: "IBM+Plex+Sans:wght@400;500;600;700" },
  { label: "DM Sans",       stack: "'DM Sans', sans-serif",                  src: "google",    family: "DM+Sans:wght@400;500;600;700" },
  { label: "Work Sans",     stack: "'Work Sans', sans-serif",                src: "google",    family: "Work+Sans:wght@400;500;600;700" },
  { label: "JetBrains Mono", stack: "'JetBrains Mono', ui-monospace, monospace", src: "google", family: "JetBrains+Mono:wght@400;500;700", note: "mono" },
];

const BY_LABEL = {};
[...DISPLAY_FONTS, ...BRAND_FONTS, ...BODY_FONTS].forEach(f => { BY_LABEL[f.label] = f; });

// ── Font loader: lazily injects <link> tags as needed
const LOADED = new Set(["gambarino", "satoshi", "clash-display"]); // already in root <head>
function loadFont(label){
  const f = BY_LABEL[label];
  if(!f) return;
  const key = f.src + ":" + (f.family || "");
  if(LOADED.has(key)) return;
  LOADED.add(key);
  const link = document.createElement("link");
  link.rel = "stylesheet";
  if(f.src === "google"){
    link.href = `https://fonts.googleapis.com/css2?family=${f.family}&display=swap`;
  } else {
    // fontshare
    const w = f.weights || "400";
    link.href = `https://api.fontshare.com/v2/css?f[]=${f.family}@${w}&display=swap`;
  }
  document.head.appendChild(link);
}

// ── Live CSS override — pipes tweak values into :root custom properties
function applyTweaks(t){
  const display = BY_LABEL[t.displayFont]?.stack || "serif";
  const brand   = BY_LABEL[t.brandFont]?.stack   || "sans-serif";
  const body    = BY_LABEL[t.bodyFont]?.stack    || "sans-serif";
  loadFont(t.displayFont); loadFont(t.brandFont); loadFont(t.bodyFont);

  // Construction notice option (none|strip|bar|console)
  if(t.constructionNotice && t.constructionNotice !== "none"){
    document.body.setAttribute("data-notice", t.constructionNotice);
  } else {
    document.body.removeAttribute("data-notice");
  }

  let styleEl = document.getElementById("__tweaks_override__");
  if(!styleEl){
    styleEl = document.createElement("style");
    styleEl.id = "__tweaks_override__";
    document.head.appendChild(styleEl);
  }
  const italicOff = t.italicAccent ? "" : `
    .wordmark .wm-limits, .brand .nl, .footer-mark .em,
    .tagline .l1 .word, .tagline .l2 .word,
    .manifesto-text .em, .octopus-title .it, .nli-title .em,
    .capture-head .em, .nli-logo .em, .center-label .em,
    .card-body em, .manifesto-text .em
    { font-style: normal !important; }
  `;
  styleEl.textContent = `
    :root{
      --display: ${display} !important;
      --brand:   ${brand}   !important;
      --body:    ${body}    !important;
    }
    body{ font-family: var(--body); font-weight:${t.bodyWeight}; font-size:${t.bodySize}%; letter-spacing:${t.letterSpacing/100}em; }
    .brand, .wordmark, .footer-mark { font-weight:${t.brandWeight} !important; }
    .wordmark, .capture-head, .nli-title, .octopus-title, .manifesto-text, .hero-eyebrow, .tagline { letter-spacing: calc(-.02em + ${t.letterSpacing/100}em); }
    .wordmark, .capture-head, .nli-title, .octopus-title, .manifesto-text { font-size-adjust: none; }
    .manifesto-text, .octopus-title, .nli-title, .capture-head, .tagline, .center-label, .card-title, .nli-logo, .footer-mark {
      /* heading size scales relative */
    }
    .manifesto-text{ font-size: clamp(${32 * t.headingSize/100}px, ${4 * t.headingSize/100}vw, ${64 * t.headingSize/100}px); }
    .octopus-title { font-size: clamp(${44 * t.headingSize/100}px, ${6 * t.headingSize/100}vw, ${92 * t.headingSize/100}px); }
    .nli-title     { font-size: clamp(${44 * t.headingSize/100}px, ${5.6 * t.headingSize/100}vw, ${86 * t.headingSize/100}px); }
    .capture-head  { font-size: clamp(${56 * t.headingSize/100}px, ${7 * t.headingSize/100}vw, ${112 * t.headingSize/100}px); }
    .wordmark      { font-weight:${t.brandWeight}; }
    ${italicOff}
  `;
}

function TypographyPanel(){
  const [t, setTweak] = useTweaks(TWEAK_DEFAULTS);
  React.useEffect(() => { applyTweaks(t); }, [t]);

  const apply = (preset) => {
    Object.entries(preset).forEach(([k,v]) => setTweak(k, v));
  };

  const presets = [
    { name: "Terminal",    vals: { displayFont:"Gambarino",        brandFont:"JetBrains Mono",   bodyFont:"JetBrains Mono",  brandWeight:700, italicAccent:true } },
    { name: "Editorial",   vals: { displayFont:"Gambarino",        brandFont:"Clash Display",    bodyFont:"Satoshi",         brandWeight:600, italicAccent:true } },
    { name: "Modern",      vals: { displayFont:"Instrument Serif", brandFont:"Switzer",          bodyFont:"Inter",           brandWeight:600, italicAccent:true } },
    { name: "Swiss",       vals: { displayFont:"DM Serif Display", brandFont:"Neue Haas Grotesk",bodyFont:"Inter",           brandWeight:500, italicAccent:false } },
    { name: "Geometric",   vals: { displayFont:"Playfair Display", brandFont:"Sora",             bodyFont:"DM Sans",         brandWeight:600, italicAccent:true } },
    { name: "Bold",        vals: { displayFont:"DM Serif Display", brandFont:"Archivo",          bodyFont:"Work Sans",       brandWeight:700, italicAccent:true } },
    { name: "Refined",     vals: { displayFont:"Cormorant Garamond", brandFont:"General Sans",   bodyFont:"Geist",           brandWeight:500, italicAccent:true } },
    { name: "Legacy",      vals: { displayFont:"Libre Caslon",     brandFont:"Manrope",          bodyFont:"IBM Plex Sans",   brandWeight:600, italicAccent:true } },
  ];

  return (
    <TweaksPanel title="Tweaks">
      <TweakSection label="Construction Notice" />
      <TweakRadio label="Style" value={t.constructionNotice}
        options={[
          {label:"Strip",   value:"strip"},
          {label:"Top Bar", value:"bar"},
          {label:"Console", value:"console"},
          {label:"Off",     value:"none"},
        ]}
        onChange={(v) => setTweak('constructionNotice', v)} />

      <TweakSection label="Presets" />
      <div style={{ display:'grid', gridTemplateColumns:'1fr 1fr', gap:6, marginBottom:4 }}>
        {presets.map(p => (
          <button key={p.name} onClick={() => apply(p.vals)}
            style={{
              appearance:'none', border:'.5px solid rgba(0,0,0,.12)', background:'rgba(255,255,255,.7)',
              color:'#29261b', font:'inherit', fontWeight:500,
              padding:'7px 10px', borderRadius:7, cursor:'default', textAlign:'left'
            }}>
            {p.name}
          </button>
        ))}
      </div>

      <TweakSection label="Fonts" />
      <TweakSelect label="Display (serif accent)" value={t.displayFont}
        options={DISPLAY_FONTS.map(f => f.label)}
        onChange={(v) => setTweak('displayFont', v)} />
      <TweakSelect label="Brand / Headings" value={t.brandFont}
        options={BRAND_FONTS.map(f => f.label)}
        onChange={(v) => setTweak('brandFont', v)} />
      <TweakSelect label="Body" value={t.bodyFont}
        options={BODY_FONTS.map(f => f.label)}
        onChange={(v) => setTweak('bodyFont', v)} />

      <TweakSection label="Weight" />
      <TweakSlider label="Brand weight" value={t.brandWeight} min={300} max={900} step={100}
        onChange={(v) => setTweak('brandWeight', v)} />
      <TweakSlider label="Body weight" value={t.bodyWeight} min={300} max={700} step={100}
        onChange={(v) => setTweak('bodyWeight', v)} />

      <TweakSection label="Scale" />
      <TweakSlider label="Heading size" value={t.headingSize} min={70} max={140} step={5} unit="%"
        onChange={(v) => setTweak('headingSize', v)} />
      <TweakSlider label="Body size" value={t.bodySize} min={85} max={120} step={5} unit="%"
        onChange={(v) => setTweak('bodySize', v)} />
      <TweakSlider label="Letter spacing" value={t.letterSpacing} min={-3} max={5} step={1} unit=""
        onChange={(v) => setTweak('letterSpacing', v)} />

      <TweakSection label="Accent" />
      <TweakToggle label="Italic serif accent" value={t.italicAccent}
        onChange={(v) => setTweak('italicAccent', v)} />
    </TweaksPanel>
  );
}

const __twkMount = document.createElement('div');
document.body.appendChild(__twkMount);
ReactDOM.createRoot(__twkMount).render(<TypographyPanel />);
