// tweaks-app.jsx — Tweaks state + UI for the cafe mock homepage.
// All visual values flow through CSS custom properties on :root, so changing
// a tweak just calls document.documentElement.style.setProperty().

const TWEAK_DEFAULTS = /*EDITMODE-BEGIN*/{
  "palette": "classic",
  "bg": "#f6f1e7",
  "text": "#2a2520",
  "heading": "#231b13",
  "accent": "#8a6a3d",
  "rule": "#d9cdb6",
  "footerBg": "#1d160f",

  "typePair": "serif-sans",
  "baseSize": 16,
  "headingWeight": 500,
  "headingTracking": -2,
  "logoTracking": 36,

  "contentWidth": 1080,
  "sectionGap": 6,
  "radius": 4,

  "heroHeight": 560,
  "heroMono": 0,
  "heroDark": 32,
  "heroAlign": "center",
  "heroKicker": "Est. since the morning",
  "heroTitle": "A quiet hour, <em>between sips.</em>",
  "heroSub": "焙煎したての一杯と、丁寧な朝食を。日々の合間に、ほんの少し立ち止まれる場所として。",

  "menuRule": "dotted",
  "menuRowHeight": 14,
  "menuCardOpacity": 100
}/*EDITMODE-END*/;

// ── Palette presets ─────────────────────────────────────────────────────────
const PALETTES = {
  classic: { bg:"#f6f1e7", text:"#2a2520", heading:"#231b13", accent:"#8a6a3d", rule:"#d9cdb6", footerBg:"#1d160f" },
  cream:   { bg:"#fbf6ec", text:"#3a2f23", heading:"#2b1f12", accent:"#b08a55", rule:"#ead9bd", footerBg:"#2b1f12" },
  mist:    { bg:"#eef0ee", text:"#262a28", heading:"#171b19", accent:"#5d6f6a", rule:"#cdd4d0", footerBg:"#1a1f1d" },
  moss:    { bg:"#eef0e6", text:"#222a1e", heading:"#15200f", accent:"#5b6f3b", rule:"#cdd4be", footerBg:"#15200f" },
  dark:    { bg:"#161310", text:"#e9e0d0", heading:"#f4ead7", accent:"#c79a5a", rule:"#3a2f22", footerBg:"#0c0907" }
};

// ── Type pair presets ───────────────────────────────────────────────────────
const TYPE_PAIRS = {
  "serif-sans": { display: '"Fraunces", "Shippori Mincho", serif',  body: '"Inter", "Hiragino Kaku Gothic ProN", system-ui, sans-serif' },
  "serif":      { display: '"Fraunces", "Shippori Mincho", serif',  body: '"Fraunces", "Shippori Mincho", "Hiragino Mincho ProN", serif' },
  "sans":       { display: '"Inter", "Hiragino Kaku Gothic ProN", sans-serif', body: '"Inter", "Hiragino Kaku Gothic ProN", system-ui, sans-serif' },
  "mincho":     { display: '"Shippori Mincho", "Hiragino Mincho ProN", serif', body: '"Shippori Mincho", "Hiragino Mincho ProN", serif' }
};

// ── Apply tweaks → CSS vars ─────────────────────────────────────────────────
function applyTweaks(t) {
  const r = document.documentElement.style;
  // Palette colors (the picker overrides whatever the preset set)
  r.setProperty('--bg', t.bg);
  r.setProperty('--text', t.text);
  r.setProperty('--heading', t.heading);
  r.setProperty('--accent', t.accent);
  r.setProperty('--rule', t.rule);
  r.setProperty('--footer-bg', t.footerBg);

  // Type
  const pair = TYPE_PAIRS[t.typePair] || TYPE_PAIRS["serif-sans"];
  r.setProperty('--font-display', pair.display);
  r.setProperty('--font-body', pair.body);
  r.setProperty('--base-size', `${t.baseSize}px`);
  r.setProperty('--heading-weight', String(t.headingWeight));
  r.setProperty('--heading-tracking', `${t.headingTracking / 100}em`);
  r.setProperty('--logo-tracking', `${t.logoTracking / 100}em`);

  // Layout
  r.setProperty('--content-w', `${t.contentWidth}px`);
  r.setProperty('--section-gap', `${t.sectionGap}rem`);
  r.setProperty('--radius', `${t.radius}px`);

  // Hero
  r.setProperty('--hero-h', `${t.heroHeight}px`);
  r.setProperty('--hero-mono', `${t.heroMono}%`);
  r.setProperty('--hero-dark', `${t.heroDark / 100}`);
  r.setProperty('--hero-align', { top: 'flex-start', center: 'center', bottom: 'flex-end' }[t.heroAlign] || 'center');

  // Menu
  const ruleMap = { dotted: 'dotted', dashed: 'dashed', solid: 'solid', none: 'none' };
  r.setProperty('--menu-rule-style', ruleMap[t.menuRule] || 'dotted');
  r.setProperty('--menu-row-pad', `${t.menuRowHeight}px`);
  r.setProperty('--menu-card-opacity', String(t.menuCardOpacity / 100));
}

// ── Hero text injection (innerHTML so <em> tags work) ───────────────────────
function applyHeroText(t) {
  const k = document.getElementById('hero-kicker');
  const ti = document.getElementById('hero-title');
  const s = document.getElementById('hero-sub');
  if (k) k.textContent = t.heroKicker;
  if (ti) ti.innerHTML = t.heroTitle;
  if (s) s.textContent = t.heroSub;
}

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

  // Re-apply on every change.
  React.useEffect(() => { applyTweaks(t); applyHeroText(t); }, [t]);

  // Choosing a palette merges its colors in (overwrites the 6 color keys).
  const choosePalette = (name) => {
    const p = PALETTES[name];
    if (!p) { setTweak('palette', name); return; }
    setTweak({ palette: name, ...p });
  };

  return (
    <TweaksPanel title="Tweaks">
      <TweakSection label="Palette" />
      <TweakSelect
        label="Preset"
        value={t.palette}
        options={[
          { value: 'classic', label: 'Classic — warm cream' },
          { value: 'cream',   label: 'Cream — golden honey' },
          { value: 'mist',    label: 'Mist — cool stone' },
          { value: 'moss',    label: 'Moss — green earth' },
          { value: 'dark',    label: 'Dark — espresso' },
        ]}
        onChange={choosePalette}
      />
      <TweakColor label="Background"  value={t.bg}       onChange={v => setTweak({ bg: v, palette: 'custom' })} />
      <TweakColor label="Body text"   value={t.text}     onChange={v => setTweak({ text: v, palette: 'custom' })} />
      <TweakColor label="Heading"     value={t.heading}  onChange={v => setTweak({ heading: v, palette: 'custom' })} />
      <TweakColor label="Accent"      value={t.accent}   onChange={v => setTweak({ accent: v, palette: 'custom' })} />
      <TweakColor label="Rule"        value={t.rule}     onChange={v => setTweak({ rule: v, palette: 'custom' })} />
      <TweakColor label="Footer bg"   value={t.footerBg} onChange={v => setTweak({ footerBg: v, palette: 'custom' })} />

      <TweakSection label="Typography" />
      <TweakRadio
        label="Type pair"
        value={t.typePair}
        options={[
          { value: 'serif-sans', label: 'Serif + Sans' },
          { value: 'serif', label: 'Serif' },
          { value: 'sans', label: 'Sans' },
          { value: 'mincho', label: 'Mincho' },
        ]}
        onChange={v => setTweak('typePair', v)}
      />
      <TweakSlider label="Base size"        value={t.baseSize}        min={13} max={20} unit="px"   onChange={v => setTweak('baseSize', v)} />
      <TweakSlider label="Heading weight"   value={t.headingWeight}   min={300} max={700} step={100} onChange={v => setTweak('headingWeight', v)} />
      <TweakSlider label="Heading tracking" value={t.headingTracking} min={-3} max={15} unit="/100em" onChange={v => setTweak('headingTracking', v)} />
      <TweakSlider label="Logo tracking"    value={t.logoTracking}    min={0} max={80} unit="/100em" onChange={v => setTweak('logoTracking', v)} />

      <TweakSection label="Layout" />
      <TweakSlider label="Content width" value={t.contentWidth} min={720} max={1280} step={20} unit="px" onChange={v => setTweak('contentWidth', v)} />
      <TweakSlider label="Section gap"   value={t.sectionGap}   min={3} max={12} step={0.5} unit="rem"  onChange={v => setTweak('sectionGap', v)} />
      <TweakSlider label="Corner radius" value={t.radius}       min={0} max={28} unit="px"             onChange={v => setTweak('radius', v)} />

      <TweakSection label="Hero" />
      <TweakSlider label="Hero height"   value={t.heroHeight} min={320} max={820} step={10} unit="px" onChange={v => setTweak('heroHeight', v)} />
      <TweakSlider label="Monochrome"    value={t.heroMono}   min={0} max={100} unit="%"              onChange={v => setTweak('heroMono', v)} />
      <TweakSlider label="Darkness"      value={t.heroDark}   min={0} max={75} unit="%"               onChange={v => setTweak('heroDark', v)} />
      <TweakRadio  label="Copy position" value={t.heroAlign}
                   options={[{value:'top',label:'Top'},{value:'center',label:'Center'},{value:'bottom',label:'Bottom'}]}
                   onChange={v => setTweak('heroAlign', v)} />
      <TweakText   label="Kicker"   value={t.heroKicker} onChange={v => setTweak('heroKicker', v)} />
      <TweakText   label="Title"    value={t.heroTitle}  onChange={v => setTweak('heroTitle', v)} />
      <TweakText   label="Subcopy"  value={t.heroSub}    onChange={v => setTweak('heroSub', v)} />

      <TweakSection label="Menu" />
      <TweakRadio  label="Divider" value={t.menuRule}
                   options={[{value:'dotted',label:'Dotted'},{value:'dashed',label:'Dashed'},{value:'solid',label:'Solid'},{value:'none',label:'None'}]}
                   onChange={v => setTweak('menuRule', v)} />
      <TweakSlider label="Row height"     value={t.menuRowHeight}   min={6} max={28} unit="px" onChange={v => setTweak('menuRowHeight', v)} />
      <TweakSlider label="Card opacity"   value={t.menuCardOpacity} min={20} max={100} unit="%" onChange={v => setTweak('menuCardOpacity', v)} />
    </TweaksPanel>
  );
}

// Apply defaults immediately on load (before React mounts) so the page
// renders with the right values from the start.
applyTweaks(TWEAK_DEFAULTS);
applyHeroText(TWEAK_DEFAULTS);

ReactDOM.createRoot(document.getElementById('tweaks-root')).render(<App />);
