// NO-SIGN4L web kit — screens

const PRODUCTS = [
  { id:"001", name:"STATIC", price:40, tag:"OBJECTS", sold:true,
    variants: [
      { key:"black", label:"BLACK", meta:"Object · black",
        img:"/assets/products/static-black-front.png", imgBack:"/assets/products/static-black-back.png",
        desc:"Heavyweight fleece sweatpants. Dropped fit, tapered leg. Embroidered NO-SIGN4L mark at hip. System-washed black. Made offline.",
        defaultFor:"dark" },
      { key:"grey", label:"GREY", meta:"Object · grey",
        img:"/assets/products/static-grey-front.png", imgBack:"/assets/products/static-grey-back.png",
        desc:"Heavyweight fleece sweatpants. Dropped fit, tapered leg. Embroidered NO-SIGN4L mark at hip. Signal grey. Made offline.",
        defaultFor:"light" },
    ]
  },
  { id:"003", name:"VAULT", price:50, tag:"OBJECTS", sold:true,
    variants: [
      { key:"black", label:"BLACK", meta:"Object · black",
        img:"/assets/products/vault.png", imgBack:"/assets/products/backpack-black-back.png",
        desc:"Tactical carry object. Reinforced straps, internal mesh compartment, matte hardware throughout. NO-SIGN4L woven label. Carry everything. Say nothing.",
        defaultFor:"dark" },
      { key:"white", label:"WHITE", meta:"Object · white",
        img:"/assets/products/backpack-white-front.png", imgBack:"/assets/products/backpack-white-back.png",
        desc:"Tactical carry object. Reinforced straps, internal mesh compartment, matte hardware throughout. NO-SIGN4L woven label. Carry everything. Say nothing.",
        defaultFor:"light" },
    ]
  },
  { id:"004", name:"PAYLOAD", price:60, meta:"Object · black", sold:true, tag:"OBJECTS",
    img:"/assets/products/payload.png",
    desc:"Heavy-duty duffle. Drop-bottom construction, side compression straps, padded carry handles. NO-SIGN4L mark at seam. Move fast. Travel light." },
  { id:"005", name:"WATER COOLING", price:30, meta:"Object · black", sold:true, tag:"OBJECTS",
    img:"/assets/products/water-cooling.png",
    desc:"Boardshort cut. Quick-dry shell, internal mesh liner, flat-lock seams. NO-SIGN4L mark at left thigh. System stays on even when you're off the grid." },
  { id:"006", name:"ANCHOR", price:10, meta:"Object · matte black", sold:true, tag:"OBJECTS",
    img:"/assets/products/anchor.png?v=2",
    desc:"Lightweight aluminum carabiner. D-gate locking clip. NO-SIGN4L engraved body. Rated for carry, not climbing. Attach to anything." },
  { id:"007", name:"BACKUP FILE", price:25, meta:"Object · white", sold:true, tag:"OBJECTS",
    img:"/assets/products/notebook-white.png",
    desc:"Hardcover system log. Unlined pages. NO-SIGN4L stamped cover. 200 pages. Write it down before it disappears." },
  { id:"008", name:"01001110", price:70, meta:"Surface · 8.25\" · 7-ply maple", sold:true, tag:"SURFACES",
    img:"/assets/products/board-binary.png",
    desc:"7-ply hard rock maple. Full-bleed binary code pattern. NO-SIGN4L mark at nose. Ed. of 200. Made offline." },
  { id:"009", name:"CORRUPT_", price:70, meta:"Surface · 8.25\" · 7-ply maple", sold:true, tag:"SURFACES",
    img:"/assets/products/board-glitch.png",
    desc:"7-ply hard rock maple. NO SIGNAL glitch bleed — high contrast black and white. Ed. of 200. Made offline." },
  { id:"010", name:"VOID", price:70, meta:"Surface · 8.25\" · 7-ply maple", sold:true, tag:"SURFACES",
    img:"/assets/products/board-sysnull.png",
    desc:"7-ply hard rock maple. Minimal system label: SYS-NULL // CODE: NULL-00 // NO LINK // OFFLINE. Ed. of 200." },
  { id:"011", name:"SHELL", price:80, tag:"OBJECTS", sold:true,
    variants: [
      { key:"black", label:"BLACK", meta:"Object · black",
        img:"/assets/products/windbreaker-black-front.png", imgBack:"/assets/products/windbreaker-black-back.png",
        desc:"Lightweight shell. Minimal construction, zip front, dropped shoulders. NO-SIGN4L mark at chest. Blocks wind. Says nothing.",
        defaultFor:"dark" },
      { key:"white", label:"WHITE", meta:"Object · white",
        img:"/assets/products/windbreaker-white-front.png", imgBack:"/assets/products/windbreaker-white-back.png",
        desc:"Lightweight shell. Minimal construction, zip front, dropped shoulders. NO-SIGN4L mark at chest. Blocks wind. Says nothing.",
        defaultFor:"light" },
    ]
  },
  { id:"012", name:"NOISE", price:40, meta:"Object · black", sold:true, tag:"OBJECTS",
    img:"/assets/products/pixel-shirt-front.png", imgBack:"/assets/products/pixel-shirt-back.png",
    desc:"Heavyweight cotton. Full-bleed pixel graphic. NO-SIGN4L mark at collar. Dropped fit. Signal lost." },
  { id:"013", name:"TRIM", price:40, meta:"Object · white", sold:true, tag:"OBJECTS",
    img:"/assets/products/collar-shirt-front.png", imgBack:"/assets/products/collar-shirt-back.png",
    desc:"Clean cut. Contrast collar detail. NO-SIGN4L mark at chest. Structured fit. Presentable even offline." },
  { id:"014", name:"SLING", price:75, meta:"Object · black", sold:true, tag:"OBJECTS",
    img:"/assets/products/crossbody.png",
    desc:"Single-strap crossbody carry. Compact main compartment, front access pocket. NO-SIGN4L woven label. One strap. Hands free." },
  { id:"015", name:"TETHER", price:20, tag:"OBJECTS", sold:true,
    variants: [
      { key:"black", label:"BLACK", meta:"Object · black",
        img:"/assets/products/keychain-black-front.png", imgBack:"/assets/products/keychain-black-back.png",
        desc:"Hard enamel keychain. NO-SIGN4L logomark. Matte black finish. Attach to anything. Lose nothing.",
        defaultFor:"dark" },
      { key:"white", label:"WHITE", meta:"Object · white",
        img:"/assets/products/keychain-white-front.png", imgBack:"/assets/products/keychain-white-back.png",
        desc:"Hard enamel keychain. NO-SIGN4L logomark. Gloss white finish. Attach to anything. Lose nothing.",
        defaultFor:"light" },
    ]
  },
  { id:"016", name:"BASE", price:15, pricePack:25, tag:"OBJECTS", sold:true,
    variants: [
      { key:"black", label:"ALL BLACK", meta:"Object · black",
        img:"/assets/products/socks-black.png",
        desc:"Mid-height. Ribbed cuff. NO-SIGN4L woven label at ankle. All black. Stay grounded.",
        defaultFor:"dark" },
      { key:"blackwhite", label:"BLACK / WHITE", meta:"Object · black + white",
        img:"/assets/products/socks-black-white.png",
        desc:"Mid-height. Ribbed cuff. NO-SIGN4L woven label at ankle. Black body, white toe and heel. Stay grounded.",
        defaultFor:"light" },
    ]
  },
];

function SignalSquares({className}) {
  return (
    <div className={"signal-squares" + (className ? " " + className : "")}>
      <span className="sq filled"></span>
      <span className="sq filled"></span>
      <span className="sq filled"></span>
      <span className="sq hollow"></span>
    </div>
  );
}

function Hero({go, onWaitlist}) {
  return (
    <section className="hero">
      <SignalSquares className="hero-squares" />
      <Lab className="kick" style={{display:"block",marginBottom:18,textTransform:"none"}}>user@lost:~$ // disconnected</Lab>
      <h1 className="hero-title">NULL SURFACE — 001</h1>
      <p className="sub">OBJECTS INTENDED FOR OFFLINE USE.<br/>NO-SIGN4L REQUIRED.</p>
      <div className="row">
        <ScrButton txt="Join Waitlist" className="btn ghost" onClick={onWaitlist} />
      </div>
      <div className="ticker">NO-SIGN4L // SYSTEM OFFLINE // CH04 // NULL</div>
    </section>
  );
}

function ProductCard({p, open}) {
  const theme = React.useContext(ThemeContext);
  const [hovered, setHovered] = React.useState(false);

  const activeVariant = p.variants
    ? (p.variants.find(v => v.defaultFor === theme) || p.variants[0])
    : null;
  const img = activeVariant ? activeVariant.img : p.img;
  const imgBack = activeVariant ? activeVariant.imgBack : p.imgBack;
  const showImg = (hovered && imgBack) ? imgBack : img;

  const blockImageSave = e => e.preventDefault();
  return (
    <div className="pcard" onClick={() => open(p)}
      onMouseEnter={() => setHovered(true)} onMouseLeave={() => setHovered(false)}>
      <div className={img ? "pimg" : "pimg scanline"}>
        {img
          ? <img className={"pimg-real" + (p.tag === "SURFACES" ? " deck" : "")} src={showImg} alt={p.name} onContextMenu={blockImageSave} onDragStart={blockImageSave} draggable="false" />
          : <img className="mark" src={MARK_W} alt="" />
        }
        {!img && <span className="nosig">NO SIGNAL</span>}
      </div>
    </div>
  );
}

const SORT_OPTIONS = [
  { label: "—", fn: (a, b) => parseInt(a.id) - parseInt(b.id) },
  { label: "NEW TO OLD", fn: (a, b) => parseInt(b.id) - parseInt(a.id) },
  { label: "OLD TO NEW", fn: (a, b) => parseInt(a.id) - parseInt(b.id) },
  { label: "PRICE: HIGH TO LOW", fn: (a, b) => b.price - a.price },
  { label: "PRICE: LOW TO HIGH", fn: (a, b) => a.price - b.price },
];

function Grid({open}) {
  const [sort, setSort] = React.useState(0);
  const sorted = [...PRODUCTS].sort(SORT_OPTIONS[sort].fn);
  return (
    <div className="gridwrap">
      <div className="gridhead">
        <Lab bright>DROP // {PRODUCTS.length} OBJECTS</Lab>
        <select
          className="sort-select"
          value={sort}
          onChange={e => setSort(Number(e.target.value))}
        >
          {SORT_OPTIONS.map((o, i) => (
            <option key={i} value={i}>{o.label}</option>
          ))}
        </select>
      </div>
      <div className="grid">
        {sorted.map(p => <ProductCard key={p.id} p={p} open={open} />)}
      </div>
    </div>
  );
}

function ProductDetail({p, back, add, onWaitlist}) {
  const theme = React.useContext(ThemeContext);

  // Variant handling
  const defaultVariant = p.variants
    ? (p.variants.find(v => v.defaultFor === theme) || p.variants[0])
    : null;
  const [activeVariant, setActiveVariant] = React.useState(defaultVariant);

  // When theme changes, auto-switch to that theme's default variant
  React.useEffect(() => {
    if (p.variants) {
      setActiveVariant(p.variants.find(v => v.defaultFor === theme) || p.variants[0]);
    }
  }, [theme]);

  const img = activeVariant ? activeVariant.img : p.img;
  const imgBack = activeVariant ? activeVariant.imgBack : p.imgBack;
  const meta = activeVariant ? activeVariant.meta : p.meta;
  const desc = activeVariant ? activeVariant.desc : p.desc;

  const SIZES = p.tag === "OBJECTS" && (p.name === "STATIC" || p.name === "WATER COOLING") ? ["XS","S","M","L","XL","XXL"]
              : p.tag === "SURFACES" ? ["8.0\"","8.25\"","8.5\""]
              : ["ONE SIZE"];
  const [size, setSize] = React.useState(SIZES.length === 1 ? SIZES[0] : null);
  const [side, setSide] = React.useState(0);

  // Reset slider side when variant changes
  React.useEffect(() => { setSide(0); }, [activeVariant]);

  // Touch swipe
  const touchStart = React.useRef(null);
  const onTouchStart = e => { touchStart.current = e.touches[0].clientX; };
  const onTouchEnd = e => {
    if (touchStart.current === null) return;
    const diff = touchStart.current - e.changedTouches[0].clientX;
    if (Math.abs(diff) > 40) {
      if (diff > 0) setSide(1);
      else setSide(0);
    }
    touchStart.current = null;
  };

  const blockImageSave = e => e.preventDefault();
  return (
    <div className="pdp">
      <div className="media" style={{position:"relative"}}>
        <span className="corner" style={{top:14,left:16}}>NO-SIGN4L™</span>
        <span className="corner" style={{top:14,right:16}}>{p.tag || "NO SIGNAL"}</span>
        {imgBack ? (
          <div className="media-slider" onTouchStart={onTouchStart} onTouchEnd={onTouchEnd}>
            <img className={"slide-img" + (p.tag === "SURFACES" ? " deck" : "")} src={side === 0 ? img : imgBack} alt={p.name + (side === 0 ? " front" : " back")} onContextMenu={blockImageSave} onDragStart={blockImageSave} draggable="false" />
            <button className="slide-arrow left" onClick={() => setSide(0)}>←</button>
            <button className="slide-arrow right" onClick={() => setSide(1)}>→</button>
            <div className="slide-dot">
              <span className={side === 0 ? "active" : ""} />
              <span className={side === 1 ? "active" : ""} />
            </div>
          </div>
        ) : img ? (
          <img className={"detail-img" + (p.tag === "SURFACES" ? " deck" : "")} src={img} alt={p.name} onContextMenu={blockImageSave} onDragStart={blockImageSave} draggable="false" />
        ) : (
          <img src={MARK_W} alt="" style={{width:"30%"}} />
        )}
        <span className="corner" style={{bottom:14,left:16}}>NULL SURFACE</span>
        <span className="corner" style={{bottom:14,right:16}}>NO-SIGN4L</span>
      </div>
      <div className="info">
        <ScrButton className="back" onClick={back} txt="← RETURN TO DROP" />
        <Lab>COMING SOON</Lab>
        <h2>{p.name}</h2>
        <span className="price">${p.price}{p.pricePack && <span style={{fontFamily:"var(--font-mono)",fontSize:13,color:"var(--fg3)",marginLeft:10}}>/ 2-PACK ${p.pricePack}</span>}</span>
        <p className="desc">{desc}</p>
        {p.variants && (
          <div style={{display:"flex",alignItems:"center",gap:10}}>
            <Lab>COLOR</Lab>
            <div style={{display:"flex",gap:6}}>
              {p.variants.map(v => (
                <button key={v.key} onClick={() => setActiveVariant(v)} title={v.label} style={{
                  width:18, height:18,
                  background: v.key === "black" ? "#111" : "#b0b0b0",
                  border: activeVariant?.key === v.key ? "2px solid var(--fg1)" : "1px solid var(--fg3)",
                  cursor:"pointer", padding:0
                }} />
              ))}
            </div>
            <span style={{fontFamily:"var(--font-mono)",fontSize:11,color:"var(--fg2)",letterSpacing:".08em"}}>{activeVariant?.label}</span>
          </div>
        )}
        <div style={{display:"flex",gap:10,flexWrap:"wrap"}}>
          <Btn variant="primary" onClick={() => {}}>I'm Interested</Btn>
          <Btn variant="ghost" onClick={() => onWaitlist && onWaitlist()}>Join Waitlist</Btn>
        </div>
        <div className="specs">
          <div className="sp"><b>Material</b><span>{meta}</span></div>
          <div className="sp"><b>Edition</b><span>LIMITED — 200 UNITS</span></div>
          <div className="sp"><b>Ships</b><span>3–5 BUSINESS DAYS</span></div>
        </div>
      </div>
    </div>
  );
}

function CartDrawer({open, items, close, remove, userId}) {
  const total = items.reduce((s, i) => s + i.price, 0);
  const [loading, setLoading] = React.useState(false);
  const [err, setErr] = React.useState("");

  const checkout = async () => {
    setLoading(true); setErr("");
    try {
      const res = await fetch("https://api.nosign4l.com/api/checkout", {
        method: "POST",
        headers: {"Content-Type": "application/json"},
        body: JSON.stringify({ items, userId: userId ?? null }),
      });
      const data = await res.json();
      if (data.url) { window.location.href = data.url; }
      else { setErr(data.error || "Checkout failed."); setLoading(false); }
    } catch(e) { setErr("Connection error."); setLoading(false); }
  };

  return (
    <>
      <div className={"scrim" + (open ? " open" : "")} onClick={close}></div>
      <aside className={"drawer" + (open ? " open" : "")}>
        <div className="dh"><Lab bright>CART // {items.length} OBJECT{items.length===1?"":"S"}</Lab><button onClick={close}>✕</button></div>
        {items.length === 0 ? (
          <div className="empty">
            <img src={MARK_W} style={{width:48,opacity:.4}} alt="" />
            <Lab>SIGNAL EMPTY</Lab>
            <span style={{fontSize:12,color:"var(--fg3)"}}>No objects acquired.</span>
          </div>
        ) : (
          <>
            <div className="items">
              {items.map((i, ix) => (
                <div className="ci" key={ix}>
                  <div className="th"><img src={MARK_W} alt="" /></div>
                  <div>
                    <div className="cn">{i.name}</div>
                    <div className="cm">SIZE {i.size}</div>
                  </div>
                  <span className="cp">${i.price}</span>
                  <button onClick={() => remove(ix)} style={{background:"none",border:"none",color:"var(--fg3)",cursor:"pointer",marginLeft:8}}>✕</button>
                </div>
              ))}
            </div>
            <div className="foot">
              <div className="total"><span>SUBTOTAL</span><b>${total}</b></div>
              {err && <div style={{fontFamily:"var(--font-mono)",fontSize:11,color:"#f44",marginBottom:8}}>{err}</div>}
              <Btn variant="primary" style={{width:"100%"}} onClick={checkout} disabled={loading}>
                {loading ? "CONNECTING..." : "Checkout →"}
              </Btn>
            </div>
          </>
        )}
      </aside>
    </>
  );
}

function StaticPage({title, kicker, children}) {
  return (
    <div className="gridwrap" style={{maxWidth:720}}>
      <Lab bright style={{display:"block",marginBottom:16}}>{kicker}</Lab>
      <h2 style={{fontFamily:"var(--font-display)",fontWeight:800,fontSize:36,textTransform:"uppercase",margin:"0 0 24px",lineHeight:1}}>{title}</h2>
      <div style={{color:"var(--fg2)",fontSize:14,lineHeight:1.8,maxWidth:560}}>{children}</div>
    </div>
  );
}

function SizingPage() {
  const T = ({headers, rows}) => (
    <div style={{overflowX:"auto",marginBottom:20}}>
      <table style={{width:"100%",borderCollapse:"collapse",fontFamily:"var(--font-mono)",fontSize:13}}>
        <thead>
          <tr>
            {headers.map(h => (
              <th key={h} style={{textAlign:"left",padding:"10px 14px",borderBottom:"1px solid var(--line-strong)",fontFamily:"var(--font-display)",fontSize:10,letterSpacing:".18em",textTransform:"uppercase",color:"var(--fg3)",whiteSpace:"nowrap"}}>{h}</th>
            ))}
          </tr>
        </thead>
        <tbody>
          {rows.map((row,i) => (
            <tr key={i} style={{borderBottom:"1px solid var(--line)"}}>
              {row.map((cell,j) => (
                <td key={j} style={{padding:"10px 14px",color:j===0?"var(--fg1)":"var(--fg2)",fontWeight:j===0?700:400,whiteSpace:"nowrap"}}>{cell}</td>
              ))}
            </tr>
          ))}
        </tbody>
      </table>
    </div>
  );

  const Section = ({label}) => (
    <div style={{fontFamily:"var(--font-display)",fontSize:9,letterSpacing:".22em",textTransform:"uppercase",color:"var(--fg3)",marginBottom:8,marginTop:20}}>{label}</div>
  );

  const Col = ({title, children}) => (
    <div style={{flex:1,minWidth:0}}>
      <div style={{fontFamily:"var(--font-display)",fontWeight:800,fontSize:18,textTransform:"uppercase",letterSpacing:".06em",marginBottom:16,paddingBottom:10,borderBottom:"1px solid var(--line-strong)",textAlign:"center"}}>{title}</div>
      {children}
    </div>
  );

  return (
    <div style={{flex:1,display:"flex",flexDirection:"column",alignItems:"center",justifyContent:"center",padding:"48px 24px"}}>
      <div style={{width:"100%",maxWidth:860}}>
      <Lab bright style={{display:"block",marginBottom:12,textAlign:"center"}}>SYS.DOC / SIZING</Lab>
      <h2 style={{fontFamily:"var(--font-display)",fontWeight:800,fontSize:36,textTransform:"uppercase",margin:"0 0 10px",lineHeight:1,textAlign:"center"}}>Size Guide</h2>
      <p style={{fontFamily:"var(--font-mono)",fontSize:13,color:"var(--fg3)",marginBottom:40,lineHeight:1.7,textAlign:"center"}}>Measurements are approximate. Compare with a similar item you already own.</p>

      <div style={{display:"flex",gap:40,flexWrap:"wrap"}}>
        <Col title="">
          <T headers={["Size","Chest","Waist","Length"]} rows={[["XS","31–34\"","24–27\"","23–25\""],["S","34–37\"","27–31\"","24–26\""],["M","37–40\"","31–34\"","25–27\""],["L","40–43\"","34–37\"","26–28\""],["XL","43–46\"","37–40\"","27–29\""],["2XL","46–49\"","40–43\"","28–30\""]]} />
        </Col>

        <Col title="">
          <T headers={["Size","Waist","Hip","Inseam"]} rows={[["XS","24–26\"","33–35\"","28–29\""],["S","26–29\"","35–38\"","29–30\""],["M","29–32\"","38–41\"","30–31\""],["L","32–35\"","41–44\"","31–32\""],["XL","35–38\"","44–47\"","32–33\""],["2XL","38–41\"","47–50\"","33–34\""]]} />
        </Col>
      </div>
      </div>
    </div>
  );
}

Object.assign(window, { PRODUCTS, SignalSquares, Hero, ProductCard, Grid, ProductDetail, CartDrawer, StaticPage, SizingPage });
