// tweaks-app.jsx — Cafe mock site Tweaks panel (workshop practice)
// All values flow into CSS custom properties on :root via setProperty.

const TWEAK_DEFAULTS = /*EDITMODE-BEGIN*/{
  "palette": "classic",
  "colorBg": "#FBF7F0",
  "colorText": "#2A2622",
  "colorHeading": "#2A1C10",
  "colorAccent": "#B89466",
  "colorRule": "#E6DBC6",
  "colorFooter": "#1F140A",

  "fontPair": "serif-sans",
  "fontSize": 16,
  "headingWeight": 500,
  "headingTracking": -2,
  "logoTracking": 28,

  "contentWidth": 1080,
  "sectionSpacing": 7,
  "radius": 14,

  "heroHeight": 560,
  "heroMono": 0,
  "heroDark": 35,
  "heroAlign": "center",
  "heroKicker": "Est. 20XX  |  Workshop Mock",
  "heroTitle": "ゆっくりとした、\u003cem\u003e一杯の\u003c/em\u003e時間を。",
  "heroSub": "焙煎したての豆と、丁寧に淹れた一杯。日々の合間の小さな休息のために。",

  "menuDivider": "dotted",
  "menuLineHeight": 1.9,
  "menuCardOpacity": 92
}/*EDITMODE-END*/;

const PALETTES = {
  classic: { colorBg:"#FBF7F0", colorText:"#2A2622", colorHeading:"#2A1C10", colorAccent:"#B89466", colorRule:"#E6DBC6", colorFooter:"#1F140A" },
  cream:   { colorBg:"#F4ECDD", colorText:"#3A2E20", colorHeading:"#3A2410", colorAccent:"#C29A6B", colorRule:"#E2D2B5", colorFooter:"#2A1A0A" },
  mist:    { colorBg:"#EEF1EE", colorText:"#26302C", colorHeading:"#1E2A26", colorAccent:"#7A8A82", colorRule:"#D5DCD7", colorFooter:"#16201C" },
  moss:    { colorBg:"#F2F1E9", colorText:"#2A2E22", colorHeading:"#1F2A18", colorAccent:"#6B7A4A", colorRule:"#D6D6C2", colorFooter:"#161E0E" },
  dark:    { colorBg:"#16120E", colorText:"#E8DFCE", colorHeading:"#F4ECD8", colorAccent:"#C9A66B", colorRule:"#3A2E22", colorFooter:"#0A0604" },
};

const FONT_PAIRS = {
  "serif-sans": { heading: '"Fraunces", "Shippori Mincho", serif', body: '"Inter", system-ui, "Hiragino Kaku Gothic ProN", sans-serif' },
  "serif":      { heading: '"Fraunces", "Shippori Mincho", serif', body: '"Fraunces", "Shippori Mincho", serif' },
  "sans":       { heading: '"Inter", system-ui, sans-serif', body: '"Inter", system-ui, "Hiragino Kaku Gothic ProN", sans-serif' },
  "mincho":     { heading: '"Shippori Mincho", "Fraunces", serif', body: '"Shippori Mincho", "Hiragino Mincho ProN", serif' },
};

const DIVIDER_STYLE = {
  dotted: 'dotted', dashed: 'dashed', solid: 'solid', none: 'none',
};

function hexToRgba(hex, a){
  const m = /^#?([0-9a-f]{6})$/i.exec(hex);
  if (!m) return hex;
  const n = parseInt(m[1], 16);
  return `rgba(${(n>>16)&255},${(n>>8)&255},${n&255},${a})`;
}

function applyTweaks(t){
  const r = document.documentElement.style;
  r.setProperty('--bg', t.colorBg);
  r.setProperty('--text', t.colorText);
  r.setProperty('--heading', t.colorHeading);
  r.setProperty('--accent', t.colorAccent);
  r.setProperty('--rule', t.colorRule);
  r.setProperty('--footer-bg', t.colorFooter);
  r.setProperty('--footer-text', hexToRgba(t.colorBg, 0.92));

  const pair = FONT_PAIRS[t.fontPair] || FONT_PAIRS["serif-sans"];
  r.setProperty('--font-heading', pair.heading);
  r.setProperty('--font-body', pair.body);
  r.setProperty('--fs-base', t.fontSize + 'px');
  r.setProperty('--heading-weight', String(t.headingWeight));
  r.setProperty('--heading-tracking', (t.headingTracking/100) + 'em');
  r.setProperty('--logo-tracking', (t.logoTracking/100) + 'em');

  r.setProperty('--content-w', t.contentWidth + 'px');
  r.setProperty('--sect-gap', t.sectionSpacing + 'rem');
  r.setProperty('--radius', t.radius + 'px');

  r.setProperty('--hero-h', t.heroHeight + 'px');
  r.setProperty('--hero-grayscale', (t.heroMono/100));
  r.setProperty('--hero-dark', (t.heroDark/100));
  const align = t.heroAlign === 'top' ? 'flex-start' : t.heroAlign === 'bottom' ? 'flex-end' : 'center';
  r.setProperty('--hero-align', align);

  r.setProperty('--menu-divider', DIVIDER_STYLE[t.menuDivider] || 'dotted');
  r.setProperty('--menu-lh', String(t.menuLineHeight));
  r.setProperty('--card-bg', hexToRgba(t.colorBg, t.menuCardOpacity/100));

  // Inline edits to text
  document.querySelectorAll('[data-bind="heroKicker"]').forEach(el => el.textContent = t.heroKicker);
  document.querySelectorAll('[data-bind="heroTitle"]').forEach(el => el.innerHTML = t.heroTitle);
  document.querySelectorAll('[data-bind="heroSub"]').forEach(el => el.textContent = t.heroSub);
}

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

  // Apply on mount and every change
  React.useEffect(() => { applyTweaks(t); }, [t]);
  
  // Also apply once immediately on mount (before first render completes)
  React.useLayoutEffect(() => { applyTweaks(t); }, []);

  // When palette preset changes, push its colors into the individual swatches
  const setPalette = (name) => {
    const p = PALETTES[name];
    if (!p) { setTweak('palette', name); return; }
    setTweak({ palette: name, ...p });
  };

  return (
    <TweaksPanel title="Tweaks">
      <TweakSection label="Color preset" />
      <TweakRadio label="Palette" value={t.palette}
        options={[
          { value:'classic', label:'Classic' },
          { value:'cream',   label:'Cream' },
          { value:'mist',    label:'Mist' },
          { value:'moss',    label:'Moss' },
          { value:'dark',    label:'Dark' },
        ]}
        onChange={setPalette} />

      <TweakSection label="Colors" />
      <TweakColor label="Background" value={t.colorBg}      onChange={v => setTweak('colorBg', v)} />
      <TweakColor label="Body text"  value={t.colorText}    onChange={v => setTweak('colorText', v)} />
      <TweakColor label="Headings"   value={t.colorHeading} onChange={v => setTweak('colorHeading', v)} />
      <TweakColor label="Accent"     value={t.colorAccent}  onChange={v => setTweak('colorAccent', v)} />
      <TweakColor label="Rules"      value={t.colorRule}    onChange={v => setTweak('colorRule', v)} />
      <TweakColor label="Footer bg"  value={t.colorFooter}  onChange={v => setTweak('colorFooter', v)} />

      <TweakSection label="Typography" />
      <TweakRadio label="Font pair" value={t.fontPair}
        options={[
          { value:'serif-sans', label:'Serif+Sans' },
          { value:'serif',      label:'Serif' },
          { value:'sans',       label:'Sans' },
          { value:'mincho',     label:'明朝' },
        ]}
        onChange={v => setTweak('fontPair', v)} />
      <TweakSlider label="Base size"        value={t.fontSize}        min={13} max={20} unit="px"   onChange={v => setTweak('fontSize', 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 spacing" value={t.sectionSpacing} min={3}   max={12}   step={0.5} unit="rem" onChange={v => setTweak('sectionSpacing', v)} />
      <TweakSlider label="Radius"          value={t.radius}         min={0}   max={28}   unit="px" onChange={v => setTweak('radius', v)} />

      <TweakSection label="Hero" />
      <TweakSlider label="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 align" value={t.heroAlign}
        options={[{value:'top',label:'Top'},{value:'center',label:'Mid'},{value:'bottom',label:'Btm'}]}
        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.menuDivider}
        options={[{value:'dotted',label:'Dot'},{value:'dashed',label:'Dash'},{value:'solid',label:'Solid'},{value:'none',label:'None'}]}
        onChange={v => setTweak('menuDivider', v)} />
      <TweakSlider label="Line height"   value={t.menuLineHeight} min={1.4} max={2.4} step={0.05} onChange={v => setTweak('menuLineHeight', v)} />
      <TweakSlider label="Card opacity"  value={t.menuCardOpacity} min={50}  max={100} unit="%" onChange={v => setTweak('menuCardOpacity', v)} />
    </TweaksPanel>
  );
}

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