/* ===== tweaks-panel.jsx ===== */
(function(){

// 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",
//     "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}
//                        onChange={(v) => setTweak('primaryColor', 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;width:100%;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;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}
`;

// ── 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 }, '*');
  }, []);
  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-noncommentable=""
           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);
  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;

  // 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;

  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>
  );
}

function TweakColor({ label, value, onChange }) {
  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>
  );
}

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,
});

})();
/* ===== components.jsx ===== */
(function(){
/* Shared components & icons. Exposes everything on window. */

const { useState, useEffect, useRef, useMemo, useCallback } = React;

/* ───────── Icons (24px, currentColor) ───────── */
const Icon = ({ d, size = 16, viewBox = "0 0 24 24", stroke = 1.7, fill = "none" }) => (
  <svg width={size} height={size} viewBox={viewBox} fill={fill} stroke="currentColor"
       strokeWidth={stroke} strokeLinecap="round" strokeLinejoin="round" aria-hidden="true">
    {typeof d === 'string' ? <path d={d}/> : d}
  </svg>
);

const I = {
  arrow: (p) => <Icon {...p} d="M5 12h14M13 6l6 6-6 6"/>,
  arrowUp: (p) => <Icon {...p} d="M12 19V5M6 11l6-6 6 6"/>,
  arrowDown: (p) => <Icon {...p} d="M12 5v14M6 13l6 6 6-6"/>,
  check: (p) => <Icon {...p} d="M5 12.5l4.5 4.5L20 6.5"/>,
  close: (p) => <Icon {...p} d="M6 6l12 12M18 6L6 18"/>,
  search: (p) => <Icon {...p} d="M11 19a8 8 0 1 0 0-16 8 8 0 0 0 0 16zM21 21l-4.3-4.3"/>,
  menu: (p) => <Icon {...p} d="M4 6h16M4 12h16M4 18h16"/>,
  bell: (p) => <Icon {...p} d="M6 8a6 6 0 1 1 12 0c0 7 3 7 3 9H3c0-2 3-2 3-9zM10 21a2 2 0 0 0 4 0"/>,
  user: (p) => <Icon {...p} d="M12 12a4 4 0 1 0 0-8 4 4 0 0 0 0 8zM4 21a8 8 0 1 1 16 0"/>,
  sun: (p) => <Icon {...p} d="M12 4v2M12 18v2M4.9 4.9l1.4 1.4M17.7 17.7l1.4 1.4M2 12h2M20 12h2M4.9 19.1l1.4-1.4M17.7 6.3l1.4-1.4M12 16a4 4 0 1 0 0-8 4 4 0 0 0 0 8z"/>,
  moon: (p) => <Icon {...p} d="M21 13a9 9 0 1 1-10-10 7 7 0 0 0 10 10z"/>,
  bolt: (p) => <Icon {...p} d="M13 2L4 14h7l-1 8 9-12h-7l1-8z"/>,
  chart: (p) => <Icon {...p} d="M3 21h18M5 17l4-6 3 3 5-8 4 6"/>,
  cart: (p) => <Icon {...p} d="M3 4h2l2 12h12l2-8H6M9 20a1 1 0 1 0 0-2 1 1 0 0 0 0 2zM18 20a1 1 0 1 0 0-2 1 1 0 0 0 0 2z"/>,
  star: (p) => <Icon {...p} d="M12 3l2.7 6 6.3.6-4.8 4.4 1.5 6.2L12 17l-5.7 3.2L7.8 14 3 9.6 9.3 9z"/>,
  starFill: (p) => <Icon {...p} fill="currentColor" stroke="none" d="M12 3l2.7 6 6.3.6-4.8 4.4 1.5 6.2L12 17l-5.7 3.2L7.8 14 3 9.6 9.3 9z"/>,
  shield: (p) => <Icon {...p} d="M12 3l8 3v6c0 5-3.5 8-8 9-4.5-1-8-4-8-9V6l8-3z"/>,
  lock: (p) => <Icon {...p} d="M6 11V8a6 6 0 1 1 12 0v3M5 11h14v10H5z"/>,
  copy: (p) => <Icon {...p} d="M9 9h11v11H9zM5 4h11v3M5 4v11h3"/>,
  link: (p) => <Icon {...p} d="M10 14l4-4M9 7H7a5 5 0 0 0 0 10h2M15 17h2a5 5 0 0 0 0-10h-2"/>,
  wallet: (p) => <Icon {...p} d="M3 7a2 2 0 0 1 2-2h13v4M3 7v12a2 2 0 0 0 2 2h15V9H5a2 2 0 0 1-2-2zM17 14h.01"/>,
  download: (p) => <Icon {...p} d="M12 4v12M6 12l6 6 6-6M4 21h16"/>,
  external: (p) => <Icon {...p} d="M14 4h6v6M10 14L20 4M19 14v6H5V5h6"/>,
  plus: (p) => <Icon {...p} d="M12 5v14M5 12h14"/>,
  minus: (p) => <Icon {...p} d="M5 12h14"/>,
  more: (p) => <Icon {...p} d="M5 12h.01M12 12h.01M19 12h.01" stroke={3}/>,
  filter: (p) => <Icon {...p} d="M4 6h16M7 12h10M10 18h4"/>,
  refresh: (p) => <Icon {...p} d="M21 12a9 9 0 1 1-3-6.7L21 8M21 3v5h-5"/>,
  cog: (p) => <Icon {...p} d="M12 15a3 3 0 1 0 0-6 3 3 0 0 0 0 6zM19.4 15a1.7 1.7 0 0 0 .3 1.8l.1.1a2 2 0 1 1-2.8 2.8l-.1-.1a1.7 1.7 0 0 0-1.8-.3 1.7 1.7 0 0 0-1 1.5V21a2 2 0 1 1-4 0v-.1a1.7 1.7 0 0 0-1.1-1.5 1.7 1.7 0 0 0-1.8.3l-.1.1a2 2 0 1 1-2.8-2.8l.1-.1a1.7 1.7 0 0 0 .3-1.8 1.7 1.7 0 0 0-1.5-1H3a2 2 0 1 1 0-4h.1a1.7 1.7 0 0 0 1.5-1.1 1.7 1.7 0 0 0-.3-1.8l-.1-.1a2 2 0 1 1 2.8-2.8l.1.1a1.7 1.7 0 0 0 1.8.3H9a1.7 1.7 0 0 0 1-1.5V3a2 2 0 1 1 4 0v.1a1.7 1.7 0 0 0 1 1.5 1.7 1.7 0 0 0 1.8-.3l.1-.1a2 2 0 1 1 2.8 2.8l-.1.1a1.7 1.7 0 0 0-.3 1.8V9c.3.6.9 1 1.5 1H21a2 2 0 1 1 0 4h-.1a1.7 1.7 0 0 0-1.5 1z"/>,
  logout: (p) => <Icon {...p} d="M9 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h4M16 17l5-5-5-5M21 12H9"/>,
  inbox: (p) => <Icon {...p} d="M22 12h-6l-2 3h-4l-2-3H2M5.5 5h13L22 12v7a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2v-7l3.5-7z"/>,
  pulse: (p) => <Icon {...p} d="M3 12h4l3-9 4 18 3-9h4"/>,
  layers: (p) => <Icon {...p} d="M12 2l10 6-10 6L2 8l10-6zM2 16l10 6 10-6M2 12l10 6 10-6"/>,
  sliders: (p) => <Icon {...p} d="M4 21v-7M4 10V3M12 21v-9M12 8V3M20 21v-5M20 12V3M1 14h6M9 8h6M17 16h6"/>,
  globe: (p) => <Icon {...p} d="M12 21a9 9 0 1 0 0-18 9 9 0 0 0 0 18zM3 12h18M12 3a14 14 0 0 1 0 18M12 3a14 14 0 0 0 0 18"/>,
  chevR: (p) => <Icon {...p} d="M9 6l6 6-6 6"/>,
  chevD: (p) => <Icon {...p} d="M6 9l6 6 6-6"/>,
  chevL: (p) => <Icon {...p} d="M15 6l-6 6 6 6"/>,
  trash: (p) => <Icon {...p} d="M3 6h18M8 6V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2M19 6l-1 14a2 2 0 0 1-2 2H8a2 2 0 0 1-2-2L5 6"/>,
  edit: (p) => <Icon {...p} d="M12 20h9M16.5 3.5a2.1 2.1 0 1 1 3 3L7 19l-4 1 1-4z"/>,
  users: (p) => <Icon {...p} d="M16 21v-2a4 4 0 0 0-4-4H6a4 4 0 0 0-4 4v2M9 11a4 4 0 1 0 0-8 4 4 0 0 0 0 8zM22 21v-2a4 4 0 0 0-3-3.9M16 3.1a4 4 0 0 1 0 7.8"/>,
  receipt: (p) => <Icon {...p} d="M5 21V3l2 2 2-2 2 2 2-2 2 2 2-2 2 2v18l-2-2-2 2-2-2-2 2-2-2-2 2zM8 9h8M8 13h8M8 17h6"/>,
  rocket: (p) => <Icon {...p} d="M5 13l-2 5 5-2M14 11l-1 1M19 5a8 8 0 0 0-8 8l-2 2 4 4 2-2a8 8 0 0 0 8-8 6 6 0 0 0-4-4z"/>,
  spark: (p) => <Icon {...p} d="M12 2v4M12 18v4M4.9 4.9l2.8 2.8M16.3 16.3l2.8 2.8M2 12h4M18 12h4M4.9 19.1l2.8-2.8M16.3 7.7l2.8-2.8"/>,
  fingerprint: (p) => <Icon {...p} d="M12 11a3 3 0 0 1 3 3v1c0 1.5-.5 3-1 4M9 20c-2-2-3-4-3-7a6 6 0 0 1 12 0M3 12a9 9 0 0 1 14.5-7.2M21 12c0 2-.3 4-1 6M12 6a5 5 0 0 0-5 5"/>,
  dollar: (p) => <Icon {...p} d="M12 2v20M17 6H9.5a3.5 3.5 0 0 0 0 7h5a3.5 3.5 0 0 1 0 7H6"/>,
  tag: (p) => <Icon {...p} d="M20.6 13.4l-7.2 7.2a2 2 0 0 1-2.8 0L3 12.9V3h9.9l7.7 7.7a2 2 0 0 1 0 2.7zM7 7h.01"/>,
  building: (p) => <Icon {...p} d="M3 21V8a2 2 0 0 1 2-2h4V3h6v18M3 21h18M9 9v0M9 13v0M9 17v0M13 13v0M13 17v0M17 21V11a2 2 0 0 1 2-2h0a2 2 0 0 1 2 2v10"/>,
  cpu: (p) => <Icon {...p} d="M4 4h16v16H4zM9 9h6v6H9zM2 9h2M2 15h2M20 9h2M20 15h2M9 2v2M15 2v2M9 20v2M15 20v2"/>,
  book: (p) => <Icon {...p} d="M4 19.5A2.5 2.5 0 0 1 6.5 17H20V3H6.5A2.5 2.5 0 0 0 4 5.5v14zM4 19.5A2.5 2.5 0 0 0 6.5 22H20v-5"/>,
  calc: (p) => <Icon {...p} d="M5 3h14a1 1 0 0 1 1 1v16a1 1 0 0 1-1 1H5a1 1 0 0 1-1-1V4a1 1 0 0 1 1-1zM8 7h8M8 11h2M12 11h.01M16 11h.01M8 15h.01M12 15h.01M16 15h.01M8 19h.01M12 19h.01M16 19h.01"/>,
  gift: (p) => <Icon {...p} d="M20 12v10H4V12M2 7h20v5H2zM12 22V7M12 7H7.5a2.5 2.5 0 0 1 0-5C11 2 12 7 12 7zM12 7h4.5a2.5 2.5 0 0 0 0-5C13 2 12 7 12 7z"/>,
  x: (p) => <Icon {...p} d="M18 6L6 18M6 6l12 12"/>,
  eye: (p) => <Icon {...p} d="M1 12s4-8 11-8 11 8 11 8-4 8-11 8S1 12 1 12z"/>,
  eyeOff: (p) => <Icon {...p} d="M17.94 17.94A10 10 0 0 1 12 20c-7 0-11-8-11-8a18 18 0 0 1 5.06-5.94M9.9 4.24A9 9 0 0 1 12 4c7 0 11 8 11 8a18 18 0 0 1-2.16 3.19M14.12 14.12a3 3 0 1 1-4.24-4.24M1 1l22 22"/>,
};

/* ───────── Logo ───────── */
const Logo = ({ size = 16 }) => (
  <span className="logo">
    <span className="logo-mark" style={{ width: size + 6, height: size + 6 }}>
      <span className="slash"></span>
    </span>
    <span style={{ fontSize: size }}>mattobot</span>
  </span>
);

/* ───────── Theme + Router (very small custom router) ───────── */
const ThemeContext = React.createContext({ theme: 'dark', setTheme: () => {} });

function useHashRoute() {
  const [hash, setHash] = useState(() => window.location.hash || '#/');
  useEffect(() => {
    const h = () => setHash(window.location.hash || '#/');
    window.addEventListener('hashchange', h);
    return () => window.removeEventListener('hashchange', h);
  }, []);
  const path = hash.replace(/^#/, '') || '/';
  const navigate = (to) => { window.location.hash = to; window.scrollTo(0, 0); };
  return { path, navigate };
}

function Link({ to, children, className = '', onClick, ...rest }) {
  return (
    <a href={"#" + to} className={className} onClick={(e) => {
      if (onClick) onClick(e);
    }} {...rest}>{children}</a>
  );
}

/* ───────── Toasts ───────── */
const ToastContext = React.createContext({ toast: () => {} });
function ToastHost({ children }) {
  const [items, setItems] = useState([]);
  const toast = useCallback((msg, kind = 'info') => {
    const id = Math.random().toString(36).slice(2);
    setItems(items => [...items, { id, msg, kind }]);
    setTimeout(() => setItems(items => items.filter(i => i.id !== id)), 3500);
  }, []);
  return (
    <ToastContext.Provider value={{ toast }}>
      {children}
      <div className="toasts">
        {items.map(i => (
          <div key={i.id} className={"toast " + (i.kind === 'error' ? 'error' : '')}>
            <span className="toast-dot"/>
            <span>{i.msg}</span>
          </div>
        ))}
      </div>
    </ToastContext.Provider>
  );
}

/* ───────── Buttons ───────── */
const Btn = ({ children, kind = 'default', size, className = '', as: As = 'button', ...p }) => {
  const cls = ['btn'];
  if (kind === 'primary') cls.push('btn-primary');
  if (kind === 'ghost') cls.push('btn-ghost');
  if (size === 'lg') cls.push('btn-lg');
  if (size === 'sm') cls.push('btn-sm');
  if (className) cls.push(className);
  return <As className={cls.join(' ')} {...p}>{children}</As>;
};

/* ───────── Tabs ───────── */
function Tabs({ items, value, onChange }) {
  return (
    <div className="tabs">
      {items.map(it => (
        <button key={it.value}
          className={value === it.value ? 'active' : ''}
          onClick={() => onChange(it.value)}>{it.label}</button>
      ))}
    </div>
  );
}

/* ───────── Spark line — pure SVG, deterministic from seed ───────── */
function seedRand(seed) {
  let s = seed;
  return () => { s = (s * 9301 + 49297) % 233280; return s / 233280; };
}
function Spark({ seed = 1, w = 220, h = 60, color = 'var(--accent)', strokeWidth = 1.5, fill = true, points = 40 }) {
  const path = useMemo(() => {
    const r = seedRand(seed);
    const ys = [];
    let y = 0.5;
    for (let i = 0; i < points; i++) {
      y += (r() - 0.5) * 0.18;
      y = Math.max(0.08, Math.min(0.92, y));
      ys.push(y);
    }
    const stepX = w / (points - 1);
    const d = ys.map((yy, i) => `${i === 0 ? 'M' : 'L'} ${(i * stepX).toFixed(1)} ${(yy * h).toFixed(1)}`).join(' ');
    const fillD = `${d} L ${w} ${h} L 0 ${h} Z`;
    return { d, fillD };
  }, [seed, w, h, points]);
  const id = "g_" + seed;
  return (
    <svg className="spark" viewBox={`0 0 ${w} ${h}`} preserveAspectRatio="none" style={{ width: '100%', height: '100%' }}>
      <defs>
        <linearGradient id={id} x1="0" x2="0" y1="0" y2="1">
          <stop offset="0%" stopColor={color} stopOpacity="0.30"/>
          <stop offset="100%" stopColor={color} stopOpacity="0"/>
        </linearGradient>
      </defs>
      {fill && <path d={path.fillD} fill={`url(#${id})`} />}
      <path d={path.d} stroke={color} strokeWidth={strokeWidth} fill="none" strokeLinejoin="round" strokeLinecap="round"/>
    </svg>
  );
}

/* ───────── Candlestick chart (procedural) ───────── */
function CandleChart({ seed = 7, w = 800, h = 320, candles = 60, withVolume = true, withSignals = false }) {
  const data = useMemo(() => {
    const r = seedRand(seed);
    let price = 100;
    const arr = [];
    for (let i = 0; i < candles; i++) {
      const open = price;
      const drift = (r() - 0.48) * 4;
      const close = open + drift;
      const high = Math.max(open, close) + r() * 2.2;
      const low  = Math.min(open, close) - r() * 2.2;
      arr.push({ open, close, high, low, vol: 0.3 + r() });
      price = close;
    }
    return arr;
  }, [seed, candles]);
  const min = Math.min(...data.map(d => d.low));
  const max = Math.max(...data.map(d => d.high));
  const pad = (max - min) * 0.05;
  const lo = min - pad, hi = max + pad;
  const chartH = withVolume ? h * 0.78 : h;
  const volH = h - chartH;
  const cw = w / candles;
  const yScale = (v) => chartH - ((v - lo) / (hi - lo)) * chartH;
  const signals = withSignals
    ? data.map((d, i) => i % 11 === 5 ? { i, type: 'buy' } : i % 13 === 7 ? { i, type: 'sell' } : null).filter(Boolean)
    : [];

  return (
    <svg viewBox={`0 0 ${w} ${h}`} preserveAspectRatio="none" style={{ width: '100%', height: '100%' }}>
      {/* grid */}
      {[0.25, 0.5, 0.75].map(p => (
        <line key={p} x1={0} x2={w} y1={p * chartH} y2={p * chartH} stroke="var(--grid)" strokeWidth="1" strokeDasharray="2 4"/>
      ))}
      {/* candles */}
      {data.map((d, i) => {
        const x = i * cw + cw * 0.5;
        const up = d.close >= d.open;
        const color = up ? 'var(--up)' : 'var(--down)';
        const yo = yScale(d.open), yc = yScale(d.close);
        const yt = Math.min(yo, yc), yb = Math.max(yo, yc);
        return (
          <g key={i}>
            <line x1={x} x2={x} y1={yScale(d.high)} y2={yScale(d.low)} stroke={color} strokeWidth="1"/>
            <rect x={x - cw * 0.32} y={yt} width={cw * 0.64} height={Math.max(1, yb - yt)} fill={color}/>
          </g>
        );
      })}
      {/* signals */}
      {signals.map(s => {
        const d = data[s.i];
        const x = s.i * cw + cw * 0.5;
        const y = s.type === 'buy' ? yScale(d.low) + 14 : yScale(d.high) - 14;
        const c = s.type === 'buy' ? 'var(--accent)' : 'var(--down)';
        return (
          <g key={s.i} fontFamily="JetBrains Mono" fontSize="9" fill={c}>
            <circle cx={x} cy={y} r="3" fill={c}/>
            <text x={x + 6} y={y + 3}>{s.type === 'buy' ? 'LONG' : 'SHORT'}</text>
          </g>
        );
      })}
      {/* volume */}
      {withVolume && data.map((d, i) => {
        const x = i * cw + cw * 0.5;
        const up = d.close >= d.open;
        const vh = d.vol * volH * 0.85;
        return <rect key={"v"+i} x={x - cw * 0.32} y={h - vh} width={cw * 0.64} height={vh}
                     fill={up ? 'var(--up)' : 'var(--down)'} opacity="0.35"/>;
      })}
      {/* moving average */}
      <path d={data.map((d, i) => {
        const x = i * cw + cw * 0.5;
        const slice = data.slice(Math.max(0, i - 9), i + 1);
        const ma = slice.reduce((a, b) => a + b.close, 0) / slice.length;
        return `${i === 0 ? 'M' : 'L'} ${x.toFixed(1)} ${yScale(ma).toFixed(1)}`;
      }).join(' ')} stroke="var(--accent)" strokeWidth="1.5" fill="none" opacity="0.9"/>
    </svg>
  );
}

/* ───────── Crypto/Asset ticker row ───────── */
function TickerRow() {
  const items = [
    ['BTC/USDT', '67,412.50', '+1.24%', 'up'],
    ['ETH/USDT', '3,498.12', '-0.42%', 'down'],
    ['SOL/USDT', '184.07', '+3.81%', 'up'],
    ['EURUSD',   '1.0842',   '+0.06%', 'up'],
    ['SPX',      '5,488.30', '-0.18%', 'down'],
    ['GOLD',     '2,431.10', '+0.92%', 'up'],
    ['NDX',      '19,210.50','+0.55%', 'up'],
    ['BNB/USDT', '604.20',   '-1.10%', 'down'],
    ['XRP/USDT', '0.5210',   '+2.06%', 'up'],
    ['DOGE/USDT','0.1302',   '-3.22%', 'down'],
  ];
  const Row = () => items.map((it, i) => (
    <span key={i}>
      <span style={{ color: 'var(--text)' }}>{it[0]}</span>{' '}
      <span>{it[1]}</span>{' '}
      <span className={it[3]}>{it[2]}</span>
    </span>
  ));
  return (
    <div className="ticker">
      <div className="ticker-track">
        <Row />
        <Row />
      </div>
    </div>
  );
}

/* ───────── Theme toggle ───────── */
function ThemeToggle() {
  const { theme, setTheme } = React.useContext(ThemeContext);
  return (
    <button className="btn btn-icon" title="Toggle theme"
      onClick={() => setTheme(theme === 'dark' ? 'light' : 'dark')}>
      {theme === 'dark' ? <I.sun size={15}/> : <I.moon size={15}/>}
    </button>
  );
}

/* ───────── Mock data: indicators ───────── */
const INDICATORS = [
  {
    slug: 'aurora-trend',
    name: 'Aurora Trend',
    tagline: 'Adaptive trend engine with multi-timeframe confluence.',
    cat: 'Trend',
    rating: 4.9, reviews: 1284,
    seed: 11,
    badges: ['Bestseller', 'New build'],
    price: { lifetime: 199, monthly: 19, yearly: 149 },
    stats: { winrate: 68.4, trades: 1240, sharpe: 2.31, dd: 8.2 },
    description: 'Aurora Trend is a confluence model that fuses an adaptive supertrend, volatility-regime filters, and a Hurst exponent gate to identify high-probability swings. Built for indices, FX majors and BTC.',
    features: [
      'Adaptive trend filter with regime detection',
      'Multi-timeframe confluence (3 TFs)',
      'Built-in alerts: webhook, email, app',
      'Backtester + statistics overlay',
      'Discord & Telegram signal forwarding',
    ],
    timeframes: ['5m', '15m', '1h', '4h', '1D'],
    markets: ['Crypto', 'Forex', 'Indices'],
  },
  {
    slug: 'volume-profile-pro',
    name: 'Volume Profile Pro',
    tagline: 'Session, composite and HTF volume profile with VAH/VAL/POC.',
    cat: 'Volume',
    rating: 4.8, reviews: 942,
    seed: 23,
    badges: ['Pro pick'],
    price: { lifetime: 249, monthly: 24, yearly: 189 },
    stats: { winrate: 64.1, trades: 980, sharpe: 1.92, dd: 11.4 },
    description: 'Render fixed-range, session, anchored and HTF composite profiles with naked POCs, value-area extensions and developing VWAP.',
    features: [
      'Anchored & rolling profile windows',
      'Naked POC tracking',
      'Single-prints & low-volume nodes',
      'Developing & yesterday VWAP',
    ],
    timeframes: ['1m', '5m', '15m', '1h'],
    markets: ['Crypto', 'Futures'],
  },
  {
    slug: 'liquidity-grid',
    name: 'Liquidity Grid',
    tagline: 'Smart-money order block + liquidity sweeps.',
    cat: 'SMC',
    rating: 4.7, reviews: 612,
    seed: 31,
    badges: ['Top SMC'],
    price: { lifetime: 179, monthly: 17, yearly: 129 },
    stats: { winrate: 61.0, trades: 720, sharpe: 1.65, dd: 12.8 },
    description: 'Auto-detect order blocks, breaker blocks, FVGs, equal highs/lows and liquidity sweeps with mitigation logic.',
    features: ['Order blocks + breakers', 'FVG / imbalance zones', 'EQH/EQL & sweeps', 'BOS/CHoCH labels'],
    timeframes: ['5m', '15m', '1h', '4h'],
    markets: ['Crypto', 'Forex'],
  },
  {
    slug: 'momentum-pulse',
    name: 'Momentum Pulse',
    tagline: 'Composite momentum with divergence engine.',
    cat: 'Momentum',
    rating: 4.6, reviews: 433,
    seed: 41,
    badges: [],
    price: { lifetime: 99, monthly: 12, yearly: 89 },
    stats: { winrate: 58.7, trades: 540, sharpe: 1.28, dd: 14.0 },
    description: 'Detects regular and hidden divergences across RSI, MACD-Z and CCI; emits a normalized composite z-score.',
    features: ['Regular + hidden divergence', 'Composite Z momentum', 'Adaptive thresholds'],
    timeframes: ['5m', '15m', '1h', '4h', '1D'],
    markets: ['All'],
  },
  {
    slug: 'volatility-regime',
    name: 'Volatility Regime',
    tagline: 'Detects expansion / contraction phases automatically.',
    cat: 'Volatility',
    rating: 4.8, reviews: 318,
    seed: 53,
    badges: ['Quant'],
    price: { lifetime: 149, monthly: 15, yearly: 119 },
    stats: { winrate: 62.3, trades: 410, sharpe: 1.71, dd: 9.6 },
    description: 'Classifies the market into 4 volatility regimes using realized vol, Yang-Zhang and ATR percentiles.',
    features: ['4-regime classification', 'Yang-Zhang vol', 'Vol-of-vol overlay'],
    timeframes: ['1h', '4h', '1D'],
    markets: ['Crypto', 'Indices'],
  },
  {
    slug: 'orderflow-tape',
    name: 'Orderflow Tape',
    tagline: 'Lightweight footprint + delta divergence on TV.',
    cat: 'Orderflow',
    rating: 4.5, reviews: 224,
    seed: 67,
    badges: ['New'],
    price: { lifetime: 229, monthly: 22, yearly: 169 },
    stats: { winrate: 60.4, trades: 280, sharpe: 1.55, dd: 10.4 },
    description: 'CVD, delta divergence, absorption and aggressor flips reconstructed from tick & lower-TF approximation.',
    features: ['CVD + delta', 'Absorption alerts', 'Aggressor flips', 'Footprint heatmap'],
    timeframes: ['1m', '5m'],
    markets: ['Crypto', 'Futures'],
  },
];

/* ───────── Helpers ───────── */
const fmt = {
  usd: (n) => '$' + n.toLocaleString('en-US', { minimumFractionDigits: 2, maximumFractionDigits: 2 }),
  num: (n) => n.toLocaleString('en-US'),
  pct: (n, d = 1) => (n >= 0 ? '+' : '') + n.toFixed(d) + '%',
};

/* ───────── Stars ───────── */
function Stars({ value = 5, size = 12 }) {
  return (
    <span style={{ display: 'inline-flex', gap: 1, color: 'var(--accent)' }}>
      {[1,2,3,4,5].map(i => i <= Math.round(value)
        ? <I.starFill key={i} size={size}/> : <I.star key={i} size={size}/>)}
    </span>
  );
}

/* ───────── Animated number counter ───────── */
function Counter({ to, prefix = '', suffix = '', duration = 1200, decimals = 0 }) {
  const [v, setV] = useState(0);
  useEffect(() => {
    let raf, t0;
    const tick = (t) => {
      if (!t0) t0 = t;
      const p = Math.min(1, (t - t0) / duration);
      const eased = 1 - Math.pow(1 - p, 3);
      setV(eased * to);
      if (p < 1) raf = requestAnimationFrame(tick);
    };
    raf = requestAnimationFrame(tick);
    return () => cancelAnimationFrame(raf);
  }, [to, duration]);
  return <span className="ticker-num">{prefix}{v.toLocaleString('en-US', { minimumFractionDigits: decimals, maximumFractionDigits: decimals })}{suffix}</span>;
}

/* ───────── Indicator card ───────── */
function IndicatorCard({ ind, onOpen }) {
  const ref = useRef(null);
  const onMove = (e) => {
    if (!ref.current) return;
    const r = ref.current.getBoundingClientRect();
    ref.current.style.setProperty('--mx', ((e.clientX - r.left) / r.width * 100) + '%');
    ref.current.style.setProperty('--my', ((e.clientY - r.top) / r.height * 100) + '%');
  };
  return (
    <div className="indicator-card lift ic-shine" ref={ref} onMouseMove={onMove}
         onClick={() => onOpen?.(ind)} style={{ cursor: 'pointer', position: 'relative' }}>
      <div className="indicator-thumb">
        <CandleChart seed={ind.seed} w={400} h={220} candles={50} withSignals={true}/>
        <div style={{ position: 'absolute', top: 10, left: 10, display: 'flex', gap: 6 }}>
          {ind.badges.slice(0, 1).map(b => <span key={b} className="pill pill-accent"><span className="dot"/>{b}</span>)}
        </div>
        <div style={{ position: 'absolute', top: 10, right: 10 }}>
          <span className="pill"><span className="dot"/>{ind.cat}</span>
        </div>
        <div className="ic-overlay">
          <span className="mini-stat">WIN {ind.stats.winrate}%</span>
          <span className="mini-stat">SHARPE {ind.stats.sharpe}</span>
          <span className="mini-stat">DD {ind.stats.dd}%</span>
        </div>
      </div>
      <div style={{ padding: 16, display: 'flex', flexDirection: 'column', gap: 10 }}>
        <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'baseline', gap: 12, flexWrap: 'wrap' }}>
          <h3 className="h3" style={{ margin: 0, minWidth: 0, flex: '1 1 auto', overflow: 'hidden', textOverflow: 'ellipsis' }}>{ind.name}</h3>
          <div style={{ textAlign: 'right', flex: 'none' }}>
            <span className="mono" style={{ fontSize: 15, fontWeight: 600 }}>{fmt.usd(ind.price.lifetime)}</span>
            <div style={{ fontSize: 10.5, color: 'var(--muted)', textTransform: 'uppercase', letterSpacing: 0.06 }}>or ${ind.price.monthly}/mo</div>
          </div>
        </div>
        <div style={{ color: 'var(--text-2)', fontSize: 13, minHeight: 38 }}>{ind.tagline}</div>
        <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', gap: 8, flexWrap: 'wrap' }}>
          <div style={{ display: 'flex', alignItems: 'center', gap: 8, fontSize: 12, color: 'var(--muted)', minWidth: 0, flexWrap: 'wrap' }}>
            <Stars value={ind.rating}/>
            <span className="mono">{ind.rating}</span>
            <span>·</span>
            <span>{fmt.num(ind.reviews)} reviews</span>
          </div>
          <span style={{ display:'flex', alignItems:'center', gap: 4, fontSize: 12, color: 'var(--accent)', flex: 'none' }}>
            View <I.arrow size={12}/>
          </span>
        </div>
      </div>
    </div>
  );
}

/* ───────── Command palette (⌘K) ───────── */
function CommandPalette() {
  const [open, setOpen] = useState(false);
  const [q, setQ] = useState('');
  const [active, setActive] = useState(0);
  const { navigate } = useHashRoute();
  useEffect(() => {
    const h = (e) => {
      if ((e.metaKey || e.ctrlKey) && e.key.toLowerCase() === 'k') {
        e.preventDefault(); setOpen(o => !o); setQ('');
      }
      if (e.key === 'Escape') setOpen(false);
    };
    window.addEventListener('keydown', h);
    return () => window.removeEventListener('keydown', h);
  }, []);
  useEffect(() => {
    if (open) document.body.style.overflow = 'hidden';
    else document.body.style.overflow = '';
    return () => { document.body.style.overflow = ''; };
  }, [open]);
  const all = [
    { cat: 'Pages', label: 'Landing', to: '/' },
    { cat: 'Pages', label: 'Marketplace', to: '/marketplace' },
    { cat: 'Pages', label: 'Login', to: '/login' },
    { cat: 'Pages', label: 'Sign up', to: '/signup' },
    { cat: 'Dashboard', label: 'Overview', to: '/dashboard' },
    { cat: 'Dashboard', label: 'My indicators', to: '/dashboard/indicators' },
    { cat: 'Dashboard', label: 'Referrals', to: '/dashboard/referrals' },
    { cat: 'Dashboard', label: 'Billing', to: '/dashboard/billing' },
    { cat: 'Dashboard', label: 'Settings', to: '/dashboard/settings' },
    { cat: 'Admin', label: 'Admin overview', to: '/admin' },
    { cat: 'Admin', label: 'Manage indicators', to: '/admin/indicators' },
    { cat: 'Admin', label: 'Users', to: '/admin/users' },
    { cat: 'Admin', label: 'Orders', to: '/admin/orders' },
    ...INDICATORS.map(i => ({ cat: 'Indicator', label: i.name, to: '/indicator/' + i.slug })),
  ];
  const filtered = all.filter(it => !q || it.label.toLowerCase().includes(q.toLowerCase()) || it.cat.toLowerCase().includes(q.toLowerCase()));
  useEffect(() => { setActive(0); }, [q, open]);
  const go = (it) => { navigate(it.to); setOpen(false); };
  if (!open) return null;
  return (
    <div className="cmdk-backdrop" onClick={() => setOpen(false)}>
      <div className="cmdk" onClick={e => e.stopPropagation()}>
        <div style={{ position: 'relative' }}>
          <span style={{ position: 'absolute', left: 16, top: 17, color: 'var(--muted)' }}><I.search size={16}/></span>
          <input className="cmdk-input" placeholder="Search…" autoFocus
                 style={{ paddingRight: 100 }}
                 value={q} onChange={e => setQ(e.target.value)}
                 onKeyDown={e => {
                   if (e.key === 'ArrowDown') { e.preventDefault(); setActive(a => Math.min(filtered.length - 1, a + 1)); }
                   if (e.key === 'ArrowUp') { e.preventDefault(); setActive(a => Math.max(0, a - 1)); }
                   if (e.key === 'Enter' && filtered[active]) go(filtered[active]);
                 }}/>
          <span className="hide-mobile" style={{ position: 'absolute', right: 14, top: 16, display: 'flex', gap: 4 }}>
            <span className="kbd">↑</span><span className="kbd">↓</span><span className="kbd">↵</span>
          </span>
        </div>
        <div className="cmdk-list" style={{ maxHeight: 'min(400px, 60vh)' }}>
          {filtered.length === 0 && <div style={{ padding: 24, textAlign: 'center', color: 'var(--muted)', fontSize: 13 }}>No results for "{q}"</div>}
          {filtered.map((it, i) => (
            <div key={it.to + i} className={"cmdk-item " + (i === active ? 'active' : '')}
                 onMouseEnter={() => setActive(i)} onClick={() => go(it)}>
              <I.chevR size={13}/>
              <span>{it.label}</span>
              <span className="cmdk-cat">{it.cat}</span>
            </div>
          ))}
        </div>
        <div style={{ padding: '8px 14px', borderTop: '1px solid var(--border)', display: 'flex', justifyContent: 'space-between', fontSize: 11, color: 'var(--muted)' }}>
          <span>{filtered.length} results</span>
          <span><span className="kbd">esc</span> to close</span>
        </div>
      </div>
    </div>
  );
}

/* ───────── Footer ───────── */
function Footer() {
  return (
    <footer className="footer">
      <div className="container" style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fit, minmax(180px, 1fr))', gap: 32 }}>
        <div>
          <Logo size={16}/>
          <p style={{ fontSize: 13, color: 'var(--muted)', marginTop: 12, maxWidth: 260 }}>
            Premium TradingView indicators with automated access binding. Made by traders, for traders.
          </p>
        </div>
        {[
          ['Product', [['Indicators', '/marketplace'], ['Algo Trading', '/algo'], ['Copy Trading', '/copy'], ['Pricing', '/pricing']]],
          ['Resources', [['Docs', '/docs'], ['Getting started', '/docs'], ['Refund policy', '/legal/refund'], ['Changelog', '/docs']]],
          ['Company', [['About', '/about'], ['Affiliates', '/affiliates'], ['Contact', '/contact'], ['Login', '/login']]],
          ['Legal', [['Terms', '/legal/terms'], ['Privacy', '/legal/privacy'], ['Disclaimer', '/legal/refund'], ['Risk', '/legal/terms']]],
        ].map(([h, items]) => (
          <div key={h}>
            <div className="eyebrow" style={{ marginBottom: 12 }}>{h}</div>
            <div style={{ display: 'flex', flexDirection: 'column', gap: 8 }}>
              {items.map(([label, to]) => <Link key={label} to={to} className="mlink" style={{ padding: 0 }}>{label}</Link>)}
            </div>
          </div>
        ))}
      </div>
      <div className="container" style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginTop: 40, paddingTop: 24, borderTop: '1px solid var(--border)', fontSize: 12, color: 'var(--muted)', flexWrap: 'wrap', gap: 12 }}>
        <div>© 2026 Mattobot Labs. All rights reserved.</div>
        <div className="mono">v2.4.1 · all systems operational <span className="live-dot" style={{ display: 'inline-block', verticalAlign: 'middle', marginLeft: 6 }}/></div>
      </div>
    </footer>
  );
}

/* ───────── Marketing top nav ───────── */
function MarketingNav({ onOpenAuth }) {
  const { navigate, path } = useHashRoute();
  const [scrolled, setScrolled] = useState(false);
  const [openMenu, setOpenMenu] = useState(null); // 'indicators' | 'products' | null
  const [mobileOpen, setMobileOpen] = useState(false);
  const closeTimer = useRef(null);

  useEffect(() => {
    const onScroll = () => setScrolled(window.scrollY > 8);
    onScroll();
    window.addEventListener('scroll', onScroll, { passive: true });
    return () => window.removeEventListener('scroll', onScroll);
  }, []);

  // Close mobile drawer on route change
  useEffect(() => { setMobileOpen(false); setOpenMenu(null); }, [path]);

  // Close menu on escape
  useEffect(() => {
    const h = (e) => { if (e.key === 'Escape') { setOpenMenu(null); setMobileOpen(false); } };
    window.addEventListener('keydown', h);
    return () => window.removeEventListener('keydown', h);
  }, []);

  // Lock body scroll when mobile drawer is open
  useEffect(() => {
    if (mobileOpen) document.body.style.overflow = 'hidden';
    else document.body.style.overflow = '';
    return () => { document.body.style.overflow = ''; };
  }, [mobileOpen]);

  const hover = (name) => {
    if (closeTimer.current) clearTimeout(closeTimer.current);
    setOpenMenu(name);
  };
  const leave = () => {
    if (closeTimer.current) clearTimeout(closeTimer.current);
    closeTimer.current = setTimeout(() => setOpenMenu(null), 120);
  };

  const featured = INDICATORS.slice(0, 3);
  const cats = ['Trend', 'Momentum', 'Volume', 'Volatility', 'Mean reversion', 'Smart money'];

  return (
    <>
      <header className={"navbar " + (scrolled ? 'navbar-scrolled' : '') + (mobileOpen ? ' nav-mobile-open' : '')}>
        <div className="container container-wide navbar-inner">
          <div className="navbar-left">
            <Link to="/" className="navbar-logo"><Logo/></Link>
            <nav className="navbar-links hide-mobile">
              <div className="nav-item-wrap"
                   onMouseEnter={() => hover('indicators')}
                   onMouseLeave={leave}>
                <button className={"nlink " + (openMenu === 'indicators' ? 'nlink-active' : '')}
                        onClick={() => navigate('/marketplace')}>
                  Indicators
                  <I.chevR size={11} style={{ transform: 'rotate(90deg)', transition: 'transform .18s var(--ease)', opacity: 0.6 }}/>
                </button>
              </div>
              <div className="nav-item-wrap"
                   onMouseEnter={() => hover('products')}
                   onMouseLeave={leave}>
                <button className={"nlink " + (openMenu === 'products' ? 'nlink-active' : '')}
                        onClick={() => setOpenMenu(m => m === 'products' ? null : 'products')}>
                  Products
                  <I.chevR size={11} style={{ transform: 'rotate(90deg)', transition: 'transform .18s var(--ease)', opacity: 0.6 }}/>
                </button>
              </div>
              <Link to="/affiliates" className="nlink">Affiliates</Link>
              <Link to="/docs" className="nlink">Docs</Link>
              <Link to="/pricing" className="nlink">Pricing</Link>
            </nav>
          </div>

          <div className="navbar-right">
            <button className="nav-search hide-tablet" onClick={() => {
              window.dispatchEvent(new KeyboardEvent('keydown', { key: 'k', metaKey: true }));
            }}>
              <I.search size={14}/>
              <span style={{ color: 'var(--muted)' }}>Search…</span>
              <span className="kbd" style={{ marginLeft: 'auto', height: 20, padding: '0 6px', fontSize: 10 }}>⌘K</span>
            </button>
            <ThemeToggle/>
            <Btn kind="ghost" size="sm" className="hide-mobile" onClick={() => navigate('/login')}>Log in</Btn>
            <Btn kind="primary" size="sm" onClick={() => navigate('/signup')}>
              <span className="hide-mobile">Get started</span>
              <span className="show-mobile">Start</span>
              <I.arrow size={12}/>
            </Btn>
            <button className="nav-burger show-mobile" onClick={() => setMobileOpen(o => !o)} aria-label="Menu">
              <span/><span/><span/>
            </button>
          </div>
        </div>

        {/* Mega menu — Indicators */}
        {openMenu === 'indicators' && (
          <div className="megamenu" onMouseEnter={() => hover('indicators')} onMouseLeave={leave}>
            <div className="container container-wide" style={{ display: 'grid', gridTemplateColumns: '220px 1fr 1.4fr', gap: 32, padding: '24px 24px 28px' }}>
              <div>
                <div className="mm-eyebrow">By category</div>
                <div style={{ display: 'flex', flexDirection: 'column', gap: 2 }}>
                  {cats.map(c => (
                    <button key={c} className="mm-cat" onClick={() => navigate('/marketplace?cat=' + encodeURIComponent(c))}>
                      <span>{c}</span>
                      <I.chevR size={11}/>
                    </button>
                  ))}
                  <div style={{ height: 1, background: 'var(--border)', margin: '8px 0' }}/>
                  <button className="mm-cat mm-cat-accent" onClick={() => navigate('/marketplace')}>
                    <span>Browse all 14</span>
                    <I.arrow size={11}/>
                  </button>
                </div>
              </div>
              <div>
                <div className="mm-eyebrow">Resources</div>
                <div style={{ display: 'flex', flexDirection: 'column', gap: 4 }}>
                  {[
                    ['Getting started', 'Connect TradingView in 30s', I.bolt],
                    ['Strategy library', 'Backtests, scripts, templates', I.book],
                    ['Risk calculator', 'Size positions correctly', I.calc],
                    ['Changelog', "What's shipped this month", I.tag],
                  ].map(([t, d, Ic]) => (
                    <a key={t} className="mm-link" onClick={(e) => { e.preventDefault(); navigate('/docs'); }}>
                      <span className="mm-link-ico"><Ic size={14}/></span>
                      <span>
                        <span className="mm-link-t">{t}</span>
                        <span className="mm-link-d">{d}</span>
                      </span>
                    </a>
                  ))}
                </div>
              </div>
              <div>
                <div className="mm-eyebrow">Featured</div>
                <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 10 }}>
                  {featured.slice(0, 2).map(ind => (
                    <button key={ind.slug} className="mm-feat" onClick={() => navigate('/indicator/' + ind.slug)}>
                      <div className="mm-feat-thumb">
                        <CandleChart seed={ind.seed} w={200} h={84} candles={28} withSignals={false}/>
                      </div>
                      <div style={{ padding: 10 }}>
                        <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', gap: 6 }}>
                          <span style={{ fontWeight: 600, fontSize: 13 }}>{ind.name}</span>
                          <span className="mono" style={{ fontSize: 11, color: 'var(--accent)' }}>${ind.price.lifetime}</span>
                        </div>
                        <div style={{ fontSize: 11, color: 'var(--muted)', marginTop: 2, lineHeight: 1.35 }}>{ind.tagline.slice(0, 60)}…</div>
                      </div>
                    </button>
                  ))}
                </div>
              </div>
            </div>
          </div>
        )}

        {/* Mega menu — Products */}
        {openMenu === 'products' && (
          <div className="megamenu" onMouseEnter={() => hover('products')} onMouseLeave={leave}>
            <div className="container container-wide" style={{ display: 'grid', gridTemplateColumns: 'repeat(3, 1fr)', gap: 16, padding: '20px 24px 24px' }}>
              <button className="mm-prod" onClick={() => navigate('/marketplace')}>
                <span className="mm-prod-ico"><I.chart size={18}/></span>
                <div>
                  <div className="mm-prod-t">Indicators<span className="mm-status mm-status-live">Live</span></div>
                  <div className="mm-prod-d">14 pro-grade Pine Scripts. Auto-bound to your TradingView.</div>
                </div>
              </button>
              <button className="mm-prod" onClick={() => navigate('/algo')}>
                <span className="mm-prod-ico"><I.cpu size={18}/></span>
                <div>
                  <div className="mm-prod-t">Algo trading<span className="mm-status mm-status-soon">Q3 '26</span></div>
                  <div className="mm-prod-d">Run our strategies on auto-pilot through your exchange API.</div>
                </div>
              </button>
              <button className="mm-prod" onClick={() => navigate('/copy')}>
                <span className="mm-prod-ico"><I.users size={18}/></span>
                <div>
                  <div className="mm-prod-t">Copy trading<span className="mm-status mm-status-soon">Q4 '26</span></div>
                  <div className="mm-prod-d">Mirror top desks. Pay performance fees only on profit.</div>
                </div>
              </button>
            </div>
          </div>
        )}
      </header>

      {/* Spacer to compensate for fixed header (height tracks .navbar via --nav-h) */}
      <div className="navbar-spacer"/>

      {/* Mobile drawer */}
      {mobileOpen && (
        <div className="mobile-drawer-backdrop" onClick={() => setMobileOpen(false)}>
          <div className="mobile-drawer" onClick={e => e.stopPropagation()} style={{ paddingTop: 'env(safe-area-inset-top, 0)' }}>
            <div style={{ padding: '18px 20px', borderBottom: '1px solid var(--border)', display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
              <Logo/>
              <button className="btn btn-icon btn-sm" aria-label="Close menu" onClick={() => setMobileOpen(false)}><I.x size={16}/></button>
            </div>
            <div style={{ padding: 16, display: 'flex', flexDirection: 'column', gap: 2, overflowY: 'auto', flex: 1 }}>
              <div className="md-eyebrow">Browse</div>
              <Link to="/marketplace" className="md-link"><I.chart size={14}/> All indicators</Link>
              <Link to="/algo" className="md-link"><I.cpu size={14}/> Algo trading <span className="mm-status mm-status-soon" style={{ marginLeft: 'auto' }}>Soon</span></Link>
              <Link to="/copy" className="md-link"><I.users size={14}/> Copy trading <span className="mm-status mm-status-soon" style={{ marginLeft: 'auto' }}>Soon</span></Link>

              <div className="md-eyebrow" style={{ marginTop: 16 }}>Categories</div>
              {cats.map(c => (
                <a key={c} className="md-link md-link-sub" onClick={() => navigate('/marketplace?cat=' + encodeURIComponent(c))}>
                  <span style={{ width: 14 }}/> {c}
                </a>
              ))}

              <div className="md-eyebrow" style={{ marginTop: 16 }}>Resources</div>
              <Link to="/affiliates" className="md-link"><I.gift size={14}/> Affiliates</Link>
              <Link to="/docs" className="md-link"><I.book size={14}/> Docs</Link>
              <Link to="/pricing" className="md-link"><I.tag size={14}/> Pricing</Link>
            </div>
            <div style={{ padding: 16, borderTop: '1px solid var(--border)', display: 'flex', flexDirection: 'column', gap: 8 }}>
              <Btn onClick={() => navigate('/login')} style={{ width: '100%' }}>Log in</Btn>
              <Btn kind="primary" onClick={() => navigate('/signup')} style={{ width: '100%' }}>Get started <I.arrow size={12}/></Btn>
            </div>
          </div>
        </div>
      )}
    </>
  );
}

/* ───────── Expose ───────── */
Object.assign(window, {
  React, ReactDOM,
  useState, useEffect, useRef, useMemo, useCallback,
  I, Icon, Logo, Btn, Tabs, Spark, CandleChart, TickerRow,
  ThemeContext, ThemeToggle, ToastContext, ToastHost,
  useHashRoute, Link, Stars, IndicatorCard, Footer, MarketingNav,
  INDICATORS, fmt, seedRand, Counter, CommandPalette,
});

})();
/* ===== marketing.jsx ===== */
(function(){
/* Marketing pages: Landing, Marketplace, Indicator detail, Algo, Copy, Affiliates */

const { useState, useEffect, useMemo } = React;

/* ───────── FAQ Components ───────── */
const FAQ_DATA = [
  { cat: 'Account', items: [
    ['How is access granted?', "Pay → confirm on-chain → we automatically add your TradingView username to the indicator's invite-only list. Median time from confirmation to access: 9 seconds."],
    ['Can I change my TradingView username?', "Yes — once every 7 days, per indicator. The dashboard shows your next unlock date with a live countdown. This rate-limit prevents account-sharing abuse."],
    ['What if I lose my TradingView account?', "Open a ticket with proof of purchase. We rebind to your new handle once verified, no extra charge — even outside the 7-day window."],
  ]},
  { cat: 'Billing & refunds', items: [
    ['Which payment methods?', "BTC (native), ETH (ERC20), and USDT on ERC20, TRC20 or BEP20. Card processing lands Q2 — already KYC'd merchants only."],
    ['How long until payment confirms?', "BTC: ~10 min (1 confirmation). ETH/USDT-ERC20: ~30 sec. USDT-TRC20: ~5 sec. We bind your indicator the moment it confirms."],
    ['Do you offer refunds?', "Yes — 7-day money-back guarantee, no questions, if the indicator doesn't work as advertised. After 7 days we issue store credit at our discretion."],
    ['Is there a free trial?', 'Three flagship indicators ship with a 7-day full-feature trial — no card needed, just your TradingView handle. Look for the "Trial" badge on cards.'],
  ]},
  { cat: 'Indicators & signals', items: [
    ['Are signals repainting?', "No. Every signal we ship is non-repainting and confirmed on bar-close. Repainting indicators are explicitly labeled as such in the changelog if we ever ship one for educational use."],
    ['What timeframes do they work on?', "Each indicator's detail page lists tested timeframes. Most work 5m → 1D; scalp-focused tools recommend 1m → 15m only."],
    ['Can I use them on stocks / forex?', "Yes — Pine Script runs on every TradingView market. We tune defaults for crypto but include preset configs for SPX, FX majors, and gold."],
  ]},
  { cat: 'Algo & copy', items: [
    ['When does algo trading launch?', 'Q3 2026. Existing indicator customers get early access two weeks before public launch.'],
    ['When does copy trading launch?', 'Q4 2026. Lead-trader applications open Q3.'],
    ['Will it work with my exchange?', "At launch: Binance, Bybit, OKX, Hyperliquid, Coinbase Advanced. Read-only API keys for monitoring; trade-only keys with no withdrawal permission for execution."],
  ]},
  { cat: 'Affiliates', items: [
    ['How does the referral program work?', "Share your referral link → anyone who signs up under it earns you 10% of every purchase they make, lifetime. Paid in USDT, weekly, no minimums above $10."],
    ['Are there tiers?', "Yes. Once you've referred $5K in volume you graduate to 15%. $25K → 20%. Top referrers get co-marketing slots on our landing page."],
  ]},
];

function FaqAccordion() {
  const [activeCat, setActiveCat] = useState(0);
  const [openIdx, setOpenIdx] = useState(0);
  const items = FAQ_DATA[activeCat].items;
  return (
    <div className="faq-right">
      <div className="faq-tabs">
        {FAQ_DATA.map((c, i) => (
          <button key={c.cat} className={"faq-tab " + (i === activeCat ? 'faq-tab-active' : '')}
                  onClick={() => { setActiveCat(i); setOpenIdx(0); }}>
            {c.cat}
            <span className="faq-tab-count">{c.items.length}</span>
          </button>
        ))}
      </div>
      <div className="faq-list">
        {items.map(([q, a], i) => {
          const open = openIdx === i;
          return (
            <div key={q} className={"faq-item " + (open ? 'faq-item-open' : '')}>
              <button className="faq-q" onClick={() => setOpenIdx(open ? -1 : i)}>
                <span className="faq-q-num">0{i + 1}</span>
                <span className="faq-q-text">{q}</span>
                <span className="faq-q-icon"><I.plus size={14}/></span>
              </button>
              <div className="faq-a-wrap">
                <div className="faq-a">{a}</div>
              </div>
            </div>
          );
        })}
      </div>
    </div>
  );
}

function FaqContact() {
  return (
    <div className="faq-contact">
      <div className="faq-contact-row">
        <span className="faq-contact-ico"><I.bolt size={14}/></span>
        <div>
          <div className="faq-contact-t">Live desk</div>
          <div className="faq-contact-d">Mon–Sun · 04:00–22:00 UTC</div>
        </div>
      </div>
      <div className="faq-contact-row">
        <span className="faq-contact-ico"><I.lock size={14}/></span>
        <div>
          <div className="faq-contact-t">Telegram support</div>
          <div className="faq-contact-d mono">@mattobot_desk</div>
        </div>
      </div>
      <div className="faq-contact-row">
        <span className="faq-contact-ico"><I.inbox size={14}/></span>
        <div>
          <div className="faq-contact-t">Email</div>
          <div className="faq-contact-d mono">desk@mattobot.io</div>
        </div>
      </div>
    </div>
  );
}

/* ───────── Landing ───────── */
function LandingPage() {
  const { navigate } = useHashRoute();
  return (
    <div className="view-enter">
      <MarketingNav/>
      <TickerRow/>

      {/* Hero */}
      <section style={{ position: 'relative', overflow: 'hidden' }}>
        <div className="aurora"/>
        <div className="grid-bg" style={{ position: 'absolute', inset: 0, opacity: 0.35, maskImage: 'radial-gradient(ellipse at 50% 30%, black 30%, transparent 75%)', WebkitMaskImage: 'radial-gradient(ellipse at 50% 30%, black 30%, transparent 75%)' }}/>
        <div className="container container-wide" style={{ position: 'relative', padding: '88px 24px 72px' }}>
          <div style={{ display: 'grid', gridTemplateColumns: 'minmax(0,1fr) minmax(0,1fr)', gap: 48, alignItems: 'center' }} className="hero-grid">
            <div className="reveal">
              <div className="tag-chip" style={{ marginBottom: 24 }}>
                <span className="live-dot"/> v2.4 · Auto-binding now live · <span style={{ color: 'var(--muted)' }}>+14 indicators shipped</span>
              </div>
              <h1 className="h1" style={{ marginTop: 0, marginBottom: 22 }}>
                Indicators that <span style={{ color: 'var(--accent)', fontStyle: 'italic', fontWeight: 500 }}>price the noise</span> out of trading.
              </h1>
              <p style={{ fontSize: 18, color: 'var(--text-2)', maxWidth: 540, marginBottom: 30, lineHeight: 1.5 }}>
                Mattobot ships pro-grade TradingView indicators with auto-bound access — link your handle, pay in crypto, the script is in your library in seconds.
              </p>
              <div style={{ display: 'flex', gap: 10, flexWrap: 'wrap' }}>
                <Btn kind="primary" size="lg" onClick={() => navigate('/marketplace')}>
                  Browse indicators <I.arrow size={14}/>
                </Btn>
                <Btn size="lg" onClick={() => navigate('/indicator/aurora-trend')}>
                  See it live <I.chart size={13}/>
                </Btn>
                <span className="kbd hide-mobile" style={{ height: 44, alignSelf: 'center', padding: '0 10px', fontSize: 11, gap: 4 }}>⌘K to search</span>
              </div>
              <div className="callout-row" style={{ marginTop: 48 }}>
                <div className="reveal reveal-2"><span className="v"><Counter to={12400} suffix="+"/></span><span className="l">active traders</span></div>
                <div className="reveal reveal-3"><span className="v"><Counter to={3.4} decimals={1} suffix="M"/></span><span className="l">signals delivered</span></div>
                <div className="reveal reveal-4"><span className="v"><Counter to={99.98} decimals={2} suffix="%"/></span><span className="l">script delivery</span></div>
              </div>
            </div>

            {/* Right hero panel — mock chart card */}
            <div className="card reveal reveal-2" style={{ padding: 0, overflow: 'hidden', boxShadow: 'var(--shadow-lg)', position: 'relative' }}>
              <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', padding: '12px 14px', borderBottom: '1px solid var(--border)', background: 'var(--bg-2)', flexWrap: 'wrap', gap: 8 }}>
                <div style={{ display: 'flex', alignItems: 'center', gap: 10 }}>
                  <span className="mono" style={{ fontWeight: 600 }}>BTC/USDT</span>
                  <span className="pill pill-up"><span className="dot"/>+1.24%</span>
                  <span className="mono" style={{ color: 'var(--muted)', fontSize: 12 }}>15m · Aurora Trend</span>
                </div>
                <div style={{ display: 'flex', alignItems: 'center', gap: 8 }}>
                  <span className="live-tag"><span className="live-dot"/>LIVE</span>
                  <div style={{ display: 'flex', gap: 4 }}>
                    <span className="kbd">15m</span><span className="kbd">1h</span><span className="kbd">4h</span>
                  </div>
                </div>
              </div>
              <div style={{ height: 'min(380px, 50vh)', minHeight: 220, position: 'relative' }}>
                <CandleChart seed={11} w={760} h={380} candles={70} withSignals={true}/>
                <div className="hide-mobile" style={{ position: 'absolute', top: 14, right: 14, padding: '8px 12px', background: 'oklch(from var(--bg) l c h / 0.85)', border: '1px solid var(--border)', borderRadius: 8, backdropFilter: 'blur(6px)' }}>
                  <div style={{ fontSize: 10.5, color: 'var(--muted)', textTransform: 'uppercase', letterSpacing: 0.06 }}>last signal</div>
                  <div className="mono" style={{ fontSize: 13, fontWeight: 600, color: 'var(--up)' }}>LONG @ 67,412.50</div>
                  <div style={{ fontSize: 10.5, color: 'var(--muted)' }}>2 min ago · +1.8%</div>
                </div>
              </div>
              <div className="hero-card-stats" style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fit, minmax(120px, 1fr))', borderTop: '1px solid var(--border)', background: 'var(--border)', gap: 1 }}>
                {[['Win rate','68.4%','up'],['Sharpe','2.31', null],['Trades','1,240', null],['Max DD','8.2%','down']].map(([l,v,k], i) => (
                  <div key={l} style={{ padding: '14px 14px', background: 'var(--surface)' }}>
                    <div style={{ fontSize: 10.5, color: 'var(--muted)', textTransform: 'uppercase', letterSpacing: 0.06 }}>{l}</div>
                    <div className="mono" style={{ fontSize: 17, fontWeight: 500, color: k === 'up' ? 'var(--up)' : k === 'down' ? 'var(--down)' : 'var(--text)' }}>{v}</div>
                  </div>
                ))}
              </div>
            </div>
          </div>
        </div>
      </section>

      {/* Brands strip */}
      <section style={{ padding: 'clamp(20px, 4vw, 32px) 0', borderTop: '1px solid var(--border)', borderBottom: '1px solid var(--border)' }}>
        <div className="container container-wide" style={{ display: 'flex', alignItems: 'center', gap: 24, flexWrap: 'wrap' }}>
          <span className="eyebrow">Compatible with</span>
          <div className="brands-row" style={{ flex: 1, justifyContent: 'space-around', flexWrap: 'wrap' }}>
            <span>● TRADINGVIEW</span>
            <span>◆ BINANCE</span>
            <span>▲ BYBIT</span>
            <span>◇ OKX</span>
            <span>■ MT5</span>
            <span>◐ KRAKEN</span>
          </div>
        </div>
      </section>

      {/* How it works */}
      <section className="container container-wide" style={{ padding: '80px 24px' }}>
        <div className="section-head">
          <div>
            <div className="eyebrow" style={{ marginBottom: 10 }}>How it works</div>
            <h2 className="h2" style={{ margin: 0 }}>From checkout to chart in 60 seconds.</h2>
          </div>
          <p style={{ maxWidth: 380, color: 'var(--muted)', fontSize: 14 }}>
            We've automated the whole grant flow — your TradingView username gets added to the indicator's invite list immediately after payment.
          </p>
        </div>
        <div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fit, minmax(250px, 1fr))', gap: 16 }}>
          {[
            ['01', 'Pick an indicator', 'Browse the marketplace, read the spec, view live performance.', I.search],
            ['02', 'Pay in crypto', 'BTC, ETH or USDT. We watch the chain, no human in the loop.', I.wallet],
            ['03', 'Bind your TV username', 'Paste your TradingView handle. We push the invite-only grant in <10s.', I.fingerprint],
            ['04', 'Trade', 'Open TradingView. The indicator sits in your Invite-only library.', I.chart],
          ].map(([n, t, d, IconComp]) => (
            <div key={n} className="card" style={{ padding: 20 }}>
              <div style={{ display: 'flex', justifyContent: 'space-between', marginBottom: 16 }}>
                <span className="mono" style={{ color: 'var(--muted)', fontSize: 12 }}>{n}</span>
                <IconComp size={18}/>
              </div>
              <div style={{ fontWeight: 600, fontSize: 16, marginBottom: 6, letterSpacing: '-0.015em' }}>{t}</div>
              <div style={{ color: 'var(--muted)', fontSize: 13.5, lineHeight: 1.5 }}>{d}</div>
            </div>
          ))}
        </div>
      </section>

      {/* Featured indicators */}
      <section className="container container-wide" style={{ padding: '0 24px 80px' }}>
        <div className="section-head">
          <div>
            <div className="eyebrow" style={{ marginBottom: 10 }}>Featured indicators</div>
            <h2 className="h2" style={{ margin: 0 }}>Tools the desks actually use.</h2>
          </div>
          <Btn onClick={() => navigate('/marketplace')}>See all <I.arrow size={13}/></Btn>
        </div>
        <div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fit, minmax(min(100%, 280px), 1fr))', gap: 16 }}>
          {INDICATORS.slice(0, 3).map(ind => (
            <IndicatorCard key={ind.slug} ind={ind} onOpen={(i) => navigate('/indicator/' + i.slug)}/>
          ))}
        </div>
      </section>

      {/* Algo / Copy preview */}
      <section className="container container-wide" style={{ padding: '0 24px 80px' }}>
        <div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fit, minmax(min(100%, 320px), 1fr))', gap: 16 }}>
          {[
            { tag: 'Q3 2026', title: 'Algo Trading', sub: 'Deploy strategies as live bots on Binance, Bybit and OKX. Webhook → execution in <40ms.', cta: 'Join waitlist', href: '/algo', seed: 21 },
            { tag: 'Q4 2026', title: 'Copy Trading', sub: 'Mirror our top performers, automatically. Position-sizing, drawdown caps, instant pause.', cta: 'Join waitlist', href: '/copy', seed: 33 },
          ].map(c => (
            <div key={c.title} className="card locked-card" style={{ padding: 0, overflow: 'hidden', minHeight: 280, position: 'relative' }}>
              <div style={{ height: 180 }}>
                <CandleChart seed={c.seed} w={600} h={180} candles={50}/>
              </div>
              <div style={{ padding: 24, position: 'relative', zIndex: 1 }}>
                <span className="pill pill-warn" style={{ marginBottom: 10 }}>Coming · {c.tag}</span>
                <div style={{ fontSize: 24, fontWeight: 600, letterSpacing: '-0.025em', marginBottom: 6 }}>{c.title}</div>
                <div style={{ color: 'var(--muted)', fontSize: 13.5, marginBottom: 16, maxWidth: 460 }}>{c.sub}</div>
                <Btn onClick={() => navigate(c.href)}>{c.cta} <I.arrow size={13}/></Btn>
              </div>
            </div>
          ))}
        </div>
      </section>

      {/* Referral CTA */}
      <section className="container container-wide" style={{ padding: '0 24px 80px' }}>
        <div className="card" style={{ padding: 40, display: 'grid', gridTemplateColumns: 'repeat(auto-fit, minmax(280px, 1fr))', gap: 32, alignItems: 'center', background: 'var(--surface)' }}>
          <div>
            <div className="eyebrow" style={{ marginBottom: 10 }}>Affiliates</div>
            <h2 className="h2" style={{ margin: 0, marginBottom: 12 }}>Earn 10% on every sale you bring.</h2>
            <p style={{ color: 'var(--muted)', maxWidth: 460, marginBottom: 20 }}>
              Lifetime tracking. Monthly payouts in USDT. No caps, no clawbacks.
            </p>
            <Btn kind="primary" onClick={() => navigate('/signup')}>Become an affiliate <I.arrow size={13}/></Btn>
          </div>
          <div style={{ display: 'grid', gridTemplateColumns: 'repeat(2, 1fr)', gap: 12 }}>
            {[['10%','Lifetime commission'],['Monthly','USDT payouts'],['$0','Minimum payout'],['90 days','Cookie window']].map(([v,l]) => (
              <div key={l} className="stat" style={{ padding: 18 }}>
                <span className="value" style={{ fontSize: 22 }}>{v}</span>
                <span className="label">{l}</span>
              </div>
            ))}
          </div>
        </div>
      </section>

      {/* FAQ */}
      {/* FAQ — split layout, categorized accordion */}
      <section style={{ position: 'relative', borderTop: '1px solid var(--border)', background: 'var(--bg-2)' }}>
        <div className="container container-wide" style={{ padding: '88px 24px 96px' }}>
          <div className="faq-grid">
            {/* Left rail */}
            <aside className="faq-aside">
              <div className="eyebrow" style={{ marginBottom: 14 }}>FAQ</div>
              <h2 className="h2" style={{ margin: '0 0 14px', fontSize: 'clamp(28px, 4vw, 40px)', lineHeight: 1.05 }}>
                Everything you'd ask before <span style={{ color: 'var(--accent)' }}>checkout.</span>
              </h2>
              <p style={{ color: 'var(--text-2)', lineHeight: 1.5, marginBottom: 24 }}>
                If your question isn't here, our desk replies in under 4 minutes during market hours.
              </p>
              <FaqContact/>
            </aside>

            {/* Right accordion */}
            <FaqAccordion/>
          </div>
        </div>
      </section>

      <Footer/>

      <style>{`
        @media (max-width: 900px) {
          .hero-grid { grid-template-columns: 1fr !important; }
        }
      `}</style>
    </div>
  );
}

/* ───────── Marketplace ───────── */
function MarketplacePage() {
  const { navigate } = useHashRoute();
  const [q, setQ] = useState('');
  const [cat, setCat] = useState('All');
  const [sort, setSort] = useState('popular');

  const cats = ['All', 'Trend', 'Volume', 'SMC', 'Momentum', 'Volatility', 'Orderflow'];
  const filtered = INDICATORS
    .filter(i => cat === 'All' || i.cat === cat)
    .filter(i => !q || i.name.toLowerCase().includes(q.toLowerCase()) || i.tagline.toLowerCase().includes(q.toLowerCase()))
    .sort((a,b) => sort === 'price-low' ? a.price.lifetime - b.price.lifetime
                : sort === 'price-high' ? b.price.lifetime - a.price.lifetime
                : sort === 'rating' ? b.rating - a.rating
                : b.reviews - a.reviews);

  return (
    <div className="view-enter">
      <MarketingNav/>
      <section className="container container-wide" style={{ padding: '40px 24px 16px' }}>
        <div className="eyebrow" style={{ marginBottom: 8 }}>Marketplace</div>
        <h1 className="h2" style={{ margin: 0, marginBottom: 8 }}>Indicators</h1>
        <p style={{ color: 'var(--muted)', maxWidth: 600 }}>Browse the full catalog. Every indicator is auto-bound to your TradingView account on purchase.</p>
      </section>
      <section className="container container-wide" style={{ padding: '0 24px 24px' }}>
        <div style={{ display: 'flex', gap: 10, flexWrap: 'wrap', alignItems: 'center', marginBottom: 20 }}>
          <div style={{ position: 'relative', flex: '1 1 220px', minWidth: 0 }}>
            <input className="input" placeholder="Search indicators…" value={q} onChange={e => setQ(e.target.value)}
              style={{ paddingLeft: 36 }}/>
            <span style={{ position: 'absolute', left: 12, top: 13, color: 'var(--muted)' }}><I.search size={14}/></span>
          </div>
          <select className="input" value={sort} onChange={e => setSort(e.target.value)} style={{ width: 'auto', minWidth: 160 }}>
            <option value="popular">Most popular</option>
            <option value="rating">Top rated</option>
            <option value="price-low">Price: low → high</option>
            <option value="price-high">Price: high → low</option>
          </select>
        </div>
        <div style={{ display: 'flex', gap: 6, flexWrap: 'wrap', marginBottom: 24, overflowX: 'auto' }} className="no-scrollbar">
          {cats.map(c => (
            <button key={c} className={"btn btn-sm" + (cat === c ? ' btn-primary' : '')} onClick={() => setCat(c)}>{c}</button>
          ))}
        </div>
        <div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fit, minmax(min(100%, 280px), 1fr))', gap: 16 }}>
          {filtered.map(ind => (
            <IndicatorCard key={ind.slug} ind={ind} onOpen={(i) => navigate('/indicator/' + i.slug)}/>
          ))}
        </div>
        {filtered.length === 0 && (
          <div className="card" style={{ padding: 40, textAlign: 'center', color: 'var(--muted)' }}>
            No indicators match your filters.
          </div>
        )}
      </section>
      <Footer/>
    </div>
  );
}

/* ───────── Indicator detail ───────── */
function IndicatorPage({ slug }) {
  const { navigate } = useHashRoute();
  const ind = INDICATORS.find(i => i.slug === slug) || INDICATORS[0];
  const [plan, setPlan] = useState('lifetime');
  const [tf, setTf] = useState(ind.timeframes[2] || ind.timeframes[0]);
  const [tab, setTab] = useState('overview');

  const planPrice = ind.price[plan];
  const planLabel = { lifetime: 'Lifetime', monthly: '/ month', yearly: '/ year' }[plan];

  return (
    <div className="view-enter">
      <MarketingNav/>
      <section className="container container-wide" style={{ padding: '32px 24px 40px' }}>
        <Link to="/marketplace" className="mlink" style={{ display: 'inline-flex', alignItems: 'center', gap: 6, fontSize: 12, marginBottom: 18 }}>
          <I.chevL size={12}/> All indicators
        </Link>
        <div style={{ display: 'grid', gridTemplateColumns: 'minmax(0, 1fr) 380px', gap: 32 }} className="ind-grid">
          {/* Left col */}
          <div style={{ minWidth: 0 }}>
            <div style={{ display: 'flex', alignItems: 'center', gap: 10, marginBottom: 12, flexWrap: 'wrap' }}>
              <span className="pill pill-accent"><span className="dot"/>{ind.cat}</span>
              {ind.badges.map(b => <span key={b} className="pill"><span className="dot"/>{b}</span>)}
            </div>
            <h1 className="h2" style={{ margin: 0, marginBottom: 10 }}>{ind.name}</h1>
            <p style={{ color: 'var(--text-2)', fontSize: 17, marginBottom: 20, maxWidth: 700 }}>{ind.tagline}</p>
            <div style={{ display: 'flex', alignItems: 'center', gap: '8px 14px', marginBottom: 24, fontSize: 13, color: 'var(--muted)', flexWrap: 'wrap' }}>
              <span style={{ display: 'inline-flex', alignItems: 'center', gap: 6 }}>
                <Stars value={ind.rating}/>
                <span className="mono">{ind.rating}</span>
                <span>({fmt.num(ind.reviews)})</span>
              </span>
              <span>·</span>
              <span><span className="mono">{fmt.num(ind.stats.trades)}</span> trades tracked</span>
              <span>·</span>
              <span>Updated 3 days ago</span>
            </div>

            <div className="card" style={{ padding: 0, overflow: 'hidden', marginBottom: 16 }}>
              <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', padding: '10px 14px', borderBottom: '1px solid var(--border)', background: 'var(--bg-2)', flexWrap: 'wrap', gap: 8 }}>
                <div style={{ display: 'flex', alignItems: 'center', gap: 10 }}>
                  <span className="mono" style={{ fontWeight: 600 }}>BTC/USDT · {tf}</span>
                  <span className="pill"><span className="dot"/>{ind.name}</span>
                </div>
                <div style={{ display: 'flex', gap: 4, flexWrap: 'wrap' }}>
                  {ind.timeframes.map(t => (
                    <button key={t} className={"btn btn-sm " + (t === tf ? 'btn-primary' : 'btn-ghost')} onClick={() => setTf(t)}>{t}</button>
                  ))}
                </div>
              </div>
              <div style={{ height: 'min(380px, 50vh)', minHeight: 220 }}>
                <CandleChart seed={ind.seed} w={760} h={380} candles={70} withSignals={true}/>
              </div>
              <div className="ind-card-stats" style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fit, minmax(120px, 1fr))', borderTop: '1px solid var(--border)', background: 'var(--border)', gap: 1 }}>
                {[['Win rate', ind.stats.winrate + '%'], ['Sharpe', ind.stats.sharpe], ['Trades', fmt.num(ind.stats.trades)], ['Max DD', ind.stats.dd + '%']].map(([l, v]) => (
                  <div key={l} style={{ padding: '14px', background: 'var(--surface)' }}>
                    <div style={{ fontSize: 11, color: 'var(--muted)', textTransform: 'uppercase', letterSpacing: 0.06 }}>{l}</div>
                    <div className="mono" style={{ fontSize: 18, fontWeight: 500 }}>{v}</div>
                  </div>
                ))}
              </div>
            </div>

            <Tabs items={[
              { value: 'overview', label: 'Overview' },
              { value: 'features', label: 'Features' },
              { value: 'reviews', label: 'Reviews' },
              { value: 'changelog', label: 'Changelog' },
            ]} value={tab} onChange={setTab}/>

            <div style={{ marginTop: 20 }}>
              {tab === 'overview' && (
                <div>
                  <p style={{ color: 'var(--text-2)', fontSize: 14.5, lineHeight: 1.65, maxWidth: 720 }}>{ind.description}</p>
                  <div style={{ display: 'flex', flexWrap: 'wrap', gap: 8, marginTop: 14 }}>
                    {ind.markets.map(m => <span key={m} className="pill"><span className="dot"/>{m}</span>)}
                    {ind.timeframes.map(t => <span key={t} className="pill"><span className="dot"/>{t}</span>)}
                  </div>
                </div>
              )}
              {tab === 'features' && (
                <ul style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fit, minmax(260px, 1fr))', gap: 10, padding: 0, listStyle: 'none' }}>
                  {ind.features.map(f => (
                    <li key={f} style={{ display: 'flex', gap: 10, alignItems: 'start', padding: 14, background: 'var(--surface)', border: '1px solid var(--border)', borderRadius: 'var(--r-md)' }}>
                      <span style={{ color: 'var(--accent)', marginTop: 2 }}><I.check size={14}/></span>
                      <span style={{ fontSize: 13.5 }}>{f}</span>
                    </li>
                  ))}
                </ul>
              )}
              {tab === 'reviews' && (
                <div style={{ display: 'flex', flexDirection: 'column', gap: 12 }}>
                  {[
                    ['Marcus T.', 4.5, '2 weeks ago', 'Cleanest trend logic I\'ve used. Replaced 3 indicators with this one.'],
                    ['Aisha R.', 5.0, '1 month ago', 'The MTF confluence is the killer feature. Cuts my false signals in half.'],
                    ['Jonas L.', 4.0, '1 month ago', 'Solid. Wish the alerts were a bit more configurable but it\'s good.'],
                  ].map(([n,r,t,c]) => (
                    <div key={n} className="card" style={{ padding: 16 }}>
                      <div style={{ display: 'flex', justifyContent: 'space-between', marginBottom: 6, gap: 8, flexWrap: 'wrap' }}>
                        <div style={{ display: 'flex', alignItems: 'center', gap: 10, flexWrap: 'wrap' }}>
                          <div style={{ width: 28, height: 28, borderRadius: 999, background: 'var(--surface-2)', display: 'inline-flex', alignItems: 'center', justifyContent: 'center', fontSize: 12, fontWeight: 600, flex: 'none' }}>{n[0]}</div>
                          <span style={{ fontWeight: 500, fontSize: 13 }}>{n}</span>
                          <Stars value={r} size={11}/>
                        </div>
                        <span style={{ color: 'var(--muted)', fontSize: 12, flex: 'none' }}>{t}</span>
                      </div>
                      <p style={{ margin: 0, fontSize: 13.5, color: 'var(--text-2)' }}>{c}</p>
                    </div>
                  ))}
                </div>
              )}
              {tab === 'changelog' && (
                <div style={{ display: 'flex', flexDirection: 'column', gap: 14 }}>
                  {[
                    ['v3.2', 'Apr 22, 2026', 'New: regime-aware exit logic. Improved alert payload schema.'],
                    ['v3.1', 'Mar 04, 2026', 'Added BNB/SOL preset. Fixed repaint on first bar.'],
                    ['v3.0', 'Jan 18, 2026', 'Major rewrite. New Hurst gate. Backtester redesign.'],
                  ].map(([v, d, c]) => (
                    <div key={v} style={{ display: 'flex', gap: 18, paddingBottom: 14, borderBottom: '1px solid var(--border)', flexWrap: 'wrap' }}>
                      <div style={{ minWidth: 100, flex: 'none' }}>
                        <div className="mono" style={{ fontWeight: 600 }}>{v}</div>
                        <div style={{ color: 'var(--muted)', fontSize: 12 }}>{d}</div>
                      </div>
                      <div style={{ fontSize: 13.5, color: 'var(--text-2)', flex: '1 1 220px', minWidth: 0 }}>{c}</div>
                    </div>
                  ))}
                </div>
              )}
            </div>
          </div>

          {/* Right col — sticky purchase */}
          <aside>
            <div className="card" style={{ padding: 22, position: 'sticky', top: 80 }}>
              <div className="eyebrow" style={{ marginBottom: 8 }}>Purchase</div>
              <div style={{ display: 'flex', alignItems: 'baseline', gap: 8, marginBottom: 18 }}>
                <span className="mono" style={{ fontSize: 36, fontWeight: 600, letterSpacing: '-0.03em' }}>{fmt.usd(planPrice)}</span>
                <span style={{ color: 'var(--muted)', fontSize: 13 }}>{planLabel}</span>
              </div>
              <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr 1fr', gap: 6, marginBottom: 18 }}>
                {[['lifetime','Lifetime', ind.price.lifetime],['yearly','Yearly', ind.price.yearly],['monthly','Monthly', ind.price.monthly]].map(([k,l,p]) => (
                  <button key={k} className={"btn btn-sm " + (plan === k ? 'btn-primary' : '')}
                    style={{ flexDirection: 'column', height: 56, gap: 2 }}
                    onClick={() => setPlan(k)}>
                    <span style={{ fontSize: 11, opacity: 0.8 }}>{l}</span>
                    <span className="mono" style={{ fontSize: 13 }}>${p}</span>
                  </button>
                ))}
              </div>
              <Btn kind="primary" size="lg" style={{ width: '100%', justifyContent: 'center' }}
                onClick={() => navigate('/purchase/' + ind.slug + '?plan=' + plan)}>
                Buy & auto-bind <I.arrow size={14}/>
              </Btn>
              <Btn size="sm" kind="ghost" style={{ width: '100%', justifyContent: 'center', marginTop: 8 }}>
                Add to cart
              </Btn>
              <div className="divider" style={{ margin: '20px 0' }}/>
              <div style={{ display: 'flex', flexDirection: 'column', gap: 10, fontSize: 13, color: 'var(--text-2)' }}>
                <div style={{ display: 'flex', gap: 10, alignItems: 'center' }}><I.shield size={14}/> 7-day money-back</div>
                <div style={{ display: 'flex', gap: 10, alignItems: 'center' }}><I.bolt size={14}/> Auto-grant in &lt;10s</div>
                <div style={{ display: 'flex', gap: 10, alignItems: 'center' }}><I.refresh size={14}/> Free updates included</div>
                <div style={{ display: 'flex', gap: 10, alignItems: 'center' }}><I.lock size={14}/> Pay in BTC, ETH, USDT</div>
              </div>
            </div>
          </aside>
        </div>
      </section>
      <Footer/>
      <style>{`
        @media (max-width: 1024px) {
          .ind-grid { grid-template-columns: 1fr !important; }
        }
      `}</style>
    </div>
  );
}

/* ───────── Coming-soon stubs (Algo, Copy, Affiliates, Docs) ───────── */
function ComingSoonPage({ kind }) {
  const meta = {
    algo: { title: 'Algo Trading', tag: 'Q3 2026', sub: 'Turn any indicator alert into a live position. Webhooks, position sizing, exchange-side execution.', seed: 21,
      bullets: ['Connect Binance, Bybit, OKX', 'Webhook alerts → orders in <40ms', 'DCA, scaled entries, trailing exits', 'Drawdown circuit-breakers'] },
    copy: { title: 'Copy Trading', tag: 'Q4 2026', sub: 'Mirror our verified traders with full risk control. One-tap pause, fixed risk per trade.', seed: 33,
      bullets: ['Verified track records (broker-side)', 'Per-trader risk caps', '1-tap pause / unwind', 'Pro & free tiers'] },
    affiliates: { title: 'Affiliates', tag: 'Live', sub: 'Earn 10% on every sale you bring, lifetime. Monthly USDT payouts, no caps.', seed: 17,
      bullets: ['10% lifetime commission', '90-day cookie window', 'Monthly USDT payouts', 'Live dashboard + UTM links'] },
    docs: { title: 'Docs', tag: 'Updated weekly', sub: 'Setup guides, alert payload reference, webhook recipes, troubleshooting.', seed: 9,
      bullets: ['Quickstart', 'TradingView setup', 'Webhook payloads', 'Troubleshooting'] },
  }[kind];
  const { navigate } = useHashRoute();
  return (
    <div className="view-enter">
      <MarketingNav/>
      <section className="container container-wide" style={{ padding: '64px 24px 40px' }}>
        <span className="pill pill-warn" style={{ marginBottom: 16 }}><span className="dot"/>{meta.tag}</span>
        <h1 className="h1" style={{ marginTop: 0, marginBottom: 16, maxWidth: 800 }}>{meta.title}.</h1>
        <p style={{ fontSize: 18, color: 'var(--text-2)', maxWidth: 640, marginBottom: 28 }}>{meta.sub}</p>
        {kind !== 'docs' && kind !== 'affiliates' && (
          <div style={{ display: 'flex', gap: 8, marginBottom: 32, flexWrap: 'wrap' }}>
            <input className="input" placeholder="you@email.com" style={{ flex: '1 1 240px', maxWidth: 320, minWidth: 0 }}/>
            <Btn kind="primary">Join waitlist <I.arrow size={13}/></Btn>
          </div>
        )}
        {kind === 'affiliates' && (
          <Btn kind="primary" size="lg" onClick={() => navigate('/dashboard/referrals')}>Open my dashboard <I.arrow size={14}/></Btn>
        )}
        <div className="card" style={{ marginTop: 40, padding: 0, overflow: 'hidden' }}>
          <div style={{ height: 240 }}>
            <CandleChart seed={meta.seed} w={1000} h={240} candles={80}/>
          </div>
          <div style={{ padding: 24, display: 'grid', gridTemplateColumns: 'repeat(auto-fit, minmax(220px, 1fr))', gap: 18, borderTop: '1px solid var(--border)' }}>
            {meta.bullets.map(b => (
              <div key={b} style={{ display: 'flex', gap: 10, fontSize: 13.5 }}>
                <span style={{ color: 'var(--accent)' }}><I.check size={14}/></span>{b}
              </div>
            ))}
          </div>
        </div>
      </section>
      <Footer/>
    </div>
  );
}

Object.assign(window, { LandingPage, MarketplacePage, IndicatorPage, ComingSoonPage });

})();
/* ===== auth.jsx ===== */
(function(){
/* Auth + Purchase flow */

const { useState, useEffect, useRef, useMemo } = React;

/* ───────── Auth shell — bold split with animated side ───────── */
function AuthShell({ children, sideKind = 'login' }) {
  return (
    <div className="auth-root">
      {/* Left form column */}
      <div className="auth-form-col">
        <div className="auth-form-head">
          <Link to="/" className="auth-back">
            <I.chevL size={12}/> Back to site
          </Link>
          <Link to="/"><Logo/></Link>
        </div>
        <div className="auth-form-body">
          <div style={{ width: '100%', maxWidth: 420 }}>{children}</div>
        </div>
        <div className="auth-form-foot">
          <span>© 2026 Mattobot</span>
          <span className="auth-foot-links">
            <a href="#">Terms</a>
            <a href="#">Privacy</a>
            <a href="#">Status <span className="live-dot"/></a>
          </span>
        </div>
      </div>

      {/* Right showcase column (hidden ≤860px via auth-show-col rule in styles.css) */}
      <div className="auth-show-col">
        <div className="aurora"/>
        <div className="grid-bg" style={{ position: 'absolute', inset: 0, opacity: 0.3 }}/>
        {sideKind === 'login' ? <LoginShowcase/> : <SignupShowcase/>}
      </div>
    </div>
  );
}

/* Animated terminal showcase for login */
function LoginShowcase() {
  const [tickI, setTickI] = useState(0);
  useEffect(() => {
    const t = setInterval(() => setTickI(i => i + 1), 1800);
    return () => clearInterval(t);
  }, []);
  const signals = [
    { sym: 'BTC/USDT', side: 'LONG', px: '67,412.50', pnl: '+1.84%', t: '15m' },
    { sym: 'ETH/USDT', side: 'LONG', px: '3,498.12', pnl: '+0.92%', t: '4h' },
    { sym: 'SOL/USDT', side: 'SHORT', px: '178.40', pnl: '+2.31%', t: '1h' },
    { sym: 'BNB/USDT', side: 'LONG', px: '614.20', pnl: '+0.48%', t: '15m' },
  ];
  const visible = signals.slice(0, 3 + (tickI % 2));
  return (
    <div className="auth-show-inner">
      <div className="auth-show-eyebrow">
        <span className="live-dot"/> Live signal feed · Aurora Trend
      </div>
      <h2 className="auth-show-title">
        Where 12,400+ traders<br/>
        <span style={{ color: 'var(--accent)', fontStyle: 'italic', fontWeight: 500 }}>start their session.</span>
      </h2>

      {/* Mock chart card */}
      <div className="auth-show-card">
        <div className="auth-show-card-head">
          <div style={{ display: 'flex', alignItems: 'center', gap: 8 }}>
            <span className="mono" style={{ fontWeight: 600, fontSize: 13 }}>BTC/USDT</span>
            <span className="pill pill-up" style={{ fontSize: 10 }}><span className="dot"/>+1.84%</span>
          </div>
          <span className="live-tag" style={{ fontSize: 9 }}><span className="live-dot"/>LIVE</span>
        </div>
        <div style={{ height: 180, position: 'relative' }}>
          <CandleChart seed={11 + (tickI % 3)} w={520} h={180} candles={50} withSignals={true}/>
        </div>
      </div>

      {/* Signal stream */}
      <div className="auth-show-stream">
        <div className="auth-show-stream-head">
          <span className="mono" style={{ fontSize: 10.5, color: 'var(--muted)', letterSpacing: 0.06 }}>RECENT SIGNALS</span>
          <span className="mono" style={{ fontSize: 10, color: 'var(--up)' }}>● {visible.length} ACTIVE</span>
        </div>
        {visible.map((s, i) => (
          <div key={s.sym + i} className="auth-show-row" style={{ animationDelay: (i * 60) + 'ms' }}>
            <span className={"auth-show-side auth-show-side-" + s.side.toLowerCase()}>{s.side}</span>
            <span className="mono" style={{ fontSize: 12, fontWeight: 600 }}>{s.sym}</span>
            <span className="mono" style={{ fontSize: 11, color: 'var(--muted)' }}>{s.t}</span>
            <span className="mono" style={{ fontSize: 11.5, marginLeft: 'auto' }}>{s.px}</span>
            <span className="mono" style={{ fontSize: 11.5, color: 'var(--up)', minWidth: 56, textAlign: 'right' }}>{s.pnl}</span>
          </div>
        ))}
      </div>

      <div className="auth-show-stats">
        <div><div className="v">12.4K</div><div className="l">Active traders</div></div>
        <div><div className="v">3.4M</div><div className="l">Signals shipped</div></div>
        <div><div className="v">99.98%</div><div className="l">Uptime</div></div>
      </div>
    </div>
  );
}

/* Showcase for signup — value props with chart background */
function SignupShowcase() {
  return (
    <div className="auth-show-inner">
      <div className="auth-show-eyebrow">
        <span className="live-dot"/> Free forever · No card needed
      </div>
      <h2 className="auth-show-title">
        Three steps,<br/>
        <span style={{ color: 'var(--accent)', fontStyle: 'italic', fontWeight: 500 }}>then you trade.</span>
      </h2>

      <div className="auth-onboard">
        {[
          ['01', 'Create account', 'Email + TradingView handle. 30 seconds.'],
          ['02', 'Browse the marketplace', '14 indicators, every category, full backtests visible.'],
          ['03', 'Pay in crypto', 'BTC, ETH, USDT. Indicator binds in seconds.'],
        ].map(([n, t, d]) => (
          <div key={n} className="auth-onboard-row">
            <div className="auth-onboard-num">{n}</div>
            <div>
              <div className="auth-onboard-t">{t}</div>
              <div className="auth-onboard-d">{d}</div>
            </div>
          </div>
        ))}
      </div>

      <div className="auth-quote">
        <div className="auth-quote-stars">
          {[1,2,3,4,5].map(i => <span key={i}>★</span>)}
        </div>
        <blockquote className="auth-quote-text">
          The auto-binding is the difference. Pay, refresh TradingView, the indicator's there. No DMs to chase. No screenshots to send.
        </blockquote>
        <div className="auth-quote-by">
          <div className="auth-avatar">MK</div>
          <div>
            <div style={{ fontSize: 13, fontWeight: 600 }}>Marcus K.</div>
            <div style={{ fontSize: 11.5, color: 'var(--muted)' }}>Crypto desk · Lifetime customer</div>
          </div>
        </div>
      </div>
    </div>
  );
}

/* Custom input with floating label and icon */
function AInput({ label, icon, type = 'text', value, onChange, required, placeholder, prefix, hint, action }) {
  const [focus, setFocus] = useState(false);
  const filled = value && value.length > 0;
  return (
    <div className="ainput-wrap">
      <div className={"ainput " + (focus ? 'ainput-focus' : '') + (filled ? ' ainput-filled' : '')}>
        {icon && <span className="ainput-ico">{icon}</span>}
        {prefix && <span className="ainput-prefix">{prefix}</span>}
        <div className="ainput-field">
          <label className="ainput-label">{label}</label>
          <input
            type={type}
            value={value}
            onChange={e => onChange(e.target.value)}
            onFocus={() => setFocus(true)}
            onBlur={() => setFocus(false)}
            required={required}
            placeholder={focus ? placeholder : ''}
          />
        </div>
        {action}
      </div>
      {hint && <span className="ainput-hint">{hint}</span>}
    </div>
  );
}

/* ───────── Login ───────── */
function LoginPage() {
  const { navigate } = useHashRoute();
  const { toast } = React.useContext(ToastContext);
  const [email, setEmail] = useState('trader@mattobot.io');
  const [pw, setPw] = useState('');
  const [showPw, setShowPw] = useState(false);
  const [loading, setLoading] = useState(false);

  const submit = (e) => {
    e.preventDefault();
    setLoading(true);
    setTimeout(() => { toast('Welcome back, Marcus.'); navigate('/dashboard'); }, 600);
  };

  return (
    <AuthShell sideKind="login">
      <h1 className="auth-h">Welcome back.</h1>
      <p className="auth-sub">Log in to access your trader dashboard.</p>

      {/* Social */}
      <div className="auth-social">
        <button type="button" className="auth-social-btn">
          <svg width="16" height="16" viewBox="0 0 24 24"><path fill="#4285F4" d="M22.56 12.25c0-.78-.07-1.53-.2-2.25H12v4.26h5.92c-.26 1.37-1.04 2.53-2.21 3.31v2.77h3.57c2.08-1.92 3.28-4.74 3.28-8.09z"/><path fill="#34A853" d="M12 23c2.97 0 5.46-.98 7.28-2.66l-3.57-2.77c-.98.66-2.23 1.06-3.71 1.06-2.86 0-5.29-1.93-6.16-4.53H2.18v2.84C3.99 20.53 7.7 23 12 23z"/><path fill="#FBBC05" d="M5.84 14.09c-.22-.66-.35-1.36-.35-2.09s.13-1.43.35-2.09V7.07H2.18C1.43 8.55 1 10.22 1 12s.43 3.45 1.18 4.93l2.85-2.22z"/><path fill="#EA4335" d="M12 5.38c1.62 0 3.06.56 4.21 1.64l3.15-3.15C17.45 2.09 14.97 1 12 1 7.7 1 3.99 3.47 2.18 7.07l3.66 2.84c.87-2.6 3.3-4.53 6.16-4.53z"/></svg>
          Google
        </button>
        <button type="button" className="auth-social-btn">
          <svg width="14" height="14" viewBox="0 0 24 24" fill="currentColor"><path d="M18.244 2.25h3.308l-7.227 8.26 8.502 11.24H16.17l-5.214-6.817L4.99 21.75H1.68l7.73-8.835L1.254 2.25H8.08l4.713 6.231zm-1.161 17.52h1.833L7.084 4.126H5.117z"/></svg>
          X / Twitter
        </button>
      </div>

      <div className="auth-divider"><span>or with email</span></div>

      <form onSubmit={submit} style={{ display: 'flex', flexDirection: 'column', gap: 14 }}>
        <AInput
          label="Email address"
          type="email"
          icon={<I.inbox size={15}/>}
          value={email}
          onChange={setEmail}
          required
          placeholder="you@example.com"
        />
        <AInput
          label="Password"
          type={showPw ? 'text' : 'password'}
          icon={<I.lock size={15}/>}
          value={pw}
          onChange={setPw}
          required
          placeholder="••••••••"
          action={
            <button type="button" className="ainput-action" onClick={() => setShowPw(s => !s)} aria-label={showPw ? 'Hide password' : 'Show password'}>
              {showPw ? <I.eyeOff size={15}/> : <I.eye size={15}/>}
            </button>
          }
        />
        <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginTop: -4, marginBottom: 8 }}>
          <label style={{ display: 'flex', alignItems: 'center', gap: 8, fontSize: 13, color: 'var(--text-2)', cursor: 'pointer' }}>
            <input type="checkbox" defaultChecked style={{ accentColor: 'var(--accent)' }}/>
            Keep me signed in
          </label>
          <a href="#" style={{ fontSize: 13, color: 'var(--accent)', textDecoration: 'none' }}>Forgot?</a>
        </div>
        <Btn kind="primary" size="lg" type="submit" disabled={loading} style={{ justifyContent: 'center' }}>
          {loading ? (
            <><span className="auth-spinner"/> Logging in…</>
          ) : (
            <>Log in <I.arrow size={14}/></>
          )}
        </Btn>
      </form>

      <p className="auth-switch">
        New to Mattobot? <Link to="/signup">Create an account</Link>
      </p>
    </AuthShell>
  );
}

/* ───────── Signup ───────── */
function SignupPage() {
  const { navigate } = useHashRoute();
  const { toast } = React.useContext(ToastContext);
  const [data, setData] = useState({ email: '', pw: '', tv: '', ref: '' });
  const set = (k) => (v) => setData(d => ({ ...d, [k]: v }));
  const [agreed, setAgreed] = useState(true);
  const [showPw, setShowPw] = useState(false);
  const [loading, setLoading] = useState(false);

  // Password strength (super simple)
  const score = useMemo(() => {
    let s = 0;
    if (data.pw.length >= 8) s++;
    if (/[A-Z]/.test(data.pw)) s++;
    if (/[0-9]/.test(data.pw)) s++;
    if (/[^a-zA-Z0-9]/.test(data.pw)) s++;
    return s;
  }, [data.pw]);
  const strength = ['', 'Weak', 'Fair', 'Good', 'Strong'][score];
  const strengthColor = ['var(--border)', 'var(--down)', 'var(--warn)', 'var(--info)', 'var(--up)'][score];

  const submit = (e) => {
    e.preventDefault();
    setLoading(true);
    setTimeout(() => { toast('Account created. Welcome.'); navigate('/dashboard'); }, 700);
  };

  return (
    <AuthShell sideKind="signup">
      <h1 className="auth-h">Create your account.</h1>
      <p className="auth-sub">Free forever. No card required.</p>

      <div className="auth-social">
        <button type="button" className="auth-social-btn">
          <svg width="16" height="16" viewBox="0 0 24 24"><path fill="#4285F4" d="M22.56 12.25c0-.78-.07-1.53-.2-2.25H12v4.26h5.92c-.26 1.37-1.04 2.53-2.21 3.31v2.77h3.57c2.08-1.92 3.28-4.74 3.28-8.09z"/><path fill="#34A853" d="M12 23c2.97 0 5.46-.98 7.28-2.66l-3.57-2.77c-.98.66-2.23 1.06-3.71 1.06-2.86 0-5.29-1.93-6.16-4.53H2.18v2.84C3.99 20.53 7.7 23 12 23z"/><path fill="#FBBC05" d="M5.84 14.09c-.22-.66-.35-1.36-.35-2.09s.13-1.43.35-2.09V7.07H2.18C1.43 8.55 1 10.22 1 12s.43 3.45 1.18 4.93l2.85-2.22z"/><path fill="#EA4335" d="M12 5.38c1.62 0 3.06.56 4.21 1.64l3.15-3.15C17.45 2.09 14.97 1 12 1 7.7 1 3.99 3.47 2.18 7.07l3.66 2.84c.87-2.6 3.3-4.53 6.16-4.53z"/></svg>
          Google
        </button>
        <button type="button" className="auth-social-btn">
          <svg width="14" height="14" viewBox="0 0 24 24" fill="currentColor"><path d="M18.244 2.25h3.308l-7.227 8.26 8.502 11.24H16.17l-5.214-6.817L4.99 21.75H1.68l7.73-8.835L1.254 2.25H8.08l4.713 6.231zm-1.161 17.52h1.833L7.084 4.126H5.117z"/></svg>
          X / Twitter
        </button>
      </div>

      <div className="auth-divider"><span>or with email</span></div>

      <form onSubmit={submit} style={{ display: 'flex', flexDirection: 'column', gap: 14 }}>
        <AInput
          label="Email address"
          type="email"
          icon={<I.inbox size={15}/>}
          value={data.email}
          onChange={set('email')}
          required
          placeholder="you@example.com"
        />
        <div>
          <AInput
            label="Password"
            type={showPw ? 'text' : 'password'}
            icon={<I.lock size={15}/>}
            value={data.pw}
            onChange={set('pw')}
            required
            placeholder="At least 8 characters"
            action={
              <button type="button" className="ainput-action" onClick={() => setShowPw(s => !s)}>
                {showPw ? <I.eyeOff size={15}/> : <I.eye size={15}/>}
              </button>
            }
          />
          {data.pw && (
            <div className="pw-strength">
              <div className="pw-strength-bars">
                {[1,2,3,4].map(i => (
                  <div key={i} style={{ background: i <= score ? strengthColor : 'var(--border)' }}/>
                ))}
              </div>
              <span className="pw-strength-label" style={{ color: strengthColor }}>{strength}</span>
            </div>
          )}
        </div>
        <AInput
          label="TradingView username"
          icon={<I.chart size={15}/>}
          value={data.tv}
          onChange={set('tv')}
          placeholder="yourtvhandle"
          prefix="@"
          hint="Optional now — required before your first purchase. Changeable once / 7 days."
        />
        <AInput
          label="Referral code"
          icon={<I.gift size={15}/>}
          value={data.ref}
          onChange={set('ref')}
          placeholder="MATTO-XXXX"
          hint="Got a code from a friend? They earn 10% of your purchases for life."
        />
        <label style={{ display: 'flex', gap: 10, alignItems: 'flex-start', fontSize: 12.5, color: 'var(--text-2)', cursor: 'pointer', marginTop: 4 }}>
          <input type="checkbox" checked={agreed} onChange={e => setAgreed(e.target.checked)} style={{ accentColor: 'var(--accent)', marginTop: 2 }}/>
          <span>
            I agree to Mattobot's <a href="#" style={{ color: 'var(--accent)' }}>Terms</a> and <a href="#" style={{ color: 'var(--accent)' }}>Privacy Policy</a>. I understand this is not financial advice.
          </span>
        </label>
        <Btn kind="primary" size="lg" type="submit" disabled={loading || !agreed} style={{ justifyContent: 'center' }}>
          {loading ? (
            <><span className="auth-spinner"/> Creating account…</>
          ) : (
            <>Create account <I.arrow size={14}/></>
          )}
        </Btn>
      </form>

      <p className="auth-switch">
        Already have an account? <Link to="/login">Log in</Link>
      </p>
    </AuthShell>
  );
}

/* ───────── Purchase flow ───────── */
function PurchasePage({ slug, plan: initialPlan }) {
  const { navigate } = useHashRoute();
  const { toast } = React.useContext(ToastContext);
  const ind = INDICATORS.find(i => i.slug === slug) || INDICATORS[0];
  const [step, setStep] = useState(1); // 1 plan, 2 tv, 3 pay, 4 done
  const [plan, setPlan] = useState(initialPlan || 'lifetime');
  const [coin, setCoin] = useState('USDT');
  const [tv, setTv] = useState('');
  const [coupon, setCoupon] = useState('');
  const [paying, setPaying] = useState(false);

  const price = ind.price[plan];
  const planLabel = { lifetime: 'Lifetime', monthly: 'Monthly', yearly: 'Yearly' }[plan];

  const coinAddr = {
    BTC: 'bc1qmt9vk2yc4n0xj7d5p8mz3a4kj9hl3qr5xnt0w6',
    ETH: '0x9bA3f1c7E5dA6BaEc4Df8a9d2B8c1F0e3D5a7C8b',
    USDT: 'TJrYbCqJk5h8FzG1nW2V3aMpL9eX4dZQ7K (TRC20)',
  };
  const coinAmt = {
    BTC: (price / 67412.5).toFixed(8),
    ETH: (price / 3498.12).toFixed(6),
    USDT: price.toFixed(2),
  };

  const goPay = () => {
    setPaying(true);
    setTimeout(() => { setPaying(false); setStep(4); toast('Payment confirmed. Indicator granted.'); }, 2400);
  };

  return (
    <div className="view-enter">
      <MarketingNav/>
      <section className="container" style={{ padding: '32px 24px 80px', maxWidth: 1080 }}>
        <Link to={"/indicator/" + ind.slug} className="mlink" style={{ display: 'inline-flex', alignItems: 'center', gap: 6, fontSize: 12, marginBottom: 18 }}>
          <I.chevL size={12}/> Back to indicator
        </Link>
        <div className="steps" style={{ marginBottom: 28 }}>
          {[
            { n: 1, l: 'Plan' }, { n: 2, l: 'TradingView' }, { n: 3, l: 'Payment' }, { n: 4, l: 'Done' },
          ].map((s, i, arr) => (
            <React.Fragment key={s.n}>
              <div className={"step " + (step === s.n ? 'active' : step > s.n ? 'done' : '')}>
                <span className="num">{step > s.n ? <I.check size={11}/> : s.n}</span>
                <span>{s.l}</span>
              </div>
              {i < arr.length - 1 && <div className="sep"/>}
            </React.Fragment>
          ))}
        </div>

        <div style={{ display: 'grid', gridTemplateColumns: 'minmax(0,1fr) 360px', gap: 24 }} className="purchase-grid">
          <div className="card" style={{ padding: 28 }}>
            {step === 1 && (
              <div>
                <div className="eyebrow">Step 1</div>
                <h2 className="h3" style={{ margin: '4px 0 18px' }}>Choose your plan</h2>
                <div style={{ display: 'flex', flexDirection: 'column', gap: 10 }}>
                  {[
                    ['lifetime', 'Lifetime', ind.price.lifetime, 'One-time payment. Forever access.', 'Best value'],
                    ['yearly', 'Yearly', ind.price.yearly, 'Billed once a year. Cancel anytime.', null],
                    ['monthly', 'Monthly', ind.price.monthly, 'Billed monthly. Cancel anytime.', null],
                  ].map(([k,l,p,d,b]) => (
                    <button key={k} onClick={() => setPlan(k)}
                      style={{ textAlign: 'left', padding: 18, border: '1px solid ' + (plan === k ? 'var(--accent)' : 'var(--border)'), borderRadius: 'var(--r-md)', background: plan === k ? 'var(--accent-soft)' : 'var(--surface)', display: 'flex', justifyContent: 'space-between', alignItems: 'center', cursor: 'pointer', gap: 16, flexWrap: 'wrap' }}>
                      <div style={{ minWidth: 0 }}>
                        <div style={{ display: 'flex', alignItems: 'center', gap: 8, flexWrap: 'wrap' }}>
                          <span style={{ fontWeight: 600, fontSize: 15 }}>{l}</span>
                          {b && <span className="pill pill-accent" style={{ fontSize: 10.5 }}>{b}</span>}
                        </div>
                        <div style={{ fontSize: 13, color: 'var(--muted)', marginTop: 2 }}>{d}</div>
                      </div>
                      <div style={{ textAlign: 'right', flex: 'none' }}>
                        <div className="mono" style={{ fontSize: 22, fontWeight: 600 }}>${p}</div>
                        <div style={{ fontSize: 11, color: 'var(--muted)' }}>{k === 'lifetime' ? 'one-time' : k === 'yearly' ? '/ year' : '/ month'}</div>
                      </div>
                    </button>
                  ))}
                </div>
                <Btn kind="primary" size="lg" style={{ marginTop: 20, width: '100%', justifyContent: 'center' }} onClick={() => setStep(2)}>
                  Continue <I.arrow size={14}/>
                </Btn>
              </div>
            )}

            {step === 2 && (
              <div>
                <div className="eyebrow">Step 2</div>
                <h2 className="h3" style={{ margin: '4px 0 6px' }}>Bind your TradingView</h2>
                <p style={{ color: 'var(--muted)', fontSize: 13.5, marginBottom: 18 }}>
                  We'll add this username to the indicator's invite-only list as soon as payment confirms.
                </p>
                <div className="field" style={{ marginBottom: 14 }}>
                  <label className="field-label">TradingView username</label>
                  <div style={{ position: 'relative' }}>
                    <span style={{ position: 'absolute', left: 12, top: 11, color: 'var(--muted)' }}>@</span>
                    <input className="input" placeholder="yourtvhandle" value={tv} onChange={e => setTv(e.target.value)} style={{ paddingLeft: 26 }} autoCapitalize="off" autoCorrect="off" spellCheck="false" inputMode="text"/>
                  </div>
                  <span className="field-help">You can change this once every 7 days for security reasons.</span>
                </div>
                <div className="card" style={{ padding: 14, background: 'var(--bg-2)', display: 'flex', gap: 10, fontSize: 13, color: 'var(--text-2)' }}>
                  <I.shield size={14}/>
                  <div>Your username is only used to grant indicator access. We never post or message from your account.</div>
                </div>
                <div style={{ display: 'flex', gap: 8, marginTop: 20, flexWrap: 'wrap' }}>
                  <Btn onClick={() => setStep(1)}>Back</Btn>
                  <Btn kind="primary" size="lg" style={{ flex: '1 1 200px', justifyContent: 'center' }} onClick={() => setStep(3)} disabled={!tv}>
                    Continue to payment <I.arrow size={14}/>
                  </Btn>
                </div>
              </div>
            )}

            {step === 3 && (
              <div>
                <div className="eyebrow">Step 3</div>
                <h2 className="h3" style={{ margin: '4px 0 18px' }}>Pay with crypto</h2>
                <div style={{ display: 'grid', gridTemplateColumns: 'repeat(3, 1fr)', gap: 8, marginBottom: 18 }}>
                  {['USDT', 'BTC', 'ETH'].map(c => (
                    <button key={c} onClick={() => setCoin(c)}
                      className={"btn " + (coin === c ? 'btn-primary' : '')}
                      style={{ height: 46, justifyContent: 'center' }}>
                      <span className="mono">{c}</span>
                    </button>
                  ))}
                </div>
                <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', padding: '12px 14px', background: 'var(--bg-2)', border: '1px solid var(--border)', borderRadius: 'var(--r-md)', marginBottom: 10 }}>
                  <div>
                    <div style={{ fontSize: 11, color: 'var(--muted)', textTransform: 'uppercase', letterSpacing: 0.06 }}>Amount due</div>
                    <div className="mono" style={{ fontSize: 18, fontWeight: 600 }}>{coinAmt[coin]} <span style={{ fontSize: 12, color: 'var(--muted)' }}>{coin}</span></div>
                  </div>
                  <div style={{ textAlign: 'right' }}>
                    <div style={{ fontSize: 11, color: 'var(--muted)' }}>≈ {fmt.usd(price)}</div>
                    <div style={{ fontSize: 11, color: 'var(--muted)' }}>locked for 14:53</div>
                  </div>
                </div>
                <div className="field" style={{ marginBottom: 14 }}>
                  <label className="field-label">Send to address ({coin})</label>
                  <div style={{ display: 'flex', gap: 6 }}>
                    <input className="input mono" readOnly value={coinAddr[coin]} style={{ fontSize: 12, flex: 1, minWidth: 0 }}/>
                    <Btn onClick={() => { navigator.clipboard?.writeText(coinAddr[coin]); toast('Address copied'); }}><I.copy size={14}/></Btn>
                  </div>
                </div>
                <div style={{ display: 'flex', gap: 14, padding: 16, background: 'var(--bg-2)', borderRadius: 'var(--r-md)', border: '1px solid var(--border)', marginBottom: 16 }}>
                  {/* Mock QR */}
                  <div style={{ width: 96, height: 96, flex: 'none', background: 'var(--surface)', borderRadius: 8, padding: 6 }}>
                    <div style={{
                      width: '100%', height: '100%',
                      backgroundImage: `repeating-conic-gradient(var(--text) 0 12.5%, transparent 12.5% 25%)`,
                      backgroundSize: '20px 20px', backgroundColor: 'var(--surface-2)', borderRadius: 4,
                      filter: 'contrast(2.5)'
                    }}/>
                  </div>
                  <div style={{ fontSize: 12.5, color: 'var(--text-2)' }}>
                    <div style={{ fontWeight: 600, marginBottom: 4, color: 'var(--text)' }}>Watching the chain…</div>
                    Send the exact amount shown above. We confirm after 1 block ({coin === 'BTC' ? '~10m' : coin === 'ETH' ? '~30s' : '~3s'}). Indicator access is granted automatically.
                  </div>
                </div>
                <div style={{ display: 'flex', gap: 8, flexWrap: 'wrap' }}>
                  <Btn onClick={() => setStep(2)}>Back</Btn>
                  <Btn kind="primary" size="lg" style={{ flex: '1 1 200px', justifyContent: 'center' }} disabled={paying} onClick={goPay}>
                    {paying ? 'Confirming on-chain…' : <>I've sent the payment <I.arrow size={14}/></>}
                  </Btn>
                </div>
                {paying && <div className="bar" style={{ marginTop: 14 }}><div style={{ width: '70%', animation: 'shimmer 1.5s linear infinite' }}/></div>}
              </div>
            )}

            {step === 4 && (
              <div style={{ textAlign: 'center', padding: '20px 0' }}>
                <div style={{ width: 56, height: 56, borderRadius: 999, background: 'var(--accent-soft)', display: 'inline-flex', alignItems: 'center', justifyContent: 'center', marginBottom: 16, color: 'var(--accent)' }}>
                  <I.check size={28}/>
                </div>
                <h2 className="h2" style={{ margin: 0, marginBottom: 8 }}>You're in.</h2>
                <p style={{ color: 'var(--muted)', maxWidth: 460, margin: '0 auto 24px' }}>
                  <strong style={{ color: 'var(--text)' }}>{ind.name}</strong> has been added to <span className="mono">@{tv || 'your-tv'}</span>'s invite-only library. Open TradingView and refresh to see it.
                </p>
                <div style={{ display: 'flex', gap: 8, justifyContent: 'center', flexWrap: 'wrap' }}>
                  <Btn kind="primary" size="lg" onClick={() => navigate('/dashboard/indicators')}>Open dashboard <I.arrow size={14}/></Btn>
                  <Btn size="lg" as="a" href="https://www.tradingview.com" target="_blank" rel="noopener">Launch TradingView <I.external size={13}/></Btn>
                </div>
              </div>
            )}
          </div>

          {/* Order summary */}
          <aside className="purchase-summary">
            <div className="card" style={{ padding: 'clamp(16px, 4vw, 22px)' }}>
              <div className="eyebrow" style={{ marginBottom: 14 }}>Order summary</div>
              <div style={{ display: 'flex', gap: 12, marginBottom: 16, paddingBottom: 16, borderBottom: '1px solid var(--border)' }}>
                <div style={{ width: 64, height: 48, borderRadius: 6, overflow: 'hidden', background: 'var(--bg-2)', flex: 'none' }}>
                  <CandleChart seed={ind.seed} w={64} h={48} candles={20} withVolume={false}/>
                </div>
                <div>
                  <div style={{ fontWeight: 600, fontSize: 14 }}>{ind.name}</div>
                  <div style={{ fontSize: 12, color: 'var(--muted)' }}>{planLabel} plan</div>
                </div>
              </div>
              <div style={{ display: 'flex', flexDirection: 'column', gap: 10, fontSize: 13 }}>
                <div style={{ display: 'flex', justifyContent: 'space-between' }}><span style={{ color: 'var(--muted)' }}>Subtotal</span><span className="mono">{fmt.usd(price)}</span></div>
                <div style={{ display: 'flex', justifyContent: 'space-between' }}><span style={{ color: 'var(--muted)' }}>Network fee</span><span className="mono">$0.00</span></div>
                <div style={{ display: 'flex', justifyContent: 'space-between' }}><span style={{ color: 'var(--muted)' }}>Discount</span><span className="mono" style={{ color: 'var(--up)' }}>—</span></div>
              </div>
              <div className="divider" style={{ margin: '14px 0' }}/>
              <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'baseline' }}>
                <span style={{ fontWeight: 600 }}>Total</span>
                <span className="mono" style={{ fontSize: 22, fontWeight: 600 }}>{fmt.usd(price)}</span>
              </div>
              <div style={{ display: 'flex', gap: 6, marginTop: 16 }}>
                <input className="input" placeholder="Coupon" value={coupon} onChange={e => setCoupon(e.target.value)} style={{ height: 36, flex: 1, minWidth: 0 }}/>
                <Btn>Apply</Btn>
              </div>
              <div style={{ marginTop: 16, padding: 12, background: 'var(--bg-2)', borderRadius: 'var(--r-md)', fontSize: 12, color: 'var(--muted)', display: 'flex', gap: 8 }}>
                <I.shield size={14}/> 7-day money-back guarantee. Cancel anytime.
              </div>
            </div>
          </aside>
        </div>
      </section>
      <style>{`
        @media (max-width: 860px) { .purchase-grid { grid-template-columns: 1fr !important; } }
        @media (min-width: 861px) { .purchase-summary > .card { position: sticky; top: 80px; } }
      `}</style>
    </div>
  );
}

Object.assign(window, { LoginPage, SignupPage, PurchasePage });

})();
/* ===== dashboard.jsx ===== */
(function(){
/* Dashboard (customer) — Overview, Indicators, Referrals, Billing, Settings + Algo/Copy soon */

const { useState, useEffect, useMemo } = React;

const OWNED = [
  { slug: 'aurora-trend',     plan: 'Lifetime', purchased: '2026-03-14', status: 'active', signals: 142, lastSignal: '2m ago' },
  { slug: 'volume-profile-pro', plan: 'Yearly', purchased: '2026-04-01', status: 'active', signals: 96,  lastSignal: '12m ago' },
  { slug: 'liquidity-grid',   plan: 'Monthly', purchased: '2026-04-22', status: 'active', signals: 38,  lastSignal: '1h ago' },
];

/* ───────── Sidebar ───────── */
function DashSidebar({ open, setOpen, role = 'customer' }) {
  const { path, navigate } = useHashRoute();
  const items = role === 'admin' ? [
    { section: 'Admin' },
    { to: '/admin', label: 'Overview', i: I.chart },
    { to: '/admin/indicators', label: 'Indicators', i: I.layers },
    { to: '/admin/users', label: 'Users', i: I.users },
    { to: '/admin/orders', label: 'Orders', i: I.receipt },
    { to: '/admin/affiliates', label: 'Affiliates', i: I.dollar },
    { to: '/admin/settings', label: 'Settings', i: I.cog },
  ] : [
    { section: 'Trading' },
    { to: '/dashboard', label: 'Overview', i: I.chart },
    { to: '/dashboard/indicators', label: 'My indicators', i: I.layers, badge: '3' },
    { to: '/dashboard/algo', label: 'Algo trading', i: I.bolt, soon: true },
    { to: '/dashboard/copy', label: 'Copy trading', i: I.users, soon: true },
    { section: 'Account' },
    { to: '/dashboard/referrals', label: 'Referrals', i: I.dollar },
    { to: '/dashboard/billing', label: 'Billing', i: I.receipt },
    { to: '/dashboard/settings', label: 'Settings', i: I.cog },
  ];
  return (
    <>
      {open && <div className="mobile-nav-overlay show-mobile" onClick={() => setOpen(false)}/>}
      <aside className={"side " + (open ? 'open' : '')}>
        <div style={{ padding: '0 6px 18px', display: 'flex', alignItems: 'center', justifyContent: 'space-between' }}>
          <Link to="/" onClick={() => setOpen(false)}><Logo size={15}/></Link>
          <button className="btn btn-icon btn-sm show-mobile" onClick={() => setOpen(false)}><I.close size={14}/></button>
        </div>
        {items.map((it, i) => it.section ? (
          <div key={i} className="side-section">{it.section}</div>
        ) : (
          <div key={it.to}
               className={"nav-item " + (path === it.to ? 'active' : '')}
               onClick={() => { navigate(it.to); setOpen(false); }}>
            <it.i size={15}/>
            <span>{it.label}</span>
            {it.badge && <span className="pill nav-badge" style={{ fontSize: 10.5, padding: '1px 7px' }}>{it.badge}</span>}
            {it.soon && <span className="pill pill-warn nav-badge" style={{ fontSize: 10 }}>Soon</span>}
          </div>
        ))}
        <div style={{ marginTop: 'auto', padding: '12px 6px', borderTop: '1px solid var(--border)' }}>
          <div style={{ display: 'flex', alignItems: 'center', gap: 10, padding: '8px 6px' }}>
            <div style={{ width: 30, height: 30, borderRadius: 999, background: 'var(--accent-soft)', color: 'var(--accent)', display: 'inline-flex', alignItems: 'center', justifyContent: 'center', fontWeight: 600, fontSize: 12 }}>MT</div>
            <div style={{ flex: 1, minWidth: 0 }}>
              <div style={{ fontSize: 13, fontWeight: 500, whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis' }}>Marcus T.</div>
              <div style={{ fontSize: 11, color: 'var(--muted)' }}>Pro plan</div>
            </div>
            <button className="btn btn-icon btn-sm" title="Log out" onClick={() => navigate('/login')}><I.logout size={13}/></button>
          </div>
        </div>
      </aside>
    </>
  );
}

/* ───────── Dashboard shell ───────── */
function DashShell({ children, title, action, role = 'customer' }) {
  const [navOpen, setNavOpen] = useState(false);
  return (
    <div style={{ display: 'flex', minHeight: '100vh', background: 'var(--bg)' }}>
      <DashSidebar open={navOpen} setOpen={setNavOpen} role={role}/>
      <div style={{ flex: 1, minWidth: 0, display: 'flex', flexDirection: 'column' }}>
        <header className="topbar">
          <div className="topbar-left" style={{ display: 'flex', alignItems: 'center', gap: 12, minWidth: 0, flex: 1 }}>
            <button className="btn btn-icon btn-sm show-mobile" onClick={() => setNavOpen(true)} style={{ flex: 'none' }}><I.menu size={14}/></button>
            <h1 className="topbar-title" style={{ margin: 0, fontSize: 18, fontWeight: 600, letterSpacing: '-0.02em', whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis', minWidth: 0, flex: 1 }}>{title}</h1>
          </div>
          <div className="topbar-right" style={{ display: 'flex', alignItems: 'center', gap: 8, flex: 'none' }}>
            <div className="hide-mobile wallet-pill"><span className="live-dot"/><span>$1,248.20 USDT</span></div>
            <ThemeToggle/>
            <button className="btn btn-icon" title="Notifications" style={{ position: 'relative' }}>
              <I.bell size={15}/>
              <span style={{ position: 'absolute', top: 6, right: 6, width: 7, height: 7, borderRadius: 999, background: 'var(--accent)' }}/>
            </button>
            {action}
          </div>
        </header>
        <main className="view-enter dash-main">{children}</main>
      </div>
    </div>
  );
}

/* ───────── Overview ───────── */
function DashOverview() {
  const { navigate } = useHashRoute();
  return (
    <DashShell title="Overview" action={
      <Btn kind="primary" size="sm" onClick={() => navigate('/marketplace')}><I.plus size={13}/><span className="hide-mobile">Add indicator</span></Btn>
    }>
      <div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fit, minmax(220px, 1fr))', gap: 12, marginBottom: 18 }}>
        {[
          ['Active indicators', '3', '+1 this month', 'up'],
          ['Signals (30d)', '276', '+12.4%', 'up'],
          ['Lifetime spend', '$627', null, null],
          ['Referral earnings', '$184.20', '+$24.00 pending', 'up'],
        ].map(([l, v, d, k]) => (
          <div key={l} className="stat">
            <span className="label">{l}</span>
            <span className="value tabular">{v}</span>
            {d && <span className={"delta pill " + (k === 'up' ? 'pill-up' : 'pill-down')} style={{ alignSelf: 'flex-start' }}><span className="dot"/>{d}</span>}
          </div>
        ))}
      </div>

      <div style={{ display: 'grid', gridTemplateColumns: '2fr 1fr', gap: 12 }} className="ov-grid">
        <div className="card" style={{ padding: 0 }}>
          <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', padding: '14px 18px', borderBottom: '1px solid var(--border)', flexWrap: 'wrap', gap: 12 }}>
            <div>
              <div style={{ fontWeight: 600, fontSize: 14 }}>Signals — last 30 days</div>
              <div style={{ fontSize: 12, color: 'var(--muted)' }}>Across all your indicators</div>
            </div>
            <Tabs value="30d" onChange={()=>{}} items={[{value:'7d',label:'7D'},{value:'30d',label:'30D'},{value:'90d',label:'90D'}]}/>
          </div>
          <div style={{ height: 'clamp(200px, 36vw, 280px)', padding: 16 }}>
            <CandleChart seed={42} w={800} h={260} candles={60} withSignals={true}/>
          </div>
        </div>

        <div className="card" style={{ padding: 0 }}>
          <div style={{ padding: '14px 18px', borderBottom: '1px solid var(--border)', display: 'flex', justifyContent: 'space-between', alignItems: 'center', flexWrap: 'wrap', gap: 12 }}>
            <div style={{ fontWeight: 600, fontSize: 14 }}>Recent activity</div>
            <span className="pill"><span className="live-dot"/>Live</span>
          </div>
          <div style={{ display: 'flex', flexDirection: 'column' }}>
            {[
              ['Aurora Trend', 'LONG signal · BTC/USDT 15m', '2m ago', 'up'],
              ['Volume Profile Pro', 'POC shift · ETH/USDT 1h', '12m ago', 'info'],
              ['Liquidity Grid', 'EQH swept · SOL/USDT 5m', '1h ago', 'down'],
              ['Aurora Trend', 'EXIT · NDX 1D', '4h ago', 'info'],
              ['Volume Profile Pro', 'New value area · BTC 4h', '8h ago', 'info'],
            ].map(([n, d, t, k], i) => (
              <div key={i} style={{ padding: '12px 18px', borderBottom: i === 4 ? 'none' : '1px solid var(--border)', display: 'flex', alignItems: 'start', gap: 10 }}>
                <span className={"pill " + (k === 'up' ? 'pill-up' : k === 'down' ? 'pill-down' : '')} style={{ marginTop: 2, flex: 'none' }}><span className="dot"/></span>
                <div style={{ flex: 1, minWidth: 0 }}>
                  <div style={{ fontSize: 13, fontWeight: 500, whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis' }}>{n}</div>
                  <div style={{ fontSize: 12, color: 'var(--muted)', whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis' }}>{d}</div>
                </div>
                <span style={{ fontSize: 11, color: 'var(--muted)', flex: 'none' }} className="mono">{t}</span>
              </div>
            ))}
          </div>
        </div>
      </div>

      <div style={{ marginTop: 18, display: 'grid', gridTemplateColumns: 'repeat(auto-fit, minmax(280px, 1fr))', gap: 12 }}>
        {OWNED.map(o => {
          const ind = INDICATORS.find(i => i.slug === o.slug);
          return (
            <div key={o.slug} className="card" style={{ padding: 16, display: 'flex', flexDirection: 'column', gap: 12, minWidth: 0 }}>
              <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'start', gap: 8, flexWrap: 'wrap' }}>
                <div style={{ minWidth: 0 }}>
                  <div style={{ fontWeight: 600, overflow: 'hidden', textOverflow: 'ellipsis' }}>{ind.name}</div>
                  <div style={{ fontSize: 12, color: 'var(--muted)' }}>{o.plan} · {o.signals} signals</div>
                </div>
                <span className="pill pill-up" style={{ flex: 'none' }}><span className="dot"/>active</span>
              </div>
              <div style={{ height: 60 }}><Spark seed={ind.seed}/></div>
              <div style={{ display: 'flex', justifyContent: 'space-between', fontSize: 12, color: 'var(--muted)' }}>
                <span>Last signal {o.lastSignal}</span>
                <Link to={'/indicator/' + o.slug} style={{ color: 'var(--accent)' }}>Open →</Link>
              </div>
            </div>
          );
        })}
      </div>

      <style>{`@media (max-width: 980px) { .ov-grid { grid-template-columns: 1fr !important; } }`}</style>
    </DashShell>
  );
}

/* ───────── My Indicators (with TV username binding) ───────── */
function DashIndicators() {
  const { toast } = React.useContext(ToastContext);
  const [tv, setTv] = useState('marcus_trades');
  const [editTv, setEditTv] = useState(false);
  const [newTv, setNewTv] = useState('');
  // 5 days ago — unlocks in 2 days
  const lockedUntil = useMemo(() => {
    const d = new Date(); d.setDate(d.getDate() + 2);
    return d.toLocaleDateString('en-US', { month: 'short', day: 'numeric' });
  }, []);

  return (
    <DashShell title="My Indicators" action={
      <Btn kind="primary" size="sm" onClick={() => window.location.hash = '/marketplace'}><I.plus size={13}/><span className="hide-mobile">Add indicator</span></Btn>
    }>
      {/* TV binding */}
      <div className="card" style={{ padding: 'clamp(16px, 4vw, 20px)', marginBottom: 16, display: 'flex', gap: 16, alignItems: 'flex-start', flexWrap: 'wrap' }}>
        <div style={{ width: 44, height: 44, borderRadius: 999, background: 'var(--accent-soft)', color: 'var(--accent)', display: 'inline-flex', alignItems: 'center', justifyContent: 'center', flex: 'none' }}>
          <I.fingerprint size={20}/>
        </div>
        <div style={{ flex: '1 1 240px', minWidth: 0 }}>
          <div style={{ fontSize: 12, color: 'var(--muted)', marginBottom: 2 }}>BOUND TRADINGVIEW USERNAME</div>
          <div style={{ display: 'flex', alignItems: 'center', gap: 10, flexWrap: 'wrap' }}>
            <span className="mono" style={{ fontSize: 18, fontWeight: 600 }}>@{tv}</span>
            <span className="pill pill-up"><span className="dot"/>verified</span>
          </div>
          <div style={{ fontSize: 12, color: 'var(--muted)', marginTop: 4 }}>
            <I.lock size={11}/> Username can be changed once every 7 days. Next change available <strong style={{ color: 'var(--text)' }}>{lockedUntil}</strong>.
          </div>
        </div>
        <Btn onClick={() => setEditTv(true)}><I.edit size={13}/> Change username</Btn>
      </div>

      {/* Indicators table */}
      <div className="card" style={{ overflow: 'hidden' }}>
        <div style={{ overflowX: 'auto' }}>
          <table className="tbl tabular">
            <thead>
              <tr>
                <th>Indicator</th>
                <th>Plan</th>
                <th>Performance (30d)</th>
                <th>Signals</th>
                <th>Status</th>
                <th>Purchased</th>
                <th></th>
              </tr>
            </thead>
            <tbody>
              {OWNED.map(o => {
                const ind = INDICATORS.find(i => i.slug === o.slug);
                return (
                  <tr key={o.slug}>
                    <td>
                      <div style={{ display: 'flex', alignItems: 'center', gap: 10, minWidth: 0 }}>
                        <div style={{ width: 36, height: 24, background: 'var(--bg-2)', borderRadius: 4, overflow: 'hidden', flex: 'none' }}>
                          <CandleChart seed={ind.seed} w={36} h={24} candles={12} withVolume={false}/>
                        </div>
                        <div style={{ minWidth: 0 }}>
                          <div style={{ fontWeight: 500, whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis' }}>{ind.name}</div>
                          <div style={{ fontSize: 11, color: 'var(--muted)' }}>{ind.cat}</div>
                        </div>
                      </div>
                    </td>
                    <td>{o.plan}</td>
                    <td style={{ minWidth: 140 }}>
                      <div style={{ height: 28, width: '100%', maxWidth: 140 }}><Spark seed={ind.seed} h={28} w={140} fill={false} strokeWidth={1.2}/></div>
                    </td>
                    <td className="mono">{o.signals}</td>
                    <td><span className="pill pill-up"><span className="dot"/>active</span></td>
                    <td className="mono" style={{ color: 'var(--muted)' }}>{o.purchased}</td>
                    <td style={{ textAlign: 'right' }}>
                      <Btn size="sm">Manage</Btn>
                    </td>
                  </tr>
                );
              })}
            </tbody>
          </table>
        </div>
      </div>

      {editTv && (
        <div className="dialog-backdrop" onClick={() => setEditTv(false)}>
          <div className="dialog" onClick={e => e.stopPropagation()}>
            <div style={{ padding: '20px 22px', borderBottom: '1px solid var(--border)', display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
              <div style={{ fontWeight: 600 }}>Change TradingView username</div>
              <button className="btn btn-icon btn-sm" onClick={() => setEditTv(false)}><I.close size={13}/></button>
            </div>
            <div style={{ padding: 22 }}>
              <p style={{ fontSize: 13, color: 'var(--text-2)', marginTop: 0 }}>
                Your indicator access will be revoked from <span className="mono">@{tv}</span> and granted to the new username. This can only be done <strong>once every 7 days</strong>.
              </p>
              <div className="field" style={{ marginBottom: 14 }}>
                <label className="field-label">New TradingView username</label>
                <div style={{ position: 'relative' }}>
                  <span style={{ position: 'absolute', left: 12, top: 11, color: 'var(--muted)' }}>@</span>
                  <input className="input" placeholder="newhandle" value={newTv} onChange={e => setNewTv(e.target.value)} style={{ paddingLeft: 26 }} autoFocus/>
                </div>
              </div>
              <div style={{ padding: 12, background: 'var(--bg-2)', borderRadius: 8, fontSize: 12.5, color: 'var(--text-2)', display: 'flex', gap: 8, marginBottom: 18 }}>
                <I.shield size={14}/>
                <div>For security, the username lock prevents account sharing and reduces fraud.</div>
              </div>
              <div style={{ display: 'flex', gap: 8, justifyContent: 'flex-end', flexWrap: 'wrap' }}>
                <Btn onClick={() => setEditTv(false)}>Cancel</Btn>
                <Btn kind="primary" disabled={!newTv} onClick={() => { setTv(newTv); setEditTv(false); toast('Username updated. Re-binding indicators…'); }}>
                  Update & re-bind
                </Btn>
              </div>
            </div>
          </div>
        </div>
      )}
    </DashShell>
  );
}

/* ───────── Referrals ───────── */
function DashReferrals() {
  const { toast } = React.useContext(ToastContext);
  const code = 'MATTO-MT9X4D';
  const link = 'https://mattobot.io/r/' + code;
  return (
    <DashShell title="Referrals">
      <style>{`@media (max-width: 860px) { .ref-grid { grid-template-columns: 1fr !important; } }`}</style>
      <div style={{ display: 'grid', gridTemplateColumns: '1.4fr 1fr', gap: 12, marginBottom: 18 }} className="ref-grid">
        <div className="card" style={{ padding: 'clamp(18px, 4vw, 24px)', position: 'relative', overflow: 'hidden' }}>
          <div className="grid-bg" style={{ position: 'absolute', inset: 0, opacity: 0.3, maskImage: 'linear-gradient(180deg, black, transparent)' }}/>
          <div style={{ position: 'relative' }}>
            <div className="eyebrow" style={{ marginBottom: 8 }}>Earn 10% on every sale you bring</div>
            <div className="mono" style={{ fontSize: 'clamp(28px, 8vw, 36px)', fontWeight: 600, letterSpacing: '-0.02em', marginBottom: 4 }}>$184.20</div>
            <div style={{ fontSize: 13, color: 'var(--muted)', marginBottom: 20 }}>Available for payout · Next payout May 1, 2026 in USDT</div>
            <Btn kind="primary">Withdraw to USDT <I.arrow size={13}/></Btn>
          </div>
        </div>
        <div className="card" style={{ padding: 'clamp(18px, 4vw, 24px)' }}>
          <div className="eyebrow" style={{ marginBottom: 12 }}>Your referral link</div>
          <div style={{ display: 'flex', gap: 6, marginBottom: 14, flexWrap: 'wrap' }}>
            <input className="input mono" readOnly value={link} style={{ fontSize: 12, flex: '1 1 200px', minWidth: 0 }}/>
            <Btn onClick={() => { navigator.clipboard?.writeText(link); toast('Link copied'); }}><I.copy size={14}/></Btn>
          </div>
          <div style={{ fontSize: 12, color: 'var(--muted)', marginBottom: 6 }}>Referral code</div>
          <div className="mono" style={{ fontSize: 18, fontWeight: 600, padding: 10, background: 'var(--bg-2)', borderRadius: 8, display: 'flex', justifyContent: 'space-between', alignItems: 'center', gap: 8, flexWrap: 'wrap' }}>
            <span style={{ minWidth: 0, overflow: 'hidden', textOverflow: 'ellipsis' }}>{code}</span>
            <Btn size="sm" onClick={() => { navigator.clipboard?.writeText(code); toast('Code copied'); }}><I.copy size={12}/></Btn>
          </div>
        </div>
      </div>

      <div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fit, minmax(180px, 1fr))', gap: 12, marginBottom: 18 }}>
        {[
          ['Total earned', '$642.80', '+$24.00 pending'],
          ['Clicks (30d)', '1,284', '+18.4%'],
          ['Conversions', '36', '+4 this week'],
          ['Conversion rate', '2.8%', null],
        ].map(([l, v, d]) => (
          <div key={l} className="stat">
            <span className="label">{l}</span>
            <span className="value">{v}</span>
            {d && <span style={{ fontSize: 11, color: 'var(--muted)' }}>{d}</span>}
          </div>
        ))}
      </div>

      <div className="card" style={{ overflow: 'hidden' }}>
        <div style={{ padding: '14px 18px', borderBottom: '1px solid var(--border)', display: 'flex', justifyContent: 'space-between', alignItems: 'center', flexWrap: 'wrap', gap: 12 }}>
          <div style={{ fontWeight: 600 }}>Recent referrals</div>
          <Tabs value="all" onChange={()=>{}} items={[{value:'all',label:'All'},{value:'paid',label:'Paid'},{value:'pending',label:'Pending'}]}/>
        </div>
        <div style={{ overflowX: 'auto' }}>
          <table className="tbl tabular">
            <thead><tr><th>Referee</th><th>Indicator</th><th>Plan</th><th>Sale</th><th>Commission</th><th>Status</th><th>Date</th></tr></thead>
            <tbody>
              {[
                ['j.miller', 'Aurora Trend', 'Lifetime', 199, 19.90, 'paid', 'Apr 28'],
                ['quant_alex', 'Volume Profile Pro', 'Yearly', 189, 18.90, 'paid', 'Apr 24'],
                ['btc_pepe', 'Liquidity Grid', 'Lifetime', 179, 17.90, 'pending', 'Apr 22'],
                ['hodlqueen', 'Aurora Trend', 'Monthly', 19, 1.90, 'paid', 'Apr 19'],
                ['c.santos', 'Momentum Pulse', 'Lifetime', 99, 9.90, 'paid', 'Apr 12'],
                ['ridgemoor', 'Volatility Regime', 'Yearly', 119, 11.90, 'pending', 'Apr 09'],
              ].map((r, i) => (
                <tr key={i}>
                  <td className="mono">@{r[0]}</td>
                  <td>{r[1]}</td>
                  <td style={{ color: 'var(--muted)' }}>{r[2]}</td>
                  <td className="mono">${r[3]}</td>
                  <td className="mono" style={{ color: 'var(--accent)' }}>+${r[4].toFixed(2)}</td>
                  <td><span className={"pill " + (r[5] === 'paid' ? 'pill-up' : 'pill-warn')}><span className="dot"/>{r[5]}</span></td>
                  <td style={{ color: 'var(--muted)' }}>{r[6]}</td>
                </tr>
              ))}
            </tbody>
          </table>
        </div>
      </div>
    </DashShell>
  );
}

/* ───────── Billing ───────── */
function DashBilling() {
  return (
    <DashShell title="Billing">
      <div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fit, minmax(220px, 1fr))', gap: 12, marginBottom: 18 }}>
        <div className="stat"><span className="label">Lifetime spend</span><span className="value">$627.00</span></div>
        <div className="stat"><span className="label">Active subscriptions</span><span className="value">2</span></div>
        <div className="stat"><span className="label">Next renewal</span><span className="value" style={{ fontSize: 18 }}>May 22, 2026</span></div>
        <div className="stat"><span className="label">Default coin</span><span className="value mono" style={{ fontSize: 18 }}>USDT (TRC20)</span></div>
      </div>
      <div className="card" style={{ overflow: 'hidden' }}>
        <div style={{ padding: '14px 18px', borderBottom: '1px solid var(--border)', display: 'flex', justifyContent: 'space-between', alignItems: 'center', flexWrap: 'wrap', gap: 12 }}>
          <div style={{ fontWeight: 600 }}>Order history</div>
          <Btn size="sm"><I.download size={12}/> Export CSV</Btn>
        </div>
        <div style={{ overflowX: 'auto' }}>
          <table className="tbl tabular">
            <thead><tr><th>Date</th><th>Indicator</th><th>Plan</th><th>Amount</th><th>Coin</th><th>Tx</th><th>Status</th><th></th></tr></thead>
            <tbody>
              {[
                ['Apr 22', 'Liquidity Grid', 'Monthly', 17, 'USDT', '0x4f2…ae1', 'paid'],
                ['Apr 01', 'Volume Profile Pro', 'Yearly', 189, 'USDT', '0x9c1…b32', 'paid'],
                ['Mar 14', 'Aurora Trend', 'Lifetime', 199, 'BTC', 'bc1…7vn', 'paid'],
                ['Feb 20', 'Momentum Pulse', 'Refunded', -99, 'USDT', '0x7d2…1ac', 'refund'],
                ['Jan 11', 'Volatility Regime', 'Yearly', 119, 'ETH', '0x12e…ff8', 'paid'],
              ].map((r, i) => (
                <tr key={i}>
                  <td className="mono" style={{ color: 'var(--muted)' }}>{r[0]}</td>
                  <td>{r[1]}</td>
                  <td style={{ color: 'var(--muted)' }}>{r[2]}</td>
                  <td className="mono">${Math.abs(r[3])}</td>
                  <td><span className="pill"><span className="dot"/>{r[4]}</span></td>
                  <td className="mono" style={{ color: 'var(--accent)', fontSize: 12 }}>{r[5]} <I.external size={10}/></td>
                  <td><span className={"pill " + (r[6] === 'paid' ? 'pill-up' : 'pill-warn')}><span className="dot"/>{r[6]}</span></td>
                  <td style={{ textAlign: 'right' }}><Btn size="sm" kind="ghost"><I.receipt size={12}/></Btn></td>
                </tr>
              ))}
            </tbody>
          </table>
        </div>
      </div>
    </DashShell>
  );
}

/* ───────── Settings ───────── */
function DashSettings() {
  const { theme, setTheme } = React.useContext(ThemeContext);
  return (
    <DashShell title="Settings">
      <div style={{ display: 'grid', gridTemplateColumns: '220px 1fr', gap: 32, maxWidth: 980 }} className="set-grid">
        <nav style={{ display: 'flex', flexDirection: 'column', gap: 2 }}>
          {['Profile', 'Security', 'Notifications', 'API & webhooks', 'Appearance'].map((s, i) => (
            <button key={s} type="button" className={"nav-item " + (i === 0 ? 'active' : '')} style={{ position: 'relative', textAlign: 'left', background: 'transparent', border: 0, cursor: 'pointer', font: 'inherit', color: 'inherit' }}>{s}</button>
          ))}
        </nav>
        <div style={{ display: 'flex', flexDirection: 'column', gap: 16 }}>
          <div className="card" style={{ padding: 22 }}>
            <div style={{ fontWeight: 600, marginBottom: 14 }}>Profile</div>
            <div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fit, minmax(220px, 1fr))', gap: 12 }}>
              <div className="field"><label className="field-label">Display name</label><input className="input" defaultValue="Marcus T."/></div>
              <div className="field"><label className="field-label">Email</label><input className="input" defaultValue="trader@mattobot.io"/></div>
              <div className="field"><label className="field-label">Country</label><input className="input" defaultValue="Singapore"/></div>
              <div className="field"><label className="field-label">Timezone</label><input className="input" defaultValue="Asia/Singapore"/></div>
            </div>
            <div style={{ display: 'flex', justifyContent: 'flex-end', marginTop: 14 }}><Btn kind="primary">Save changes</Btn></div>
          </div>
          <div className="card" style={{ padding: 22 }}>
            <div style={{ fontWeight: 600, marginBottom: 14 }}>Appearance</div>
            <div className="field" style={{ marginBottom: 12 }}>
              <label className="field-label">Theme</label>
              <div style={{ display: 'flex', gap: 8, flexWrap: 'wrap' }}>
                {['dark', 'light'].map(t => (
                  <button key={t} className={"btn " + (theme === t ? 'btn-primary' : '')} onClick={() => setTheme(t)} style={{ textTransform: 'capitalize' }}>
                    {t === 'dark' ? <I.moon size={13}/> : <I.sun size={13}/>} {t}
                  </button>
                ))}
              </div>
            </div>
          </div>
        </div>
      </div>
      <style>{`@media (max-width: 760px) { .set-grid { grid-template-columns: 1fr !important; } }`}</style>
    </DashShell>
  );
}

/* ───────── Algo / Copy soon (in-dashboard) ───────── */
function DashAlgoSoon() {
  return (
    <DashShell title="Algo Trading">
      <div className="card" style={{ padding: 0, overflow: 'hidden' }}>
        <div style={{ padding: 'clamp(20px, 5vw, 32px)', display: 'flex', flexDirection: 'column', gap: 14, alignItems: 'start' }}>
          <span className="pill pill-warn"><span className="dot"/>Q3 2026</span>
          <h2 className="h2" style={{ margin: 0 }}>Bring your indicators to life.</h2>
          <p style={{ color: 'var(--muted)', maxWidth: 580, margin: 0 }}>
            Connect Binance, Bybit or OKX. Forward your indicator alerts as live orders. Position-size in dollars or risk %, with built-in drawdown circuit-breakers.
          </p>
          <Btn kind="primary">Join waitlist <I.arrow size={13}/></Btn>
        </div>
        <div style={{ height: 'clamp(180px, 32vw, 280px)', borderTop: '1px solid var(--border)' }}>
          <CandleChart seed={61} w={1000} h={280} candles={70}/>
        </div>
      </div>
    </DashShell>
  );
}
function DashCopySoon() {
  return (
    <DashShell title="Copy Trading">
      <div className="card" style={{ padding: 0, overflow: 'hidden' }}>
        <div style={{ padding: 'clamp(20px, 5vw, 32px)', display: 'flex', flexDirection: 'column', gap: 14, alignItems: 'start' }}>
          <span className="pill pill-warn"><span className="dot"/>Q4 2026</span>
          <h2 className="h2" style={{ margin: 0 }}>Mirror the best, automatically.</h2>
          <p style={{ color: 'var(--muted)', maxWidth: 580, margin: 0 }}>
            Curated, broker-verified traders. Per-trader risk caps. One-tap pause and unwind. Performance you can audit on-chain.
          </p>
          <Btn kind="primary">Join waitlist <I.arrow size={13}/></Btn>
        </div>
        <style>{`.copy-perf-cell + .copy-perf-cell { border-top: 1px solid var(--border); } @media (min-width: 660px) { .copy-perf-cell + .copy-perf-cell { border-top: none; border-left: 1px solid var(--border); } }`}</style>
        <div className="copy-perf" style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fit, minmax(220px, 1fr))', borderTop: '1px solid var(--border)' }}>
          {[['QuantLynx', 142.4, 18, 31], ['NorthDelta', 98.2, 24, 22], ['TapeReader', 76.5, 12, 19]].map(([n, p, dd, t]) => (
            <div key={n} className="copy-perf-cell" style={{ padding: 18 }}>
              <div style={{ fontWeight: 600, marginBottom: 4 }}>{n}</div>
              <div style={{ height: 56 }}><Spark seed={n.length * 7}/></div>
              <div style={{ display: 'flex', justifyContent: 'space-between', fontSize: 11, color: 'var(--muted)', marginTop: 8, flexWrap: 'wrap', gap: 4 }}>
                <span>+{p}%</span><span>DD {dd}%</span><span>{t} live</span>
              </div>
            </div>
          ))}
        </div>
      </div>
    </DashShell>
  );
}

Object.assign(window, { DashOverview, DashIndicators, DashReferrals, DashBilling, DashSettings, DashAlgoSoon, DashCopySoon, DashShell });

})();
/* ===== admin.jsx ===== */
(function(){
/* Admin dashboard */

const { useState } = React;

function AdminOverview() {
  return (
    <DashShell title="Admin · Overview" role="admin">
      <div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fit, minmax(220px, 1fr))', gap: 12, marginBottom: 18 }}>
        {[
          ['Revenue (30d)', '$48,294', '+18.4%', 'up'],
          ['New customers', '342', '+24', 'up'],
          ['Active subscriptions', '1,284', '+62', 'up'],
          ['Refund rate', '1.2%', '-0.3%', 'down'],
          ['Pending payouts', '$3,241', null, null],
          ['Active indicators', '6', null, null],
        ].map(([l,v,d,k]) => (
          <div key={l} className="stat">
            <span className="label">{l}</span>
            <span className="value tabular">{v}</span>
            {d && <span className={"pill " + (k==='up'?'pill-up':'pill-down')} style={{alignSelf:'flex-start'}}><span className="dot"/>{d}</span>}
          </div>
        ))}
      </div>
      <div style={{ display: 'grid', gridTemplateColumns: '2fr 1fr', gap: 12, marginBottom: 18 }} className="adm-grid">
        <div className="card" style={{ padding: 0, overflow: 'hidden' }}>
          <div style={{ padding: '14px 18px', borderBottom: '1px solid var(--border)', display: 'flex', justifyContent: 'space-between', flexWrap: 'wrap', gap: 12 }}>
            <div style={{ fontWeight: 600 }}>Revenue · last 90 days</div>
            <Tabs value="90d" onChange={()=>{}} items={[{value:'30d',label:'30D'},{value:'90d',label:'90D'},{value:'YTD',label:'YTD'}]}/>
          </div>
          <div style={{ height: 'clamp(200px, 36vw, 280px)', padding: 12 }}>
            <CandleChart seed={88} w={800} h={260} candles={60}/>
          </div>
        </div>
        <div className="card" style={{ padding: 0, overflow: 'hidden' }}>
          <div style={{ padding: '14px 18px', borderBottom: '1px solid var(--border)', fontWeight: 600 }}>Top sellers</div>
          {INDICATORS.slice(0,5).map((ind,i) => (
            <div key={ind.slug} style={{ display: 'flex', alignItems: 'center', gap: 10, padding: '12px 18px', borderBottom: i===4?'none':'1px solid var(--border)' }}>
              <span className="mono" style={{ fontSize: 11, color: 'var(--muted)', width: 16, flex: 'none' }}>0{i+1}</span>
              <div style={{ width: 36, height: 22, background: 'var(--bg-2)', borderRadius: 4, overflow: 'hidden', flex: 'none' }}>
                <CandleChart seed={ind.seed} w={36} h={22} candles={12} withVolume={false}/>
              </div>
              <div style={{ flex: 1, minWidth: 0 }}>
                <div style={{ fontSize: 13, fontWeight: 500, whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis' }}>{ind.name}</div>
                <div style={{ fontSize: 11, color: 'var(--muted)' }}>{280 - i*40} sales</div>
              </div>
              <span className="mono" style={{ fontSize: 13, whiteSpace: 'nowrap', flex: 'none' }}>${(12490 - i*2400).toLocaleString()}</span>
            </div>
          ))}
        </div>
      </div>
      <div className="card" style={{ overflow: 'hidden' }}>
        <div style={{ padding: '14px 18px', borderBottom: '1px solid var(--border)', display: 'flex', justifyContent: 'space-between' }}>
          <div style={{ fontWeight: 600 }}>Recent orders</div>
          <Btn size="sm">View all</Btn>
        </div>
        <div style={{ overflowX: 'auto' }}>
          <table className="tbl tabular">
            <thead><tr><th>Order</th><th>Customer</th><th>Indicator</th><th>Plan</th><th>Amount</th><th>TV bind</th><th>Status</th><th>Date</th></tr></thead>
            <tbody>
              {[
                ['#A4291','marcus_trades','Aurora Trend','Lifetime',199,'granted','paid','2m ago'],
                ['#A4290','quant_alex','Volume Profile Pro','Yearly',189,'granted','paid','12m ago'],
                ['#A4289','btc_pepe','Liquidity Grid','Monthly',17,'pending','watching','22m ago'],
                ['#A4288','j.miller','Aurora Trend','Lifetime',199,'granted','paid','38m ago'],
                ['#A4287','c.santos','Momentum Pulse','Yearly',89,'granted','paid','1h ago'],
                ['#A4286','hodlqueen','Volatility Regime','Lifetime',149,'failed','expired','2h ago'],
              ].map((r,i) => (
                <tr key={i}>
                  <td className="mono">{r[0]}</td>
                  <td className="mono">@{r[1]}</td>
                  <td>{r[2]}</td>
                  <td style={{ color: 'var(--muted)' }}>{r[3]}</td>
                  <td className="mono">${r[4]}</td>
                  <td><span className={"pill " + (r[5]==='granted'?'pill-up':r[5]==='pending'?'pill-warn':'pill-down')}><span className="dot"/>{r[5]}</span></td>
                  <td><span className={"pill " + (r[6]==='paid'?'pill-up':r[6]==='watching'?'pill-warn':'pill-down')}><span className="dot"/>{r[6]}</span></td>
                  <td style={{ color: 'var(--muted)' }}>{r[7]}</td>
                </tr>
              ))}
            </tbody>
          </table>
        </div>
      </div>
      <style>{`@media (max-width: 880px) { .adm-grid { grid-template-columns: 1fr !important; } }`}</style>
    </DashShell>
  );
}

function AdminIndicators() {
  return (
    <DashShell title="Admin · Indicators" role="admin" action={
      <Btn kind="primary" size="sm"><I.plus size={13}/><span className="hide-mobile">New indicator</span></Btn>
    }>
      <div className="card" style={{ overflow: 'hidden' }}>
        <div style={{ overflowX: 'auto' }}>
          <table className="tbl tabular">
            <thead><tr><th>Name</th><th>Category</th><th>Lifetime</th><th>Yearly</th><th>Monthly</th><th>Sales (30d)</th><th>Rating</th><th>Status</th><th></th></tr></thead>
            <tbody>
              {INDICATORS.map(ind => (
                <tr key={ind.slug}>
                  <td>
                    <div style={{ display: 'flex', alignItems: 'center', gap: 10 }}>
                      <div style={{ width: 36, height: 22, background: 'var(--bg-2)', borderRadius: 4, overflow: 'hidden' }}>
                        <CandleChart seed={ind.seed} w={36} h={22} candles={12} withVolume={false}/>
                      </div>
                      <span style={{ fontWeight: 500 }}>{ind.name}</span>
                    </div>
                  </td>
                  <td style={{ color: 'var(--muted)' }}>{ind.cat}</td>
                  <td className="mono">${ind.price.lifetime}</td>
                  <td className="mono">${ind.price.yearly}</td>
                  <td className="mono">${ind.price.monthly}</td>
                  <td className="mono">{Math.floor(ind.reviews/3)}</td>
                  <td className="mono">{ind.rating} ★</td>
                  <td><span className="pill pill-up"><span className="dot"/>live</span></td>
                  <td style={{ textAlign: 'right' }}>
                    <div style={{ display: 'inline-flex', gap: 4 }}>
                      <Btn size="sm" kind="ghost"><I.edit size={12}/></Btn>
                      <Btn size="sm" kind="ghost"><I.more size={12}/></Btn>
                    </div>
                  </td>
                </tr>
              ))}
            </tbody>
          </table>
        </div>
      </div>
    </DashShell>
  );
}

function AdminUsers() {
  return (
    <DashShell title="Admin · Users" role="admin">
      <div style={{ display: 'flex', gap: 8, marginBottom: 16, flexWrap: 'wrap' }}>
        <input className="input" placeholder="Search by email or TV username…" style={{ flex: '1 1 220px', maxWidth: 360, minWidth: 0 }}/>
        <Btn><I.filter size={13}/> Filter</Btn>
      </div>
      <div className="card" style={{ overflow: 'hidden' }}>
        <div style={{ overflowX: 'auto' }}>
          <table className="tbl tabular">
            <thead><tr><th>User</th><th>TradingView</th><th>Indicators</th><th>Spent</th><th>Joined</th><th>Last active</th><th>Status</th><th></th></tr></thead>
            <tbody>
              {[
                ['marcus_trades','trader@mattobot.io',3,627,'Jan 2026','2m ago','active'],
                ['quant_alex','alex.k@hedge.fund',5,1184,'Nov 2025','12m ago','active'],
                ['btc_pepe','pepe@proton.me',1,17,'Apr 2026','22m ago','trial'],
                ['j.miller','jmiller@gmail.com',2,398,'Mar 2026','1h ago','active'],
                ['hodlqueen','queen@hodl.fyi',4,748,'Dec 2025','3h ago','active'],
                ['c.santos','santos@mac.io',1,99,'Apr 2026','1d ago','active'],
                ['ridgemoor','ridge@bm.co',2,238,'Feb 2026','2d ago','suspended'],
              ].map((r,i) => (
                <tr key={i}>
                  <td>
                    <div style={{ display: 'flex', alignItems: 'center', gap: 10 }}>
                      <div style={{ width: 26, height: 26, borderRadius: 999, background: 'var(--surface-2)', display: 'inline-flex', alignItems: 'center', justifyContent: 'center', fontSize: 11, fontWeight: 600 }}>{r[0][0].toUpperCase()}</div>
                      <span style={{ fontSize: 12.5, color: 'var(--muted)' }}>{r[1]}</span>
                    </div>
                  </td>
                  <td className="mono">@{r[0]}</td>
                  <td className="mono">{r[2]}</td>
                  <td className="mono">${r[3]}</td>
                  <td style={{ color: 'var(--muted)' }}>{r[4]}</td>
                  <td style={{ color: 'var(--muted)' }}>{r[5]}</td>
                  <td><span className={"pill " + (r[6]==='active'?'pill-up':r[6]==='trial'?'pill-warn':'pill-down')}><span className="dot"/>{r[6]}</span></td>
                  <td style={{ textAlign: 'right' }}><Btn size="sm" kind="ghost"><I.more size={12}/></Btn></td>
                </tr>
              ))}
            </tbody>
          </table>
        </div>
      </div>
    </DashShell>
  );
}

function AdminOrders() {
  return (
    <DashShell title="Admin · Orders" role="admin">
      <div className="card" style={{ overflow: 'hidden' }}>
        <div style={{ padding: '14px 18px', borderBottom: '1px solid var(--border)', display: 'flex', alignItems: 'center', gap: 8, flexWrap: 'wrap' }}>
          <Tabs value="all" onChange={()=>{}} items={[{value:'all',label:'All'},{value:'pending',label:'Pending'},{value:'paid',label:'Paid'},{value:'refund',label:'Refunded'}]}/>
          <Btn size="sm" style={{ marginLeft: 'auto' }}><I.download size={12}/> Export</Btn>
        </div>
        <div style={{ overflowX: 'auto' }}>
          <table className="tbl tabular">
            <thead><tr><th>Order</th><th>Customer</th><th>Item</th><th>Coin</th><th>Amount</th><th>Tx</th><th>Bind</th><th>Status</th><th>Date</th></tr></thead>
            <tbody>
              {Array.from({length: 8}).map((_, i) => {
                const ind = INDICATORS[i % INDICATORS.length];
                const status = ['paid','paid','paid','watching','paid','refund','paid','paid'][i];
                return (
                  <tr key={i}>
                    <td className="mono">#A42{91-i}</td>
                    <td className="mono">@user_{i+1}</td>
                    <td>{ind.name}</td>
                    <td><span className="pill"><span className="dot"/>{['USDT','BTC','ETH','USDT'][i%4]}</span></td>
                    <td className="mono">${ind.price.lifetime}</td>
                    <td className="mono" style={{ color: 'var(--accent)', fontSize: 12 }}>0x{Math.random().toString(16).slice(2,5)}…{Math.random().toString(16).slice(2,5)}</td>
                    <td><span className="pill pill-up"><span className="dot"/>granted</span></td>
                    <td><span className={"pill " + (status==='paid'?'pill-up':status==='watching'?'pill-warn':'pill-down')}><span className="dot"/>{status}</span></td>
                    <td style={{ color: 'var(--muted)' }}>{i+1}h ago</td>
                  </tr>
                );
              })}
            </tbody>
          </table>
        </div>
      </div>
    </DashShell>
  );
}

function AdminAffiliates() {
  return (
    <DashShell title="Admin · Affiliates" role="admin">
      <div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fit, minmax(200px, 1fr))', gap: 12, marginBottom: 18 }}>
        {[['Affiliates active','248'],['Pending payouts','$3,241.20'],['Paid YTD','$28,492'],['Top earner','quant_alex']].map(([l,v]) => (
          <div key={l} className="stat"><span className="label">{l}</span><span className="value" style={{ fontSize: 22, whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis', maxWidth: '100%' }}>{v}</span></div>
        ))}
      </div>
      <div className="card" style={{ overflow: 'hidden' }}>
        <div style={{ padding: '14px 18px', borderBottom: '1px solid var(--border)', fontWeight: 600 }}>Top affiliates</div>
        <div style={{ overflowX: 'auto' }}>
          <table className="tbl tabular">
            <thead><tr><th>Affiliate</th><th>Code</th><th>Clicks</th><th>Conv.</th><th>Earned</th><th>Pending</th><th>Last payout</th></tr></thead>
            <tbody>
              {[
                ['quant_alex','MATTO-QA12',8420,184,'$3,481','$284','Apr 1'],
                ['marcus_trades','MATTO-MT9X',2810,62,'$642','$24','Apr 1'],
                ['hodlqueen','MATTO-HQ44',2104,48,'$498','$48','Apr 1'],
                ['c.santos','MATTO-CS22',1602,32,'$324','$0','Apr 1'],
                ['j.miller','MATTO-JM17',980,21,'$211','$11','Apr 1'],
              ].map((r,i) => (
                <tr key={i}>
                  <td className="mono">@{r[0]}</td>
                  <td className="mono">{r[1]}</td>
                  <td className="mono">{r[2].toLocaleString()}</td>
                  <td className="mono">{r[3]}</td>
                  <td className="mono">{r[4]}</td>
                  <td className="mono" style={{ color: 'var(--accent)' }}>{r[5]}</td>
                  <td style={{ color: 'var(--muted)' }}>{r[6]}</td>
                </tr>
              ))}
            </tbody>
          </table>
        </div>
      </div>
    </DashShell>
  );
}

function AdminSettings() {
  return (
    <DashShell title="Admin · Settings" role="admin">
      <div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fit, minmax(min(100%, 280px), 1fr))', gap: 12 }}>
        {[
          ['Wallet addresses', 'BTC / ETH / USDT receivers', I.wallet],
          ['TradingView API', 'Auto-grant integration credentials', I.fingerprint],
          ['Affiliate rate', 'Currently 10% lifetime', I.dollar],
          ['Refund window', '7 days, configurable', I.refresh],
          ['Notifications', 'Email + Discord webhooks', I.bell],
          ['Roles & access', 'Admin, support, finance', I.users],
        ].map(([t,s,Ic]) => (
          <div key={t} className="card" style={{ padding: 18 }}>
            <div style={{ width: 36, height: 36, borderRadius: 8, background: 'var(--surface-2)', display: 'inline-flex', alignItems: 'center', justifyContent: 'center', marginBottom: 12 }}><Ic size={16}/></div>
            <div style={{ fontWeight: 600 }}>{t}</div>
            <div style={{ fontSize: 13, color: 'var(--muted)', marginBottom: 12 }}>{s}</div>
            <Btn size="sm">Configure</Btn>
          </div>
        ))}
      </div>
    </DashShell>
  );
}

Object.assign(window, { AdminOverview, AdminIndicators, AdminUsers, AdminOrders, AdminAffiliates, AdminSettings });

})();
/* ===== extra-pages.jsx ===== */
(function(){
/* Additional marketing/legal pages: Pricing, About, Contact, Legal, 404, Affiliates, Docs */

const { useState: usX, useEffect: ueX, useMemo: umX } = React;

/* ───────── Page chrome ───────── */
function PageHero({ eyebrow, title, sub, children }) {
  return (
    <section style={{ position: 'relative', borderBottom: '1px solid var(--border)' }}>
      <div className="aurora" style={{ opacity: 0.5 }}/>
      <div className="grid-bg" style={{ position: 'absolute', inset: 0, opacity: 0.25, maskImage: 'radial-gradient(ellipse at 50% 30%, black 30%, transparent 75%)', WebkitMaskImage: 'radial-gradient(ellipse at 50% 30%, black 30%, transparent 75%)' }}/>
      <div className="container container-wide" style={{ position: 'relative', padding: 'clamp(56px, 9vw, 96px) 24px clamp(48px, 7vw, 72px)', textAlign: 'center' }}>
        <div className="eyebrow" style={{ marginBottom: 16 }}>{eyebrow}</div>
        <h1 className="h1" style={{ margin: '0 auto 16px', maxWidth: 820, fontSize: 'clamp(34px, 5.5vw, 60px)' }}>{title}</h1>
        {sub && <p style={{ fontSize: 17, color: 'var(--text-2)', maxWidth: 640, margin: '0 auto 24px', lineHeight: 1.55 }}>{sub}</p>}
        {children}
      </div>
    </section>
  );
}

/* ───────── Pricing ───────── */
function PricingPage() {
  const { navigate } = useHashRoute();
  const [billing, setBilling] = usX('lifetime'); // monthly | yearly | lifetime

  const plans = [
    {
      key: 'starter', name: 'Starter', tagline: 'Try one tool risk-free.',
      price: { monthly: 29, yearly: 290, lifetime: 199 },
      desc: 'Perfect for casual traders dipping a toe in.',
      includes: ['1 indicator of your choice', 'Standard alert delivery', 'Email support', 'Auto-bound TradingView access', '7-day money-back'],
      missing: ['Premium indicators (Smart Money, Orderflow)', 'Backtest reports', 'Priority desk support'],
    },
    {
      key: 'pro', name: 'Pro', tagline: 'For traders who actually trade.',
      price: { monthly: 79, yearly: 790, lifetime: 599 },
      desc: 'Three indicators, every alert channel, priority support.',
      featured: true,
      includes: ['3 indicators of your choice', 'Telegram + Discord + email alerts', 'Premium indicators included', 'Backtest reports + screener', 'Priority desk support (4-min SLA)', 'Auto-bound TradingView access', '7-day money-back'],
    },
    {
      key: 'desk', name: 'Desk', tagline: 'For prop & trading desks.',
      price: { monthly: 249, yearly: 2490, lifetime: 1899 },
      desc: 'Every indicator we make, plus team-seat sharing.',
      includes: ['All 14 indicators (and any new releases)', 'Up to 5 team seats', 'Webhook integrations', 'Custom alert routing', 'Dedicated Slack channel', 'Early access to algo / copy', 'Custom indicator requests', '14-day money-back'],
    },
  ];

  const period = billing === 'monthly' ? '/mo' : billing === 'yearly' ? '/yr' : 'one-time';
  const saveBadge = billing === 'yearly' ? '2 months free' : billing === 'lifetime' ? 'Best value' : null;

  const features = [
    ['Indicators', { starter: '1', pro: '3', desk: '14 (all)' }],
    ['Premium indicators', { starter: false, pro: true, desk: true }],
    ['Auto-bound TradingView access', { starter: true, pro: true, desk: true }],
    ['Telegram + Discord alerts', { starter: false, pro: true, desk: true }],
    ['Backtest reports', { starter: false, pro: true, desk: true }],
    ['Webhook integrations', { starter: false, pro: false, desk: true }],
    ['Team seats', { starter: '1', pro: '1', desk: 'Up to 5' }],
    ['Support SLA', { starter: '24h email', pro: '4-min desk', desk: 'Dedicated Slack' }],
    ['Money-back', { starter: '7 days', pro: '7 days', desk: '14 days' }],
    ['Early algo / copy access', { starter: false, pro: false, desk: true }],
  ];

  return (
    <div className="view-enter">
      <MarketingNav/>
      <PageHero
        eyebrow="Pricing"
        title="Pay once. Trade forever."
        sub="Three plans. All with auto-bound TradingView access, no card-on-file games, and a money-back guarantee."
      >
        <div className="billing-toggle">
          {[
            ['monthly', 'Monthly'],
            ['yearly', 'Yearly', '−17%'],
            ['lifetime', 'Lifetime', 'Best value'],
          ].map(([k, l, b]) => (
            <button key={k} className={"billing-toggle-btn " + (billing === k ? 'active' : '')} onClick={() => setBilling(k)}>
              {l}
              {b && <span className={"billing-toggle-tag" + (k === 'lifetime' ? ' billing-toggle-tag-accent' : '')}>{b}</span>}
            </button>
          ))}
        </div>
      </PageHero>

      {/* Plan cards */}
      <section className="container container-wide" style={{ padding: '40px 24px 24px' }}>
        <div className="pricing-grid">
          {plans.map(p => (
            <div key={p.key} className={"pricing-card " + (p.featured ? 'pricing-card-featured' : '')}>
              {p.featured && <div className="pricing-card-flag">Most popular</div>}
              <div className="pricing-card-head">
                <h3 className="h3" style={{ margin: 0 }}>{p.name}</h3>
                <div style={{ color: 'var(--text-2)', fontSize: 14, marginTop: 4 }}>{p.tagline}</div>
              </div>
              <div className="pricing-price">
                <span className="pricing-currency">$</span>
                <span className="pricing-num">{p.price[billing]}</span>
                <span className="pricing-period">{period}</span>
              </div>
              <div style={{ fontSize: 13, color: 'var(--muted)', marginBottom: 18 }}>{p.desc}</div>
              <Btn kind={p.featured ? 'primary' : 'default'} size="lg" style={{ width: '100%', justifyContent: 'center' }} onClick={() => navigate('/signup')}>
                {p.featured ? 'Start with Pro' : `Choose ${p.name}`} <I.arrow size={14}/>
              </Btn>
              <ul className="pricing-list">
                {p.includes.map(it => (
                  <li key={it}><span className="pricing-li-ico"><I.check size={11}/></span>{it}</li>
                ))}
                {(p.missing || []).map(it => (
                  <li key={it} className="pricing-li-off"><span className="pricing-li-ico" style={{ background: 'transparent', color: 'var(--faint)' }}><I.x size={10}/></span>{it}</li>
                ))}
              </ul>
            </div>
          ))}
        </div>
      </section>

      {/* Compare table */}
      <section className="container container-wide" style={{ padding: '40px 24px 80px' }}>
        <h2 className="h2" style={{ margin: '0 0 24px' }}>Compare every plan.</h2>
        <div className="compare-wrap">
          <table className="compare-table">
            <thead>
              <tr>
                <th></th>
                {plans.map(p => (
                  <th key={p.key}>
                    <div style={{ fontWeight: 600 }}>{p.name}</div>
                    <div className="mono" style={{ fontSize: 13, color: 'var(--muted)', marginTop: 2 }}>${p.price[billing]}<span style={{ fontSize: 11 }}> {period}</span></div>
                  </th>
                ))}
              </tr>
            </thead>
            <tbody>
              {features.map(([f, vals]) => (
                <tr key={f}>
                  <td className="compare-feat">{f}</td>
                  {['starter', 'pro', 'desk'].map(k => (
                    <td key={k} className="compare-val">
                      {vals[k] === true ? <span style={{ color: 'var(--up)' }}><I.check size={14}/></span>
                        : vals[k] === false ? <span style={{ color: 'var(--faint)' }}><I.minus size={14}/></span>
                        : <span style={{ fontSize: 13 }}>{vals[k]}</span>}
                    </td>
                  ))}
                </tr>
              ))}
            </tbody>
          </table>
        </div>
      </section>

      {/* FAQ stub */}
      <section style={{ borderTop: '1px solid var(--border)', background: 'var(--bg-2)' }}>
        <div className="container container-wide" style={{ padding: '64px 24px 80px' }}>
          <div style={{ display: 'grid', gridTemplateColumns: 'minmax(0, 280px) 1fr', gap: 60, alignItems: 'start' }} className="pricing-faq-grid">
            <h2 className="h2" style={{ margin: 0 }}>Pricing questions.</h2>
            <div style={{ display: 'flex', flexDirection: 'column', gap: 4 }}>
              {[
                ['Can I switch plans?', "Yes — upgrade any time, prorated. Downgrades apply at next renewal."],
                ['What if I lose access to TradingView?', "Open a ticket with proof. We rebind to your new handle once verified, no extra charge."],
                ['Are there hidden fees?', "No. Crypto network fees are paid by us. There are no chargebacks because we don't take cards."],
                ['How does Lifetime work?', "Pay once, own the indicator forever — including all future updates. Tied to your TradingView handle, transferable once with verification."],
              ].map(([q, a]) => (
                <details key={q} className="pricing-faq-item">
                  <summary>{q} <I.plus size={13}/></summary>
                  <div>{a}</div>
                </details>
              ))}
            </div>
          </div>
        </div>
      </section>

      <Footer/>
    </div>
  );
}

/* ───────── About ───────── */
function AboutPage_OLD_UNUSED() {
  const team = [
    { name: 'Marcus Vega', role: 'Founder · Quant', initials: 'MV', bio: '8 years prop equities. Wrote the first Mattobot indicator on a flight to Singapore.' },
    { name: 'Yuki Tanaka', role: 'Head of Research', initials: 'YT', bio: 'Ex-Citadel. Builds the math behind the curtain. PhD in stochastic control.' },
    { name: 'Diego Rojas', role: 'Engineering Lead', initials: 'DR', bio: 'Ex-Coinbase. Pine Script obsessive. Owns the auto-binding pipeline.' },
    { name: 'Lena Hartmann', role: 'Customer Desk', initials: 'LH', bio: '10K+ tickets answered. The voice on Telegram during volatility.' },
  ];

  const milestones = [
    ['2023', 'Founded', 'First indicator shipped to a Discord of 12 friends.'],
    ['2024', 'Marketplace v1', 'Public launch. 6 indicators, 800 customers in month one.'],
    ['2025', 'Auto-binding', 'TradingView handle integration. Median delivery time drops from 6 hours to 9 seconds.'],
    ['2026', 'Algo + copy', 'Algo trading lands Q3, copy trading lands Q4.'],
  ];

  return (
    <div className="view-enter">
      <MarketingNav/>
      <PageHero
        eyebrow="About"
        title="Built by traders. For traders."
        sub="Mattobot started as a private Discord. Today it's a 12-person team shipping the indicators we wish existed when we were on the trading floor."
      />

      {/* Stats strip */}
      <section className="container container-wide" style={{ padding: '0 24px' }}>
        <div className="about-stats">
          {[
            ['12,400+', 'active traders'],
            ['3.4M', 'signals delivered'],
            ['$47M', 'paid to affiliates'],
            ['99.98%', 'uptime'],
          ].map(([v, l]) => (
            <div key={l}>
              <div className="about-stat-v">{v}</div>
              <div className="about-stat-l">{l}</div>
            </div>
          ))}
        </div>
      </section>

      {/* Mission */}
      <section className="container container-wide" style={{ padding: '80px 24px 56px' }}>
        <div style={{ display: 'grid', gridTemplateColumns: 'minmax(0, 280px) 1fr', gap: 60 }} className="about-grid">
          <div className="eyebrow">Our mission</div>
          <div>
            <h2 className="h2" style={{ margin: 0, marginBottom: 20, fontSize: 'clamp(26px, 3.5vw, 36px)' }}>
              Most retail traders lose money to <span style={{ color: 'var(--accent)' }}>noise.</span>
            </h2>
            <p style={{ fontSize: 16, color: 'var(--text-2)', lineHeight: 1.65, margin: 0 }}>
              We build tools that filter market noise from market signal. Pure non-repainting, bar-close-confirmed indicators with transparent math. No black boxes. No "secret strategy." If you don't like the logic, we publish the formula.
            </p>
            <p style={{ fontSize: 16, color: 'var(--text-2)', lineHeight: 1.65, marginTop: 18 }}>
              We don't take a cut of your trades. We sell tools, once. The only thing we want from you after checkout is a 5-star review when the trade hits target.
            </p>
          </div>
        </div>
      </section>

      {/* Timeline */}
      <section style={{ borderTop: '1px solid var(--border)', background: 'var(--bg-2)' }}>
        <div className="container container-wide" style={{ padding: '64px 24px 72px' }}>
          <div className="eyebrow" style={{ marginBottom: 12 }}>Timeline</div>
          <h2 className="h2" style={{ margin: '0 0 40px' }}>Three years in.</h2>
          <div className="timeline">
            {milestones.map(([y, t, d]) => (
              <div key={y} className="timeline-row">
                <div className="timeline-year">{y}</div>
                <div className="timeline-dot"/>
                <div>
                  <div className="timeline-t">{t}</div>
                  <div className="timeline-d">{d}</div>
                </div>
              </div>
            ))}
          </div>
        </div>
      </section>

      {/* Team */}
      <section className="container container-wide" style={{ padding: '80px 24px 96px' }}>
        <div className="eyebrow" style={{ marginBottom: 12 }}>Team</div>
        <h2 className="h2" style={{ margin: '0 0 32px' }}>The people behind the desk.</h2>
        <div className="team-grid">
          {team.map(p => (
            <div key={p.name} className="team-card">
              <div className="team-avatar">{p.initials}</div>
              <div style={{ fontWeight: 600, fontSize: 15 }}>{p.name}</div>
              <div style={{ fontSize: 12, color: 'var(--accent)', textTransform: 'uppercase', letterSpacing: 0.06, marginTop: 2, marginBottom: 12 }}>{p.role}</div>
              <div style={{ fontSize: 13, color: 'var(--text-2)', lineHeight: 1.5 }}>{p.bio}</div>
            </div>
          ))}
        </div>
      </section>

      <Footer/>
    </div>
  );
}

/* ───────── Contact ───────── */
function ContactPage() {
  const { toast } = React.useContext(ToastContext);
  const [data, setData] = usX({ name: '', email: '', topic: 'general', msg: '' });
  const [sent, setSent] = usX(false);
  const submit = (e) => { e.preventDefault(); setSent(true); toast('Message sent — we reply in under 4 minutes.'); };

  return (
    <div className="view-enter">
      <MarketingNav/>
      <PageHero
        eyebrow="Contact"
        title="The desk replies in under 4 minutes."
        sub="Mon–Sun, 04:00–22:00 UTC. Outside those hours we still answer — usually within an hour."
      />
      <section className="container container-wide" style={{ padding: '40px 24px 96px' }}>
        <div className="contact-grid">
          {/* Channels */}
          <div style={{ display: 'flex', flexDirection: 'column', gap: 12 }}>
            {[
              { ico: <I.bolt size={16}/>, t: 'Live desk', d: 'Telegram · @mattobot_desk', m: 'Avg. 4 min', cta: 'Open Telegram' },
              { ico: <I.inbox size={16}/>, t: 'Email', d: 'desk@mattobot.io', m: 'Avg. 2 hours', cta: 'Send email' },
              { ico: <I.users size={16}/>, t: 'Community', d: 'Discord · 8,400 members', m: 'Live', cta: 'Join server' },
              { ico: <I.shield size={16}/>, t: 'Security', d: 'security@mattobot.io', m: 'PGP available', cta: 'Report a vuln' },
            ].map(c => (
              <a key={c.t} href="#" className="contact-card" style={{ flexWrap: 'wrap', rowGap: 8 }}>
                <span className="contact-card-ico" style={{ flex: 'none' }}>{c.ico}</span>
                <div style={{ flex: '1 1 160px', minWidth: 0 }}>
                  <div style={{ fontWeight: 600, fontSize: 14 }}>{c.t}</div>
                  <div style={{ fontSize: 12.5, color: 'var(--muted)', marginTop: 2, overflowWrap: 'anywhere' }}>{c.d}</div>
                </div>
                <div style={{ textAlign: 'right', flex: 'none' }}>
                  <div className="mono" style={{ fontSize: 11, color: 'var(--accent)' }}>{c.m}</div>
                  <div style={{ fontSize: 11, color: 'var(--muted)', marginTop: 2 }}>{c.cta} →</div>
                </div>
              </a>
            ))}
          </div>

          {/* Form */}
          <div className="card" style={{ padding: 'clamp(18px, 4vw, 28px)' }}>
            {sent ? (
              <div style={{ textAlign: 'center', padding: '32px 0' }}>
                <div style={{ width: 56, height: 56, borderRadius: 999, background: 'var(--accent-soft)', display: 'inline-flex', alignItems: 'center', justifyContent: 'center', marginBottom: 16, color: 'var(--accent)' }}>
                  <I.check size={28}/>
                </div>
                <h2 className="h3" style={{ margin: '0 0 8px' }}>Message sent.</h2>
                <p style={{ color: 'var(--muted)' }}>We'll reply to <span className="mono">{data.email}</span> within 4 minutes.</p>
                <Btn style={{ marginTop: 16 }} onClick={() => { setSent(false); setData({ name: '', email: '', topic: 'general', msg: '' }); }}>Send another</Btn>
              </div>
            ) : (
              <form onSubmit={submit} style={{ display: 'flex', flexDirection: 'column', gap: 14 }}>
                <h2 className="h3" style={{ margin: 0 }}>Send us a message</h2>
                <div className="contact-row-2">
                  <div className="field">
                    <label className="field-label">Your name</label>
                    <input className="input" required value={data.name} onChange={e => setData({...data, name: e.target.value})} placeholder="Marcus K."/>
                  </div>
                  <div className="field">
                    <label className="field-label">Email</label>
                    <input className="input" type="email" required value={data.email} onChange={e => setData({...data, email: e.target.value})} placeholder="you@example.com"/>
                  </div>
                </div>
                <div className="field">
                  <label className="field-label">Topic</label>
                  <div className="contact-topic">
                    {[
                      ['general', 'General'],
                      ['support', 'Support'],
                      ['billing', 'Billing'],
                      ['partnership', 'Partnership'],
                    ].map(([v, l]) => (
                      <button key={v} type="button" className={"contact-topic-btn " + (data.topic === v ? 'active' : '')} onClick={() => setData({...data, topic: v})}>
                        {l}
                      </button>
                    ))}
                  </div>
                </div>
                <div className="field">
                  <label className="field-label">Message</label>
                  <textarea className="input" rows={5} required value={data.msg} onChange={e => setData({...data, msg: e.target.value})} placeholder="What's going on?"/>
                </div>
                <Btn kind="primary" size="lg" type="submit" style={{ justifyContent: 'center', marginTop: 4 }}>
                  Send message <I.arrow size={14}/>
                </Btn>
              </form>
            )}
          </div>
        </div>
      </section>
      <Footer/>
    </div>
  );
}

/* ───────── Affiliates (real page) ───────── */
function AffiliatesPage() {
  const { navigate } = useHashRoute();
  const [vol, setVol] = usX(2500);
  const tier = vol >= 25000 ? 20 : vol >= 5000 ? 15 : 10;
  const monthly = (vol * (tier / 100));

  const tiers = [
    { name: 'Starter', cut: 10, vol: '$0 – $5K' },
    { name: 'Pro', cut: 15, vol: '$5K – $25K' },
    { name: 'Elite', cut: 20, vol: '$25K+' },
  ];

  return (
    <div className="view-enter">
      <MarketingNav/>
      <PageHero
        eyebrow="Affiliate program"
        title="10% lifetime. Paid in USDT. Weekly."
        sub="Share your link. Anyone who signs up under it earns you 10% of every purchase they make, forever. No tricks. No clawbacks."
      >
        <div style={{ display: 'flex', gap: 8, justifyContent: 'center', flexWrap: 'wrap', marginTop: 12 }}>
          <Btn kind="primary" size="lg" onClick={() => navigate('/signup')}>Become an affiliate <I.arrow size={14}/></Btn>
          <Btn size="lg" onClick={() => navigate('/dashboard/referrals')}>See dashboard</Btn>
        </div>
      </PageHero>

      {/* Calculator */}
      <section className="container container-wide" style={{ padding: '64px 24px 56px' }}>
        <div className="calc-grid">
          <div>
            <div className="eyebrow" style={{ marginBottom: 8 }}>Earnings calculator</div>
            <h2 className="h2" style={{ margin: '0 0 16px' }}>How much could you make?</h2>
            <p style={{ color: 'var(--text-2)', lineHeight: 1.55, marginBottom: 24 }}>
              Drag the slider to see what your monthly USDT payout looks like at different referral volumes.
            </p>
            <div className="calc-card">
              <div style={{ display: 'flex', justifyContent: 'space-between', marginBottom: 12 }}>
                <span style={{ fontSize: 13, color: 'var(--muted)' }}>Monthly volume referred</span>
                <span className="mono" style={{ fontSize: 16, fontWeight: 600 }}>${vol.toLocaleString()}</span>
              </div>
              <input type="range" min={500} max={50000} step={500} value={vol} onChange={e => setVol(+e.target.value)} className="calc-range" style={{ background: `linear-gradient(90deg, var(--accent) 0%, var(--accent) ${((vol - 500) / (50000 - 500)) * 100}%, var(--surface-2) ${((vol - 500) / (50000 - 500)) * 100}%)` }}/>
              <div style={{ display: 'flex', justifyContent: 'space-between', fontSize: 11, color: 'var(--faint)', marginTop: 6 }}>
                <span>$500</span><span>$25K</span><span>$50K</span>
              </div>
            </div>
            <div className="calc-result">
              <div>
                <div className="calc-result-l">Your tier</div>
                <div className="calc-result-v">{tiers.find(t => t.cut === tier).name}</div>
                <div className="mono" style={{ fontSize: 12, color: 'var(--accent)' }}>{tier}% commission</div>
              </div>
              <div className="calc-result-arrow"><I.arrow size={16}/></div>
              <div>
                <div className="calc-result-l">Monthly payout</div>
                <div className="calc-result-v" style={{ color: 'var(--up)' }}>${monthly.toFixed(0)}</div>
                <div className="mono" style={{ fontSize: 12, color: 'var(--muted)' }}>${(monthly * 12).toFixed(0)} / year</div>
              </div>
            </div>
          </div>

          {/* Tiers visual */}
          <div className="aff-tiers">
            <div className="eyebrow" style={{ marginBottom: 16 }}>Tiers</div>
            {tiers.map(t => (
              <div key={t.name} className={"aff-tier " + (t.cut === tier ? 'aff-tier-active' : '')}>
                <div className="aff-tier-cut">{t.cut}<span style={{ fontSize: 16 }}>%</span></div>
                <div style={{ flex: 1 }}>
                  <div style={{ fontWeight: 600, fontSize: 14 }}>{t.name}</div>
                  <div className="mono" style={{ fontSize: 12, color: 'var(--muted)' }}>{t.vol} referred</div>
                </div>
                {t.cut === tier && <span className="pill pill-accent">Your tier</span>}
              </div>
            ))}
          </div>
        </div>
      </section>

      {/* How it works */}
      <section style={{ borderTop: '1px solid var(--border)', background: 'var(--bg-2)' }}>
        <div className="container container-wide" style={{ padding: '64px 24px 80px' }}>
          <div className="eyebrow" style={{ marginBottom: 12 }}>How it works</div>
          <h2 className="h2" style={{ margin: '0 0 32px' }}>Three steps to start earning.</h2>
          <div className="aff-steps">
            {[
              ['01', 'Sign up & grab your link', 'Free account. Your unique code is generated instantly.'],
              ['02', 'Share with traders', 'Telegram, X, YouTube reviews, your blog — wherever your audience is.'],
              ['03', 'Get paid weekly in USDT', 'Friday payouts above $10. No clawbacks. No expiration.'],
            ].map(([n, t, d]) => (
              <div key={n} className="aff-step">
                <div className="aff-step-num">{n}</div>
                <div className="aff-step-t">{t}</div>
                <div className="aff-step-d">{d}</div>
              </div>
            ))}
          </div>
        </div>
      </section>

      {/* Top affiliates leaderboard */}
      <section className="container container-wide" style={{ padding: '64px 24px 96px' }}>
        <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'baseline', flexWrap: 'wrap', gap: 12, marginBottom: 24 }}>
          <div>
            <div className="eyebrow" style={{ marginBottom: 8 }}>Leaderboard</div>
            <h2 className="h2" style={{ margin: 0 }}>Top affiliates · this month</h2>
          </div>
          <span className="mono" style={{ fontSize: 12, color: 'var(--muted)' }}>updated 2m ago</span>
        </div>
        <div className="card" style={{ padding: 0, overflow: 'hidden' }}>
          {[
            { rank: 1, name: '@signal_sensei', vol: 47820, earned: 9564, refs: 142 },
            { rank: 2, name: '@cryptocoach_jp', vol: 31240, earned: 6248, refs: 88 },
            { rank: 3, name: '@deskmonk', vol: 22150, earned: 3322, refs: 64 },
            { rank: 4, name: '@theta_trades', vol: 14400, earned: 2160, refs: 41 },
            { rank: 5, name: '@orderflow_om', vol: 9120, earned: 1368, refs: 28 },
          ].map(r => (
            <div key={r.rank} className="leaderboard-row">
              <div className={"leaderboard-rank " + (r.rank <= 3 ? 'leaderboard-rank-top' : '')}>{r.rank.toString().padStart(2, '0')}</div>
              <div style={{ display: 'flex', alignItems: 'center', gap: 12, flex: 1, minWidth: 0 }}>
                <div className="auth-avatar" style={{ width: 32, height: 32, fontSize: 11, background: 'var(--surface-2)', color: 'var(--text)', flex: 'none' }}>{r.name.slice(1, 3).toUpperCase()}</div>
                <span className="mono" style={{ fontSize: 13, fontWeight: 500, minWidth: 0, overflow: 'hidden', textOverflow: 'ellipsis' }}>{r.name}</span>
              </div>
              <div className="leaderboard-stat hide-mobile"><span className="l">Refs</span><span className="v mono">{r.refs}</span></div>
              <div className="leaderboard-stat hide-mobile"><span className="l">Volume</span><span className="v mono">${r.vol.toLocaleString()}</span></div>
              <div className="leaderboard-stat"><span className="l">Earned</span><span className="v mono" style={{ color: 'var(--up)' }}>${r.earned.toLocaleString()}</span></div>
            </div>
          ))}
        </div>
      </section>

      <Footer/>
    </div>
  );
}

/* ───────── Docs ───────── */
function DocsPage() {
  const { navigate } = useHashRoute();
  const [active, setActive] = usX('getting-started');
  const sections = {
    'getting-started': {
      title: 'Getting started',
      cat: 'Quickstart',
      content: [
        { t: 'Create your account', p: "Sign up with email. No card needed. Add your TradingView handle in settings, or wait until your first purchase prompts you." },
        { t: 'Buy your first indicator', p: "Browse the marketplace, pick a plan (monthly / yearly / lifetime), and pay in BTC, ETH, or USDT. Median time from confirmation → access: 9 seconds." },
        { t: 'Open it in TradingView', p: "Refresh TradingView. Open the indicator panel → invite-only scripts. Your purchased indicator appears at the top. Add it to your chart." },
        { t: 'Configure alerts', p: "Right-click the indicator → Add Alert. Set a Telegram or Discord webhook URL (we provide both in your dashboard) to receive every signal in real-time." },
      ],
    },
    'tradingview': {
      title: 'TradingView binding',
      cat: 'Quickstart',
      content: [
        { t: 'How auto-binding works', p: "When your payment confirms on-chain, our backend pings TradingView's invite API with your username. Access propagates within 5–30 seconds." },
        { t: 'Changing your TV username', p: "Once every 7 days. Lock prevents account-sharing abuse. Your dashboard shows a live countdown to the next unlock." },
        { t: 'I lost access to my TV account', p: "Open a support ticket with proof of original purchase. We rebind to your new handle once verified." },
      ],
    },
    'indicators': {
      title: 'Using indicators',
      cat: 'Indicators',
      content: [
        { t: 'Repainting policy', p: "We do not ship repainting indicators in production. All signals are confirmed on bar-close. If we ever ship one for educational use, it's labeled in the changelog." },
        { t: 'Recommended timeframes', p: "Each indicator's detail page lists tested timeframes. As a rule: trend tools 1H+, momentum tools 15m+, scalp tools 1m–15m." },
        { t: 'Markets supported', p: "Pine Script runs on every TradingView market. Defaults are tuned for crypto; preset configs ship for SPX, FX majors, and gold." },
      ],
    },
    'alerts': {
      title: 'Webhooks & alerts',
      cat: 'Indicators',
      content: [
        { t: 'Setting up Telegram alerts', p: "Generate your webhook token in Settings → Integrations. Right-click any indicator → Add Alert → paste the webhook URL. Alerts arrive in <1 second." },
        { t: 'Discord, Slack, custom', p: "We support every webhook-compatible service. Build custom payloads in the alert message editor." },
        { t: 'Rate limits', p: "Up to 240 alerts per hour per indicator. Anything above triggers throttle for 5 minutes." },
      ],
    },
    'billing': {
      title: 'Billing',
      cat: 'Account',
      content: [
        { t: 'Payment methods', p: "BTC (native), ETH (ERC20), USDT (ERC20, TRC20, BEP20). Card processing lands Q2 2026 — KYC'd merchants only." },
        { t: 'Refund policy', p: "7-day money-back guarantee on all plans, no questions asked. Beyond 7 days we issue store credit at our discretion." },
        { t: 'Switching plans', p: "Upgrade any time, prorated. Downgrades take effect at next renewal. Lifetime upgrades from monthly/yearly receive credit toward the lifetime price." },
      ],
    },
    'security': {
      title: 'Security',
      cat: 'Account',
      content: [
        { t: '2FA', p: "TOTP-based 2FA available in Settings → Security. We strongly recommend enabling it on accounts with active subscriptions." },
        { t: 'API keys', p: "When algo trading lands (Q3 2026), exchange API keys are stored encrypted at rest. Trade-only permissions; no withdrawal access ever requested." },
        { t: 'Reporting vulnerabilities', p: "security@mattobot.io. PGP key on the contact page. Bounties up to $5,000 for critical issues." },
      ],
    },
  };

  const grouped = {};
  Object.entries(sections).forEach(([k, s]) => { (grouped[s.cat] ||= []).push([k, s.title]); });
  const cur = sections[active];

  return (
    <div className="view-enter">
      <MarketingNav/>
      <section className="container container-wide" style={{ padding: '40px 24px 80px' }}>
        <div className="docs-grid">
          {/* Sidebar */}
          <aside className="docs-side">
            <div className="docs-search">
              <I.search size={13}/>
              <input placeholder="Search docs…"/>
              <span className="kbd hide-mobile" style={{ fontSize: 10 }}>⌘K</span>
            </div>
            {Object.entries(grouped).map(([cat, items]) => (
              <div key={cat} style={{ marginTop: 18 }}>
                <div className="docs-cat">{cat}</div>
                {items.map(([k, t]) => (
                  <button key={k} onClick={() => setActive(k)} className={"docs-link " + (active === k ? 'docs-link-active' : '')}>
                    {t}
                  </button>
                ))}
              </div>
            ))}
            <div className="docs-cta">
              <div style={{ fontSize: 12, color: 'var(--muted)', marginBottom: 8 }}>Need a human?</div>
              <Btn size="sm" onClick={() => navigate('/contact')} style={{ width: '100%', justifyContent: 'center' }}>Contact desk</Btn>
            </div>
          </aside>

          {/* Content */}
          <div className="docs-content">
            <div style={{ fontSize: 12, color: 'var(--muted)', marginBottom: 8, display: 'flex', alignItems: 'center', gap: 6, flexWrap: 'wrap' }}>
              Docs <I.chevR size={10}/> {cur.cat} <I.chevR size={10}/> <span style={{ color: 'var(--text-2)' }}>{cur.title}</span>
            </div>
            <h1 className="h1" style={{ margin: '0 0 12px', fontSize: 'clamp(28px, 4vw, 38px)' }}>{cur.title}</h1>
            <p style={{ color: 'var(--text-2)', fontSize: 15, marginBottom: 28 }}>Last updated 2 days ago · Reading time ≈ 4 min</p>
            {cur.content.map((c, i) => (
              <div key={i} className="docs-block">
                <h3 className="h3" style={{ margin: '0 0 10px' }}>{c.t}</h3>
                <p style={{ color: 'var(--text-2)', lineHeight: 1.65, margin: 0 }}>{c.p}</p>
              </div>
            ))}
            <div className="docs-feedback">
              <span style={{ fontSize: 13, color: 'var(--text-2)' }}>Was this helpful?</span>
              <div style={{ display: 'flex', gap: 8 }}>
                <Btn size="sm">👍 Yes</Btn>
                <Btn size="sm">👎 No</Btn>
              </div>
            </div>
          </div>
        </div>
      </section>
      <Footer/>
    </div>
  );
}

/* ───────── Legal pages (Terms / Privacy / Refund) ───────── */
function LegalPage({ kind }) {
  const docs = {
    terms: {
      title: 'Terms of Service',
      updated: 'October 2025',
      sections: [
        ['1. Acceptance of Terms', "By accessing Mattobot you agree to these terms. If you don't agree, don't use the service."],
        ['2. Eligibility', "You must be 18+ and legally able to enter contracts. Trading is not available to residents of OFAC-sanctioned countries."],
        ['3. Indicators are tools, not advice', "Mattobot indicators are technical analysis tools. They do not constitute financial, investment, legal, or tax advice. Trading involves substantial risk of loss."],
        ['4. License & restrictions', "Purchase grants a non-transferable license to use the indicator on your TradingView account. You may not redistribute, reverse-engineer, or share access."],
        ['5. TradingView username changes', "Limited to once per 7 days per indicator to prevent account sharing. Compromised accounts may rebind sooner with verified support tickets."],
        ['6. Refunds', "7-day money-back guarantee on all plans. Beyond 7 days, refunds are at our discretion. See Refund Policy."],
        ['7. Service availability', "We target 99.9% uptime but do not guarantee uninterrupted service. Scheduled maintenance windows posted in #status on Discord."],
        ['8. Termination', "We may suspend accounts for fraud, abuse, or violations of these terms. You may close your account anytime."],
        ['9. Liability', "Mattobot is not liable for trading losses. Maximum liability is limited to fees paid in the 12 months preceding the claim."],
        ['10. Governing law', "These terms are governed by the laws of Delaware, USA. Disputes resolved by arbitration in Wilmington, DE."],
      ],
    },
    privacy: {
      title: 'Privacy Policy',
      updated: 'October 2025',
      sections: [
        ['1. What we collect', "Email, TradingView username, payment data (handled by our crypto processor — we never see card info), and basic usage analytics."],
        ['2. Why we collect it', "To deliver indicator access, send transactional emails, prevent fraud, and improve the product. We don't sell data."],
        ['3. Cookies', "We use cookies only for session and preference storage. No advertising trackers."],
        ['4. Third parties', "TradingView (for indicator access), Stripe (future card processing), and Sendgrid (transactional email). All bound by data-processing agreements."],
        ['5. Your rights', "GDPR/CCPA: request export or deletion at any time via privacy@mattobot.io. We respond within 30 days."],
        ['6. Data retention', "Account data kept while your account is active. Closed accounts purged after 90 days, except where law requires retention (tax records: 7 years)."],
        ['7. Security', "TLS 1.3 in transit. AES-256 at rest. Annual penetration tests. Bug bounty program at security@mattobot.io."],
      ],
    },
    refund: {
      title: 'Refund Policy',
      updated: 'October 2025',
      sections: [
        ['Money-back guarantee', "Every plan includes a 7-day money-back guarantee from the date of purchase. No questions asked. We refund in the same crypto you paid with, at the rate at time of refund."],
        ['How to request', "Open a ticket at desk@mattobot.io with your order ID. We process within 24 hours."],
        ['Outside the 7-day window', "Refunds are at our discretion. We'll typically issue store credit equal to the prorated unused portion."],
        ['Exceptions', "We do not refund: (a) accounts terminated for fraud or abuse, (b) purchases made with stolen funds, (c) requests after 30 days."],
        ['Chargebacks', "We don't process cards, so chargebacks are not applicable. Crypto refunds are final once sent."],
      ],
    },
  };
  const doc = docs[kind] || docs.terms;
  return (
    <div className="view-enter">
      <MarketingNav/>
      <section className="container" style={{ padding: '40px 24px 96px', maxWidth: 760 }}>
        <Link to="/" className="auth-back" style={{ marginLeft: -12, marginBottom: 18 }}>
          <I.chevL size={12}/> Back home
        </Link>
        <div className="eyebrow" style={{ marginBottom: 12 }}>Legal</div>
        <h1 className="h1" style={{ margin: '0 0 12px', fontSize: 'clamp(30px, 5vw, 44px)' }}>{doc.title}</h1>
        <p style={{ color: 'var(--muted)', fontSize: 14, marginBottom: 36 }}>Last updated {doc.updated}</p>
        <div style={{ display: 'flex', gap: 8, marginBottom: 32, flexWrap: 'wrap' }}>
          {[['terms','Terms'],['privacy','Privacy'],['refund','Refund']].map(([k, l]) => (
            <Link key={k} to={"/legal/" + k} className={"legal-tab " + (kind === k ? 'legal-tab-active' : '')}>{l}</Link>
          ))}
        </div>
        <div className="legal-doc">
          {doc.sections.map(([t, p]) => (
            <div key={t} className="legal-section">
              <h2>{t}</h2>
              <p>{p}</p>
            </div>
          ))}
        </div>
      </section>
      <Footer/>
    </div>
  );
}

/* ───────── 404 ───────── */
function NotFoundPage() {
  const { navigate } = useHashRoute();
  return (
    <div className="view-enter">
      <MarketingNav/>
      <section style={{ position: 'relative', minHeight: 'calc(100vh - 64px)', display: 'flex', alignItems: 'center', overflow: 'hidden' }}>
        <div className="aurora"/>
        <div className="grid-bg" style={{ position: 'absolute', inset: 0, opacity: 0.3 }}/>
        <div className="container container-wide" style={{ position: 'relative', padding: '80px 24px', textAlign: 'center' }}>
          <div className="not-found-num">
            <span>4</span>
            <span className="not-found-zero">
              <span className="not-found-zero-inner"/>
            </span>
            <span>4</span>
          </div>
          <h1 className="h1" style={{ margin: '24px auto 16px', fontSize: 'clamp(28px, 4vw, 40px)' }}>This chart doesn't exist.</h1>
          <p style={{ fontSize: 16, color: 'var(--text-2)', maxWidth: 480, margin: '0 auto 32px' }}>
            The page you're after either moved, was retired, or never existed. Let's get you back to a profitable view.
          </p>
          <div style={{ display: 'flex', gap: 8, justifyContent: 'center', flexWrap: 'wrap' }}>
            <Btn kind="primary" size="lg" onClick={() => navigate('/')}>Back to landing <I.arrow size={14}/></Btn>
            <Btn size="lg" onClick={() => navigate('/marketplace')}>Browse indicators</Btn>
            <Btn size="lg" onClick={() => navigate('/contact')}>Contact desk</Btn>
          </div>
        </div>
      </section>
      <Footer/>
    </div>
  );
}

Object.assign(window, { PricingPage, ContactPage, AffiliatesPage, DocsPage, LegalPage, NotFoundPage });

})();
/* ===== about-page.jsx ===== */
(function(){
/* About page — completely rebuilt
   Style: editorial trading-floor narrative. Asymmetric grid,
   numbered chapters, mono-data callouts, manifesto, principles,
   live "desk" stat block, ticker-tape stack of milestones, team rolodex. */

const { useState: usAb, useEffect: ueAb, useMemo: umAb, useRef: urAb } = React;

function AboutPage() {
  const { navigate } = useHashRoute();
  const [activeChapter, setActiveChapter] = usAb(0);

  /* ──────────────── Data ──────────────── */

  const principles = [
    { n: '01', t: 'No repaint. Ever.', d: "If a signal moves after the bar closes, it's broken. We ship deterministic logic — what you see at 09:32 is what you saw at 09:31." },
    { n: '02', t: 'Math is public.',   d: "Every indicator ships with its formula in plain English. No 'proprietary AI engine' marketing. If you can't explain it, it's not a strategy." },
    { n: '03', t: 'One price. Owned.', d: "Lifetime means lifetime. No card-on-file. No surprise renewals. You buy a tool the way you'd buy a wrench." },
    { n: '04', t: "We don't trade your money.", d: "Mattobot will never custody funds. Algo Q3 sends webhooks to your exchange. Copy Q4 routes through your keys, on your risk." },
    { n: '05', t: 'The desk picks up.', d: "Every paying customer has a Telegram handle to a human on the desk. Median first-reply time this quarter: 3 min 42 s." },
  ];

  const chapters = [
    {
      year: '2023',
      tag: 'Origin',
      title: 'A spreadsheet on a flight to Singapore.',
      body: "Marcus was up 17% on the year and didn't know why. Yuki opened his sheet on a 14-hour flight, found the alpha was almost entirely from a single intra-day pattern, and turned it into 80 lines of Pine Script. They named it Aurora. They shipped it to a Discord of twelve friends. Six of them quit their jobs.",
      stat: ['12', 'discord members on day one'],
    },
    {
      year: '2024',
      tag: 'Marketplace v1',
      title: 'Public launch. 800 customers in 30 days.',
      body: "Six indicators behind a checkout page. The whole thing was held together with cron jobs and Stripe receipts. The first month was a fire. The second month we hired Lena to answer the fire. We've never let go of the desk-first philosophy since.",
      stat: ['800', 'customers in month one'],
    },
    {
      year: '2025',
      tag: 'Auto-binding',
      title: 'TradingView access drops from 6 hours to 9 seconds.',
      body: "Until 2025 every customer waited up to six hours for a human to manually invite their TradingView handle. We built a webhook bridge into TV's admin API. Median provisioning time fell to 9 seconds. Refunds dropped 40%. Affiliate share jumped to 22% of revenue overnight.",
      stat: ['9 s', 'median provisioning time'],
    },
    {
      year: '2026',
      tag: 'Coming up',
      title: 'Algo trading lands Q3. Copy trading lands Q4.',
      body: "Two missions remain. Algo turns any indicator alert into an exchange-side limit order, with position sizing and risk caps you control. Copy lets the top 5% of our customers monetize their edge — they trade, you mirror, they get a cut, no custody anywhere.",
      stat: ['Q3 / Q4', 'next two launches'],
    },
  ];

  const team = [
    { initials: 'MV', name: 'Marcus Vega',     role: 'Founder · Quant',         loc: 'NYC',    bio: '8 yrs prop equities. Wrote Aurora on a flight.', stat: '17 indicators authored' },
    { initials: 'YT', name: 'Yuki Tanaka',     role: 'Head of Research',         loc: 'Tokyo',  bio: 'Ex-Citadel. PhD in stochastic control. Owns the math.', stat: '4 papers in review' },
    { initials: 'DR', name: 'Diego Rojas',     role: 'Engineering Lead',         loc: 'Madrid', bio: 'Ex-Coinbase. Pine Script obsessive. Built the binding pipeline.', stat: '99.98% uptime FY25' },
    { initials: 'LH', name: 'Lena Hartmann',   role: 'Customer Desk Lead',       loc: 'Berlin', bio: '10K+ tickets answered. The voice on Telegram during volatility.', stat: '3m 42s median reply' },
    { initials: 'AK', name: 'Aisha Khan',      role: 'Risk · Backtests',         loc: 'London', bio: 'Ex-Man Group. Validates every signal across 14 years of tape.', stat: '2.4M backtests run' },
    { initials: 'OL', name: 'Olu Lawal',       role: 'Affiliate Operations',     loc: 'Lagos',  bio: 'Runs the affiliate desk. Pays out every Friday in USDT.', stat: '$47M paid lifetime' },
  ];

  const liveStats = [
    { v: '12,406',  l: 'active traders',     d: '+184 this week' },
    { v: '3.4M',    l: 'signals delivered',  d: '+12K today' },
    { v: '$47.2M',  l: 'paid to affiliates', d: 'since 2024' },
    { v: '99.98%',  l: 'uptime · 365d',      d: 'no incidents 47 d' },
    { v: '14',      l: 'shipped indicators', d: '2 in QA' },
    { v: '47',      l: 'team + contractors', d: '11 countries' },
  ];

  const press = [
    "Modular Capital",
    "Bloomberg Crypto",
    "Decrypt",
    "Forbes Fintech",
    "The Block",
    "TradingView Blog",
  ];

  return (
    <div className="view-enter ab-root">
      <MarketingNav/>

      {/* ════════════════ HERO ════════════════ */}
      <section className="ab-hero">
        <div className="ab-hero-grid">
          {/* Left: kicker + huge title */}
          <div className="ab-hero-left">
            <div className="ab-hero-kicker">
              <span className="ab-hero-bar"/>
              <span className="mono">FILE · MATTOBOT / 001</span>
              <span className="mono ab-hero-meta">Founded 2023 · Wilmington, DE</span>
            </div>
            <h1 className="ab-hero-title">
              We build the<br/>
              <span className="ab-hero-em">indicators</span><br/>
              we wished we<br/>
              had on the floor.
            </h1>
            <div className="ab-hero-sig">
              <div className="ab-hero-sig-line"/>
              <div>
                <div className="mono ab-hero-sig-name">— Marcus Vega, Founder</div>
                <div className="ab-hero-sig-sub">est. June 2023, on a flight to Singapore.</div>
              </div>
            </div>
          </div>

          {/* Right: terminal-style desk panel */}
          <div className="ab-hero-right">
            <div className="ab-hero-desk">
              <div className="ab-hero-desk-head">
                <span className="ab-hero-desk-dots">
                  <span/><span/><span/>
                </span>
                <span className="mono ab-hero-desk-title">desk · live</span>
                <span className="ab-hero-desk-status"><span className="live-dot"/> open</span>
              </div>
              <div className="ab-hero-desk-body">
                {[
                  ['07:14:32', 'order', '@kai_fx purchased Aurora Trend · Lifetime'],
                  ['07:14:01', 'bind',  '@deskmonk · TV access provisioned in 8s'],
                  ['07:13:45', 'pay',   'USDT 599 · TX confirmed · 12 confs'],
                  ['07:12:58', 'desk',  'Lena replied to #18429 in 2m 11s'],
                  ['07:12:14', 'algo',  'EURUSD · BUY signal · 1.0832'],
                  ['07:11:30', 'aff',   '@signal_sensei → +$248 commission'],
                  ['07:10:55', 'order', '@orderflow_om purchased Pulse Velocity'],
                ].map((r, i) => (
                  <div key={i} className="ab-hero-desk-row">
                    <span className="mono ab-hero-desk-time">{r[0]}</span>
                    <span className={"ab-hero-desk-tag tag-" + r[1]}>{r[1]}</span>
                    <span className="ab-hero-desk-msg">{r[2]}</span>
                  </div>
                ))}
              </div>
              <div className="ab-hero-desk-foot">
                <span className="mono">live feed · 90s window</span>
                <span className="mono">refresh 1.0s</span>
              </div>
            </div>
          </div>
        </div>
      </section>

      {/* ════════════════ MARQUEE ════════════════ */}
      <section className="ab-marquee">
        <div className="ab-marquee-track">
          {[...Array(2)].map((_, k) => (
            <div key={k} className="ab-marquee-row">
              {press.map(p => (
                <span key={p + k} className="ab-marquee-item">
                  <span className="ab-marquee-dot"/> as seen in <span className="ab-marquee-name">{p}</span>
                </span>
              ))}
            </div>
          ))}
        </div>
      </section>

      {/* ════════════════ BY THE NUMBERS ════════════════ */}
      <section className="ab-stats-sec">
        <div className="container container-wide">
          <div className="ab-section-head">
            <span className="mono ab-sec-tag">§ 02 · Today</span>
            <h2 className="ab-h2">By the numbers,<br/><span className="ab-h2-mute">as of right now.</span></h2>
          </div>
          <div className="ab-stats-grid">
            {liveStats.map((s, i) => (
              <div key={s.l} className="ab-stat" style={{ '--i': i }}>
                <div className="ab-stat-rule"/>
                <div className="ab-stat-v mono">{s.v}</div>
                <div className="ab-stat-l">{s.l}</div>
                <div className="ab-stat-d mono">{s.d}</div>
              </div>
            ))}
          </div>
        </div>
      </section>

      {/* ════════════════ MANIFESTO ════════════════ */}
      <section className="ab-manifesto">
        <div className="container container-wide">
          <div className="ab-section-head">
            <span className="mono ab-sec-tag">§ 03 · Manifesto</span>
          </div>
          <p className="ab-quote">
            <span className="ab-quote-mark">"</span>
            Most retail traders lose money to <em>noise</em>. We don't sell magic — we sell filters. Every line of Pine we ship is one we'd run on our own book.
            <span className="ab-quote-mark ab-quote-end">"</span>
          </p>
          <div className="ab-quote-cite">
            <div className="ab-quote-avatar">MV</div>
            <div>
              <div className="ab-quote-name">Marcus Vega</div>
              <div className="ab-quote-role mono">Founder · Mattobot Labs</div>
            </div>
          </div>
        </div>
      </section>

      {/* ════════════════ PRINCIPLES ════════════════ */}
      <section className="ab-principles-sec">
        <div className="container container-wide">
          <div className="ab-section-head">
            <span className="mono ab-sec-tag">§ 04 · Operating principles</span>
            <h2 className="ab-h2">Five rules we won't bend.</h2>
          </div>
          <div className="ab-principles">
            {principles.map((p, i) => (
              <div key={p.n} className="ab-principle" style={{ '--i': i }}>
                <div className="ab-principle-num mono">{p.n}</div>
                <div className="ab-principle-body">
                  <h3 className="ab-principle-t">{p.t}</h3>
                  <p className="ab-principle-d">{p.d}</p>
                </div>
                <div className="ab-principle-tick">✓</div>
              </div>
            ))}
          </div>
        </div>
      </section>

      {/* ════════════════ STORY / CHAPTERS ════════════════ */}
      <section className="ab-story-sec">
        <div className="container container-wide">
          <div className="ab-section-head">
            <span className="mono ab-sec-tag">§ 05 · The story</span>
            <h2 className="ab-h2">Three years.<br/><span className="ab-h2-mute">Four chapters.</span></h2>
          </div>

          <div className="ab-story">
            {/* Chapter selector rail */}
            <aside className="ab-story-rail">
              <div className="ab-story-rail-line"/>
              {chapters.map((c, i) => (
                <button
                  key={c.year}
                  className={"ab-story-rail-btn " + (activeChapter === i ? 'active' : '')}
                  onClick={() => setActiveChapter(i)}
                >
                  <span className="ab-story-rail-dot"/>
                  <span className="mono ab-story-rail-year">{c.year}</span>
                  <span className="ab-story-rail-tag">{c.tag}</span>
                </button>
              ))}
            </aside>

            {/* Active chapter */}
            <article className="ab-story-body" key={activeChapter}>
              <div className="ab-story-head">
                <span className="mono ab-story-chap">CHAPTER {String(activeChapter + 1).padStart(2, '0')}</span>
                <span className="ab-story-yearbig mono">{chapters[activeChapter].year}</span>
              </div>
              <h3 className="ab-story-title">{chapters[activeChapter].title}</h3>
              <p className="ab-story-text">{chapters[activeChapter].body}</p>
              <div className="ab-story-stat">
                <div className="ab-story-stat-v mono">{chapters[activeChapter].stat[0]}</div>
                <div className="ab-story-stat-l">{chapters[activeChapter].stat[1]}</div>
              </div>
              <div className="ab-story-nav">
                <button
                  className="ab-story-nav-btn"
                  disabled={activeChapter === 0}
                  onClick={() => setActiveChapter(i => Math.max(0, i - 1))}
                >
                  <I.chevL size={12}/> Prev
                </button>
                <span className="mono ab-story-nav-of">
                  {String(activeChapter + 1).padStart(2, '0')} / {String(chapters.length).padStart(2, '0')}
                </span>
                <button
                  className="ab-story-nav-btn"
                  disabled={activeChapter === chapters.length - 1}
                  onClick={() => setActiveChapter(i => Math.min(chapters.length - 1, i + 1))}
                >
                  Next <I.chevR size={12}/>
                </button>
              </div>
            </article>
          </div>
        </div>
      </section>

      {/* ════════════════ TEAM ════════════════ */}
      <section className="ab-team-sec">
        <div className="container container-wide">
          <div className="ab-section-head">
            <span className="mono ab-sec-tag">§ 06 · Crew</span>
            <h2 className="ab-h2">The 47 humans<br/><span className="ab-h2-mute">running the desk.</span></h2>
            <p className="ab-section-sub">Six of them, in their own words.</p>
          </div>
          <div className="ab-team">
            {team.map((p, i) => (
              <div key={p.name} className="ab-team-card" style={{ '--i': i }}>
                <div className="ab-team-card-top">
                  <div className="ab-team-avatar">{p.initials}</div>
                  <div className="mono ab-team-loc"><span className="live-dot"/>{p.loc}</div>
                </div>
                <div className="ab-team-name">{p.name}</div>
                <div className="ab-team-role mono">{p.role}</div>
                <p className="ab-team-bio">{p.bio}</p>
                <div className="ab-team-stat mono">
                  <span className="ab-team-stat-arrow">→</span>{p.stat}
                </div>
              </div>
            ))}
          </div>

          <div className="ab-team-foot">
            <div>
              <div className="mono ab-team-foot-l">Hiring · Q2 2026</div>
              <div className="ab-team-foot-t">Senior Quant Researcher · ML Engineer · Customer Desk (APAC)</div>
            </div>
            <Btn kind="primary" onClick={() => navigate('/contact')}>See open roles <I.arrow size={13}/></Btn>
          </div>
        </div>
      </section>

      {/* ════════════════ CTA ════════════════ */}
      <section className="ab-cta-sec">
        <div className="container container-wide">
          <div className="ab-cta">
            <div className="ab-cta-grid-bg"/>
            <div className="ab-cta-left">
              <div className="mono ab-sec-tag">§ 07 · Get on the tape</div>
              <h2 className="ab-cta-title">Indicators built by people who still trade.</h2>
              <p className="ab-cta-sub">Pick one tool. Pay once. Trade with it forever. Or talk to the desk first — we'll tell you which one fits your style.</p>
            </div>
            <div className="ab-cta-actions">
              <Btn kind="primary" size="lg" onClick={() => navigate('/marketplace')}>Browse indicators <I.arrow size={14}/></Btn>
              <Btn size="lg" onClick={() => navigate('/contact')}>Talk to the desk</Btn>
            </div>
          </div>
        </div>
      </section>

      <Footer/>
    </div>
  );
}

Object.assign(window, { AboutPage });

})();
