/* ==== tweaks-panel ==== */

// tweaks-panel.jsx
// Reusable Tweaks shell + form-control helpers.
//
// Owns the host protocol (listens for __activate_edit_mode / __deactivate_edit_mode,
// posts __edit_mode_available / __edit_mode_set_keys / __edit_mode_dismissed) so
// individual prototypes don't re-roll it. Ships a consistent set of controls so you
// don't hand-draw <input type="range">, segmented radios, steppers, etc.
//
// Usage (in an HTML file that loads React + Babel):
//
//   const TWEAK_DEFAULTS = /*EDITMODE-BEGIN*/{
//     "primaryColor": "#D97757",
//     "palette": ["#D97757", "#29261b", "#f6f4ef"],
//     "fontSize": 16,
//     "density": "regular",
//     "dark": false
//   }/*EDITMODE-END*/;
//
//   function App() {
//     const [t, setTweak] = useTweaks(TWEAK_DEFAULTS);
//     return (
//       <div style={{ fontSize: t.fontSize, color: t.primaryColor }}>
//         Hello
//         <TweaksPanel>
//           <TweakSection label="Typography" />
//           <TweakSlider label="Font size" value={t.fontSize} min={10} max={32} unit="px"
//                        onChange={(v) => setTweak('fontSize', v)} />
//           <TweakRadio  label="Density" value={t.density}
//                        options={['compact', 'regular', 'comfy']}
//                        onChange={(v) => setTweak('density', v)} />
//           <TweakSection label="Theme" />
//           <TweakColor  label="Primary" value={t.primaryColor}
//                        options={['#D97757', '#2A6FDB', '#1F8A5B', '#7A5AE0']}
//                        onChange={(v) => setTweak('primaryColor', v)} />
//           <TweakColor  label="Palette" value={t.palette}
//                        options={[['#D97757', '#29261b', '#f6f4ef'],
//                                  ['#475569', '#0f172a', '#f1f5f9']]}
//                        onChange={(v) => setTweak('palette', v)} />
//           <TweakToggle label="Dark mode" value={t.dark}
//                        onChange={(v) => setTweak('dark', v)} />
//         </TweaksPanel>
//       </div>
//     );
//   }
//
// ─────────────────────────────────────────────────────────────────────────────

const __TWEAKS_STYLE = `
  .twk-panel{position:fixed;right:16px;bottom:16px;z-index:2147483646;width:280px;
    max-height:calc(100vh - 32px);display:flex;flex-direction:column;
    transform:scale(var(--dc-inv-zoom,1));transform-origin:bottom right;
    background:rgba(250,249,247,.78);color:#29261b;
    -webkit-backdrop-filter:blur(24px) saturate(160%);backdrop-filter:blur(24px) saturate(160%);
    border:.5px solid rgba(255,255,255,.6);border-radius:14px;
    box-shadow:0 1px 0 rgba(255,255,255,.5) inset,0 12px 40px rgba(0,0,0,.18);
    font:11.5px/1.4 ui-sans-serif,system-ui,-apple-system,sans-serif;overflow:hidden}
  .twk-hd{display:flex;align-items:center;justify-content:space-between;
    padding:10px 8px 10px 14px;cursor:move;user-select:none}
  .twk-hd b{font-size:12px;font-weight:600;letter-spacing:.01em}
  .twk-x{appearance:none;border:0;background:transparent;color:rgba(41,38,27,.55);
    width:22px;height:22px;border-radius:6px;cursor:default;font-size:13px;line-height:1}
  .twk-x:hover{background:rgba(0,0,0,.06);color:#29261b}
  .twk-body{padding:2px 14px 14px;display:flex;flex-direction:column;gap:10px;
    overflow-y:auto;overflow-x:hidden;min-height:0;
    scrollbar-width:thin;scrollbar-color:rgba(0,0,0,.15) transparent}
  .twk-body::-webkit-scrollbar{width:8px}
  .twk-body::-webkit-scrollbar-track{background:transparent;margin:2px}
  .twk-body::-webkit-scrollbar-thumb{background:rgba(0,0,0,.15);border-radius:4px;
    border:2px solid transparent;background-clip:content-box}
  .twk-body::-webkit-scrollbar-thumb:hover{background:rgba(0,0,0,.25);
    border:2px solid transparent;background-clip:content-box}
  .twk-row{display:flex;flex-direction:column;gap:5px}
  .twk-row-h{flex-direction:row;align-items:center;justify-content:space-between;gap:10px}
  .twk-lbl{display:flex;justify-content:space-between;align-items:baseline;
    color:rgba(41,38,27,.72)}
  .twk-lbl>span:first-child{font-weight:500}
  .twk-val{color:rgba(41,38,27,.5);font-variant-numeric:tabular-nums}

  .twk-sect{font-size:10px;font-weight:600;letter-spacing:.06em;text-transform:uppercase;
    color:rgba(41,38,27,.45);padding:10px 0 0}
  .twk-sect:first-child{padding-top:0}

  .twk-field{appearance:none;box-sizing:border-box;width:100%;min-width:0;height:26px;padding:0 8px;
    border:.5px solid rgba(0,0,0,.1);border-radius:7px;
    background:rgba(255,255,255,.6);color:inherit;font:inherit;outline:none}
  .twk-field:focus{border-color:rgba(0,0,0,.25);background:rgba(255,255,255,.85)}
  select.twk-field{padding-right:22px;
    background-image:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='10' height='6' viewBox='0 0 10 6'><path fill='rgba(0,0,0,.5)' d='M0 0h10L5 6z'/></svg>");
    background-repeat:no-repeat;background-position:right 8px center}

  .twk-slider{appearance:none;-webkit-appearance:none;width:100%;height:4px;margin:6px 0;
    border-radius:999px;background:rgba(0,0,0,.12);outline:none}
  .twk-slider::-webkit-slider-thumb{-webkit-appearance:none;appearance:none;
    width:14px;height:14px;border-radius:50%;background:#fff;
    border:.5px solid rgba(0,0,0,.12);box-shadow:0 1px 3px rgba(0,0,0,.2);cursor:default}
  .twk-slider::-moz-range-thumb{width:14px;height:14px;border-radius:50%;
    background:#fff;border:.5px solid rgba(0,0,0,.12);box-shadow:0 1px 3px rgba(0,0,0,.2);cursor:default}

  .twk-seg{position:relative;display:flex;padding:2px;border-radius:8px;
    background:rgba(0,0,0,.06);user-select:none}
  .twk-seg-thumb{position:absolute;top:2px;bottom:2px;border-radius:6px;
    background:rgba(255,255,255,.9);box-shadow:0 1px 2px rgba(0,0,0,.12);
    transition:left .15s cubic-bezier(.3,.7,.4,1),width .15s}
  .twk-seg.dragging .twk-seg-thumb{transition:none}
  .twk-seg button{appearance:none;position:relative;z-index:1;flex:1;border:0;
    background:transparent;color:inherit;font:inherit;font-weight:500;min-height:22px;
    border-radius:6px;cursor:default;padding:4px 6px;line-height:1.2;
    overflow-wrap:anywhere}

  .twk-toggle{position:relative;width:32px;height:18px;border:0;border-radius:999px;
    background:rgba(0,0,0,.15);transition:background .15s;cursor:default;padding:0}
  .twk-toggle[data-on="1"]{background:#34c759}
  .twk-toggle i{position:absolute;top:2px;left:2px;width:14px;height:14px;border-radius:50%;
    background:#fff;box-shadow:0 1px 2px rgba(0,0,0,.25);transition:transform .15s}
  .twk-toggle[data-on="1"] i{transform:translateX(14px)}

  .twk-num{display:flex;align-items:center;box-sizing:border-box;min-width:0;height:26px;padding:0 0 0 8px;
    border:.5px solid rgba(0,0,0,.1);border-radius:7px;background:rgba(255,255,255,.6)}
  .twk-num-lbl{font-weight:500;color:rgba(41,38,27,.6);cursor:ew-resize;
    user-select:none;padding-right:8px}
  .twk-num input{flex:1;min-width:0;height:100%;border:0;background:transparent;
    font:inherit;font-variant-numeric:tabular-nums;text-align:right;padding:0 8px 0 0;
    outline:none;color:inherit;-moz-appearance:textfield}
  .twk-num input::-webkit-inner-spin-button,.twk-num input::-webkit-outer-spin-button{
    -webkit-appearance:none;margin:0}
  .twk-num-unit{padding-right:8px;color:rgba(41,38,27,.45)}

  .twk-btn{appearance:none;height:26px;padding:0 12px;border:0;border-radius:7px;
    background:rgba(0,0,0,.78);color:#fff;font:inherit;font-weight:500;cursor:default}
  .twk-btn:hover{background:rgba(0,0,0,.88)}
  .twk-btn.secondary{background:rgba(0,0,0,.06);color:inherit}
  .twk-btn.secondary:hover{background:rgba(0,0,0,.1)}

  .twk-swatch{appearance:none;-webkit-appearance:none;width:56px;height:22px;
    border:.5px solid rgba(0,0,0,.1);border-radius:6px;padding:0;cursor:default;
    background:transparent;flex-shrink:0}
  .twk-swatch::-webkit-color-swatch-wrapper{padding:0}
  .twk-swatch::-webkit-color-swatch{border:0;border-radius:5.5px}
  .twk-swatch::-moz-color-swatch{border:0;border-radius:5.5px}

  .twk-chips{display:flex;gap:6px}
  .twk-chip{position:relative;appearance:none;flex:1;min-width:0;height:46px;
    padding:0;border:0;border-radius:6px;overflow:hidden;cursor:default;
    box-shadow:0 0 0 .5px rgba(0,0,0,.12),0 1px 2px rgba(0,0,0,.06);
    transition:transform .12s cubic-bezier(.3,.7,.4,1),box-shadow .12s}
  .twk-chip:hover{transform:translateY(-1px);
    box-shadow:0 0 0 .5px rgba(0,0,0,.18),0 4px 10px rgba(0,0,0,.12)}
  .twk-chip[data-on="1"]{box-shadow:0 0 0 1.5px rgba(0,0,0,.85),
    0 2px 6px rgba(0,0,0,.15)}
  .twk-chip>span{position:absolute;top:0;bottom:0;right:0;width:34%;
    display:flex;flex-direction:column;box-shadow:-1px 0 0 rgba(0,0,0,.1)}
  .twk-chip>span>i{flex:1;box-shadow:0 -1px 0 rgba(0,0,0,.1)}
  .twk-chip>span>i:first-child{box-shadow:none}
  .twk-chip svg{position:absolute;top:6px;left:6px;width:13px;height:13px;
    filter:drop-shadow(0 1px 1px rgba(0,0,0,.3))}
`;

// ── useTweaks ───────────────────────────────────────────────────────────────
// Single source of truth for tweak values. setTweak persists via the host
// (__edit_mode_set_keys → host rewrites the EDITMODE block on disk).
function useTweaks(defaults) {
  const [values, setValues] = React.useState(defaults);
  // Accepts either setTweak('key', value) or setTweak({ key: value, ... }) so a
  // useState-style call doesn't write a "[object Object]" key into the persisted
  // JSON block.
  const setTweak = React.useCallback((keyOrEdits, val) => {
    const edits = typeof keyOrEdits === 'object' && keyOrEdits !== null
      ? keyOrEdits : { [keyOrEdits]: val };
    setValues((prev) => ({ ...prev, ...edits }));
    window.parent.postMessage({ type: '__edit_mode_set_keys', edits }, '*');
    // Same-window signal so in-page listeners (deck-stage rail thumbnails)
    // can react — the parent message only reaches the host, not peers.
    window.dispatchEvent(new CustomEvent('tweakchange', { detail: edits }));
  }, []);
  return [values, setTweak];
}

// ── TweaksPanel ─────────────────────────────────────────────────────────────
// Floating shell. Registers the protocol listener BEFORE announcing
// availability — if the announce ran first, the host's activate could land
// before our handler exists and the toolbar toggle would silently no-op.
// The close button posts __edit_mode_dismissed so the host's toolbar toggle
// flips off in lockstep; the host echoes __deactivate_edit_mode back which
// is what actually hides the panel.
function TweaksPanel({ title = 'Tweaks', children }) {
  const [open, setOpen] = React.useState(false);
  const dragRef = React.useRef(null);
  const offsetRef = React.useRef({ x: 16, y: 16 });
  const PAD = 16;

  const clampToViewport = React.useCallback(() => {
    const panel = dragRef.current;
    if (!panel) return;
    const w = panel.offsetWidth, h = panel.offsetHeight;
    const maxRight = Math.max(PAD, window.innerWidth - w - PAD);
    const maxBottom = Math.max(PAD, window.innerHeight - h - PAD);
    offsetRef.current = {
      x: Math.min(maxRight, Math.max(PAD, offsetRef.current.x)),
      y: Math.min(maxBottom, Math.max(PAD, offsetRef.current.y)),
    };
    panel.style.right = offsetRef.current.x + 'px';
    panel.style.bottom = offsetRef.current.y + 'px';
  }, []);

  React.useEffect(() => {
    if (!open) return;
    clampToViewport();
    if (typeof ResizeObserver === 'undefined') {
      window.addEventListener('resize', clampToViewport);
      return () => window.removeEventListener('resize', clampToViewport);
    }
    const ro = new ResizeObserver(clampToViewport);
    ro.observe(document.documentElement);
    return () => ro.disconnect();
  }, [open, clampToViewport]);

  React.useEffect(() => {
    const onMsg = (e) => {
      const t = e?.data?.type;
      if (t === '__activate_edit_mode') setOpen(true);
      else if (t === '__deactivate_edit_mode') setOpen(false);
    };
    window.addEventListener('message', onMsg);
    window.parent.postMessage({ type: '__edit_mode_available' }, '*');
    return () => window.removeEventListener('message', onMsg);
  }, []);

  const dismiss = () => {
    setOpen(false);
    window.parent.postMessage({ type: '__edit_mode_dismissed' }, '*');
  };

  const onDragStart = (e) => {
    const panel = dragRef.current;
    if (!panel) return;
    const r = panel.getBoundingClientRect();
    const sx = e.clientX, sy = e.clientY;
    const startRight = window.innerWidth - r.right;
    const startBottom = window.innerHeight - r.bottom;
    const move = (ev) => {
      offsetRef.current = {
        x: startRight - (ev.clientX - sx),
        y: startBottom - (ev.clientY - sy),
      };
      clampToViewport();
    };
    const up = () => {
      window.removeEventListener('mousemove', move);
      window.removeEventListener('mouseup', up);
    };
    window.addEventListener('mousemove', move);
    window.addEventListener('mouseup', up);
  };

  if (!open) return null;
  return (
    <>
      <style>{__TWEAKS_STYLE}</style>
      <div ref={dragRef} className="twk-panel" data-omelette-chrome=""
           style={{ right: offsetRef.current.x, bottom: offsetRef.current.y }}>
        <div className="twk-hd" onMouseDown={onDragStart}>
          <b>{title}</b>
          <button className="twk-x" aria-label="Close tweaks"
                  onMouseDown={(e) => e.stopPropagation()}
                  onClick={dismiss}>✕</button>
        </div>
        <div className="twk-body">
          {children}
        </div>
      </div>
    </>
  );
}

// ── Layout helpers ──────────────────────────────────────────────────────────

function TweakSection({ label, children }) {
  return (
    <>
      <div className="twk-sect">{label}</div>
      {children}
    </>
  );
}

function TweakRow({ label, value, children, inline = false }) {
  return (
    <div className={inline ? 'twk-row twk-row-h' : 'twk-row'}>
      <div className="twk-lbl">
        <span>{label}</span>
        {value != null && <span className="twk-val">{value}</span>}
      </div>
      {children}
    </div>
  );
}

// ── Controls ────────────────────────────────────────────────────────────────

function TweakSlider({ label, value, min = 0, max = 100, step = 1, unit = '', onChange }) {
  return (
    <TweakRow label={label} value={`${value}${unit}`}>
      <input type="range" className="twk-slider" min={min} max={max} step={step}
             value={value} onChange={(e) => onChange(Number(e.target.value))} />
    </TweakRow>
  );
}

function TweakToggle({ label, value, onChange }) {
  return (
    <div className="twk-row twk-row-h">
      <div className="twk-lbl"><span>{label}</span></div>
      <button type="button" className="twk-toggle" data-on={value ? '1' : '0'}
              role="switch" aria-checked={!!value}
              onClick={() => onChange(!value)}><i /></button>
    </div>
  );
}

function TweakRadio({ label, value, options, onChange }) {
  const trackRef = React.useRef(null);
  const [dragging, setDragging] = React.useState(false);
  // The active value is read by pointer-move handlers attached for the lifetime
  // of a drag — ref it so a stale closure doesn't fire onChange for every move.
  const valueRef = React.useRef(value);
  valueRef.current = value;

  // Segments wrap mid-word once per-segment width runs out. The track is
  // ~248px (280 panel − 28 body pad − 4 seg pad), each button loses 12px
  // to its own padding, and 11.5px system-ui averages ~6.3px/char — so 2
  // options fit ~16 chars each, 3 fit ~10. Past that (or >3 options), fall
  // back to a dropdown rather than wrap.
  const labelLen = (o) => String(typeof o === 'object' ? o.label : o).length;
  const maxLen = options.reduce((m, o) => Math.max(m, labelLen(o)), 0);
  const fitsAsSegments = maxLen <= ({ 2: 16, 3: 10 }[options.length] ?? 0);
  if (!fitsAsSegments) {
    // <select> emits strings — map back to the original option value so the
    // fallback stays type-preserving (numbers, booleans) like the segment path.
    const resolve = (s) => {
      const m = options.find((o) => String(typeof o === 'object' ? o.value : o) === s);
      return m === undefined ? s : typeof m === 'object' ? m.value : m;
    };
    return <TweakSelect label={label} value={value} options={options}
                        onChange={(s) => onChange(resolve(s))} />;
  }
  const opts = options.map((o) => (typeof o === 'object' ? o : { value: o, label: o }));
  const idx = Math.max(0, opts.findIndex((o) => o.value === value));
  const n = opts.length;

  const segAt = (clientX) => {
    const r = trackRef.current.getBoundingClientRect();
    const inner = r.width - 4;
    const i = Math.floor(((clientX - r.left - 2) / inner) * n);
    return opts[Math.max(0, Math.min(n - 1, i))].value;
  };

  const onPointerDown = (e) => {
    setDragging(true);
    const v0 = segAt(e.clientX);
    if (v0 !== valueRef.current) onChange(v0);
    const move = (ev) => {
      if (!trackRef.current) return;
      const v = segAt(ev.clientX);
      if (v !== valueRef.current) onChange(v);
    };
    const up = () => {
      setDragging(false);
      window.removeEventListener('pointermove', move);
      window.removeEventListener('pointerup', up);
    };
    window.addEventListener('pointermove', move);
    window.addEventListener('pointerup', up);
  };

  return (
    <TweakRow label={label}>
      <div ref={trackRef} role="radiogroup" onPointerDown={onPointerDown}
           className={dragging ? 'twk-seg dragging' : 'twk-seg'}>
        <div className="twk-seg-thumb"
             style={{ left: `calc(2px + ${idx} * (100% - 4px) / ${n})`,
                      width: `calc((100% - 4px) / ${n})` }} />
        {opts.map((o) => (
          <button key={o.value} type="button" role="radio" aria-checked={o.value === value}>
            {o.label}
          </button>
        ))}
      </div>
    </TweakRow>
  );
}

function TweakSelect({ label, value, options, onChange }) {
  return (
    <TweakRow label={label}>
      <select className="twk-field" value={value} onChange={(e) => onChange(e.target.value)}>
        {options.map((o) => {
          const v = typeof o === 'object' ? o.value : o;
          const l = typeof o === 'object' ? o.label : o;
          return <option key={v} value={v}>{l}</option>;
        })}
      </select>
    </TweakRow>
  );
}

function TweakText({ label, value, placeholder, onChange }) {
  return (
    <TweakRow label={label}>
      <input className="twk-field" type="text" value={value} placeholder={placeholder}
             onChange={(e) => onChange(e.target.value)} />
    </TweakRow>
  );
}

function TweakNumber({ label, value, min, max, step = 1, unit = '', onChange }) {
  const clamp = (n) => {
    if (min != null && n < min) return min;
    if (max != null && n > max) return max;
    return n;
  };
  const startRef = React.useRef({ x: 0, val: 0 });
  const onScrubStart = (e) => {
    e.preventDefault();
    startRef.current = { x: e.clientX, val: value };
    const decimals = (String(step).split('.')[1] || '').length;
    const move = (ev) => {
      const dx = ev.clientX - startRef.current.x;
      const raw = startRef.current.val + dx * step;
      const snapped = Math.round(raw / step) * step;
      onChange(clamp(Number(snapped.toFixed(decimals))));
    };
    const up = () => {
      window.removeEventListener('pointermove', move);
      window.removeEventListener('pointerup', up);
    };
    window.addEventListener('pointermove', move);
    window.addEventListener('pointerup', up);
  };
  return (
    <div className="twk-num">
      <span className="twk-num-lbl" onPointerDown={onScrubStart}>{label}</span>
      <input type="number" value={value} min={min} max={max} step={step}
             onChange={(e) => onChange(clamp(Number(e.target.value)))} />
      {unit && <span className="twk-num-unit">{unit}</span>}
    </div>
  );
}

// Relative-luminance contrast pick — checkmarks drawn over a swatch need to
// read on both #111 and #fafafa without per-option configuration. Hex input
// only (#rgb / #rrggbb); named or rgb()/hsl() colors fall through to "light".
function __twkIsLight(hex) {
  const h = String(hex).replace('#', '');
  const x = h.length === 3 ? h.replace(/./g, (c) => c + c) : h.padEnd(6, '0');
  const n = parseInt(x.slice(0, 6), 16);
  if (Number.isNaN(n)) return true;
  const r = (n >> 16) & 255, g = (n >> 8) & 255, b = n & 255;
  return r * 299 + g * 587 + b * 114 > 148000;
}

const __TwkCheck = ({ light }) => (
  <svg viewBox="0 0 14 14" aria-hidden="true">
    <path d="M3 7.2 5.8 10 11 4.2" fill="none" strokeWidth="2.2"
          strokeLinecap="round" strokeLinejoin="round"
          stroke={light ? 'rgba(0,0,0,.78)' : '#fff'} />
  </svg>
);

// TweakColor — curated color/palette picker. Each option is either a single
// hex string or an array of 1-5 hex strings; the card adapts — a lone color
// renders solid, a palette renders colors[0] as the hero (left ~2/3) with the
// rest stacked in a sharp column on the right. onChange emits the
// option in the shape it was passed (string stays string, array stays array).
// Without options it falls back to the native color input for back-compat.
function TweakColor({ label, value, options, onChange }) {
  if (!options || !options.length) {
    return (
      <div className="twk-row twk-row-h">
        <div className="twk-lbl"><span>{label}</span></div>
        <input type="color" className="twk-swatch" value={value}
               onChange={(e) => onChange(e.target.value)} />
      </div>
    );
  }
  // Native <input type=color> emits lowercase hex per the HTML spec, so
  // compare case-insensitively. String() guards JSON.stringify(undefined),
  // which returns the primitive undefined (no .toLowerCase).
  const key = (o) => String(JSON.stringify(o)).toLowerCase();
  const cur = key(value);
  return (
    <TweakRow label={label}>
      <div className="twk-chips" role="radiogroup">
        {options.map((o, i) => {
          const colors = Array.isArray(o) ? o : [o];
          const [hero, ...rest] = colors;
          const sup = rest.slice(0, 4);
          const on = key(o) === cur;
          return (
            <button key={i} type="button" className="twk-chip" role="radio"
                    aria-checked={on} data-on={on ? '1' : '0'}
                    aria-label={colors.join(', ')} title={colors.join(' · ')}
                    style={{ background: hero }}
                    onClick={() => onChange(o)}>
              {sup.length > 0 && (
                <span>
                  {sup.map((c, j) => <i key={j} style={{ background: c }} />)}
                </span>
              )}
              {on && <__TwkCheck light={__twkIsLight(hero)} />}
            </button>
          );
        })}
      </div>
    </TweakRow>
  );
}

function TweakButton({ label, onClick, secondary = false }) {
  return (
    <button type="button" className={secondary ? 'twk-btn secondary' : 'twk-btn'}
            onClick={onClick}>{label}</button>
  );
}

Object.assign(window, {
  useTweaks, TweaksPanel, TweakSection, TweakRow,
  TweakSlider, TweakToggle, TweakRadio, TweakSelect,
  TweakText, TweakNumber, TweakColor, TweakButton,
});


/* ==== Nav ==== */
/* Nav — sticky cream bar with chunky ink border on scroll */
function Nav({ tweaks }) {
  const [scrolled, setScrolled] = React.useState(false);
  const [open, setOpen] = React.useState(false);

  React.useEffect(() => {
    const onScroll = () => setScrolled(window.scrollY > 40);
    window.addEventListener('scroll', onScroll);
    onScroll();
    return () => window.removeEventListener('scroll', onScroll);
  }, []);

  const links = [
  { href: '#obsession', label: 'Obsession' },
  { href: '#process', label: 'Process' },
  { href: '#catalog', label: 'Catalogue' },
  { href: '#ingredients', label: 'Ingredients' },
  { href: '#founder', label: 'Founder' },
  { href: '#contact', label: 'Contact' }];


  return (
    <>
      <nav
        className={'site-nav ' + (scrolled ? 'is-scrolled' : '')}
        style={navStyles.bar}>
        
        <a href="#top" style={navStyles.brand} aria-label="Gustai home">
          <img src="assets/logo-gustai.png" alt="Gustai" style={navStyles.logo} />
        </a>

        <div className="nav-links" style={navStyles.links}>
          {links.map((l) =>
          <a key={l.href} href={l.href} style={navStyles.link}>{l.label}</a>
          )}
        </div>

        <div style={navStyles.right}>
          <span className="nav-loc" style={navStyles.loc}>
            <span style={{ width: 8, height: 8, borderRadius: 999, background: 'var(--basil-bright)', display: 'inline-block', marginRight: 8, boxShadow: '0 0 0 3px rgba(79,174,93,0.25)' }}></span>
            
          </span>
          <a href="#contact" className="btn btn-sugo nav-cta" style={{ padding: '12px 18px', fontSize: 13 }}>
            Request quote →
          </a>
          <button
            className="nav-burger"
            aria-label="Menu"
            onClick={() => setOpen(!open)}
            style={navStyles.burger}>
            
            <span style={{ ...navStyles.burgerLine, transform: open ? 'translateY(5px) rotate(45deg)' : 'none' }}></span>
            <span style={{ ...navStyles.burgerLine, opacity: open ? 0 : 1 }}></span>
            <span style={{ ...navStyles.burgerLine, transform: open ? 'translateY(-5px) rotate(-45deg)' : 'none' }}></span>
          </button>
        </div>
      </nav>

      {/* mobile menu */}
      <div className={'nav-mobile-menu ' + (open ? 'is-open' : '')} style={{
        ...navStyles.mobileMenu,
        transform: open ? 'translateY(0)' : 'translateY(-110%)'
      }}>
        {links.map((l) =>
        <a
          key={l.href}
          href={l.href}
          style={navStyles.mobileLink}
          onClick={() => setOpen(false)}>
          
            {l.label}
          </a>
        )}
        <a href="#contact" className="btn btn-sugo" onClick={() => setOpen(false)} style={{ marginTop: 16 }}>
          Request quote →
        </a>
      </div>
    </>);

}

const navStyles = {
  bar: {
    position: 'fixed',
    top: 0, left: 0, right: 0,
    zIndex: 100,
    display: 'flex',
    alignItems: 'center',
    justifyContent: 'space-between',
    padding: '14px 24px',
    background: 'rgba(249, 237, 214, 0.92)',
    backdropFilter: 'blur(10px)',
    WebkitBackdropFilter: 'blur(10px)',
    borderBottom: '2px solid var(--ink)',
    color: 'var(--ink)',
    transition: 'padding var(--dur) var(--ease-out)'
  },
  brand: {
    display: 'flex',
    alignItems: 'center',
    textDecoration: 'none'
  },
  logo: {
    height: 36,
    width: 'auto'
  },
  links: {
    display: 'flex',
    gap: 28,
    alignItems: 'center'
  },
  link: {
    fontFamily: 'var(--font-body)',
    fontWeight: 700,
    fontSize: 13,
    letterSpacing: '0.06em',
    textTransform: 'uppercase',
    color: 'var(--ink)',
    textDecoration: 'none',
    padding: '8px 4px'
  },
  right: {
    display: 'flex',
    alignItems: 'center',
    gap: 14
  },
  loc: {
    fontFamily: 'var(--font-mono)',
    fontSize: 11,
    letterSpacing: '0.12em',
    textTransform: 'uppercase',
    color: 'var(--ink-2)',
    display: 'inline-flex',
    alignItems: 'center'
  },
  burger: {
    display: 'none',
    flexDirection: 'column',
    gap: 4,
    width: 44, height: 44,
    border: '2px solid var(--ink)',
    background: 'var(--paper)',
    borderRadius: 8,
    alignItems: 'center',
    justifyContent: 'center',
    cursor: 'pointer',
    boxShadow: '3px 3px 0 var(--ink)'
  },
  burgerLine: {
    width: 18, height: 2, background: 'var(--ink)',
    transition: 'transform 200ms var(--ease-out), opacity 200ms var(--ease-out)',
    display: 'block'
  },
  mobileMenu: {
    position: 'fixed',
    top: 64, left: 12, right: 12,
    background: 'var(--paper)',
    border: '2.5px solid var(--ink)',
    borderRadius: 18,
    boxShadow: '6px 6px 0 var(--ink)',
    padding: 18,
    zIndex: 99,
    display: 'flex',
    flexDirection: 'column',
    gap: 4,
    transition: 'transform 320ms var(--ease-bounce)'
  },
  mobileLink: {
    fontFamily: 'var(--font-display)',
    fontWeight: 900,
    fontSize: 22,
    color: 'var(--ink)',
    textDecoration: 'none',
    padding: '12px 4px',
    borderBottom: '1px dashed var(--line-strong)',
    textTransform: 'uppercase',
    letterSpacing: '-0.02em'
  }
};

window.Nav = Nav;

/* ==== Hero ==== */
/* Hero — full-viewport flour canvas + giant editorial type
   - <video> tag inside .hero-media will autoplay if a src is provided via tweak;
     otherwise the canvas takes over.
*/
function Hero({ tweaks }) {
  const canvasRef = React.useRef(null);
  const videoRef = React.useRef(null);

  React.useEffect(() => {
    if (!window.FlourCanvas || !canvasRef.current) return;
    const inst = window.FlourCanvas(canvasRef.current, { count: 240 });
    return () => inst && inst.stop && inst.stop();
  }, []);

  const videoSrc = tweaks && tweaks.heroVideoSrc || '';

  const ctaCopy = tweaks && tweaks.heroCta ? tweaks.heroCta : 'See the catalogue';

  return (
    <section id="top" style={heroStyles.wrap}>
      <div style={heroStyles.media}>
        {videoSrc ?
        <video
          ref={videoRef}
          src={videoSrc}
          autoPlay
          muted
          loop
          playsInline
          style={heroStyles.video} /> :


        <canvas ref={canvasRef} style={heroStyles.canvas} />
        }
        <div style={heroStyles.vignette}></div>
      </div>

      <div style={heroStyles.content} className="hero-content">
        <div style={heroStyles.topRow}>
          <div className="readout" style={{ color: 'var(--cream)', opacity: 0.7 }}>

          </div>
          <div className="readout" style={{ color: 'var(--cream)', opacity: 0.7, textAlign: 'right' }}>
            <br />
            DOUGH · 23.0 °C · 25% HYD.
          </div>
        </div>

        <div style={heroStyles.headlineWrap}>
          <div className="eyebrow" style={{ color: 'var(--yolk)' }}>
            Fresh pasta · Made in Phuket
          </div>
          <h1 className="display display-xl" style={heroStyles.headline}>
            fresh<br />
            <span style={{ fontStyle: 'italic', color: 'var(--sugo-soft)' }}>pasta.</span><br />
            that's it.
          </h1>
          <p style={heroStyles.lede}>Restaurant-grade fresh pasta — bronze-die extruded, hand sheeted, and filled . Built for the way professional kitchens actually work. On the plate in three minutes.



          </p>

          <div style={heroStyles.ctaRow}>
            <a href="#catalog" className="btn btn-sugo">
              {ctaCopy} →
            </a>
            <a href="#contact" className="btn btn-outline">
              Get in touch
            </a>
          </div>

          <div style={heroStyles.stats}>
            <Stat n="27+" label="bronze-die shapes" />
            <Stat n="3–4" label="min cook time" suffix="" />
            <Stat n="2 kg" label="MOQ per item" />
            <Stat n="100%" label="italian flour" />
          </div>
        </div>

        <div style={heroStyles.scrollCue}>
          <span className="readout" style={{ color: 'var(--cream)', opacity: 0.6 }}>SCROLL</span>
          <div style={heroStyles.scrollLine}></div>
        </div>
      </div>
    </section>);

}

function Stat({ n, label, suffix }) {
  return (
    <div style={{ display: 'flex', flexDirection: 'column', gap: 4 }}>
      <span style={{
        fontFamily: 'var(--font-display)', fontWeight: 900,
        fontSize: 'clamp(28px, 3vw, 44px)', lineHeight: 1,
        letterSpacing: '-0.04em', color: 'var(--cream)'
      }}>{n}{suffix !== undefined ? suffix : ''}</span>
      <span className="readout" style={{ color: 'var(--cream)', opacity: 0.7 }}>{label}</span>
    </div>);

}

const heroStyles = {
  wrap: {
    position: 'relative',
    minHeight: '100svh',
    height: '100svh',
    overflow: 'hidden',
    background: 'var(--ink)',
    color: 'var(--cream)'
  },
  media: {
    position: 'absolute', inset: 0, zIndex: 0
  },
  canvas: {
    width: '100%', height: '100%', display: 'block'
  },
  video: {
    width: '100%', height: '100%', objectFit: 'cover'
  },
  vignette: {
    position: 'absolute', inset: 0,
    background: 'radial-gradient(ellipse at center, rgba(26,20,16,0) 30%, rgba(26,20,16,0.55) 100%), linear-gradient(180deg, rgba(26,20,16,0.4) 0%, rgba(26,20,16,0) 30%, rgba(26,20,16,0) 60%, rgba(26,20,16,0.85) 100%)',
    pointerEvents: 'none'
  },
  content: {
    position: 'relative',
    zIndex: 2,
    height: '100%',
    display: 'flex',
    flexDirection: 'column',
    justifyContent: 'space-between',
    padding: 'clamp(80px, 9vh, 120px) clamp(20px, 4vw, 64px) clamp(28px, 4vh, 56px)',
    maxWidth: 1600,
    margin: '0 auto'
  },
  topRow: {
    display: 'flex',
    justifyContent: 'space-between',
    alignItems: 'flex-start',
    gap: 20
  },
  headlineWrap: {
    maxWidth: 1100
  },
  headline: {
    margin: '14px 0 0',
    color: 'var(--cream)'
  },
  lede: {
    fontFamily: 'var(--font-body)',
    fontSize: 'clamp(15px, 1.3vw, 19px)',
    lineHeight: 1.55,
    color: 'var(--cream)',
    opacity: 0.85,
    maxWidth: 560,
    marginTop: 28,
    fontWeight: 500
  },
  ctaRow: {
    display: 'flex',
    gap: 14,
    marginTop: 32,
    flexWrap: 'wrap'
  },
  stats: {
    display: 'flex',
    gap: 'clamp(20px, 4vw, 56px)',
    marginTop: 44,
    paddingTop: 24,
    borderTop: '2px dashed rgba(249,237,214,0.25)',
    flexWrap: 'wrap'
  },
  scrollCue: {
    display: 'flex',
    alignItems: 'center',
    gap: 12
  },
  scrollLine: {
    width: 60, height: 2, background: 'rgba(249,237,214,0.4)'
  }
};

window.Hero = Hero;

/* ==== Marquee ==== */
/* Marquee — endless scrolling text bar. Cream on ink, with sugo accents. */
function Marquee({ items, bg, fg, accent }) {
  bg = bg || 'var(--ink)';
  fg = fg || 'var(--cream)';
  accent = accent || 'var(--sugo)';
  items = items || [
    '100% Fresh',
    'Made in Phuket',
    'Molino Casillo flours',
    'Bronze-die extruded',
    'For restaurants, hotels & caterers',
    '3–4 min cook time',
    'Temperature controlled',
    'Air-purified production',
  ];

  // duplicate items so the marquee loops seamlessly
  const loop = [...items, ...items, ...items];

  return (
    <div style={{ ...marqStyles.wrap, background: bg, color: fg, borderTop: '2px solid currentColor', borderBottom: '2px solid currentColor' }}>
      <div style={marqStyles.track}>
        {loop.map((s, i) => (
          <span key={i} style={marqStyles.item}>
            <span>{s}</span>
            <span style={{ color: accent, margin: '0 28px', fontSize: '1.4em', lineHeight: 1 }}>✦</span>
          </span>
        ))}
      </div>
    </div>
  );
}

const marqStyles = {
  wrap: {
    overflow: 'hidden',
    padding: '18px 0',
    whiteSpace: 'nowrap',
  },
  track: {
    display: 'inline-flex',
    alignItems: 'center',
    animation: 'marqueeScroll 50s linear infinite',
    willChange: 'transform',
  },
  item: {
    display: 'inline-flex',
    alignItems: 'center',
    fontFamily: 'var(--font-display)',
    fontWeight: 900,
    fontStyle: 'italic',
    fontSize: 'clamp(28px, 4vw, 56px)',
    letterSpacing: '-0.025em',
    textTransform: 'uppercase',
  },
};

// inject keyframes once
if (!document.getElementById('marquee-keyframes')) {
  const s = document.createElement('style');
  s.id = 'marquee-keyframes';
  s.textContent = `
    @keyframes marqueeScroll {
      0%   { transform: translateX(0); }
      100% { transform: translateX(-33.3333%); }
    }
  `;
  document.head.appendChild(s);
}

window.Marquee = Marquee;


/* ==== Obsession ==== */
/* Obsession — precision / temperature / hydration as science
   Cream background. Big italic headline. Three pillars with lab readouts.
*/
function Obsession() {
  const pillars = [
  {
    n: '01',
    label: 'Temperature',
    readout: '22.0 °C · ± 0.5',
    title: 'Cold rooms. Hot opinions.',
    body: 'Every room — mixing, extrusion, drying, packing — is climate-controlled and thermometered. Dough resting cold gives us gluten that behaves the same on a Tuesday as a Saturday.',
    stat: '4',
    statLabel: 'thermo­meters per batch'
  },
  {
    n: '02',
    label: 'Hydration',
    readout: '25% · ±0.4',
    title: 'Water is an ingredient.',
    body: 'Hydration is measured to the tenth of a percent and adjusted to the day\'s flour. The same shape gets the same bite, the same yield, every single run.',
    stat: '0.4%',
    statLabel: 'hydration tolerance'
  },
  {
    n: '03',
    label: 'Consistency',
    readout: 'CV < 1.5%',
    title: 'Same plate. Every plate.',
    body: 'Our clients run service. They cannot afford a batch that cooks differently. We sample every run, log every reading, and never ship outside spec.',
    stat: '100%',
    statLabel: 'batches logged'
  }];


  return (
    <section id="obsession" className="bg-cream section-pad">
      <div className="container">
        <div style={obsStyles.head}>
          <div className="eyebrow" style={{ color: 'var(--sugo)' }}>
            № 01 · The obsession
          </div>
          <h2 className="display display-lg" style={obsStyles.h2}>
            we treat pasta<br />
            <span className="it" style={{ color: 'var(--sugo)' }}>like a science.</span>
          </h2>
          <p style={obsStyles.lede}>Consistency isn't a marketing word here, it's an engineering target. Your chef gets the same texture, the same hydration, the same cook time on every single delivery. So service runs the way you planned it, not the way the dough decided.




          </p>
        </div>

        <div style={obsStyles.grid}>
          {pillars.map((p) =>
          <article key={p.n} className="card" style={obsStyles.card}>
              <header style={obsStyles.cardHead}>
                <span className="num" style={{ color: 'var(--sugo)' }}>/ {p.n}</span>
                <span className="readout" style={{ color: 'var(--ink-3)' }}>{p.label}</span>
              </header>

              <div style={obsStyles.reading}>
                <span className="mono" style={{ background: 'var(--ink)', color: 'var(--cream)', padding: '4px 10px', borderRadius: 6, fontSize: 11, letterSpacing: '0.08em' }}>
                  {p.readout}
                </span>
              </div>

              <h3 className="display display-sm" style={obsStyles.cardTitle}>
                {p.title}
              </h3>

              <p style={obsStyles.cardBody}>
                {p.body}
              </p>

              <footer style={{ ...obsStyles.cardFoot, alignItems: "center" }}>
                <span style={obsStyles.bigNum}>{p.stat}</span>
                <span className="readout" style={{ color: 'var(--ink-3)' }}>{p.statLabel}</span>
              </footer>
            </article>
          )}
        </div>
      </div>
    </section>);

}

const obsStyles = {
  head: {
    display: 'grid',
    gridTemplateColumns: 'minmax(0, 1fr)',
    gap: 24,
    marginBottom: 64,
    maxWidth: 1200
  },
  h2: {
    color: 'var(--ink)',
    margin: 0
  },
  lede: {
    fontSize: 'clamp(17px, 1.6vw, 22px)',
    lineHeight: 1.5,
    color: 'var(--ink-2)',
    maxWidth: 720,
    margin: 0,
    fontWeight: 500
  },
  grid: {
    display: 'grid',
    gridTemplateColumns: 'repeat(auto-fit, minmax(280px, 1fr))',
    gap: 24
  },
  card: {
    padding: 28,
    display: 'flex',
    flexDirection: 'column',
    gap: 16,
    minHeight: 380
  },
  cardHead: {
    display: 'flex',
    justifyContent: 'space-between',
    alignItems: 'center'
  },
  reading: {},
  cardTitle: {
    color: 'var(--ink)',
    margin: 0,
    fontStyle: 'italic'
  },
  cardBody: {
    fontSize: 15,
    lineHeight: 1.55,
    color: 'var(--ink-2)',
    margin: 0,
    flex: 1
  },
  cardFoot: {
    display: 'flex',
    alignItems: 'baseline',
    gap: 10,
    paddingTop: 18,
    borderTop: '2px dashed var(--line-strong)'
  },
  bigNum: {
    fontFamily: 'var(--font-display)',
    fontWeight: 900,
    fontSize: 44,
    letterSpacing: '-0.04em',
    color: 'var(--sugo)',
    lineHeight: 1
  }
};

window.Obsession = Obsession;

/* ==== Process ==== */
/* Process — 6 steps, each with lab-style readouts, on dark ink background */
function Process() {
  const steps = [
    {
      n: '01',
      time: 'STEP 01',
      title: 'Flour intake',
      detail: 'Vacuum-sealed Molino Casillo bags opened the morning of mix. Moisture logged. Lot # recorded against the batch.',
      reading: 'MOISTURE · 13.0%',
    },
    {
      n: '02',
      time: 'STEP 02',
      title: 'Hydration',
      detail: 'Filtered water dialed to the flour\'s daily moisture reading. Adjusted to the tenth of a percent before the mixer turns.',
      reading: 'HYDRATION · 25.0% ±0.4',
    },
    {
      n: '03',
      time: 'STEP 03',
      title: 'Mixing & rest',
      detail: 'Slow-knead in a temperature-controlled room. Dough rests cold so gluten relaxes evenly — no surprises at extrusion.',
      reading: 'DOUGH · 22.0 °C',
    },
    {
      n: '04',
      time: 'STEP 04',
      title: 'Bronze-die extrusion',
      detail: 'Pushed through bronze dies for the rough, porous "ruvida" surface that grabs sauce. Each shape cut to spec.',
      reading: 'DIE · BRONZE · 27+ SHAPES',
    },
    {
      n: '05',
      time: 'STEP 05',
      title: 'Controlled packaging',
      detail: 'Packages are held at low humidity and at 4 degree tempratures.',
      reading: 'PACK · 4 °C · LOW RH',
    },
    {
      n: '06',
      time: 'STEP 06',
      title: 'Cold delivery',
      detail: 'Portioned to your spec, sealed, palletized cold. On a chef\'s line the next day. Same product, every order.',
      reading: 'CHAIN · 0–4 °C',
    },
  ];

  return (
    <section id="process" className="bg-ink section-pad" style={{ color: 'var(--cream)' }}>
      <div className="container">
        <div style={procStyles.head}>
          <div className="eyebrow" style={{ color: 'var(--yolk)' }}>
            № 02 · The process
          </div>
          <h2 className="display display-lg" style={procStyles.h2}>
            six steps.<br />
            <span className="it" style={{ color: 'var(--yolk)' }}>logged every time.</span>
          </h2>
          <p style={procStyles.lede}>
            Every batch travels through the same six controlled stages. Each one
            measured, each one recorded. If a reading drifts, the batch doesn't
            ship — it's that simple.
          </p>
        </div>

        <ol style={procStyles.list}>
          {steps.map((s, i) => (
            <li key={s.n} style={procStyles.row}>
              <div style={procStyles.left}>
                <span style={procStyles.bigN}>{s.n}</span>
                <span className="readout" style={{ color: 'var(--cream)', opacity: 0.55 }}>{s.time}</span>
              </div>
              <div style={procStyles.mid}>
                <h3 className="display display-md" style={procStyles.rowTitle}>
                  {s.title}
                </h3>
                <p style={procStyles.rowBody}>{s.detail}</p>
              </div>
              <div style={procStyles.right}>
                <span style={procStyles.reading}>{s.reading}</span>
              </div>
            </li>
          ))}
        </ol>

        <div style={procStyles.foot}>
          <span className="readout" style={{ opacity: 0.6 }}>End of cycle</span>
          <span style={procStyles.line}></span>
          <span className="readout" style={{ opacity: 0.6 }}>Batch certified</span>
        </div>
      </div>
    </section>
  );
}

const procStyles = {
  head: {
    display: 'grid',
    gap: 24,
    marginBottom: 72,
    maxWidth: 1100,
  },
  h2: {
    color: 'var(--cream)',
    margin: 0,
  },
  lede: {
    fontSize: 'clamp(17px, 1.6vw, 22px)',
    lineHeight: 1.5,
    color: 'var(--cream)',
    opacity: 0.78,
    maxWidth: 720,
    margin: 0,
    fontWeight: 500,
  },
  list: {
    listStyle: 'none',
    margin: 0,
    padding: 0,
    display: 'flex',
    flexDirection: 'column',
  },
  row: {
    display: 'grid',
    gridTemplateColumns: '180px minmax(0, 1fr) 220px',
    gap: 32,
    padding: '36px 0',
    borderTop: '2px dashed rgba(249,237,214,0.2)',
    alignItems: 'baseline',
  },
  left: {
    display: 'flex',
    flexDirection: 'column',
    gap: 6,
  },
  bigN: {
    fontFamily: 'var(--font-display)',
    fontWeight: 900,
    fontSize: 'clamp(48px, 5vw, 88px)',
    letterSpacing: '-0.05em',
    color: 'var(--sugo)',
    lineHeight: 1,
    fontStyle: 'italic',
  },
  mid: { },
  rowTitle: {
    color: 'var(--cream)',
    margin: '0 0 12px',
    fontStyle: 'italic',
  },
  rowBody: {
    fontSize: 16,
    lineHeight: 1.55,
    color: 'var(--cream)',
    opacity: 0.78,
    margin: 0,
    maxWidth: 580,
  },
  right: {
    textAlign: 'right',
  },
  reading: {
    fontFamily: 'var(--font-mono)',
    fontSize: 12,
    letterSpacing: '0.08em',
    color: 'var(--yolk)',
    background: 'rgba(244, 196, 60, 0.1)',
    border: '1.5px solid rgba(244, 196, 60, 0.45)',
    padding: '8px 12px',
    borderRadius: 6,
    display: 'inline-block',
  },
  foot: {
    display: 'flex',
    alignItems: 'center',
    gap: 16,
    marginTop: 40,
    paddingTop: 32,
    borderTop: '2px dashed rgba(249,237,214,0.25)',
  },
  line: { flex: 1, height: 2, background: 'rgba(249,237,214,0.15)' },
};

window.Process = Process;


/* ==== Catalog ==== */
/* Catalog preview — sampler of pasta shapes + categories, link to full page.
   No prices. Uses real photographs only — no illustrated icons. */
function Catalog() {
  const shapes = [
  { img: 'spaghetti-chitarra', code: '№24',  name: 'Spaghetti Chitarra Ruvida', diam: '2 × 2 mm', tag: 'BESTSELLER' },
  { img: 'mafaldine',          code: '№55',  name: 'Mafaldine Ruvida',          diam: '8 mm' },
  { img: 'creste-di-gallo',    code: '№145', name: 'Creste di Gallo Ruvida',    diam: '10 mm' },
  { img: 'gemelli',            code: '№215', name: 'Gemelli Ruvida',            diam: '8.8 mm' },
  { img: 'radiatori',          code: '№260', name: 'Radiatori Ruvida',          diam: '' },
  { img: 'paccheri',           code: '№397', name: 'Paccheri Ruvida',           diam: '' },
  { img: 'strozzapreti',       code: '№220', name: 'Strozzapreti Ruvida',       diam: '' },
  { img: 'trottole',           code: '№370', name: 'Trottole Ruvida',           diam: '10.4 mm' },
  { img: 'campanelle',         code: '—',    name: 'Campanelle',                diam: '8.3 mm', tag: 'NEW' },
  { img: 'girandole',          code: '—',    name: 'Girandole',                 diam: '10.5 mm', tag: 'NEW' }];


  const ranges = [
  { id: 'bronze',    label: 'Bronze-die extruded',    count: '27+ shapes', sub: 'Ruvida — rough, sauce-gripping' },
  { id: 'sheeted',   label: 'Sheeted egg pasta',      count: '14 shapes',  sub: 'Standard + ultra-premium extra-yolk' },
  { id: 'filled',    label: 'Filled pasta',           count: '4 fillings', sub: 'Ravioli & tortelloni, customisable' },
  { id: 'specialty', label: 'Specialty & squid-ink',  count: '7 shapes',   sub: 'Cavatelli, gnocchi, Spanish squid ink' },
  { id: 'sauces',    label: 'Artisanal sauces',       count: '4 sauces',   sub: 'Slow-cooked ragùs & creams' }];


  return (
    <section id="catalog" className="bg-paper section-pad" style={{ color: 'var(--ink)' }}>
      <div className="container">
        <div style={catStyles.head}>
          <div>
            <div className="eyebrow" style={{ color: 'var(--sugo)' }}>
              № 03 · The catalogue
            </div>
            <h2 className="display display-lg" style={catStyles.h2}>
              meet the<br />
              <span className="it" style={{ color: 'var(--sugo)' }}>shapes.</span>
            </h2>
          </div>
          <div style={catStyles.headRight}>
            <p style={catStyles.lede}>
              Twenty-seven bronze-die extruded workhorses, plus sheeted egg,
              hand-made specialty, filled pasta and squid-ink ranges. Custom
              shapes, portion grams and private-label runs on request.
            </p>
            <div style={catStyles.headCtas}>
              <a href="catalogue.html" className="btn btn-sugo">View full catalogue →</a>
              <a href="#contact" className="btn btn-outline-ink">Request a quote</a>
            </div>
          </div>
        </div>

        {/* Hero composite shot */}
        <figure style={catStyles.composite}>
          <img
            src="assets/pasta/composite.png"
            alt="A grid of Gustai pasta shapes laid out on natural wood"
            style={catStyles.compositeImg}
          />
          <figcaption style={catStyles.compositeCap}>
            <span className="readout" style={{ color: 'var(--cream)' }}>FIG. 03 · LINEUP · MAY 2026</span>
            <span style={catStyles.compositeBig}>Ten of the workhorses.</span>
          </figcaption>
        </figure>

        {/* Range chips */}
        <div style={catStyles.ranges}>
          {ranges.map((r) =>
          <a key={r.id} href="catalogue.html" style={catStyles.range}>
              <div style={catStyles.rangeTop}>
                <span style={catStyles.rangeLabel}>{r.label}</span>
                <span style={catStyles.rangeCount}>{r.count}</span>
              </div>
              <span style={catStyles.rangeSub}>{r.sub}</span>
              <span style={catStyles.rangeArrow}>→</span>
            </a>
          )}
        </div>

        {/* Shape grid — real photos */}
        <div style={catStyles.grid}>
          {shapes.map((s, i) =>
          <article key={s.img} className="catalog-tile" style={catStyles.tile}>
              {s.tag &&
            <span style={{ ...catStyles.tag, background: s.tag === 'NEW' ? 'var(--yolk)' : 'var(--sugo)', color: s.tag === 'NEW' ? 'var(--ink)' : 'var(--cream)' }}>
                  {s.tag}
                </span>
            }
              <div style={catStyles.imgWrap}>
                <img
                  src={`assets/pasta/${s.img}.png`}
                  alt={s.name}
                  style={catStyles.img}
                  loading="lazy"
                />
              </div>
              <div style={catStyles.tileBody}>
                <span style={catStyles.tileCode}>{s.code}</span>
                <span style={catStyles.tileName}>{s.name}</span>
                {s.diam && <span style={catStyles.tileDiam}>{s.diam}</span>}
              </div>
            </article>
          )}
        </div>

        <div style={catStyles.foot}>
          <span className="readout" style={{ color: 'var(--ink-3)' }}>MOQ 2 KG / ITEM · DELIVERED COLD · MON–FRI</span>
          <a href="catalogue.html" style={catStyles.footLink}>See all 50+ items →</a>
        </div>
      </div>
    </section>);

}

const catStyles = {
  head: {
    display: 'grid',
    gridTemplateColumns: 'repeat(auto-fit, minmax(min(100%, 360px), 1fr))',
    gap: 'clamp(32px, 5vw, 48px)',
    marginBottom: 56,
    alignItems: 'end'
  },
  h2: {
    color: 'var(--ink)',
    margin: '20px 0 0'
  },
  headRight: {
    display: 'flex',
    flexDirection: 'column',
    gap: 24
  },
  lede: {
    fontSize: 18,
    lineHeight: 1.55,
    color: 'var(--ink-2)',
    margin: 0,
    maxWidth: 560,
    fontWeight: 500
  },
  headCtas: {
    display: 'flex',
    gap: 12,
    flexWrap: 'wrap'
  },
  composite: {
    position: 'relative',
    margin: '0 0 56px',
    border: '3px solid var(--ink)',
    borderRadius: 20,
    boxShadow: '8px 8px 0 var(--ink)',
    overflow: 'hidden',
    background: 'var(--ink)',
  },
  compositeImg: {
    width: '100%',
    height: 'clamp(280px, 38vw, 560px)',
    objectFit: 'cover',
    display: 'block',
  },
  compositeCap: {
    position: 'absolute',
    left: 24, bottom: 20, right: 24,
    display: 'flex',
    flexDirection: 'column',
    gap: 6,
    color: 'var(--cream)',
    textShadow: '0 2px 12px rgba(0,0,0,0.5)',
  },
  compositeBig: {
    fontFamily: 'var(--font-display)',
    fontWeight: 900,
    fontStyle: 'italic',
    fontSize: 'clamp(28px, 4vw, 56px)',
    letterSpacing: '-0.035em',
    color: 'var(--cream)',
    lineHeight: 1,
  },
  ranges: {
    display: 'grid',
    gridTemplateColumns: 'repeat(auto-fit, minmax(220px, 1fr))',
    gap: 12,
    marginBottom: 56
  },
  range: {
    position: 'relative',
    display: 'flex',
    flexDirection: 'column',
    gap: 8,
    padding: '18px 20px',
    border: '2px solid var(--ink)',
    borderRadius: 14,
    background: 'var(--cream)',
    color: 'var(--ink)',
    textDecoration: 'none',
    transition: 'transform var(--dur) var(--ease-bounce), box-shadow var(--dur) var(--ease-bounce)',
    boxShadow: '4px 4px 0 var(--ink)'
  },
  rangeTop: {
    display: 'flex',
    justifyContent: 'space-between',
    alignItems: 'baseline',
    gap: 10
  },
  rangeLabel: {
    fontFamily: 'var(--font-display)',
    fontWeight: 900,
    fontSize: 15,
    letterSpacing: '-0.01em',
    textTransform: 'uppercase'
  },
  rangeCount: {
    fontFamily: 'var(--font-mono)',
    fontSize: 11,
    color: 'var(--sugo-deep)',
    background: 'var(--sugo-soft)',
    padding: '3px 7px',
    borderRadius: 6,
    letterSpacing: '0.04em'
  },
  rangeSub: {
    fontFamily: 'var(--font-body)',
    fontSize: 13,
    color: 'var(--ink-3)',
    lineHeight: 1.4
  },
  rangeArrow: {
    fontFamily: 'var(--font-display)',
    fontSize: 18,
    color: 'var(--sugo)',
    marginTop: 4
  },
  grid: {
    display: 'grid',
    gridTemplateColumns: 'repeat(auto-fill, minmax(240px, 1fr))',
    gap: 18
  },
  tile: {
    position: 'relative',
    background: 'var(--cream)',
    border: '2.5px solid var(--ink)',
    borderRadius: 18,
    padding: 16,
    boxShadow: '5px 5px 0 var(--ink)',
    transition: 'transform 220ms var(--ease-bounce), box-shadow 220ms var(--ease-bounce)',
    display: 'flex',
    flexDirection: 'column',
    gap: 14,
    cursor: 'pointer',
    overflow: 'hidden',
  },
  imgWrap: {
    aspectRatio: '1 / 1',
    background: 'var(--ink)',
    border: '2px solid var(--ink)',
    borderRadius: 12,
    overflow: 'hidden',
  },
  img: {
    width: '100%',
    height: '100%',
    objectFit: 'cover',
    display: 'block',
  },
  tileBody: {
    display: 'flex',
    flexDirection: 'column',
    gap: 4,
    padding: '0 4px 4px'
  },
  tileCode: {
    fontFamily: 'var(--font-mono)',
    fontSize: 11,
    letterSpacing: '0.08em',
    color: 'var(--ink-3)'
  },
  tileName: {
    fontFamily: 'var(--font-display)',
    fontStyle: 'italic',
    fontWeight: 900,
    fontSize: 18,
    letterSpacing: '-0.02em',
    color: 'var(--ink)',
    lineHeight: 1.1
  },
  tileDiam: {
    fontFamily: 'var(--font-mono)',
    fontSize: 11,
    color: 'var(--sugo)',
    letterSpacing: '0.05em'
  },
  tag: {
    position: 'absolute',
    top: 8,
    right: 8,
    fontFamily: 'var(--font-display)',
    fontWeight: 900,
    fontSize: 11,
    letterSpacing: '0.08em',
    padding: '4px 9px 3px',
    borderRadius: 4,
    border: '2px solid var(--ink)',
    boxShadow: '2px 2px 0 var(--ink)',
    transform: 'rotate(3deg)',
    zIndex: 2
  },
  foot: {
    display: 'flex',
    justifyContent: 'space-between',
    alignItems: 'center',
    marginTop: 48,
    paddingTop: 24,
    borderTop: '2px dashed var(--line-strong)',
    flexWrap: 'wrap',
    gap: 16
  },
  footLink: {
    fontFamily: 'var(--font-display)',
    fontWeight: 900,
    fontSize: 16,
    color: 'var(--sugo)',
    textDecoration: 'none',
    fontStyle: 'italic'
  }
};

window.Catalog = Catalog;


/* ==== Ingredients ==== */
/* Ingredients — the Molino Casillo story.
   Sugo background. Editorial split. Big quote-style block. */
function Ingredients() {
  const points = [
  {
    n: '01',
    title: 'Molino Casillo, full stop',
    body: 'A family-run Italian mill founded in 1958, recognized as one of the world\'s top wheat millers. We do not blend, switch, or substitute.'
  },
  {
    n: '02',
    title: 'Vacuum-sealed at the mill',
    body: 'Casillo ships in vacuum bags — moisture and aroma locked the moment it leaves the mill. We open each bag fresh, the morning of mix.'
  },
  {
    n: '03',
    title: 'Same flour. Every day.',
    body: 'Vacuum sealing means the flour we put in the mixer on a Friday is identical to the flour we put in on a Monday. No drift. No surprise.'
  },
  {
    n: '04',
    title: 'Free-range eggs · 00 flour · water',
    body: 'For our sheeted and egg ranges — free-range eggs, Italian 00 flour, filtered water. Nothing else goes in. Nothing else needs to.'
  }];


  return (
    <section id="ingredients" className="bg-sugo section-pad" style={{ color: 'var(--cream)' }}>
      <div className="container">
        <div style={ingStyles.layout}>
          <div style={ingStyles.left}>
            <div className="eyebrow" style={{ color: 'var(--yolk)' }}>

            </div>
            <h2 className="display display-lg" style={ingStyles.h2}>
              we use one<br />
              <span className="it" style={{ color: 'var(--yolk)' }}>flour.</span>
            </h2>
            <p style={ingStyles.lede}>
              The best pasta starts before you touch the dough. We picked our
              flour and we stuck with it — Italian-milled, vacuum-sealed,
              fresh every day.
            </p>

            {/* Mock flour bag visual */}
            <div style={ingStyles.bagWrap}>
              <div style={ingStyles.bag}>
                <div style={ingStyles.bagTop}>
                  <span style={ingStyles.bagBrand}>MOLINO CASILLO</span>
                  <span style={ingStyles.bagSince}>SINCE 1958 · ITALIA</span>
                </div>
                <div style={ingStyles.bagMid}>
                  <span style={ingStyles.bagBig}>SEMOLA<br /><span style={{ fontStyle: 'italic' }}>rimacinata</span></span>
                  <span style={ingStyles.bagSpec}>100% durum wheat · vacuum sealed</span>
                </div>
                <div style={ingStyles.bagFoot}>
                  <span style={ingStyles.bagLot}>LOT · 2026-05-12</span>
                  <span style={ingStyles.bagWeight}>25 kg / 55 lb</span>
                </div>
                <div style={ingStyles.vacuumStamp}>VACUUM</div>
              </div>
              <div style={ingStyles.bagShadow}></div>
            </div>
          </div>

          <div style={ingStyles.right}>
            <ul style={ingStyles.list}>
              {points.map((p) =>
              <li key={p.n} style={ingStyles.item}>
                  <span style={ingStyles.itemN}>/ {p.n}</span>
                  <div>
                    <h3 style={ingStyles.itemTitle}>{p.title}</h3>
                    <p style={ingStyles.itemBody}>{p.body}</p>
                  </div>
                </li>
              )}
            </ul>

            <div style={ingStyles.quote}>
              <span style={ingStyles.quoteMark}>“</span>
              <p style={ingStyles.quoteText}>
                If the flour changes, the pasta changes. We refused to let that
                happen. So we picked a flour that doesn't.
              </p>
              <span style={ingStyles.quoteAttr}>— Uriel, Founder</span>
            </div>
          </div>
        </div>
      </div>
    </section>);

}

const ingStyles = {
  layout: {
    display: 'grid',
    gridTemplateColumns: 'repeat(auto-fit, minmax(min(100%, 380px), 1fr))',
    gap: 'clamp(40px, 6vw, 64px)',
    alignItems: 'start'
  },
  left: {},
  h2: {
    color: 'var(--cream)',
    margin: '20px 0 24px'
  },
  lede: {
    fontSize: 'clamp(17px, 1.6vw, 22px)',
    lineHeight: 1.5,
    color: 'var(--cream)',
    opacity: 0.9,
    margin: '0 0 48px',
    maxWidth: 480,
    fontWeight: 500
  },
  bagWrap: {
    position: 'relative',
    width: '100%',
    maxWidth: 380,
    aspectRatio: '3 / 4'
  },
  bag: {
    position: 'relative',
    width: '100%', height: '100%',
    background: 'linear-gradient(180deg, #f6e8c8 0%, #efd9a8 100%)',
    color: 'var(--ink)',
    border: '3px solid var(--ink)',
    borderRadius: 14,
    boxShadow: '8px 8px 0 var(--ink)',
    padding: 24,
    display: 'flex',
    flexDirection: 'column',
    justifyContent: 'space-between',
    transform: 'rotate(-2deg)',
    overflow: 'hidden'
  },
  bagTop: {
    display: 'flex', flexDirection: 'column', gap: 6
  },
  bagBrand: {
    fontFamily: 'var(--font-display)',
    fontWeight: 900,
    fontSize: 'clamp(20px, 2.3vw, 30px)',
    letterSpacing: '-0.03em',
    color: 'var(--ink)'
  },
  bagSince: {
    fontFamily: 'var(--font-mono)',
    fontSize: 10,
    letterSpacing: '0.18em',
    color: 'var(--ink-2)'
  },
  bagMid: {
    display: 'flex', flexDirection: 'column', gap: 8
  },
  bagBig: {
    fontFamily: 'var(--font-display)',
    fontWeight: 900,
    fontStyle: 'normal',
    fontSize: 'clamp(38px, 5vw, 64px)',
    letterSpacing: '-0.045em',
    lineHeight: 0.95,
    color: 'var(--sugo-deep)',
    textTransform: 'uppercase'
  },
  bagSpec: {
    fontFamily: 'var(--font-body)',
    fontSize: 12,
    color: 'var(--ink-2)',
    letterSpacing: '0.06em',
    textTransform: 'uppercase',
    fontWeight: 600
  },
  bagFoot: {
    display: 'flex',
    justifyContent: 'space-between',
    alignItems: 'flex-end',
    paddingTop: 16,
    borderTop: '2px dashed var(--ink-3)'
  },
  bagLot: {
    fontFamily: 'var(--font-mono)',
    fontSize: 11,
    color: 'var(--ink-2)'
  },
  bagWeight: {
    fontFamily: 'var(--font-display)',
    fontWeight: 900,
    fontSize: 18,
    letterSpacing: '-0.02em',
    color: 'var(--ink)'
  },
  vacuumStamp: {
    position: 'absolute',
    top: 24, right: -32,
    background: 'var(--sugo)',
    color: 'var(--cream)',
    fontFamily: 'var(--font-display)',
    fontWeight: 900,
    fontSize: 13,
    letterSpacing: '0.18em',
    padding: '6px 36px',
    transform: 'rotate(40deg)',
    border: '2px solid var(--ink)',
    boxShadow: '2px 2px 0 var(--ink)'
  },
  bagShadow: {
    position: 'absolute',
    inset: '8% -8% -10% 8%',
    background: 'rgba(0,0,0,0.12)',
    borderRadius: 14,
    zIndex: -1,
    filter: 'blur(16px)'
  },
  right: {
    display: 'flex',
    flexDirection: 'column',
    gap: 32
  },
  list: {
    listStyle: 'none',
    margin: 0,
    padding: 0,
    display: 'flex',
    flexDirection: 'column'
  },
  item: {
    display: 'grid',
    gridTemplateColumns: '64px 1fr',
    gap: 16,
    padding: '20px 0',
    borderTop: '2px dashed rgba(249,237,214,0.3)',
    alignItems: 'baseline'
  },
  itemN: {
    fontFamily: 'var(--font-mono)',
    fontSize: 13,
    color: 'var(--yolk)',
    letterSpacing: '0.04em'
  },
  itemTitle: {
    fontFamily: 'var(--font-display)',
    fontWeight: 900,
    fontStyle: 'italic',
    fontSize: 'clamp(20px, 2vw, 26px)',
    letterSpacing: '-0.02em',
    color: 'var(--cream)',
    margin: '0 0 8px'
  },
  itemBody: {
    fontFamily: 'var(--font-body)',
    fontSize: 15,
    lineHeight: 1.55,
    color: 'var(--cream)',
    opacity: 0.85,
    margin: 0
  },
  quote: {
    position: 'relative',
    background: 'var(--ink)',
    color: 'var(--cream)',
    border: '2.5px solid var(--ink)',
    borderRadius: 18,
    padding: '32px 32px 28px',
    boxShadow: '6px 6px 0 var(--yolk)'
  },
  quoteMark: {
    position: 'absolute',
    top: -18,
    left: 24,
    fontFamily: 'var(--font-display)',
    fontWeight: 900,
    fontSize: 80,
    lineHeight: 1,
    color: 'var(--yolk)'
  },
  quoteText: {
    fontFamily: 'var(--font-display)',
    fontStyle: 'italic',
    fontWeight: 900,
    fontSize: 'clamp(20px, 2.2vw, 28px)',
    letterSpacing: '-0.02em',
    lineHeight: 1.2,
    color: 'var(--cream)',
    margin: '0 0 16px',
    textWrap: 'balance'
  },
  quoteAttr: {
    fontFamily: 'var(--font-mono)',
    fontSize: 12,
    letterSpacing: '0.1em',
    color: 'var(--yolk)',
    textTransform: 'uppercase'
  }
};

window.Ingredients = Ingredients;

/* ==== Founder ==== */
/* Founder — Uriel Sebastian Copelev bio. Cream bg, magazine-style.
   Portrait placeholder (slot for upload). */
function Founder() {
  return (
    <section id="founder" className="bg-cream section-pad" style={{ color: 'var(--ink)' }}>
      <div className="container">
        <div style={fStyles.grid}>
          {/* Left: portrait */}
          <div style={fStyles.portraitCol}>
            <div style={fStyles.portrait}>
              <img
                src="assets/founder-uriel.jpg"
                alt="Uriel Sebastian Copelev — Founder of Gustai"
                style={{ width: '100%', height: '100%', display: 'block', objectFit: 'cover', borderRadius: 14 }} />
            </div>
            <div style={fStyles.caption}>
              <span className="readout" style={{ color: 'var(--ink-3)' }}> FOUNDER - URIEL SEBASTIAN</span>
            </div>

            {/* CV strip */}
            <div style={fStyles.cv}>
              <CVRow place="New York · Manhattan" lines={['Tao Asian Bistro 58th St', 'Sushi Samba', 'STK · Bagatelle (Meatpacking)', 'Strip House (Union Square)', 'Pazo · One Little West 12th St']} />
              <CVRow place="The Hamptons" lines={['Pink Elephant (Southampton)', 'Sunset Beach (Shelter Island)', 'Day & Night brunch series']} />
              <CVRow place="Miami · Sushi Samba" lines={['Operations & culinary direction']} />
              <CVRow place="China" lines={['Farmhouse Juice — founder & operator', 'Mega-mart R&D — Costco · Sam\'s · Hema']} />
              <CVRow place="Phuket — today" lines={['Gustai · Founder & Operator', 'Global F&B operator & culinary producer']} />
            </div>
          </div>

          {/* Right: copy */}
          <div style={fStyles.copyCol}>
            <div className="eyebrow" style={{ color: 'var(--sugo)' }}>

            </div>
            <h2 className="display display-lg" style={fStyles.h2}>
              Uriel<br />
              <span className="it" style={{ color: 'var(--sugo)' }}>Sebastian.</span>
            </h2>

            <p style={fStyles.role}>
              Founder & Operator, Gustai<br />
              <span style={{ color: 'var(--ink-3)' }}>Global F&B operator · Culinary producer · Premium dough specialist</span>
            </p>

            <div style={fStyles.body}>
              <p>
                A seasoned culinary producer and hospitality operator whose career
                spans top-tier dining hubs across three continents. Currently based
                in Phuket, where he founded Gustai — an artisanal food production
                facility specialising in fresh pasta and premium dough formulations
                for the regional hospitality sector.
              </p>
              <p>
                Uriel's deep foundation in food and beverage was forged in the
                fast-paced, high-stakes environment of New York. As a key operator,
                he was instrumental in the success of some of the city's most
                iconic, high-energy dining and nightlife venues — Tao, Sushi Samba,
                STK, Bagatelle, Strip House, Pazo, One Little West 12th — and in
                exclusive lifestyle destinations including Sunset Beach on Shelter
                Island and Pink Elephant in Manhattan and Southampton.
              </p>
              <p>
                Transitioning his expertise to the Asian market, Uriel ventured
                into entrepreneurship and large-scale culinary innovation in China.
                He founded and operated Farmhouse Juice, navigating high-volume
                health and wellness retail, and stepped into the world of mega-mart
                R&D as a consultant for Costco, Sam's Club and Hema — driving
                product development and scalable food solutions.
              </p>
              <p>
                Today at Gustai, Uriel merges the uncompromising quality of
                artisanal culinary techniques with the operational precision he
                honed globally. He partners directly with executive chefs and
                directors in Phuket's hospitality sector, delivering specialised,
                high-quality production solutions tailored for world-class resorts
                and restaurants.
              </p>
            </div>

            <div style={fStyles.directLine}>
              <span className="readout" style={{ color: 'var(--ink-3)' }}>DIRECT LINE</span>
              <div style={fStyles.directRow}>
                <a href="mailto:uriel@gustai.co" style={fStyles.directLink}>uriel@gustai.co</a>
                <span style={{ color: 'var(--line-strong)' }}>·</span>
                <a href="https://wa.me/66837108887?text=Hi%20Gustai%2C%20I%27d%20like%20to%20chat%20about%20pasta." style={fStyles.directLink}>+66 83 710 8887</a>
              </div>
            </div>
          </div>
        </div>
      </div>
    </section>);

}

function CVRow({ place, lines }) {
  return (
    <div className="cv-row" style={{ display: 'grid', gridTemplateColumns: '1fr 1.6fr', gap: 16, padding: '14px 0', borderTop: '1px dashed var(--line-strong)' }}>
      <span style={{
        fontFamily: 'var(--font-display)',
        fontWeight: 900,
        fontStyle: 'italic',
        fontSize: 14,
        letterSpacing: '-0.01em',
        color: 'var(--sugo)',
        textTransform: 'uppercase'
      }}>{place}</span>
      <ul style={{ margin: 0, padding: 0, listStyle: 'none', display: 'flex', flexDirection: 'column', gap: 3 }}>
        {lines.map((l, i) =>
        <li key={i} style={{ fontFamily: 'var(--font-body)', fontSize: 13, color: 'var(--ink-2)', lineHeight: 1.4 }}>{l}</li>
        )}
      </ul>
    </div>);

}

const fStyles = {
  grid: {
    display: 'grid',
    gridTemplateColumns: 'repeat(auto-fit, minmax(min(100%, 380px), 1fr))',
    gap: 'clamp(40px, 6vw, 64px)',
    alignItems: 'start'
  },
  portraitCol: {
    display: 'flex',
    flexDirection: 'column',
    gap: 16,
    position: 'sticky',
    top: 90
  },
  portrait: {
    width: '100%',
    aspectRatio: '3 / 4',
    border: '3px solid var(--ink)',
    borderRadius: 14,
    boxShadow: '8px 8px 0 var(--ink)',
    overflow: 'hidden',
    background: 'var(--paper)'
  },
  caption: {
    paddingLeft: 4
  },
  cv: {
    marginTop: 16
  },
  copyCol: {
    display: 'flex',
    flexDirection: 'column',
    gap: 24
  },
  h2: {
    color: 'var(--ink)',
    margin: '14px 0 0'
  },
  role: {
    fontFamily: 'var(--font-body)',
    fontSize: 17,
    fontWeight: 600,
    color: 'var(--ink)',
    margin: 0,
    lineHeight: 1.4
  },
  body: {
    display: 'flex',
    flexDirection: 'column',
    gap: 16,
    fontSize: 16,
    lineHeight: 1.6,
    color: 'var(--ink-2)'
  },
  directLine: {
    marginTop: 16,
    padding: '20px 24px',
    background: 'var(--paper)',
    border: '2px solid var(--ink)',
    borderRadius: 12,
    boxShadow: '4px 4px 0 var(--ink)',
    display: 'flex',
    flexDirection: 'column',
    gap: 8
  },
  directRow: {
    display: 'flex',
    alignItems: 'center',
    gap: 14,
    flexWrap: 'wrap'
  },
  directLink: {
    fontFamily: 'var(--font-display)',
    fontWeight: 900,
    fontStyle: 'italic',
    fontSize: 'clamp(20px, 2vw, 26px)',
    letterSpacing: '-0.02em',
    color: 'var(--sugo)',
    textDecoration: 'none'
  }
};

window.Founder = Founder;

/* ==== Hospitality ==== */
/* Hospitality — client philosophy section. Dark ink + big quote. */
function Hospitality() {
  return (
    <section id="hospitality" className="bg-ink section-pad" style={{ color: 'var(--cream)', position: 'relative', overflow: 'hidden' }}>
      <div className="container" style={{ position: 'relative', zIndex: 2 }}>
        <div style={hStyles.layout}>
          <div>
            <div className="eyebrow" style={{ color: 'var(--yolk)' }}>

            </div>
            <h2 className="display display-lg" style={hStyles.h2}>
              we treat<br />
              <span className="it" style={{ color: 'var(--yolk)' }}>your kitchen</span><br />
              like you treat<br />
              your guests.
            </h2>
          </div>

          <div style={hStyles.right}>
            <p style={hStyles.lede}>
              We're a production house, but service isn't a side dish here.
              Your chef calls — we answer. Your spec changes — we change with it.
              Your event needs an extra portion run on a Friday — we'll figure it out.
            </p>
            <p style={hStyles.lede}>
              Because the chef on the line — and the room they're cooking for —
              deserves the same hospitality they're handing out to their guests.
              We hold ourselves to that standard. Every order. Every delivery.
            </p>

            <ul style={hStyles.bullets}>
              <Bullet text="Direct line to the founder, 24/7" />
              <Bullet text="Spec changes accepted" />
              <Bullet text="Cold-chain deliveries Monday through Friday" />
              <Bullet text="Private-label and custom shape runs available" />
            </ul>

            <div style={hStyles.cta}>
              <a href="#contact" className="btn btn-yolk">Talk to Uriel →</a>
            </div>
          </div>
        </div>
      </div>

      {/* Decorative "open" stamp */}
      <div style={hStyles.stamp}>
        <span>SERVICE</span>
        <span style={{ fontSize: 12, opacity: 0.7 }}>MON · TUE · WED · THU · FRI</span>
        <span>OPEN</span>
      </div>
    </section>);

}

function Bullet({ text }) {
  return (
    <li style={{
      display: 'flex', alignItems: 'flex-start', gap: 14,
      padding: '14px 0', borderTop: '1.5px dashed rgba(249,237,214,0.22)',
      fontFamily: 'var(--font-body)', fontSize: 16, lineHeight: 1.5,
      color: 'var(--cream)'
    }}>
      <span style={{
        fontFamily: 'var(--font-display)',
        fontWeight: 900,
        fontStyle: 'italic',
        fontSize: 18,
        color: 'var(--sugo-soft)',
        lineHeight: 1.3
      }}>→</span>
      <span>{text}</span>
    </li>);

}

const hStyles = {
  layout: {
    display: 'grid',
    gridTemplateColumns: 'repeat(auto-fit, minmax(min(100%, 380px), 1fr))',
    gap: 'clamp(40px, 6vw, 64px)',
    alignItems: 'start'
  },
  h2: {
    color: 'var(--cream)',
    margin: '20px 0 0'
  },
  right: {
    display: 'flex',
    flexDirection: 'column',
    gap: 16,
    paddingTop: 24
  },
  lede: {
    fontSize: 'clamp(16px, 1.4vw, 19px)',
    lineHeight: 1.6,
    color: 'var(--cream)',
    opacity: 0.9,
    margin: 0,
    fontWeight: 500
  },
  bullets: {
    listStyle: 'none',
    margin: '20px 0 0',
    padding: 0
  },
  cta: {
    marginTop: 24
  },
  stamp: {
    position: 'absolute',
    right: -40,
    bottom: -40,
    width: 240, height: 240,
    border: '4px solid var(--yolk)',
    borderRadius: '50%',
    display: 'flex',
    flexDirection: 'column',
    alignItems: 'center',
    justifyContent: 'center',
    gap: 6,
    fontFamily: 'var(--font-display)',
    fontWeight: 900,
    fontSize: 32,
    letterSpacing: '0.08em',
    color: 'var(--yolk)',
    transform: 'rotate(-8deg)',
    opacity: 0.85,
    zIndex: 1,
    pointerEvents: 'none'
  }
};

window.Hospitality = Hospitality;

/* ==== Press ==== */
/* Press / certifications strip — placeholder badges + "trusted by" row.
   Compact section between hospitality and contact. */
function Press() {
  // certifications — visual placeholders, swappable
  const certs = [
  { line1: 'MACHINES', line2: 'LAMONFERRINA/SIRMAN' },
  { line1: 'GMP', line2: 'Good Mfg. Practice' },
  { line1: '100%', line2: 'Italian Flour' },
  { line1: 'BRONZE', line2: 'Die Extruded' },
  { line1: 'COLD', line2: 'Chain -20–4 °C' }];


  // partners — generic placeholders ("Property A" style — to be swapped by user)
  const partners = [
  'FIRA BEACH CLUB', 'CAFE DEL MAR', 'YONA', 'AMANPURI',
  'INTERCONTINENTAL', 'PULLMAN', 'MOVENPICK', 'WYNDHAM GRAND'];


  return (
    <section className="bg-cream" style={{ padding: 'clamp(56px, 7vw, 96px) 0', color: 'var(--ink)' }}>
      <div className="container">
        <div style={prStyles.head}>
          <div className="eyebrow" style={{ color: 'var(--sugo)' }}>Press · Trust · Certifications</div>
          <h3 className="display display-md" style={{ color: 'var(--ink)', margin: '12px 0 0', fontStyle: 'italic' }}>
            on the line at Phuket's<br />best kitchens.
          </h3>
        </div>

        {/* certs */}
        <div style={prStyles.certRow}>
          {certs.map((c) =>
          <div key={c.line1} style={prStyles.cert}>
              <span style={prStyles.certBig}>{c.line1}</span>
              <span style={prStyles.certSub}>{c.line2}</span>
            </div>
          )}
        </div>

        {/* partners */}
        <div style={prStyles.partnersHead}>
          <span className="readout" style={{ color: 'var(--ink-3)' }}>SELECTED PARTNERS · 2025–26</span>
          <span style={{ flex: 1, height: 2, borderTop: '2px dashed var(--line-strong)', alignSelf: 'center' }}></span>
          <span className="readout" style={{ color: 'var(--ink-3)' }}>FULL LIST ON REQUEST</span>
        </div>
        <div style={{ ...prStyles.partners, alignItems: "flex-start" }}>
          {partners.map((p, i) =>
          <span key={i} style={prStyles.partner}>{p}</span>
          )}
        </div>
      </div>
    </section>);

}

const prStyles = {
  head: {
    marginBottom: 40
  },
  certRow: {
    display: 'grid',
    gridTemplateColumns: 'repeat(auto-fit, minmax(160px, 1fr))',
    gap: 12,
    marginBottom: 56
  },
  cert: {
    padding: '20px 18px',
    border: '2px solid var(--ink)',
    borderRadius: 12,
    background: 'var(--paper)',
    boxShadow: '4px 4px 0 var(--ink)',
    display: 'flex',
    flexDirection: 'column',
    gap: 4,
    alignItems: 'flex-start'
  },
  certBig: {
    fontFamily: 'var(--font-display)',
    fontWeight: 900,
    fontStyle: 'italic',
    fontSize: 'clamp(24px, 2.5vw, 36px)',
    letterSpacing: '-0.03em',
    color: 'var(--sugo)',
    lineHeight: 1
  },
  certSub: {
    fontFamily: 'var(--font-mono)',
    fontSize: 11,
    letterSpacing: '0.1em',
    color: 'var(--ink-3)',
    textTransform: 'uppercase'
  },
  partnersHead: {
    display: 'flex',
    alignItems: 'center',
    gap: 16,
    marginBottom: 20
  },
  partners: {
    display: 'flex',
    flexWrap: 'wrap',
    gap: 10
  },
  partner: {
    fontFamily: 'var(--font-display)',
    fontWeight: 900,
    fontSize: 14,
    letterSpacing: '0.04em',
    textTransform: 'uppercase',
    padding: '10px 16px',
    border: '2px solid var(--ink)',
    borderRadius: 999,
    background: 'transparent',
    color: 'var(--ink)',
    opacity: 0.55
  }
};

window.Press = Press;

/* ==== Contact ==== */
/* Contact — phone, email, LINE QR placeholder, location.
   Paper bg. Big editorial split. */
function Contact() {
  const [copied, setCopied] = React.useState(false);

  const copy = (text) => {
    if (navigator.clipboard) {
      navigator.clipboard.writeText(text);
      setCopied(true);
      setTimeout(() => setCopied(false), 1600);
    }
  };

  return (
    <section id="contact" className="bg-paper section-pad" style={{ color: 'var(--ink)', position: 'relative' }}>
      <div className="container">
        <div style={cStyles.head}>
          <div className="eyebrow" style={{ color: 'var(--sugo)' }}>

          </div>
          <h2 className="display display-lg" style={cStyles.h2}>
            let's<br />
            <span className="it" style={{ color: 'var(--sugo)' }}>cook.</span>
          </h2>
          <p style={cStyles.lede}>
            Send a chef line, grab a sample run, or get on the order list. Tap any
            number to copy it, scan the QR for an instant LINE chat with Uriel.
          </p>
        </div>

        <div style={cStyles.grid}>
          {/* Email card */}
          <ContactCard
            label="EMAIL"
            value="uriel@gustai.co"
            href="mailto:uriel@gustai.co"
            big
            onClick={() => copy('uriel@gustai.co')}
            accent="var(--sugo)" />
          

          {/* Phone card → WhatsApp chat */}
          <ContactCard
            label="WHATSAPP"
            value="+66 83 710 8887"
            href="https://wa.me/66837108887?text=Hi%20Gustai%2C%20I%27d%20like%20to%20chat%20about%20pasta."
            big
            onClick={() => copy('+66837108887')}
            accent="var(--basil)" />
          

          {/* LINE QR */}
          <article style={{ ...cStyles.card, ...cStyles.qrCard }}>
            <header style={cStyles.cardHead}>
              <span className="readout" style={{ color: 'var(--ink-3)' }}>LINE · INSTANT MESSAGE</span>
              <span style={{ ...cStyles.lineBadge }}>LINE</span>
            </header>
            <div style={cStyles.qrWrap}>
              <a href="https://line.me/R/ti/p/%40gustai" target="_blank" rel="noopener" style={{ display: 'block', lineHeight: 0 }}>
                <img
                  src="assets/line-qr.png"
                  alt="Add Gustai on LINE"
                  width="200"
                  height="200"
                  onError={(e) => { e.currentTarget.src = 'https://api.qrserver.com/v1/create-qr-code/?size=240x240&margin=2&data=' + encodeURIComponent('https://line.me/R/ti/p/@gustai'); }}
                  style={{ width: 200, height: 200, display: 'block', background: 'var(--cream)', padding: 14, border: '2.5px solid var(--ink)', borderRadius: 12, boxShadow: '6px 6px 0 var(--ink)', boxSizing: 'content-box' }} />
              </a>
              <span style={cStyles.qrCornerStamp}>SCAN ME</span>
            </div>
            <div style={cStyles.qrFoot}>
              <span style={cStyles.lineId}>@gustai</span>
              <span className="readout" style={{ color: 'var(--ink-3)' }}>Add as a friend on LINE</span>
            </div>
          </article>

          {/* Location card */}
          <article style={{ ...cStyles.card, ...cStyles.locCard }}>
            <header style={cStyles.cardHead}>
              <span className="readout" style={{ color: 'var(--cream)', opacity: 0.7 }}>WORKSHOP</span>
              <span className="readout" style={{ color: 'var(--yolk)' }}>7.8804° N · 98.3923° E</span>
            </header>
            <h3 style={cStyles.locTitle}>
              Phuket,<br /><span className="it">Thailand</span>
            </h3>
            <p style={cStyles.locBody}>
              Production house & cold-chain delivery hub. Deliveries Mon–Fri across
              Phuket. Outside-Phuket routes quoted on request.
            </p>
            <div style={cStyles.locFoot}>
              <span style={cStyles.dot}></span>
              <span style={{ fontFamily: 'var(--font-mono)', fontSize: 12, color: 'var(--cream)', letterSpacing: '0.06em' }}>OPEN · 08:00 – 18:00 ICT</span>
            </div>
          </article>

          {/* Quote form */}
          <article style={{ ...cStyles.card, ...cStyles.formCard }}>
            <header style={cStyles.cardHead}>
              <span className="readout" style={{ color: 'var(--ink-3)' }}>REQUEST A QUOTE</span>
            </header>
            <h3 style={cStyles.formTitle}>Tell us what your kitchen needs.</h3>
            <form style={cStyles.form} onSubmit={(e) => {
              e.preventDefault();
              const name = (document.getElementById('qname') || {}).value || '';
              const prop = (document.getElementById('qprop') || {}).value || '';
              const phone = (document.getElementById('qphone') || {}).value || '';
              const need = (document.getElementById('qneed') || {}).value || '';
              const body = encodeURIComponent(
                'Name: ' + name + '\n' +
                'Property: ' + prop + '\n' +
                'Phone / LINE: ' + phone + '\n\n' +
                'Needs:\n' + need
              );
              window.location.href = 'mailto:uriel@gustai.co?subject=Gustai%20quote%20request&body=' + body;
            }}>
              <Field label="Your name" id="qname" placeholder="Chef de cuisine, GM, F&B director…" />
              <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 12 }}>
                <Field label="Property" id="qprop" placeholder="Restaurant or hotel" />
                <Field label="Phone or LINE" id="qphone" placeholder="+66…" />
              </div>
              <Field label="What do you need?" id="qneed" placeholder="Shapes, portion grams, weekly volume…" textarea />
              <button type="submit" className="btn btn-sugo" style={{ alignSelf: 'flex-start', marginTop: 4 }}>
                Send to Uriel →
              </button>
            </form>
          </article>
        </div>

        {/* Copy toast */}
        <div style={{ ...cStyles.toast, opacity: copied ? 1 : 0, transform: copied ? 'translateY(0)' : 'translateY(10px)' }}>
          Copied to clipboard
        </div>
      </div>
    </section>);

}

function ContactCard({ label, value, href, big, onClick, accent }) {
  return (
    <a href={href} onClick={onClick} style={{
      ...cStyles.card,
      ...cStyles.bigCard,
      borderColor: 'var(--ink)',
      textDecoration: 'none'
    }}>
      <header style={cStyles.cardHead}>
        <span className="readout" style={{ color: 'var(--ink-3)' }}>{label}</span>
        <span style={{ ...cStyles.copyHint, color: accent }}>TAP TO COPY</span>
      </header>
      <span style={{
        fontFamily: 'var(--font-display)',
        fontStyle: 'italic',
        fontWeight: 900,
        fontSize: big ? 'clamp(28px, 3.4vw, 48px)' : 24,
        letterSpacing: '-0.025em',
        color: 'var(--ink)',
        lineHeight: 1.05,
        wordBreak: 'break-word'
      }}>{value}</span>
      <span style={{
        marginTop: 'auto',
        fontFamily: 'var(--font-display)',
        fontWeight: 900,
        color: accent,
        fontSize: 14,
        letterSpacing: '0.06em',
        textTransform: 'uppercase'
      }}>Open →</span>
    </a>);

}

function Field({ label, id, placeholder, textarea }) {
  const Tag = textarea ? 'textarea' : 'input';
  return (
    <label style={{ display: 'flex', flexDirection: 'column', gap: 6 }}>
      <span style={{
        fontFamily: 'var(--font-mono)',
        fontSize: 11,
        color: 'var(--ink-3)',
        letterSpacing: '0.08em',
        textTransform: 'uppercase'
      }}>{label}</span>
      <Tag
        id={id}
        placeholder={placeholder}
        rows={textarea ? 3 : undefined}
        style={{
          fontFamily: 'var(--font-body)',
          fontSize: 15,
          padding: '12px 14px',
          background: 'var(--cream)',
          color: 'var(--ink)',
          border: '2px solid var(--ink)',
          borderRadius: 10,
          outline: 'none',
          resize: textarea ? 'vertical' : undefined,
          boxShadow: 'inset 0 2px 0 rgba(0,0,0,0.04)'
        }} />
      
    </label>);

}

function FakeQR() {
  // Generate a deterministic-ish QR-looking grid (decorative only)
  const N = 21;
  const cells = [];
  // seed pattern
  const seed = (i, j) => (i * 137 + j * 31 + (i ^ j)) % 7 < 3;
  for (let i = 0; i < N; i++) {
    for (let j = 0; j < N; j++) {
      cells.push({ i, j, on: seed(i, j) });
    }
  }
  // finder boxes corners
  const isFinder = (i, j) =>
  i < 7 && j < 7 || i < 7 && j > N - 8 || i > N - 8 && j < 7;

  return (
    <div style={{ background: 'var(--cream)', padding: 14, border: '2.5px solid var(--ink)', borderRadius: 12, boxShadow: '6px 6px 0 var(--ink)' }}>
      <div style={{ display: 'grid', gridTemplateColumns: `repeat(${N}, 1fr)`, gap: 2, width: 200, height: 200 }}>
        {cells.map((c, k) => {
          if (isFinder(c.i, c.j)) {
            const inner = c.i % 7 >= 2 && c.i % 7 <= 4 && c.j % 7 >= 2 && c.j % 7 <= 4;
            const border = c.i % 7 === 0 || c.i % 7 === 6 || c.j % 7 === 0 || c.j % 7 === 6;
            return <div key={k} style={{ background: inner || border ? 'var(--ink)' : 'var(--cream)' }}></div>;
          }
          return <div key={k} style={{ background: c.on ? 'var(--ink)' : 'transparent' }}></div>;
        })}
      </div>
      <div style={{
        position: 'absolute'
        // center sugo marker — typical of LINE-style QR
      }}></div>
    </div>);

}

const cStyles = {
  head: {
    maxWidth: 1100,
    marginBottom: 64,
    display: 'grid',
    gap: 20
  },
  h2: {
    color: 'var(--ink)',
    margin: 0
  },
  lede: {
    fontSize: 'clamp(17px, 1.5vw, 21px)',
    lineHeight: 1.5,
    color: 'var(--ink-2)',
    maxWidth: 640,
    margin: 0,
    fontWeight: 500
  },
  grid: {
    display: 'grid',
    gridTemplateColumns: 'repeat(12, 1fr)',
    gap: 18
  },
  card: {
    border: '2.5px solid var(--ink)',
    borderRadius: 18,
    background: 'var(--cream)',
    color: 'var(--ink)',
    padding: 24,
    boxShadow: '6px 6px 0 var(--ink)',
    display: 'flex',
    flexDirection: 'column',
    gap: 16,
    minHeight: 240,
    transition: 'transform var(--dur) var(--ease-bounce), box-shadow var(--dur) var(--ease-bounce)'
  },
  bigCard: {
    gridColumn: 'span 6',
    cursor: 'pointer'
  },
  cardHead: {
    display: 'flex',
    justifyContent: 'space-between',
    alignItems: 'center',
    gap: 12
  },
  copyHint: {
    fontFamily: 'var(--font-mono)',
    fontSize: 11,
    letterSpacing: '0.1em',
    textTransform: 'uppercase'
  },
  qrCard: {
    gridColumn: 'span 4',
    alignItems: 'center',
    textAlign: 'center'
  },
  lineBadge: {
    fontFamily: 'var(--font-display)',
    fontWeight: 900,
    fontSize: 11,
    background: '#06C755',
    color: 'white',
    padding: '4px 8px',
    borderRadius: 5,
    border: '2px solid var(--ink)',
    boxShadow: '2px 2px 0 var(--ink)',
    letterSpacing: '0.08em'
  },
  qrWrap: {
    position: 'relative'
  },
  qrCornerStamp: {
    position: 'absolute',
    top: -10, right: -22,
    background: 'var(--sugo)',
    color: 'var(--cream)',
    fontFamily: 'var(--font-display)',
    fontWeight: 900,
    fontSize: 11,
    letterSpacing: '0.1em',
    padding: '5px 9px 4px',
    borderRadius: 4,
    border: '2px solid var(--ink)',
    boxShadow: '3px 3px 0 var(--ink)',
    transform: 'rotate(6deg)'
  },
  qrFoot: {
    display: 'flex', flexDirection: 'column', gap: 4, alignItems: 'center'
  },
  lineId: {
    fontFamily: 'var(--font-display)',
    fontWeight: 900,
    fontStyle: 'italic',
    fontSize: 22,
    letterSpacing: '-0.02em',
    color: 'var(--ink)'
  },
  locCard: {
    gridColumn: 'span 4',
    background: 'var(--ink)',
    color: 'var(--cream)',
    borderColor: 'var(--ink)',
    boxShadow: '6px 6px 0 var(--sugo)'
  },
  locTitle: {
    fontFamily: 'var(--font-display)',
    fontWeight: 900,
    fontSize: 'clamp(36px, 4vw, 56px)',
    letterSpacing: '-0.04em',
    lineHeight: 0.95,
    color: 'var(--cream)',
    margin: 0,
    textTransform: 'uppercase'
  },
  locBody: {
    fontFamily: 'var(--font-body)',
    fontSize: 14,
    lineHeight: 1.5,
    color: 'var(--cream)',
    opacity: 0.8,
    margin: 0
  },
  locFoot: {
    display: 'flex', alignItems: 'center', gap: 8, marginTop: 'auto'
  },
  dot: {
    width: 10, height: 10, borderRadius: 999,
    background: 'var(--basil-bright)',
    boxShadow: '0 0 0 3px rgba(79,174,93,0.3)'
  },
  formCard: {
    gridColumn: 'span 8'
  },
  qSmall: {
    fontFamily: 'var(--font-mono)',
    fontSize: 11,
    background: 'var(--yolk)',
    color: 'var(--ink)',
    padding: '4px 8px',
    borderRadius: 4,
    border: '1.5px solid var(--ink)',
    letterSpacing: '0.06em'
  },
  formTitle: {
    fontFamily: 'var(--font-display)',
    fontWeight: 900,
    fontStyle: 'italic',
    fontSize: 'clamp(24px, 2.2vw, 32px)',
    letterSpacing: '-0.025em',
    color: 'var(--ink)',
    margin: 0
  },
  form: {
    display: 'flex',
    flexDirection: 'column',
    gap: 12
  },
  toast: {
    position: 'fixed',
    bottom: 28,
    left: '50%',
    transform: 'translateX(-50%)',
    background: 'var(--ink)',
    color: 'var(--cream)',
    padding: '12px 18px',
    borderRadius: 12,
    border: '2px solid var(--ink)',
    boxShadow: '4px 4px 0 var(--sugo)',
    fontFamily: 'var(--font-display)',
    fontWeight: 900,
    fontSize: 14,
    letterSpacing: '0.04em',
    textTransform: 'uppercase',
    transition: 'opacity 220ms, transform 220ms',
    zIndex: 200,
    pointerEvents: 'none'
  }
};

window.Contact = Contact;

/* ==== Footer ==== */
/* Footer — ink bg, giant italic wordmark, contact + nav, micro legal */
function Footer() {
  return (
    <footer className="bg-ink section-pad" style={{ color: 'var(--cream)', paddingBottom: 32, position: 'relative', overflow: 'hidden' }}>
      <div className="container" style={{ position: 'relative', zIndex: 2 }}>
        {/* Giant wordmark */}
        <div style={ftStyles.wordmarkRow}>
          <h2 className="display" style={ftStyles.giant}>
            Gusta<span style={{ fontStyle: 'italic', color: 'var(--sugo)' }}>i.</span>
          </h2>
          <span style={ftStyles.tag}>
            <span style={{ width: 10, height: 10, borderRadius: 999, background: 'var(--basil-bright)', boxShadow: '0 0 0 4px rgba(79,174,93,0.25)' }}></span>
            Fresh today
          </span>
        </div>

        <div style={ftStyles.grid}>
          {/* Address column */}
          <div style={ftStyles.col}>
            <span className="readout" style={ftStyles.colLabel}>WORKSHOP</span>
            <p style={ftStyles.addr}>
              Gustai Production House<br />
              Phuket, Thailand
            </p>
            <span className="readout" style={{ ...ftStyles.colLabel, marginTop: 18 }}>HOURS</span>
            <p style={ftStyles.addr}>
              Monday — Friday<br />
              08:00 – 18:00 ICT
            </p>
          </div>

          {/* Sitemap */}
          <div style={ftStyles.col}>
            <span className="readout" style={ftStyles.colLabel}>SITEMAP</span>
            <FtLink href="#top">Top</FtLink>
            <FtLink href="#obsession">The obsession</FtLink>
            <FtLink href="#process">Process</FtLink>
            <FtLink href="#catalog">Catalogue (preview)</FtLink>
            <FtLink href="catalogue.html">Full catalogue</FtLink>
            <FtLink href="#ingredients">Ingredients</FtLink>
            <FtLink href="#founder">Founder</FtLink>
            <FtLink href="#contact">Contact</FtLink>
          </div>

          {/* Contact */}
          <div style={ftStyles.col}>
            <span className="readout" style={ftStyles.colLabel}>DIRECT</span>
            <a href="mailto:uriel@gustai.co" style={ftStyles.bigLink}>uriel@gustai.co</a>
            <a href="https://wa.me/66837108887?text=Hi%20Gustai%2C%20I%27d%20like%20to%20chat%20about%20pasta." style={ftStyles.bigLink}>+66 83 710 8887</a>
            <div style={{ display: 'flex', gap: 10, marginTop: 18 }}>
              <a href="#" style={ftStyles.social}>Instagram ↗</a>
              <a href="#contact" style={ftStyles.social}>LINE @gustai</a>
            </div>
          </div>

          {/* Manifesto */}
          <div style={ftStyles.col}>
            <span className="readout" style={ftStyles.colLabel}>THE PROMISE</span>
            <p style={ftStyles.manifesto}>
              Restaurant-grade fresh pasta — bronze-die, sheeted, filled and
              sauced — for chefs who refuse to compromise on the plate. Built in
              Phuket. Delivered cold.
            </p>
          </div>
        </div>

        {/* Legal strip */}
        <div style={{ ...ftStyles.legal, alignItems: "center" }}>
          <span style={{ fontFamily: 'var(--font-mono)', fontSize: 12, opacity: 0.6 }}>
            © 2026 Gustai. All rights reserved.
          </span>
          <span style={{ fontFamily: 'var(--font-mono)', fontSize: 12, opacity: 0.6 }}>

          </span>
          <span style={{ fontFamily: 'var(--font-mono)', fontSize: 12, opacity: 0.6 }}>

          </span>
        </div>
      </div>

      {/* decorative oversize italic mark */}
      <span style={ftStyles.glyph} aria-hidden="true">G</span>
    </footer>);

}

function FtLink({ href, children }) {
  return (
    <a href={href} style={ftStyles.navLink}>{children}</a>);

}

const ftStyles = {
  wordmarkRow: {
    display: 'flex',
    alignItems: 'flex-end',
    justifyContent: 'space-between',
    gap: 24,
    paddingBottom: 32,
    borderBottom: '2px dashed rgba(249,237,214,0.2)',
    marginBottom: 48,
    flexWrap: 'wrap'
  },
  giant: {
    fontSize: 'clamp(80px, 18vw, 280px)',
    letterSpacing: '-0.06em',
    color: 'var(--cream)',
    margin: 0,
    fontStyle: 'italic',
    lineHeight: 0.85,
    textTransform: 'lowercase'
  },
  tag: {
    display: 'inline-flex',
    alignItems: 'center',
    gap: 10,
    fontFamily: 'var(--font-mono)',
    fontSize: 12,
    letterSpacing: '0.14em',
    textTransform: 'uppercase',
    color: 'var(--cream)',
    opacity: 0.9,
    padding: '8px 14px',
    border: '1.5px solid rgba(249,237,214,0.3)',
    borderRadius: 999
  },
  grid: {
    display: 'grid',
    gridTemplateColumns: 'repeat(4, 1fr)',
    gap: 32,
    marginBottom: 56
  },
  col: {
    display: 'flex',
    flexDirection: 'column',
    gap: 8
  },
  colLabel: {
    color: 'var(--yolk)',
    marginBottom: 4
  },
  addr: {
    fontFamily: 'var(--font-body)',
    fontSize: 14,
    lineHeight: 1.55,
    color: 'var(--cream)',
    opacity: 0.85,
    margin: 0
  },
  navLink: {
    fontFamily: 'var(--font-body)',
    fontSize: 14,
    color: 'var(--cream)',
    textDecoration: 'none',
    padding: '4px 0',
    opacity: 0.85
  },
  bigLink: {
    fontFamily: 'var(--font-display)',
    fontWeight: 900,
    fontStyle: 'italic',
    fontSize: 'clamp(18px, 1.6vw, 22px)',
    color: 'var(--cream)',
    letterSpacing: '-0.02em',
    textDecoration: 'none',
    lineHeight: 1.3
  },
  social: {
    fontFamily: 'var(--font-body)',
    fontSize: 13,
    color: 'var(--cream)',
    textDecoration: 'none',
    padding: '6px 12px',
    border: '1.5px solid rgba(249,237,214,0.4)',
    borderRadius: 999,
    opacity: 0.85
  },
  manifesto: {
    fontFamily: 'var(--font-body)',
    fontSize: 14,
    lineHeight: 1.55,
    color: 'var(--cream)',
    opacity: 0.85,
    margin: 0
  },
  legal: {
    display: 'flex',
    justifyContent: 'space-between',
    paddingTop: 24,
    borderTop: '2px dashed rgba(249,237,214,0.2)',
    flexWrap: 'wrap',
    gap: 12
  },
  glyph: {
    position: 'absolute',
    right: -40,
    bottom: -120,
    fontFamily: 'var(--font-display)',
    fontWeight: 900,
    fontStyle: 'italic',
    fontSize: 600,
    color: 'var(--sugo)',
    opacity: 0.07,
    lineHeight: 1,
    pointerEvents: 'none',
    zIndex: 1
  }
};

window.Footer = Footer;

/* ==== App ==== */
/* App — main composition. Wires nav + sections + tweaks. */

const TWEAK_DEFAULTS = /*EDITMODE-BEGIN*/{
  "heroTreatment": "flour-canvas",
  "accent": "sugo",
  "heroCta": "See the catalogue",
  "heroVideoSrc": "",
  "showMarquee": true,
  "showPress": true,
  "showHospitality": true,
  "italicWordmark": true
}/*EDITMODE-END*/;

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

  // Apply accent color globally
  React.useEffect(() => {
    const root = document.documentElement;
    if (t.accent === 'yolk') {
      root.style.setProperty('--accent-1', 'var(--yolk)');
    } else if (t.accent === 'basil') {
      root.style.setProperty('--accent-1', 'var(--basil)');
    } else {
      root.style.setProperty('--accent-1', 'var(--sugo)');
    }
  }, [t.accent]);

  return (
    <div>
      <Nav tweaks={t} />
      <Hero tweaks={t} />
      {t.showMarquee && <Marquee />}
      <Obsession />
      <Process />
      <Catalog />
      <Ingredients />
      <Founder />
      {t.showHospitality && <Hospitality />}
      {t.showPress && <Press />}
      <Contact />
      <Footer />

      <TweaksPanel title="Tweaks">
        <TweakSection label="Hero" />
        <TweakSelect
          label="Hero background"
          value={t.heroTreatment}
          options={[
            { value: 'flour-canvas', label: 'Flour canvas (animated)' },
            { value: 'video', label: 'Video file (paste URL)' },
          ]}
          onChange={(v) => setTweak('heroTreatment', v)}
        />
        {t.heroTreatment === 'video' && (
          <TweakText
            label="Video URL"
            value={t.heroVideoSrc}
            placeholder="https://… .mp4"
            onChange={(v) => setTweak('heroVideoSrc', v)}
          />
        )}
        <TweakText
          label="CTA copy"
          value={t.heroCta}
          onChange={(v) => setTweak('heroCta', v)}
        />

        <TweakSection label="Palette" />
        <TweakRadio
          label="Accent"
          value={t.accent}
          options={['sugo', 'yolk', 'basil']}
          onChange={(v) => setTweak('accent', v)}
        />

        <TweakSection label="Sections" />
        <TweakToggle
          label="Marquee bar"
          value={t.showMarquee}
          onChange={(v) => setTweak('showMarquee', v)}
        />
        <TweakToggle
          label="Hospitality section"
          value={t.showHospitality}
          onChange={(v) => setTweak('showHospitality', v)}
        />
        <TweakToggle
          label="Press / certifications"
          value={t.showPress}
          onChange={(v) => setTweak('showPress', v)}
        />
      </TweaksPanel>
    </div>
  );
}

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