/* ============================================================================
   tweaks-panel.jsx — Clippa shared "Tweaks" inspector shell.

   A tiny floating dev panel used to drive a design's demo state machine. It is
   the ONLY place this project uses React; the app itself is plain vanilla JS.
   Loaded via <script type="text/babel" src="tweaks-panel.jsx">, so every
   top-level declaration here becomes a global the inline TweaksApp can use:

     useTweaks(defaults)  -> [state, setTweak]
     <TweaksPanel>            floating collapsible card
     <TweakSection label/>    small mono divider label
     <TweakSelect  label value options onChange/>
     <TweakSlider  label value min max step unit onChange/>
     <TweakToggle  label value onChange/>

   Self-styling: injects its own <style> once (tw-* classes) so it never
   depends on the host document's CSS. Matches the dark surface + purple accent.
   ========================================================================== */

(function injectTweakStyles() {
  if (typeof document === "undefined") return;
  if (document.getElementById("tw-styles")) return;
  const s = document.createElement("style");
  s.id = "tw-styles";
  s.textContent = `
  .tw-root{ position:fixed; right:16px; bottom:16px; z-index:45;
    width:238px; font-family:"Geist Mono","JetBrains Mono",ui-monospace,monospace;
    color:#F4F4F5; }
  .tw-card{ background:#131316; border:1px solid rgba(255,255,255,0.10);
    border-radius:12px; box-shadow:0 18px 50px rgba(0,0,0,0.55);
    overflow:hidden; backdrop-filter:blur(4px); }
  .tw-head{ display:flex; align-items:center; justify-content:space-between;
    height:38px; padding:0 12px; cursor:pointer; user-select:none;
    border-bottom:1px solid rgba(255,255,255,0.07); }
  .tw-head.closed{ border-bottom:none; }
  .tw-title{ display:flex; align-items:center; gap:7px; font-size:11px;
    font-weight:500; letter-spacing:.10em; text-transform:uppercase;
    color:#A1A1AA; }
  .tw-dot{ width:7px; height:7px; border-radius:50%; background:#8B3DFF;
    box-shadow:0 0 8px rgba(139,61,255,0.8); }
  .tw-chev{ color:#71717A; transition:transform .2s cubic-bezier(.25,.6,.3,1); }
  .tw-chev.open{ transform:rotate(180deg); }
  .tw-body{ padding:6px 12px 12px; display:flex; flex-direction:column; gap:2px; }
  .tw-section{ font-size:10px; font-weight:500; letter-spacing:.12em;
    text-transform:uppercase; color:#71717A; margin:12px 0 4px; }
  .tw-section:first-child{ margin-top:4px; }
  .tw-row{ display:flex; align-items:center; justify-content:space-between;
    gap:10px; min-height:30px; }
  .tw-label{ font-size:11px; color:#A1A1AA; white-space:nowrap; }
  .tw-val{ font-size:11px; color:#F4F4F5; font-variant-numeric:tabular-nums;
    min-width:34px; text-align:right; }
  /* select */
  .tw-select{ appearance:none; -webkit-appearance:none;
    background:#1A1A1E; color:#F4F4F5; border:1px solid rgba(255,255,255,0.12);
    border-radius:6px; height:26px; padding:0 24px 0 9px; font:inherit;
    font-size:11px; cursor:pointer; min-width:118px;
    background-image:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 24 24' fill='none' stroke='%2371717A' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'><path d='M6 9l6 6 6-6'/></svg>");
    background-repeat:no-repeat; background-position:right 7px center; }
  .tw-select:focus-visible{ outline:1px solid rgba(139,61,255,0.5); outline-offset:1px; }
  /* range */
  .tw-range{ -webkit-appearance:none; appearance:none; width:110px; height:4px;
    border-radius:3px; background:#2A2A30; cursor:pointer; }
  .tw-range::-webkit-slider-thumb{ -webkit-appearance:none; width:14px; height:14px;
    border-radius:50%; background:#8B3DFF; box-shadow:0 0 0 3px rgba(139,61,255,0.18);
    cursor:pointer; }
  .tw-range::-moz-range-thumb{ width:14px; height:14px; border:none; border-radius:50%;
    background:#8B3DFF; box-shadow:0 0 0 3px rgba(139,61,255,0.18); cursor:pointer; }
  .tw-slrow{ display:flex; align-items:center; gap:9px; }
  /* toggle */
  .tw-toggle{ position:relative; width:34px; height:20px; border-radius:11px;
    background:#2A2A30; border:1px solid rgba(255,255,255,0.08); cursor:pointer;
    transition:background .18s cubic-bezier(.25,.6,.3,1); flex:0 0 auto; }
  .tw-toggle.on{ background:#8B3DFF; border-color:transparent; }
  .tw-knob{ position:absolute; top:2px; left:2px; width:14px; height:14px;
    border-radius:50%; background:#fff; transition:transform .18s cubic-bezier(.25,.6,.3,1); }
  .tw-toggle.on .tw-knob{ transform:translateX(14px); }
  @media (prefers-reduced-motion: reduce){
    .tw-chev,.tw-knob,.tw-toggle{ transition:none; }
  }
  `;
  document.head.appendChild(s);
})();

/* Hook: a flat bag of tweak values + a setter that updates one key. */
function useTweaks(defaults) {
  const [state, setState] = React.useState(defaults);
  const setTweak = React.useCallback((key, value) => {
    setState((prev) => (prev[key] === value ? prev : { ...prev, [key]: value }));
  }, []);
  return [state, setTweak];
}

function TwChevron({ open }) {
  return (
    <svg className={"tw-chev" + (open ? " open" : "")} width="14" height="14"
         viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5"
         strokeLinecap="round" strokeLinejoin="round">
      <path d="M6 9l6 6 6-6" />
    </svg>
  );
}

function TweaksPanel({ title = "Tweaks", children }) {
  const [open, setOpen] = React.useState(true);
  return (
    <div className="tw-root">
      <div className="tw-card">
        <div className={"tw-head" + (open ? "" : " closed")}
             onClick={() => setOpen((o) => !o)}>
          <span className="tw-title"><span className="tw-dot" />{title}</span>
          <TwChevron open={open} />
        </div>
        {open && <div className="tw-body">{children}</div>}
      </div>
    </div>
  );
}

function TweakSection({ label }) {
  return <div className="tw-section">{label}</div>;
}

function TweakSelect({ label, value, options, onChange }) {
  return (
    <div className="tw-row">
      <span className="tw-label">{label}</span>
      <select className="tw-select" value={value}
              onChange={(e) => onChange(e.target.value)}>
        {options.map((o) => <option key={o} value={o}>{o}</option>)}
      </select>
    </div>
  );
}

function TweakSlider({ label, value, min, max, step, unit = "", onChange }) {
  return (
    <div className="tw-row">
      <span className="tw-label">{label}</span>
      <span className="tw-slrow">
        <input className="tw-range" type="range" min={min} max={max} step={step}
               value={value}
               onChange={(e) => onChange(parseFloat(e.target.value))} />
        <span className="tw-val">{value}{unit}</span>
      </span>
    </div>
  );
}

function TweakToggle({ label, value, onChange }) {
  return (
    <div className="tw-row">
      <span className="tw-label">{label}</span>
      <button type="button" className={"tw-toggle" + (value ? " on" : "")}
              role="switch" aria-checked={value} aria-label={label}
              onClick={() => onChange(!value)}>
        <span className="tw-knob" />
      </button>
    </div>
  );
}
