// Footer — physics sign wall + utility footer (social & legal from Supabase)

const PALETTE = [
  { id:"default", bg:null,      fg:null,   swatch:"var(--bg-surface-2)", border:"var(--border-default)" },
  { id:"flame",   bg:"#FD3A25", fg:"#fff", swatch:"#FD3A25" },
  { id:"cobalt",  bg:"#2563EB", fg:"#fff", swatch:"#2563EB" },
  { id:"emerald", bg:"#16A34A", fg:"#fff", swatch:"#16A34A" },
  { id:"violet",  bg:"#7C3AED", fg:"#fff", swatch:"#7C3AED" },
  { id:"amber",   bg:"#D97706", fg:"#fff", swatch:"#D97706" },
  { id:"rose",    bg:"#DB2777", fg:"#fff", swatch:"#DB2777" },
  { id:"ink",     bg:"#09090B", fg:"#fff", swatch:"#09090B" },
];

const CANVAS_H  = 600;
const GRAVITY   = 0.055;
const DAMP_X    = 0.975;
const DAMP_Y    = 0.978;
const FLR_BNCE  = 0.12;
const WALL_BNCE = 0.18;
const MAX_ITEMS = 80;

function pillWidth(name) { return Math.min(name.length, 30) * 7.4 + 32; }

// ─── Social icon map ──────────────────────────────────────────
const SOCIAL_ICONS = {
  twitter:   <svg viewBox="0 0 24 24" width="16" height="16" fill="currentColor"><path d="M18.244 2.25h3.308l-7.227 8.26 8.502 11.24H16.17l-4.714-6.231-5.401 6.231H2.747l7.73-8.835L1.254 2.25H8.08l4.265 5.635 5.899-5.635zm-1.161 17.52h1.833L7.084 4.126H5.117z"/></svg>,
  linkedin:  <svg viewBox="0 0 24 24" width="16" height="16" fill="currentColor"><path d="M20.447 20.452h-3.554v-5.569c0-1.328-.027-3.037-1.852-3.037-1.853 0-2.136 1.445-2.136 2.939v5.667H9.351V9h3.414v1.561h.046c.477-.9 1.637-1.85 3.37-1.85 3.601 0 4.267 2.37 4.267 5.455v6.286zM5.337 7.433a2.062 2.062 0 01-2.063-2.065 2.064 2.064 0 112.063 2.065zm1.782 13.019H3.555V9h3.564v11.452zM22.225 0H1.771C.792 0 0 .774 0 1.729v20.542C0 23.227.792 24 1.771 24h20.451C23.2 24 24 23.227 24 22.271V1.729C24 .774 23.2 0 22.222 0h.003z"/></svg>,
  github:    <svg viewBox="0 0 24 24" width="16" height="16" fill="currentColor"><path d="M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12"/></svg>,
  dribbble:  <svg viewBox="0 0 24 24" width="16" height="16" fill="currentColor"><path d="M12 24C5.385 24 0 18.615 0 12S5.385 0 12 0s12 5.385 12 12-5.385 12-12 12zm10.12-10.358c-.35-.11-3.17-.953-6.384-.438 1.34 3.684 1.887 6.684 1.992 7.308 2.3-1.555 3.936-4.02 4.395-6.87zm-6.115 7.808c-.153-.9-.75-4.032-2.19-7.77l-.066.02c-5.79 2.015-7.86 6.017-8.04 6.4 1.73 1.35 3.92 2.165 6.29 2.165 1.42 0 2.77-.29 4-.814zm-11.62-2.073c.232-.4 3.045-5.055 8.332-6.765.135-.045.27-.084.405-.12-.26-.585-.54-1.167-.832-1.74C7.17 12.775 2.206 12.73 1.756 12.72l-.004.28c0 2.01.605 3.88 1.63 5.44zm-1.64-7.33c.46.008 4.953.145 9.822-1.302-1.44-2.56-2.99-4.622-3.21-4.913-2.98 1.407-5.157 4.015-6.612 6.215zM12 2.163c-.63 0-1.24.08-1.84.22.22.3 1.79 2.35 3.21 4.965 3.034-1.137 4.327-2.863 4.485-3.086A9.968 9.968 0 0012 2.163zm7.798 4.868c-.19.25-1.622 2.08-4.79 3.385.2.413.39.83.57 1.25.065.148.13.295.19.446 3.39-.428 6.745.257 7.1.33-.025-1.96-.62-3.784-1.6-5.41l-.47.0z"/></svg>,
  instagram: <svg viewBox="0 0 24 24" width="16" height="16" fill="currentColor"><path d="M12 2.163c3.204 0 3.584.012 4.85.07 3.252.148 4.771 1.691 4.919 4.919.058 1.265.069 1.645.069 4.849 0 3.205-.012 3.584-.069 4.849-.149 3.225-1.664 4.771-4.919 4.919-1.266.058-1.644.07-4.85.07-3.204 0-3.584-.012-4.849-.07-3.26-.149-4.771-1.699-4.919-4.92-.058-1.265-.07-1.644-.07-4.849 0-3.204.013-3.583.07-4.849.149-3.227 1.664-4.771 4.919-4.919 1.266-.057 1.645-.069 4.849-.069zM12 0C8.741 0 8.333.014 7.053.072 2.695.272.273 2.69.073 7.052.014 8.333 0 8.741 0 12c0 3.259.014 3.668.072 4.948.2 4.358 2.618 6.78 6.98 6.98C8.333 23.986 8.741 24 12 24c3.259 0 3.668-.014 4.948-.072 4.354-.2 6.782-2.618 6.979-6.98.059-1.28.073-1.689.073-4.948 0-3.259-.014-3.667-.072-4.947-.196-4.354-2.617-6.78-6.979-6.98C15.668.014 15.259 0 12 0zm0 5.838a6.162 6.162 0 100 12.324 6.162 6.162 0 000-12.324zM12 16a4 4 0 110-8 4 4 0 010 8zm6.406-11.845a1.44 1.44 0 100 2.881 1.44 1.44 0 000-2.881z"/></svg>,
  facebook:  <svg viewBox="0 0 24 24" width="16" height="16" fill="currentColor"><path d="M24 12.073c0-6.627-5.373-12-12-12s-12 5.373-12 12c0 5.99 4.388 10.954 10.125 11.854v-8.385H7.078v-3.47h3.047V9.43c0-3.007 1.792-4.669 4.533-4.669 1.312 0 2.686.235 2.686.235v2.953H15.83c-1.491 0-1.956.925-1.956 1.874v2.25h3.328l-.532 3.47h-2.796v8.385C19.612 23.027 24 18.062 24 12.073z"/></svg>,
  youtube:   <svg viewBox="0 0 24 24" width="16" height="16" fill="currentColor"><path d="M23.498 6.186a3.016 3.016 0 00-2.122-2.136C19.505 3.545 12 3.545 12 3.545s-7.505 0-9.377.505A3.017 3.017 0 00.502 6.186C0 8.07 0 12 0 12s0 3.93.502 5.814a3.016 3.016 0 002.122 2.136c1.871.505 9.376.505 9.376.505s7.505 0 9.377-.505a3.015 3.015 0 002.122-2.136C24 15.93 24 12 24 12s0-3.93-.502-5.814zM9.545 15.568V8.432L15.818 12l-6.273 3.568z"/></svg>,
  tiktok:    <svg viewBox="0 0 24 24" width="16" height="16" fill="currentColor"><path d="M12.525.02c1.31-.02 2.61-.01 3.91-.02.08 1.53.63 3.09 1.75 4.17 1.12 1.11 2.7 1.62 4.24 1.79v4.03c-1.44-.05-2.89-.35-4.2-.97-.57-.26-1.1-.59-1.62-.93-.01 2.92.01 5.84-.02 8.75-.08 1.4-.54 2.79-1.35 3.94-1.31 1.92-3.58 3.17-5.91 3.21-1.43.08-2.86-.31-4.08-1.03-2.02-1.19-3.44-3.37-3.65-5.71-.02-.5-.03-1-.01-1.49.18-1.9 1.12-3.72 2.58-4.96 1.66-1.44 3.98-2.13 6.15-1.72.02 1.48-.04 2.96-.04 4.44-.99-.32-2.15-.23-3.02.37-.63.41-1.11 1.04-1.36 1.75-.21.51-.15 1.07-.14 1.61.24 1.64 1.82 3.02 3.5 2.87 1.12-.01 2.19-.66 2.77-1.61.19-.33.4-.67.41-1.06.1-1.79.06-3.57.07-5.36.01-4.03-.01-8.05.02-12.07z"/></svg>,
  behance:   <svg viewBox="0 0 24 24" width="16" height="16" fill="currentColor"><path d="M6.938 4.503c.702 0 1.34.06 1.92.188.577.13 1.07.33 1.485.61.41.28.733.65.96 1.12.225.47.34 1.05.34 1.73 0 .74-.17 1.36-.507 1.86-.338.5-.837.9-1.502 1.22.906.26 1.576.72 2.022 1.37.448.66.665 1.45.665 2.36 0 .75-.13 1.39-.41 1.93-.28.55-.67 1-.158 1.35-.544.35-1.15.59-1.817.74-.666.15-1.36.22-2.08.22H0V4.51h6.938zm-.43 5.56c.6 0 1.09-.14 1.46-.41.367-.28.55-.72.55-1.32 0-.34-.06-.62-.19-.84-.126-.22-.298-.39-.513-.52-.217-.12-.47-.21-.757-.26-.29-.04-.6-.07-.93-.07H3.59V10.06h2.92zm.23 5.81c.36 0 .695-.03 1.006-.1.313-.07.586-.18.822-.34.235-.16.423-.37.56-.63.138-.26.207-.59.207-.99 0-.79-.222-1.36-.67-1.7-.445-.34-1.03-.51-1.76-.51H3.59v4.27h3.148zm9.122-5.5c.42-.46.97-.69 1.67-.69.43 0 .81.1 1.12.29.32.19.58.44.79.74.21.3.36.65.45 1.03.09.38.13.77.13 1.17H15.04c.04.7.24 1.22.59 1.56.35.34.82.52 1.39.52.44 0 .82-.1 1.13-.31.31-.21.51-.44.61-.69h2.41c-.38 1.14-1 1.97-1.83 2.49-.84.52-1.84.78-3.01.78-.82 0-1.56-.13-2.23-.39-.67-.26-1.24-.63-1.7-1.11-.47-.48-.83-1.06-1.09-1.74-.25-.68-.38-1.43-.38-2.26 0-.8.13-1.54.38-2.21.25-.67.61-1.25 1.07-1.73.47-.48 1.03-.85 1.69-1.11.66-.26 1.4-.39 2.23-.39.9 0 1.69.17 2.37.51.68.34 1.24.8 1.67 1.37.44.57.75 1.22.95 1.96.2.74.27 1.53.2 2.37h-7.01c0-.81.24-1.45.72-1.91zM17.34 9.9c-.33-.33-.8-.5-1.42-.5-.4 0-.74.07-1.01.21-.27.14-.49.31-.66.52-.17.2-.29.43-.36.67-.07.25-.11.48-.12.71h4.18c-.07-.74-.28-1.28-.61-1.61zm-2.38-3.66h4.77V7.5h-4.77V6.24z"/></svg>,
};

// ─── Physics wall ─────────────────────────────────────────────
const PhysicsWall = React.forwardRef(({ initialEntries }, ref) => {
  const containerRef = React.useRef(null);
  const stateRef     = React.useRef({ items:[], dragging:null, W:0, raf:null });

  React.useImperativeHandle(ref, () => ({
    addItem:      (name, color)          => spawnText(name, color),
    addImageItem: (dataUrl, color, w, h) => spawnImage(dataUrl, color, w, h),
  }));

  function attachDrag(item) {
    const state = stateRef.current;
    let lx = 0, ly = 0, vx = 0, vy = 0;
    const onDown = (e) => {
      e.stopPropagation(); e.preventDefault();
      state.dragging = item.id;
      item.el.style.cursor    = "grabbing";
      item.el.style.zIndex    = "20";
      item.el.style.boxShadow = "var(--shadow-btn-dark)";
      const cx = e.clientX ?? e.touches?.[0]?.clientX;
      const cy = e.clientY ?? e.touches?.[0]?.clientY;
      lx = cx; ly = cy; vx = 0; vy = 0;
      const onMove = (ev) => {
        ev.preventDefault();
        const mx = ev.clientX ?? ev.touches?.[0]?.clientX;
        const my = ev.clientY ?? ev.touches?.[0]?.clientY;
        vx = mx - lx; vy = my - ly; lx = mx; ly = my;
        const r = containerRef.current.getBoundingClientRect();
        item.x = mx - r.left - item.w / 2;
        item.y = my - r.top  - item.h / 2;
        item.el.style.transform = `translate(${item.x}px,${item.y}px)`;
      };
      const onUp = () => {
        state.dragging = null;
        item.el.style.cursor    = "grab";
        item.el.style.zIndex    = "";
        item.el.style.boxShadow = "";
        item.vx = vx * 0.45; item.vy = vy * 0.45;
        window.removeEventListener("mousemove", onMove);
        window.removeEventListener("mouseup",   onUp);
        window.removeEventListener("touchmove", onMove);
        window.removeEventListener("touchend",  onUp);
      };
      window.addEventListener("mousemove", onMove);
      window.addEventListener("mouseup",   onUp);
      window.addEventListener("touchmove", onMove, { passive:false });
      window.addEventListener("touchend",  onUp);
    };
    item.el.addEventListener("mousedown",  onDown);
    item.el.addEventListener("touchstart", onDown, { passive:false });
  }

  function pushItem(item) {
    const state = stateRef.current;
    if (state.items.length >= MAX_ITEMS) {
      const old = state.items.shift();
      old.el?.parentNode?.removeChild(old.el);
    }
    attachDrag(item);
    state.items.push(item);
    containerRef.current?.appendChild(item.el);
    item.el.style.transform = `translate(${item.x}px,${item.y}px)`;
  }

  function spawnText(name, color) {
    const W  = stateRef.current.W || containerRef.current?.offsetWidth || 800;
    const w  = pillWidth(name), h = 30;
    const el = document.createElement("span");
    el.className   = "ag-wall__entry";
    el.textContent = name.length > 30 ? name.slice(0, 29) + "…" : name;
    let css = "position:absolute;top:0;left:0;cursor:grab;user-select:none;will-change:transform;touch-action:none;";
    if (color?.bg) css += `background:${color.bg};color:${color.fg};border-color:${color.bg}40;`;
    el.style.cssText = css;
    pushItem({
      id: Date.now() + Math.random(), name, el, w, h,
      x: Math.random() * Math.max(10, W - w - 10) + 5,
      y: 20,
      vx: (Math.random() - 0.5) * 1.5,
      vy: -1.5,
    });
  }

  function spawnImage(dataUrl, color, iw = 120, ih = 75) {
    const W  = stateRef.current.W || containerRef.current?.offsetWidth || 800;
    const el = document.createElement("img");
    el.src = dataUrl; el.draggable = false;
    const border = color?.bg ? `2px solid ${color.bg}` : "1px solid var(--border-default)";
    el.style.cssText = `
      position:absolute;top:0;left:0;
      width:${iw}px;height:${ih}px;
      border-radius:10px;border:${border};
      background:#fff;object-fit:contain;
      box-shadow:var(--shadow-btn-light);
      cursor:grab;user-select:none;
      will-change:transform;touch-action:none;
    `;
    pushItem({
      id: Date.now() + Math.random(), name:"sig", el, w:iw, h:ih,
      x: W / 2 - iw / 2 + (Math.random() - 0.5) * 60,
      y: 30,
      vx: (Math.random() - 0.5) * 1.2,
      vy: -2,
    });
  }

  React.useEffect(() => {
    const container = containerRef.current;
    if (!container) return;
    const state = stateRef.current;
    state.W = container.offsetWidth;

    initialEntries.slice(0, MAX_ITEMS).forEach((entry) => {
      const colorObj = entry.color ? { bg: entry.color, fg: '#fff' } : null;
      if (entry.signature_image) {
        spawnImage(entry.signature_image, colorObj, 120, 75);
      } else {
        spawnText(entry.text_content || entry.name, colorObj);
      }
    });

    const tick = () => {
      const { items, dragging } = state;
      const W = state.W;
      for (let i = 0; i < items.length; i++) {
        const it = items[i];
        if (it.id === dragging) continue;
        it.vy += GRAVITY; it.vx *= DAMP_X; it.vy *= DAMP_Y;
        it.x += it.vx; it.y += it.vy;
        if (it.x < 0)               { it.x = 0;           it.vx =  Math.abs(it.vx) * WALL_BNCE; }
        if (it.x + it.w > W)        { it.x = W - it.w;    it.vx = -Math.abs(it.vx) * WALL_BNCE; }
        if (it.y < 0)               { it.y = 0;           it.vy =  Math.abs(it.vy) * WALL_BNCE; }
        if (it.y + it.h > CANVAS_H - 1) {
          it.y  = CANVAS_H - it.h - 1;
          it.vy = Math.abs(it.vy) < 0.8 ? 0 : -Math.abs(it.vy) * FLR_BNCE;
          it.vx *= 0.88;
        }
        it.el.style.transform = `translate(${it.x}px,${it.y}px)`;
      }
      for (let i = 0; i < items.length - 1; i++) {
        for (let j = i + 1; j < items.length; j++) {
          const a = items[i], b = items[j];
          const dx  = (a.x + a.w/2) - (b.x + b.w/2);
          const dy  = (a.y + a.h/2) - (b.y + b.h/2);
          const mnX = (a.w + b.w)/2 + 3;
          const mnY = (a.h + b.h)/2 + 3;
          if (Math.abs(dx) < mnX && Math.abs(dy) < mnY) {
            const px = mnX - Math.abs(dx), py = mnY - Math.abs(dy);
            if (px < py) {
              const push = px * 0.28 * Math.sign(dx || 1);
              if (a.id !== dragging) { a.x += push; a.vx += push * 0.012; }
              if (b.id !== dragging) { b.x -= push; b.vx -= push * 0.012; }
            } else {
              const push = py * 0.28 * Math.sign(dy || 1);
              if (a.id !== dragging) { a.y += push; a.vy += push * 0.012; }
              if (b.id !== dragging) { b.y -= push; b.vy -= push * 0.012; }
            }
          }
        }
      }
      state.raf = requestAnimationFrame(tick);
    };

    state.raf = requestAnimationFrame(tick);
    const onResize = () => { state.W = container.offsetWidth; };
    window.addEventListener("resize", onResize);
    return () => {
      cancelAnimationFrame(state.raf);
      window.removeEventListener("resize", onResize);
      state.items.forEach(it => it.el?.parentNode?.removeChild(it.el));
      state.items = [];
    };
  }, []);

  return <div ref={containerRef} className="ag-wall__canvas" aria-label="Interactive wall of names"/>;
});

// ─── Draw panel ───────────────────────────────────────────────
const DrawPanel = ({ color, onClose, onAdd, lang = 'en' }) => {
  const canvasRef = React.useRef(null);

  React.useEffect(() => {
    const canvas = canvasRef.current;
    if (!canvas) return;
    const ctx = canvas.getContext("2d");
    ctx.fillStyle = "#fff";
    ctx.fillRect(0, 0, canvas.width, canvas.height);
    const stroke = color?.bg || "#09090B";
    ctx.strokeStyle = stroke; ctx.fillStyle = stroke;
    ctx.lineWidth = 2.5; ctx.lineCap = "round"; ctx.lineJoin = "round";
    let drawing = false, lx = 0, ly = 0;
    const pos = (e) => {
      const r = canvas.getBoundingClientRect();
      return {
        x: ((e.clientX ?? e.touches?.[0]?.clientX) - r.left) * (canvas.width  / r.width),
        y: ((e.clientY ?? e.touches?.[0]?.clientY) - r.top)  * (canvas.height / r.height),
      };
    };
    const onDown = (e) => { e.stopPropagation(); e.preventDefault(); drawing = true; const {x,y} = pos(e); lx=x; ly=y; ctx.beginPath(); ctx.arc(x,y,1.5,0,Math.PI*2); ctx.fill(); };
    const onMove = (e) => { if (!drawing) return; e.stopPropagation(); e.preventDefault(); const {x,y} = pos(e); ctx.beginPath(); ctx.moveTo(lx,ly); ctx.lineTo(x,y); ctx.stroke(); lx=x; ly=y; };
    const onUp   = () => { drawing = false; };
    canvas.addEventListener("mousedown",  onDown);
    canvas.addEventListener("mousemove",  onMove);
    window.addEventListener("mouseup",    onUp);
    canvas.addEventListener("touchstart", onDown, { passive:false });
    canvas.addEventListener("touchmove",  onMove, { passive:false });
    canvas.addEventListener("touchend",   onUp);
    return () => {
      canvas.removeEventListener("mousedown",  onDown);
      canvas.removeEventListener("mousemove",  onMove);
      window.removeEventListener("mouseup",    onUp);
      canvas.removeEventListener("touchstart", onDown);
      canvas.removeEventListener("touchmove",  onMove);
      canvas.removeEventListener("touchend",   onUp);
    };
  }, [color]);

  const clear = () => {
    const ctx = canvasRef.current?.getContext("2d");
    if (!ctx) return;
    ctx.fillStyle = "#fff";
    ctx.fillRect(0, 0, canvasRef.current.width, canvasRef.current.height);
  };

  return (
    <div className="ag-wall__draw-panel">
      <div className="ag-wall__draw-head">
        <span>{t('wall.drawTitle', lang)}</span>
        <button type="button" onClick={onClose} aria-label="Close draw panel">×</button>
      </div>
      <canvas ref={canvasRef} className="ag-wall__draw-canvas" width={216} height={130}/>
      <div className="ag-wall__draw-foot">
        <Button variant="light" onClick={clear}>{t('wall.clearBtn', lang)}</Button>
        <Button variant="dark"  onClick={() => { const d = canvasRef.current?.toDataURL(); if (d) onAdd(d); }}>{t('wall.addToWall', lang)}</Button>
      </div>
    </div>
  );
};

// ─── Wall section ─────────────────────────────────────────────
const PenIcon = () => (
  <svg viewBox="0 0 24 24" width="13" height="13" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" aria-hidden="true">
    <path d="M12 20h9"/><path d="M16.5 3.5a2.121 2.121 0 0 1 3 3L7 19l-4 1 1-4L16.5 3.5z"/>
  </svg>
);

const Wall = ({ lang = 'en' }) => {
  const physicsRef  = React.useRef(null);
  const [value,     setValue]    = React.useState("");
  const [flash,     setFlash]    = React.useState(false);
  const [color,     setColor]    = React.useState(null);
  const [showDraw,  setShowDraw] = React.useState(false);
  const [entries,   setEntries]  = React.useState(null);
  const [pendingData, setPendingData] = React.useState(null);
  const [showEmailModal, setShowEmailModal] = React.useState(false);
  const [modalEmail, setModalEmail] = React.useState('');
  const [emailSubmitting, setEmailSubmitting] = React.useState(false);
  const [emailError, setEmailError] = React.useState('');

  React.useEffect(() => {
    db.from('sign_wall_items')
      .select('id, name, text_content, signature_image, color')
      .eq('is_hidden', false)
      .order('created_at', { ascending: false })
      .limit(MAX_ITEMS)
      .then(({ data, error }) => {
        if (error) console.error('[wall] fetch failed:', error);
        setEntries(data || []);
      });
  }, []);

  const triggerFlash = () => { setFlash(true); setTimeout(() => setFlash(false), 1400); };

  const submitText = (e) => {
    e.preventDefault();
    const name = value.trim().replace(/[\n\r]/g, "").slice(0, 50);
    if (!name) return;
    physicsRef.current?.addItem(name, color);
    setValue("");
    triggerFlash();
    setPendingData({ type: 'text', name, text_content: name, signature_image: null, color: color?.bg || null });
    setModalEmail('');
    setEmailError('');
    setShowEmailModal(true);
  };

  const addSignature = (dataUrl) => {
    physicsRef.current?.addImageItem(dataUrl, color, 120, 75);
    setShowDraw(false);
    triggerFlash();
    setPendingData({ type: 'logo', name: value.trim() || 'Signature', text_content: null, signature_image: dataUrl, color: color?.bg || null });
    setModalEmail('');
    setEmailError('');
    setShowEmailModal(true);
  };

  const confirmEmail = async (email) => {
    const trimmed = email.trim();
    if (!trimmed || !trimmed.includes('@')) {
      setEmailError('Please enter a valid email');
      return;
    }

    setEmailSubmitting(true);
    setEmailError('');
    console.log('[wall] confirming email:', trimmed, 'with pending:', pendingData);

    const { error } = await db.from('sign_wall_items').insert([{
      ...pendingData,
      email: trimmed,
      is_hidden: false,
    }]);

    if (error) {
      console.error('[wall] insert failed:', error);
      if (error.code === '23505' || error.message?.includes('duplicate')) {
        setEmailError(t('wall.errorDup', lang));
      } else {
        setEmailError(t('wall.errorGeneral', lang));
      }
      setEmailSubmitting(false);
      return;
    }

    localStorage.setItem('signed_wall_email', trimmed);
    setPendingData(null);
    setShowEmailModal(false);
    setModalEmail('');
    setEmailError('');
    setValue("");
    triggerFlash();
    setEmailSubmitting(false);
  };

  return (
    <section className="ag-wall">
      <div className="ag-wall__canvas-wrap">
        {entries !== null && <PhysicsWall ref={physicsRef} initialEntries={entries} />}

        <div className="ag-wall__ui">
          <div className="ag-wall__head">
            <h2 className="ag-wall__title">{t('wall.title', lang)}</h2>
            <p className="ag-wall__sub">{t('wall.sub', lang)}</p>
          </div>

          <form className="ag-wall__form" onSubmit={submitText} autoComplete="off">
            <input
              className="ag-wall__input"
              type="text"
              placeholder={t('wall.placeholder', lang)}
              maxLength={50}
              value={value}
              onChange={(e) => setValue(e.target.value)}
              aria-label={t('wall.placeholder', lang)}
              style={color?.bg ? { borderColor: color.bg, boxShadow: `0 0 0 3px ${color.bg}22` } : {}}
            />
            <Button variant="dark" type="submit">{t('wall.signBtn', lang)}</Button>
          </form>

          <div className="ag-wall__toolbar">
            <div className="ag-wall__palette" role="group" aria-label="Entry color">
              <span className="ag-wall__palette-label">{t('wall.colorLabel', lang)}</span>
              {PALETTE.map((p) => (
                <button
                  key={p.id}
                  type="button"
                  className={"ag-wall__swatch" + (p.id === "default" ? " ag-wall__swatch--default" : "") + (color?.id === p.id || (!color && p.id === "default") ? " is-on" : "")}
                  style={{ background: p.swatch || p.bg, borderColor: p.border || p.bg, color: p.bg || "var(--fg-secondary)" }}
                  onClick={() => setColor(p.id === "default" ? null : p)}
                  aria-label={p.id}
                  aria-pressed={color?.id === p.id || (!color && p.id === "default")}
                />
              ))}
            </div>
            <Button variant="light" onClick={() => setShowDraw((v) => !v)}>
              <PenIcon/> {showDraw ? t('wall.closeDrawBtn', lang) : t('wall.drawBtn', lang)}
            </Button>
          </div>

          {flash && <p className="ag-wall__flash" aria-live="polite">{t('wall.flash', lang)}</p>}
        </div>

        {showDraw && <DrawPanel color={color} onClose={() => setShowDraw(false)} onAdd={addSignature} lang={lang}/>}
      </div>

      {showEmailModal && (
        <div className="ag-modal-overlay" onClick={() => { setShowEmailModal(false); setEmailError(''); }} role="presentation">
          <div className="ag-modal" onClick={e => e.stopPropagation()} role="dialog" aria-labelledby="wall-email-title">
            <button
              type="button"
              className="ag-modal__close"
              onClick={() => { setShowEmailModal(false); setEmailError(''); }}
              aria-label="Close"
            >
              ×
            </button>

            <h3 id="wall-email-title" style={{ margin: '0 0 12px', fontSize: '18px', fontWeight: 700 }}>{t('wall.modalTitle', lang)}</h3>
            <p style={{ margin: '0 0 8px', fontSize: '14px', color: 'var(--fg-secondary)' }}>
              {t('wall.modalDesc1', lang)}
            </p>
            <p style={{ margin: '0 0 16px', fontSize: '13px', color: 'var(--fg-secondary)' }}>
              {t('wall.modalDesc2', lang)}
            </p>

            <div className="ag-field" style={{ marginBottom: emailError ? '8px' : '12px' }}>
              <input
                type="email"
                placeholder="your@email.com"
                value={modalEmail}
                onChange={(e) => { setModalEmail(e.target.value); setEmailError(''); }}
                disabled={emailSubmitting}
                aria-invalid={!!emailError}
                style={{ width: '100%', padding: '10px 12px', borderRadius: '8px', border: emailError ? '1px solid rgb(220,38,38)' : '1px solid var(--border-default)', fontFamily: 'inherit' }}
              />
              {emailError && (
                <span style={{ display: 'block', marginTop: '6px', fontSize: '13px', color: 'rgb(220,38,38)' }}>
                  {emailError}
                </span>
              )}
            </div>

            <Button
              variant="dark"
              onClick={() => confirmEmail(modalEmail)}
              disabled={emailSubmitting}
            >
              {emailSubmitting ? t('wall.saving', lang) : t('wall.confirm', lang)}
            </Button>
          </div>
        </div>
      )}
    </section>
  );
};

// ─── Footer ───────────────────────────────────────────────────
const Footer = ({ lang = 'en' }) => {
  const [legalPages,  setLegalPages]  = React.useState([]);
  const [socialLinks, setSocialLinks] = React.useState([]);

  const scrollTo = (id) => {
    const el = document.getElementById(id);
    if (!el) return;
    const top = el.getBoundingClientRect().top + window.scrollY - 80;
    window.scrollTo({ top, behavior: "smooth" });
  };

  React.useEffect(() => {
    // Fetch legal pages for footer links
    db.from('legal_pages')
      .select('slug, content_json')
      .then(({ data }) => { if (data) setLegalPages(data); });

    // Fetch social links from settings
    db.from('content_sections')
      .select('content_json')
      .eq('section_name', 'social_links')
      .single()
      .then(({ data }) => {
        if (Array.isArray(data?.content_json)) setSocialLinks(data.content_json);
      });
  }, []);

  const activeSocial = socialLinks.filter(l => l.url);

  return (
    <>
      <Wall lang={lang} />
      <footer className="ag-ufooter">
        <div className="ag-ufooter__inner">
          <a className="ag-ufooter__logo" onClick={() => scrollTo("ag-section-home")}>
            <img src="assets/logo-mark.png" alt="Blan" className="ag-footer__logo-img"/>
          </a>
          <nav className="ag-ufooter__nav" aria-label="Footer navigation">
            <a onClick={() => scrollTo("ag-section-services")}>{t('footer.services', lang)}</a>
            <a onClick={() => scrollTo("ag-section-pricing")}>{t('footer.pricing', lang)}</a>
            <a onClick={() => scrollTo("ag-section-contact")}>{t('footer.contact', lang)}</a>
            <a href="request-menu.html">{t('footer.requestMenu', lang)}</a>
          </nav>

          {/* Legal links — dynamic from Supabase, fallback to defaults */}
          <div className="ag-ufooter__legal">
            {legalPages.length > 0 ? (
              legalPages.map(p => (
                <a key={p.slug} href={`legal.html?slug=${p.slug}`}>
                  {i18(p.content_json?.title, lang) || p.slug}
                </a>
              ))
            ) : (
              <>
                <a href="legal.html?slug=privacy-policy">Privacy Policy</a>
                <a href="legal.html?slug=terms">Terms of Service</a>
              </>
            )}
            <a href="for-ai.html" className="ag-ufooter__ai-link" target="_blank" rel="noopener">
              <SparkleIcon size={12}/> {t('footer.aiGuide', lang)}
            </a>
          </div>

          {/* Social links — dynamic from Supabase */}
          {activeSocial.length > 0 && (
            <div className="ag-ufooter__social">
              {activeSocial.map(link => (
                <a
                  key={link.id || link.platform}
                  href={link.url}
                  className="ag-ufooter__social-link"
                  aria-label={link.platform}
                  target="_blank"
                  rel="noopener noreferrer"
                >
                  {link.icon_url ? (
                    <img src={link.icon_url} alt={link.platform} style={{ width: 16, height: 16, objectFit: 'contain', display: 'block' }} />
                  ) : (
                    SOCIAL_ICONS[link.platform] || (
                      <svg viewBox="0 0 24 24" width="16" height="16" fill="currentColor">
                        <circle cx="12" cy="12" r="10"/>
                      </svg>
                    )
                  )}
                </a>
              ))}
            </div>
          )}
        </div>

        <div className="ag-ufooter__base">
          <span>{t('footer.copyright', lang)}</span>
          <a className="ag-ufooter__top"
            onClick={() => window.scrollTo({ top: 0, behavior: "smooth" })}>
            {t('footer.backToTop', lang)}
          </a>
        </div>
      </footer>
    </>
  );
};

window.Footer = Footer;
