/* global React, ReactDOM, useTweaks, TweaksPanel, TweakSection, TweakRadio, TweakToggle, TweakColor */
const { useState, useEffect, useRef, useMemo } = React;
const D = window.STARWRX_DATA;

/* ------------------------------------------------------------------ */
/* component styles (injected once)                                    */
/* ------------------------------------------------------------------ */
const css = `
/* ---- nav ---- */
.nav { position: sticky; top: 0; z-index: 50; backdrop-filter: blur(14px);
  background: color-mix(in srgb, var(--bg) 78%, transparent);
  border-bottom: 1px solid var(--line); }
.nav-in { display: flex; align-items: center; justify-content: space-between; height: 66px; }
.brand { display: flex; align-items: center; gap: 11px; font-weight: 700; letter-spacing: -0.01em; font-size: 19px; }
.brand-mark { width: 26px; height: 26px; position: relative; flex: none; }
.brand-mark i { position: absolute; inset: 0; border: 1.5px solid var(--accent); }
.brand-mark i:nth-child(1) { transform: rotate(0deg); opacity: .9; }
.brand-mark i:nth-child(2) { transform: rotate(45deg); opacity: .4; }
.brand sup { font-family: "JetBrains Mono", monospace; font-size: 9px; color: var(--faint); letter-spacing: .1em; vertical-align: super; }
.nav-links { display: flex; align-items: center; gap: 30px; }
.nav-links a { font-family: "JetBrains Mono", monospace; font-size: 12.5px; letter-spacing: .04em; color: var(--dim); transition: color .2s; }
.nav-links a:hover { color: var(--text); }
.nav-pill { display: inline-flex; align-items: center; gap: 8px; font-family: "JetBrains Mono", monospace;
  font-size: 11px; letter-spacing: .08em; color: var(--dim); border: 1px solid var(--line-2);
  padding: 7px 12px; border-radius: 100px; }
.dot { width: 7px; height: 7px; border-radius: 50%; background: var(--ok); position: relative; flex: none; }
.dot.live::after { content: ""; position: absolute; inset: -4px; border-radius: 50%; border: 1px solid var(--ok);
  animation: ping 2.4s ease-out infinite; }
.dot.warn { background: var(--warn); } .dot.warn::after { border-color: var(--warn); }
.dot.stage { background: var(--stage); }
@keyframes ping { 0%{transform:scale(.6);opacity:.9} 100%{transform:scale(1.8);opacity:0} }
@media (max-width: 760px){ .nav-links a:not(.nav-pill){ display:none; } }

/* ---- hero ---- */
.hero { padding-top: clamp(70px, 12vh, 120px); padding-bottom: clamp(40px, 7vh, 80px); }
.hero-tag { color: var(--dim); font-size: clamp(16px,2vw,20px); max-width: 540px; line-height: 1.5; margin: 26px 0 0; }
.wordmark { font-weight: 700; letter-spacing: -0.04em; line-height: 0.9; margin: 22px 0 0;
  font-size: clamp(64px, 13vw, 158px); }
.wordmark.duo { background: linear-gradient(100deg, var(--accent), var(--accent-2));
  -webkit-background-clip: text; background-clip: text; color: transparent; }
.cta-row { display: flex; gap: 14px; flex-wrap: wrap; margin-top: 38px; }
.btn { display: inline-flex; align-items: center; gap: 10px; font-family: "JetBrains Mono", monospace;
  font-size: 13px; letter-spacing: .03em; padding: 13px 20px; border-radius: 100px; cursor: pointer;
  border: 1px solid var(--line-2); color: var(--text); background: transparent; transition: all .2s; }
.btn:hover { border-color: var(--line-3); transform: translateY(-1px); }
.btn.primary { background: var(--accent); border-color: var(--accent); color: #fff; }
.btn.primary:hover { box-shadow: 0 8px 30px var(--accent-soft); }
.btn .arr { transition: transform .2s; } .btn:hover .arr { transform: translate(2px,-2px); }

/* hero split panel */
.hero-split { display: grid; grid-template-columns: 1.05fr 0.95fr; gap: 56px; align-items: center; }
@media (max-width: 900px){ .hero-split { grid-template-columns: 1fr; gap: 40px; } }
.panel { border: 1px solid var(--line-2); border-radius: var(--r); background:
  linear-gradient(180deg, var(--bg-3), var(--bg-2)); overflow: hidden; }
.panel-bar { display: flex; align-items: center; gap: 8px; padding: 12px 16px; border-bottom: 1px solid var(--line);
  font-family: "JetBrains Mono", monospace; font-size: 11px; color: var(--faint); letter-spacing: .06em; }
.panel-bar b { color: var(--dim); font-weight: 500; margin-left: auto; }
.tl { width: 11px; height: 11px; border-radius: 50%; border: 1px solid var(--line-3); }
.panel-body { padding: 8px 0; }
.svc { display: flex; align-items: center; gap: 14px; padding: 13px 18px; font-family: "JetBrains Mono", monospace; font-size: 12.5px; }
.svc + .svc { border-top: 1px solid var(--line); }
.svc .nm { color: var(--text); }
.svc .up { margin-left: auto; color: var(--faint); font-size: 11px; }
.svc .st { color: var(--ok); font-size: 11px; letter-spacing: .04em; min-width: 92px; text-align: right; }
.svc .st.warn { color: var(--warn); } .svc .st.stage { color: var(--stage); }

/* hero terminal */
.term { border: 1px solid var(--line-2); border-radius: var(--r); background: #0c0e13; overflow: hidden;
  box-shadow: 0 40px 120px -40px rgba(0,0,0,.8); max-width: 720px; }
.term-body { padding: 22px 24px 26px; font-family: "JetBrains Mono", monospace; font-size: 13.5px; line-height: 1.85; min-height: 250px; }
.term .ln { white-space: pre-wrap; }
.term .pr { color: var(--accent); } .term .ok { color: var(--ok); } .term .dim2 { color: var(--faint); }
.term .cur { display: inline-block; width: 8px; height: 16px; background: var(--accent); vertical-align: -2px;
  animation: blink 1s steps(1) infinite; } @keyframes blink { 50%{opacity:0} }

/* ---- status strip ---- */
.strip { border-top: 1px solid var(--line); border-bottom: 1px solid var(--line); background: var(--bg-2); }
.strip-in { display: flex; align-items: center; gap: 34px; padding: 18px 0; flex-wrap: wrap;
  font-family: "JetBrains Mono", monospace; font-size: 12px; }
.strip .lab { color: var(--faint); letter-spacing: .12em; text-transform: uppercase; font-size: 10.5px; }
.strip .grp { display: flex; align-items: center; gap: 11px; }
.strip .val { color: var(--text); }
.strip .accent { color: var(--accent); }
.strip .svcdots { display: flex; gap: 7px; margin-left: auto; }
.strip .sd { width: 9px; height: 9px; border-radius: 50%; background: var(--ok); position: relative; }
.strip .sd.warn { background: var(--warn); } .strip .sd.stage { background: var(--stage); }
.strip .sd:hover::after { content: attr(data-d); position: absolute; bottom: 150%; left: 50%; transform: translateX(-50%);
  background: var(--bg-card); border: 1px solid var(--line-2); padding: 4px 8px; border-radius: 6px; white-space: nowrap;
  font-size: 10px; color: var(--dim); }
@media (max-width:680px){ .strip .svcdots{ margin-left:0; } }

/* ---- capabilities ---- */
.caps { display: grid; grid-template-columns: repeat(2,1fr); gap: 1px; background: var(--line);
  border: 1px solid var(--line); border-radius: var(--r); overflow: hidden; }
@media (max-width: 720px){ .caps { grid-template-columns: 1fr; } }
.cap { background: var(--bg); padding: 38px 34px; transition: background .25s; position: relative; }
.cap:hover { background: var(--bg-2); }
.cap .n { font-family: "JetBrains Mono", monospace; font-size: 12px; color: var(--accent); letter-spacing: .1em; }
.cap h3 { font-size: 23px; font-weight: 600; letter-spacing: -0.01em; margin: 16px 0 10px; }
.cap p { color: var(--dim); font-size: 15px; margin: 0 0 20px; max-width: 40ch; }
.cap .tags { display: flex; gap: 7px; flex-wrap: wrap; }
.tag { font-family: "JetBrains Mono", monospace; font-size: 10.5px; letter-spacing: .04em; color: var(--faint);
  border: 1px solid var(--line-2); padding: 4px 9px; border-radius: 5px; }

/* ---- portfolio ---- */
.grid { display: grid; grid-template-columns: repeat(2, 1fr); gap: 22px; }
@media (max-width: 820px){ .grid { grid-template-columns: 1fr; } }
.card { border: 1px solid var(--line-2); border-radius: var(--r); background: var(--bg-card); overflow: hidden;
  transition: transform .3s cubic-bezier(.2,.6,.2,1), border-color .3s, box-shadow .3s; display: flex; flex-direction: column; }
.card:hover { transform: translateY(-4px); border-color: var(--line-3); box-shadow: 0 30px 60px -30px rgba(0,0,0,.7); }
.shot { position: relative; aspect-ratio: 16/9; background: var(--bg-2); border-bottom: 1px solid var(--line); }
.shot image-slot { display: block; width: 100%; height: 100%; }
.shot .badge { position: absolute; top: 12px; left: 12px; z-index: 3; display: inline-flex; align-items: center; gap: 7px;
  font-family: "JetBrains Mono", monospace; font-size: 10.5px; letter-spacing: .05em; text-transform: uppercase;
  background: color-mix(in srgb, var(--bg) 80%, transparent); backdrop-filter: blur(6px);
  border: 1px solid var(--line-2); padding: 6px 10px; border-radius: 100px; color: var(--dim); }
.card-body { padding: 22px 22px 20px; display: flex; flex-direction: column; gap: 13px; flex: 1; }
.card .dom { font-family: "JetBrains Mono", monospace; font-size: 15px; color: var(--text); display: flex; align-items: center; gap: 9px; }
.card .dom .ext { margin-left: auto; color: var(--faint); transition: color .2s, transform .2s; }
.card:hover .dom .ext { color: var(--accent); transform: translate(2px,-2px); }
.card .role { font-size: 12px; font-family: "JetBrains Mono", monospace; color: var(--accent); letter-spacing: .04em; margin-top: -6px; }
.card .desc { color: var(--dim); font-size: 14px; line-height: 1.5; margin: 0; }
.card .stack { display: flex; gap: 6px; flex-wrap: wrap; margin-top: auto; }
.card .meta { display: flex; align-items: center; gap: 16px; padding-top: 14px; border-top: 1px solid var(--line);
  font-family: "JetBrains Mono", monospace; font-size: 10.5px; color: var(--faint); flex-wrap: wrap; }
.card .meta .k { color: var(--dim); }
.card .meta .up { margin-left: auto; }
.bar { height: 2px; background: var(--line); border-radius: 2px; overflow: hidden; position: relative; }
.bar i { position: absolute; inset: 0; width: 40%; background: var(--warn);
  animation: slide 1.6s ease-in-out infinite; }
@keyframes slide { 0%{left:-40%} 100%{left:100%} }

/* ---- stack ---- */
.stack-list { border-top: 1px solid var(--line); }
.srow { display: grid; grid-template-columns: 56px 1fr auto; align-items: center; gap: 22px; padding: 26px 6px;
  border-bottom: 1px solid var(--line); transition: padding-left .25s, background .25s; }
.srow:hover { padding-left: 18px; background: linear-gradient(90deg, var(--accent-soft), transparent 60%); }
.srow .abbr { width: 44px; height: 44px; border: 1px solid var(--line-2); border-radius: 9px; display: grid; place-items: center;
  font-family: "JetBrains Mono", monospace; font-size: 14px; color: var(--accent); font-weight: 600; }
.srow .sn { font-size: 20px; font-weight: 500; letter-spacing: -0.01em; }
.srow .sr { font-family: "JetBrains Mono", monospace; font-size: 12px; color: var(--faint); letter-spacing: .03em; }
@media (max-width: 560px){ .srow .sr { display:none; } }

/* ---- footer ---- */
.foot { border-top: 1px solid var(--line); padding: 46px 0 60px; }
.foot-in { display: flex; align-items: flex-start; justify-content: space-between; gap: 28px; flex-wrap: wrap;
  font-family: "JetBrains Mono", monospace; font-size: 11.5px; color: var(--faint); }
.foot .fcol { display: flex; flex-direction: column; gap: 8px; }
.foot .fcol .ft { color: var(--dim); letter-spacing: .1em; text-transform: uppercase; font-size: 10px; }
.foot a:hover { color: var(--accent); }
.foot .bld { display: flex; gap: 10px; flex-wrap: wrap; align-items: center; }
.foot .bld span { border: 1px solid var(--line); padding: 4px 9px; border-radius: 5px; }
`;

function injectCSS() {
  if (document.getElementById("starwrx-css")) return;
  const el = document.createElement("style");
  el.id = "starwrx-css"; el.textContent = css;
  document.head.appendChild(el);
}
injectCSS();

const statusMap = {
  operational: { cls: "", label: "Operational" },
  deploying:   { cls: "warn", label: "Deploying" },
  staging:     { cls: "stage", label: "Staging" },
};

/* ------------------------------------------------------------------ */
/* hooks                                                               */
/* ------------------------------------------------------------------ */
function useReveal() {
  useEffect(() => {
    const els = document.querySelectorAll(".reveal");
    const io = new IntersectionObserver((es) => {
      es.forEach((e) => { if (e.isIntersecting) { e.target.classList.add("in"); io.unobserve(e.target); } });
    }, { threshold: 0.12 });
    els.forEach((e) => io.observe(e));
    return () => io.disconnect();
  });
}

function useMonitorClock() {
  // simulated continuous monitoring uptime
  const base = 247 * 86400 + 14 * 3600 + 32 * 60 + 8;
  const [t, setT] = useState(base);
  useEffect(() => { const id = setInterval(() => setT((x) => x + 1), 1000); return () => clearInterval(id); }, []);
  const d = Math.floor(t / 86400), h = Math.floor((t % 86400) / 3600), m = Math.floor((t % 3600) / 60), s = t % 60;
  const p = (n) => String(n).padStart(2, "0");
  return `${d}d ${p(h)}:${p(m)}:${p(s)}`;
}

/* ------------------------------------------------------------------ */
/* nav                                                                 */
/* ------------------------------------------------------------------ */
function Nav() {
  return (
    <nav className="nav">
      <div className="wrap nav-in">
        <a className="brand" href="#top">
          <span className="brand-mark"><i></i><i></i></span>
          STARWRX<sup>™</sup>
        </a>
        <div className="nav-links">
          <a href="#build">/build</a>
          <a href="#work">/work</a>
          <a href="#stack">/stack</a>
          <span className="nav-pill"><span className="dot live"></span>ALL SYSTEMS NOMINAL</span>
        </div>
      </div>
    </nav>
  );
}

/* ------------------------------------------------------------------ */
/* hero variants                                                       */
/* ------------------------------------------------------------------ */
function HeroCopy({ duo }) {
  return (
    <React.Fragment>
      <span className="kicker">SALTWRX LLC · WEB SERVICES</span>
      <h1 className={"wordmark" + (duo ? " duo" : "")}>STARWRX</h1>
      <p className="hero-tag">
        Web services for SALTWRX&nbsp;LLC and its subsidiaries. We design, build,
        and keep every brand property online.
      </p>
      <div className="cta-row">
        <a className="btn primary" href="#work">View portfolio <span className="arr">↓</span></a>
        <a className="btn" href="#stack">The stack</a>
      </div>
    </React.Fragment>
  );
}

function ServicePanel() {
  return (
    <div className="panel">
      <div className="panel-bar">
        <span className="tl"></span><span className="tl"></span><span className="tl"></span>
        <span style={{ marginLeft: 10 }}>status · live</span>
        <b>{D.projects.length} properties</b>
      </div>
      <div className="panel-body">
        {D.projects.map((p) => {
          const s = statusMap[p.status];
          return (
            <div className="svc" key={p.domain}>
              <span className={"dot " + (p.status === "deploying" ? "warn live" : p.status === "staging" ? "stage" : "")}></span>
              <span className="nm">{p.domain}</span>
              <span className="up">{p.uptime}%</span>
              <span className={"st " + s.cls}>{s.label}</span>
            </div>
          );
        })}
      </div>
    </div>
  );
}

const TERM_LINES = [
  { t: "$ starwrx status --all", c: "pr" },
  { t: "", c: "" },
  { t: "✓ baddyarmor.com          operational   99.99%", c: "ok" },
  { t: "✓ store.baddyarmor.com    operational   100.0%", c: "ok" },
  { t: "✓ saltwrx.org             operational   100.0%", c: "ok" },
  { t: "✓ primeflipz.com          operational   99.99%", c: "ok" },
  { t: "✓ bellaalmaranch.com      operational   100.0%", c: "ok" },
  { t: "✓ starwrx.com             operational   100.0%", c: "ok" },
  { t: "", c: "" },
  { t: "6 properties · 6 operational", c: "pr" },
];

function Terminal() {
  const [shown, setShown] = useState(0);
  useEffect(() => {
    if (shown >= TERM_LINES.length) return;
    const delay = TERM_LINES[shown].t === "" ? 120 : 360;
    const id = setTimeout(() => setShown((s) => s + 1), delay);
    return () => clearTimeout(id);
  }, [shown]);
  return (
    <div className="term">
      <div className="panel-bar">
        <span className="tl"></span><span className="tl"></span><span className="tl"></span>
        <span style={{ marginLeft: 10 }}>starwrx@ops — zsh</span>
      </div>
      <div className="term-body">
        {TERM_LINES.slice(0, shown).map((l, i) => (
          <div className={"ln " + l.c} key={i}>{l.t || "\u00a0"}</div>
        ))}
        {shown >= TERM_LINES.length && <span className="ln pr">$ <span className="cur"></span></span>}
      </div>
    </div>
  );
}

function Hero({ variant, duo }) {
  if (variant === "split") {
    return (
      <header className="hero" id="top">
        <div className="wrap hero-split">
          <div className="reveal in"><HeroCopy duo={duo} /></div>
          <div className="reveal in"><ServicePanel /></div>
        </div>
      </header>
    );
  }
  if (variant === "terminal") {
    return (
      <header className="hero" id="top">
        <div className="wrap" style={{ textAlign: "center" }}>
          <div style={{ display: "inline-flex", flexDirection: "column", alignItems: "center", maxWidth: 760 }}>
            <span className="kicker">SALTWRX LLC · WEB SERVICES</span>
            <h1 className={"wordmark" + (duo ? " duo" : "")} style={{ fontSize: "clamp(52px,9vw,104px)" }}>STARWRX</h1>
            <p className="hero-tag" style={{ textAlign: "center", margin: "20px auto 34px" }}>
              Web services for SALTWRX&nbsp;LLC and its subsidiaries.
            </p>
          </div>
          <div style={{ display: "flex", justifyContent: "center" }}><Terminal /></div>
        </div>
      </header>
    );
  }
  // stacked (default)
  return (
    <header className="hero" id="top">
      <div className="wrap reveal in" style={{ maxWidth: 880 }}>
        <HeroCopy duo={duo} />
      </div>
    </header>
  );
}

/* ------------------------------------------------------------------ */
/* status strip                                                        */
/* ------------------------------------------------------------------ */
function StatusStrip() {
  const clock = useMonitorClock();
  const live = D.projects.filter((p) => p.status === "operational").length;
  return (
    <div className="strip">
      <div className="wrap strip-in">
        <div className="grp"><span className="dot live"></span><span className="val">OPERATIONAL</span></div>
        <div className="grp"><span className="lab">90d uptime</span><span className="accent">99.96%</span></div>
        <div className="grp"><span className="lab">monitoring</span><span className="val">{clock}</span></div>
        <div className="grp"><span className="lab">live</span><span className="val">{live}/{D.projects.length}</span></div>
        <div className="svcdots">
          {D.projects.map((p) => (
            <span key={p.domain} data-d={p.domain}
              className={"sd " + (p.status === "deploying" ? "warn" : p.status === "staging" ? "stage" : "")}></span>
          ))}
        </div>
      </div>
    </div>
  );
}

/* ------------------------------------------------------------------ */
/* capabilities                                                        */
/* ------------------------------------------------------------------ */
function Capabilities() {
  return (
    <section id="build">
      <div className="wrap">
        <div className="sec-head reveal">
          <div>
            <span className="kicker">WHAT WE BUILD</span>
            <h2 className="sec-title">Four things, done properly.</h2>
          </div>
          <p className="sec-note">Every SALTWRX property runs on the same disciplined pipeline — no snowflakes.</p>
        </div>
        <div className="caps reveal">
          {D.capabilities.map((c) => (
            <div className="cap" key={c.n}>
              <span className="n">{c.n}</span>
              <h3>{c.title}</h3>
              <p>{c.desc}</p>
              <div className="tags">{c.tags.map((t) => <span className="tag" key={t}>{t}</span>)}</div>
            </div>
          ))}
        </div>
      </div>
    </section>
  );
}

/* ------------------------------------------------------------------ */
/* portfolio                                                           */
/* ------------------------------------------------------------------ */
function ProjectCard({ p }) {
  const s = statusMap[p.status];
  return (
    <article className="card">
      <div className="shot">
        <span className="badge">
          <span className={"dot " + (p.status === "deploying" ? "warn live" : p.status === "staging" ? "stage" : "live")}></span>
          {s.label}
        </span>
        <image-slot id={p.slot} src={p.src} fit="cover" placeholder={"drop screenshot · " + p.domain}></image-slot>
      </div>
      <div className="card-body">
        <div className="dom">{p.domain}<span className="ext">↗</span></div>
        <div className="role">{p.role}</div>
        <p className="desc">{p.desc}</p>
        <div className="stack">{p.stack.map((t) => <span className="tag" key={t}>{t}</span>)}</div>
        {p.status === "deploying" && <div className="bar"><i></i></div>}
        <div className="meta">
          <span className="k">{p.deploy.branch}</span>
          <span>· {p.deploy.hash}</span>
          <span>· {p.deploy.when}</span>
          <span className="up">↑ {p.uptime}%</span>
        </div>
      </div>
    </article>
  );
}

function Portfolio() {
  return (
    <section id="work">
      <div className="wrap">
        <div className="sec-head reveal">
          <div>
            <span className="kicker">PORTFOLIO · {D.projects.length} PROPERTIES</span>
            <h2 className="sec-title">Live properties.</h2>
          </div>
          <p className="sec-note">Brand sites and storefronts currently built and maintained by STARWRX.</p>
        </div>
        <div className="grid reveal">
          {D.projects.map((p) => <ProjectCard key={p.domain} p={p} />)}
        </div>
      </div>
    </section>
  );
}

/* ------------------------------------------------------------------ */
/* stack                                                               */
/* ------------------------------------------------------------------ */
function Stack() {
  return (
    <section id="stack">
      <div className="wrap">
        <div className="sec-head reveal">
          <div>
            <span className="kicker">THE STACK</span>
            <h2 className="sec-title">Boring tools. On purpose.</h2>
          </div>
          <p className="sec-note">A small, dependable toolchain shared across every property.</p>
        </div>
        <div className="stack-list reveal">
          {D.stack.map((t) => (
            <div className="srow" key={t.name}>
              <span className="abbr">{t.abbr}</span>
              <span className="sn">{t.name}</span>
              <span className="sr">{t.role}</span>
            </div>
          ))}
        </div>
      </div>
    </section>
  );
}

/* ------------------------------------------------------------------ */
/* footer                                                              */
/* ------------------------------------------------------------------ */
function Footer() {
  const b = D.build;
  return (
    <footer className="foot">
      <div className="wrap foot-in">
        <div className="fcol">
          <span className="ft">STARWRX</span>
          <span>Web services</span>
          <span>A division of SALTWRX&nbsp;LLC</span>
          <span>DFW · TX</span>
        </div>
        <div className="fcol">
          <span className="ft">Build</span>
          <div className="bld">
            <span>{b.version}</span>
            <span>{b.branch}@{b.hash}</span>
            <span>{b.env}</span>
          </div>
          <span style={{ marginTop: 6 }}>© 2026 SALTWRX LLC · starwrx.com</span>
        </div>
      </div>
    </footer>
  );
}

/* ------------------------------------------------------------------ */
/* app + tweaks                                                        */
/* ------------------------------------------------------------------ */
const ACCENTS = {
  blue:   { a: "#5479ff", b: "#5479ff", duo: false },
  violet: { a: "#9d6bff", b: "#9d6bff", duo: false },
  duo:    { a: "#5479ff", b: "#9d6bff", duo: true },
};

const TWEAK_DEFAULTS = /*EDITMODE-BEGIN*/{
  "accent": "duo",
  "hero": "split",
  "texture": true
}/*EDITMODE-END*/;

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

  const acc = ACCENTS[t.accent] || ACCENTS.duo;
  useEffect(() => {
    const r = document.documentElement;
    r.style.setProperty("--accent", acc.a);
    r.style.setProperty("--accent-2", acc.b);
    r.style.setProperty("--accent-soft", acc.a + "20");
    document.body.style.setProperty("--show-tex", t.texture ? "0.5" : "0");
  }, [t.accent, t.texture]);

  useEffect(() => {
    const id = "tex-toggle";
    let el = document.getElementById(id);
    if (!el) { el = document.createElement("style"); el.id = id; document.head.appendChild(el); }
    el.textContent = `body::before{opacity:${t.texture ? 0.5 : 0};}`;
  }, [t.texture]);

  return (
    <React.Fragment>
      <Nav />
      <Hero variant={t.hero} duo={acc.duo} />
      <StatusStrip />
      <Capabilities />
      <Portfolio />
      <Stack />
      <Footer />

      <TweaksPanel>
        <TweakSection label="Hero layout" />
        <TweakRadio label="Variant" value={t.hero}
          options={["stacked", "split", "terminal"]}
          onChange={(v) => setTweak("hero", v)} />
        <TweakSection label="Accent" />
        <TweakRadio label="Color" value={t.accent}
          options={["blue", "violet", "duo"]}
          onChange={(v) => setTweak("accent", v)} />
        <TweakSection label="Surface" />
        <TweakToggle label="Grid texture" value={t.texture}
          onChange={(v) => setTweak("texture", v)} />
      </TweaksPanel>
    </React.Fragment>
  );
}

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