/* ============================================================
   Sid Sanghavi — site app
   Hash-router. React 18. Editorial layout. One accent color.
   ============================================================ */

const { useState, useEffect, useMemo, useRef } = React;
const { TweaksPanel, useTweaks, TweakSection, TweakRadio, TweakColor, TweakToggle } = window;

const DATA = window.SITE_DATA;

// ---------------- Hash router ----------------
function useRoute() {
  const [route, setRoute] = useState(() => parseHash(window.location.hash));
  useEffect(() => {
    const onHash = () => setRoute(parseHash(window.location.hash));
    window.addEventListener("hashchange", onHash);
    return () => window.removeEventListener("hashchange", onHash);
  }, []);
  return route;
}

function parseHash(h) {
  const clean = (h || "").replace(/^#\/?/, "");
  if (!clean) return { name: "home", params: {} };
  const [path, qs] = clean.split("?");
  const parts = path.split("/").filter(Boolean);
  const params = Object.fromEntries(new URLSearchParams(qs || ""));
  if (parts[0] === "projects") return { name: "projects", params };
  if (parts[0] === "writing" && parts[1]) return { name: "article", params: { slug: parts[1] }};
  if (parts[0] === "writing") return { name: "writing", params };
  if (parts[0] === "career") return { name: "career", params };
  if (parts[0] === "about") return { name: "about", params };
  return { name: "home", params: {} };
}

function go(path) {
  window.location.hash = path;
  window.scrollTo({ top: 0, behavior: "instant" in document.documentElement.style ? "instant" : "auto" });
}

// ---------------- Tweak defaults ----------------
const TWEAK_DEFAULTS = {
  "type_pairing": "instrument-newsreader",
  "accent": "#B84718",
  "density": "list",
  "thumb_strategy": "type-only",
  "show_now": true,
  "homepage_layout": "editorial"
};

const TYPE_PAIRS = {
  "instrument-newsreader": {
    display: '"Instrument Serif", "Newsreader", Georgia, serif',
    serif:   '"Newsreader", "Source Serif 4", Georgia, serif',
    sans:    '"Geist", "Inter", system-ui, sans-serif',
    mono:    '"JetBrains Mono", ui-monospace, monospace',
    label:   "Instrument + Newsreader",
  },
};

// ============================================================
// Top-level App
// ============================================================
function App() {
  const [tweaks, setTweak] = useTweaks(TWEAK_DEFAULTS);
  const route = useRoute();

  return (
    <>
      <Header route={route} />
      <main>
        {route.name === "home" && <Home tweaks={tweaks} />}
        {route.name === "projects" && <ProjectsPage tweaks={tweaks} initialParams={route.params} />}
        {route.name === "writing" && <WritingIndex />}
        {route.name === "article" && <Article slug={route.params.slug} />}
        {route.name === "career" && <CareerPage />}
        {route.name === "about" && <About />}
      </main>
      <Footer />
    </>
  );
}

// ============================================================
// Header / Footer
// ============================================================
function Header({ route }) {
  const NavLink = ({ to, label }) => {
    const active =
      (to === "" && route.name === "home") ||
      (to === "/projects" && route.name === "projects") ||
      (to === "/career" && route.name === "career") ||
      (to === "/writing" && (route.name === "writing" || route.name === "article"));
    return (
      <a
        href={"#" + to}
        className={"masthead__nav-link" + (active ? " is-active" : "")}
      >
        {label}
      </a>
    );
  };

  return (
    <header className="masthead">
      <div className="shell">
        <div className="masthead__row">
          <a href="#" className="masthead__brand" aria-label="Home">
            Siddhit Sanghavi
          </a>
          <nav className="masthead__nav" aria-label="Primary">
            <NavLink to="/projects" label="Projects" />
            <NavLink to="/career" label="Career" />
            <NavLink to="/writing" label="Writing" />
            <NavLink to="/about" label="About" />
            <ObfuscatedEmail className="masthead__nav-link" label="Contact" />
          </nav>
        </div>
      </div>
      <div className="shell" style={{ marginTop: "1.4rem" }}>
        <hr className="rule" />
      </div>
    </header>
  );
}

function Footer() {
  return (
    <footer className="shell">
      <div className="foot">
        <div>© Siddhit Sanghavi · 2026</div>
        <div style={{ display: "flex", gap: "1.2rem" }}>
          <a href="https://github.com/siddhit" target="_blank" rel="noopener">GitHub</a>
          <a href="https://www.linkedin.com/in/siddhit/" target="_blank" rel="noopener">LinkedIn</a>
          <ObfuscatedEmail />
          <a href="#" onClick={(e) => { e.preventDefault(); window.scrollTo({top:0,behavior:'smooth'}); }}>Top ↑</a>
        </div>
      </div>
    </footer>
  );
}

function ObfuscatedEmail({ className, label }) {
  const user = "hello";
  const domain = "siddh.it";
  const display = `${user}[at]${domain.replace(".", "[dot]")}`;
  const onClick = (e) => {
    e.preventDefault();
    window.location.href = `mailto:${user}@${domain}`;
  };
  return (
    <a className={className} href="#" onClick={onClick} aria-label="Send email">
      {label || display}
    </a>
  );
}

// ============================================================
// Home
// ============================================================
function Home({ tweaks }) {
  return (
    <div className="shell">
      <Intro />
      <RecentWriting />
      <ProjectsPreview tweaks={tweaks} />
      {tweaks.show_now && <NowStrip />}
    </div>
  );
}

function Intro() {
  return (
    <section className="intro">
      <p className="intro__lede">
        Building for the <em>offline</em>, <em>physical</em>, and <em>built</em> world.
      </p>
      <p className="intro__sub">
        Industrial engineer by training. Most recently ran a home-remodeling
        franchise in Austin as Owner Operator — sixty-plus bathrooms and
        kitchens, $0 to $500K. Currently on sabbatical: building open APIs
        for industrial standards, an interactive map of Gujarati literature,
        and the occasional essay. Before that: shipping launch tools at
        Ford, vehicle-imaging admin software at Cox Automotive, and a
        manufacturing execution system at a YC startup.
      </p>
      <div className="intro__links">
        <a href="#/projects">See projects →</a>
        <a href="#/writing">Read the writing →</a>
        <ObfuscatedEmail label="Say hi →" />
      </div>
    </section>
  );
}

function RecentWriting() {
  const items = DATA.writing.slice(0, 2);
  return (
    <section className="sec">
      <div className="sec__head">
        <h2 className="sec__title">Recent writing</h2>
        <a className="sec__more" href="#/writing">Archive →</a>
      </div>
      <ul className="writing">
        {items.map((a) => (
          <li className="writing__item" key={a.id}>
            <div className="label">{a.date} · {a.reading}</div>
            <h3 className="writing__title" style={{marginTop:".4rem"}}>
              <a href={"#/writing/" + a.slug}>{a.title}</a>
            </h3>
            <p className="writing__sub">{a.subtitle}</p>
            <p className="writing__excerpt">{a.excerpt}</p>
            <div className="writing__meta">
              {a.tags.map((t) => <span key={t}>{t}</span>)}
            </div>
          </li>
        ))}
      </ul>
    </section>
  );
}

function ProjectsPreview({ tweaks }) {
  return (
    <section className="sec">
      <div className="sec__head">
        <h2 className="sec__title">Selected projects</h2>
        <a className="sec__more" href="#/projects">Filter & browse →</a>
      </div>
      <ProjectIndex
        projects={DATA.projects}
        density={tweaks.density}
        thumbStrategy={tweaks.thumb_strategy}
      />
    </section>
  );
}

function NowStrip() {
  const items = [
    { k: "Building", v: <><strong>OpenPTS</strong> — adding a video-to-motion-codes pipeline using vision models.</> },
    { k: "Reading", v: <><em><a href="https://books.apple.com/us/book/the-psychology-of-money/id1518559900" target="_blank" rel="noopener">The Psychology of Money</a></em> by Morgan Housel.</> },
    { k: "Listening", v: <><em><a href="https://books.apple.com/us/audiobook/arthashastra-vol-1-unabridged/id1533369346" target="_blank" rel="noopener">Arthashastra, Vol. 1</a></em> — audiobook, on long drives.</> },
    { k: "Where", v: <>Austin, TX. Mostly at home, sometimes at a jobsite.</> },
  ];
  return (
    <section className="sec">
      <div className="sec__head">
        <h2 className="sec__title">Now</h2>
        <span className="sec__more">Updated weekly-ish</span>
      </div>
      <div className="now">
        {items.map((r, i) => (
          <div className="now__row" key={i}>
            <div className="now__k">{r.k}</div>
            <div className="now__v">{r.v}</div>
          </div>
        ))}
      </div>
    </section>
  );
}

// ============================================================
// Project index
// ============================================================
function ProjectIndex({ projects, density, thumbStrategy }) {
  const showRich = density === "rich" && thumbStrategy === "screenshots";
  return (
    <ul className="idx">
      {projects.map((p, i) => (
        <li className={"idx__row" + (showRich ? " idx__row--rich" : "")} key={p.id}>
          <div className="idx__num">{String(i + 1).padStart(2, "0")}</div>
          <div className="idx__main">
            <h3 className="idx__title">
              {p.external
                ? <a href={p.external} target="_blank" rel="noopener">{p.title} <span className="idx__ext">↗</span></a>
                : <a href={"#/projects?focus=" + p.id}>{p.title}</a>}
            </h3>
            <p className="idx__kicker">{p.kicker}</p>
            <div className="idx__meta">
              <span><strong>{p.role}</strong></span>
              <span>{p.org}</span>
            </div>
            <div className="idx__tags">
              {p.tags.map((t) => (
                <a className="idx__tag" key={t} href={"#/projects?tag=" + encodeURIComponent(t)}>{t}</a>
              ))}
            </div>
          </div>
          {showRich && p.thumb && <img className="idx__thumb" src={p.thumb} alt="" loading="lazy" />}
          <div className="idx__year">{p.year}</div>
        </li>
      ))}
    </ul>
  );
}

// ============================================================
// /projects
// ============================================================
function ProjectsPage({ tweaks, initialParams }) {
  const [activeBucket, setActiveBucket] = useState(initialParams.bucket || "all");
  const [activeTags, setActiveTags] = useState(() => {
    const t = initialParams.tag;
    return t ? [decodeURIComponent(t)] : [];
  });
  const [focusId, setFocusId] = useState(initialParams.focus || null);

  useEffect(() => {
    const qs = new URLSearchParams();
    if (activeBucket !== "all") qs.set("bucket", activeBucket);
    if (activeTags.length) qs.set("tag", activeTags.join(","));
    if (focusId) qs.set("focus", focusId);
    const next = "/projects" + (qs.toString() ? "?" + qs.toString() : "");
    if (window.location.hash !== "#" + next) {
      history.replaceState(null, "", "#" + next);
    }
  }, [activeBucket, activeTags, focusId]);

  const filtered = useMemo(() => {
    return DATA.projects.filter((p) => {
      if (activeBucket !== "all" && p.bucket !== activeBucket) return false;
      if (activeTags.length && !activeTags.every((t) => p.tags.includes(t))) return false;
      return true;
    });
  }, [activeBucket, activeTags]);

  const allTags = useMemo(() => {
    const counts = {};
    DATA.projects.forEach((p) => {
      if (activeBucket !== "all" && p.bucket !== activeBucket) return;
      p.tags.forEach((t) => (counts[t] = (counts[t] || 0) + 1));
    });
    return Object.entries(counts).sort((a, b) => b[1] - a[1] || a[0].localeCompare(b[0]));
  }, [activeBucket]);

  const toggleTag = (t) => {
    setActiveTags((prev) => prev.includes(t) ? prev.filter((x) => x !== t) : [...prev, t]);
  };

  const focused = focusId ? DATA.projects.find((p) => p.id === focusId) : null;

  return (
    <div className="shell">
      <section className="sec" style={{paddingTop: "2rem"}}>
        <div className="label" style={{marginBottom:".5rem"}}>Index</div>
        <h1 className="reader__title" style={{fontSize:"clamp(2rem,4vw,2.6rem)", marginBottom:"0.6rem"}}>Projects, sorted by tag.</h1>
        <p className="intro__sub" style={{maxWidth:"54ch"}}>
          Some are work, some are personal. Filter by bucket or hashtag —
          everything’s the same kind of thing if you squint: shipping software
          near physical systems.
        </p>

        <div className="chips" style={{marginTop:"1.5rem"}}>
          {DATA.buckets.map((b) => (
            <button
              key={b.id}
              className={"chip chip--bucket" + (activeBucket === b.id ? " is-active" : "")}
              onClick={() => setActiveBucket(b.id)}
            >
              {b.label}
            </button>
          ))}
        </div>

        <div className="chips">
          {allTags.map(([t, count]) => (
            <button
              key={t}
              className={"chip" + (activeTags.includes(t) ? " is-active" : "")}
              onClick={() => toggleTag(t)}
            >
              {t} <span className="chip__count">{count}</span>
            </button>
          ))}
          {(activeTags.length > 0) && (
            <button className="chip" onClick={() => setActiveTags([])} style={{borderStyle:"dashed"}}>
              Clear
            </button>
          )}
        </div>

        <div className="label" style={{margin: "1rem 0 0.5rem"}}>
          {filtered.length} {filtered.length === 1 ? "project" : "projects"}
          {activeBucket !== "all" ? " in " + activeBucket : ""}
          {activeTags.length ? " · tagged " + activeTags.join(" + ") : ""}
        </div>

        <ProjectIndex
          projects={filtered}
          density={tweaks.density}
          thumbStrategy={tweaks.thumb_strategy}
        />
      </section>

      {focused && <ProjectFocus project={focused} onClose={() => setFocusId(null)} />}
    </div>
  );
}

function ProjectFocus({ project, onClose }) {
  return (
    <section className="sec" style={{borderTop:"1px solid var(--rule)"}}>
      <div className="sec__head">
        <h2 className="sec__title">{project.title}</h2>
        <button className="chip" onClick={onClose}>Close</button>
      </div>
      <div className="feat">
        <div>
          {project.thumb
            ? <img className="feat__img" src={project.thumb} alt="" />
            : <div className="feat__img" style={{background:"var(--paper-2)"}} />}
          <div className="feat__cap">{project.year} · {project.role} · {project.org}</div>
        </div>
        <div>
          <p className="feat__kicker">{project.kicker}</p>
          <p className="feat__body">{project.summary}</p>
          <div className="idx__tags" style={{marginBottom: "1rem"}}>
            {project.tags.map((t) => <span className="idx__tag" key={t}>{t}</span>)}
          </div>
          <div className="intro__links">
            {project.live && <a href={project.live} target="_blank" rel="noopener">Live →</a>}
            {project.repo && <a href={project.repo} target="_blank" rel="noopener">Source →</a>}
          </div>
        </div>
      </div>
    </section>
  );
}

// ============================================================
// /writing index
// ============================================================
function WritingIndex() {
  return (
    <div className="shell">
      <section className="sec" style={{paddingTop:"2rem"}}>
        <div className="label" style={{marginBottom:".5rem"}}>Archive</div>
        <h1 className="reader__title" style={{fontSize:"clamp(2rem,4vw,2.6rem)", marginBottom:"0.6rem"}}>Writing.</h1>
        <p className="intro__sub" style={{maxWidth:"54ch"}}>
          Long-form when something’s worth working out on paper. Industrial
          history, AI, product thinking — usually all three at once.
        </p>
        <ul className="writing" style={{marginTop:"2rem"}}>
          {DATA.writing.map((a) => (
            <li className="writing__item" key={a.id}>
              <div className="label">{a.date} · {a.reading}</div>
              <h3 className="writing__title" style={{marginTop:".4rem"}}>
                <a href={"#/writing/" + a.slug}>{a.title}</a>
              </h3>
              <p className="writing__sub">{a.subtitle}</p>
              <p className="writing__excerpt">{a.excerpt}</p>
              <div className="writing__meta">
                {a.tags.map((t) => <span key={t}>{t}</span>)}
              </div>
            </li>
          ))}
        </ul>
      </section>
    </div>
  );
}

// ============================================================
// Article reader
// ============================================================
function Article({ slug }) {
  const article = DATA.writing.find((a) => a.slug === slug);
  const body = DATA.articleBodies[slug];
  const progressRef = useRef(null);

  useEffect(() => {
    const onScroll = () => {
      const h = document.documentElement;
      const max = h.scrollHeight - h.clientHeight;
      const pct = max > 0 ? Math.min(1, h.scrollTop / max) : 0;
      if (progressRef.current) progressRef.current.style.transform = `scaleX(${pct})`;
    };
    window.addEventListener("scroll", onScroll, { passive: true });
    onScroll();
    return () => window.removeEventListener("scroll", onScroll);
  }, [slug]);

  if (!article || !body) {
    return <div className="shell"><p style={{padding:"3rem 0"}}>Not found. <a href="#/writing">Back to writing</a></p></div>;
  }

  let footnoteIdx = 0;

  return (
    <>
      <div className="progress" ref={progressRef} aria-hidden="true" />
      <div className="shell--narrow">
        <article className="reader">
          <a className="reader__back" href="#/writing">← Writing</a>

          <div className="label" style={{marginBottom:"1rem"}}>{article.date} · {article.reading}</div>
          <h1 className="reader__title">{article.title}</h1>
          <p className="reader__sub">{article.subtitle}</p>
          <div className="reader__meta">
            <span>By Sid Sanghavi</span>
            {article.tags.slice(0,3).map((t) => <span key={t}>{t}</span>)}
          </div>

          <div className="reader__body">
            {body.map((block, i) => {
              if (block.type === "lede") return <p key={i} className="lede">{block.text}</p>;
              if (block.type === "h2") return <h2 key={i}>{block.text}</h2>;
              if (block.type === "ol") return <ol key={i}>{block.items.map((it, j) => <li key={j}>{it}</li>)}</ol>;
              if (block.type === "ul") return <ul key={i}>{block.items.map((it, j) => <li key={j}>{it}</li>)}</ul>;
              if (block.type === "callout") return <p key={i} className="callout">{block.text}</p>;
              if (block.note) {
                footnoteIdx += 1;
                return (
                  <p key={i}>
                    {block.text}
                    <sup className="fnote">{footnoteIdx}</sup>
                    <span className="marginnote">
                      <span className="num">{footnoteIdx}.</span>
                      {block.note.text}
                    </span>
                  </p>
                );
              }
              return <p key={i}>{block.text}</p>;
            })}
          </div>

          <hr className="rule" style={{marginTop:"3rem"}} />
          <div className="label" style={{marginTop:"2rem"}}>End</div>
          <p style={{color:"var(--ink-2)", marginTop:".5rem"}}>
            Thanks for reading. If this resonated, write back: <ObfuscatedEmail />.
          </p>
        </article>
      </div>
    </>
  );
}

// ============================================================
// /career
// ============================================================
function CareerPage() {
  return (
    <div className="shell">
      <section className="sec" style={{paddingTop: "2rem"}}>
        <div className="label" style={{marginBottom:".5rem"}}>Timeline</div>
        <h1 className="reader__title" style={{fontSize:"clamp(2rem,4vw,2.8rem)", marginBottom:"0.6rem"}}>
          Career, in order.
        </h1>
        <p className="intro__sub" style={{maxWidth:"56ch"}}>
          Roles I’ve held, in reverse-chronological order. Each role links to
          the specific products that shipped during it — those live on the{" "}
          <a href="#/projects">Projects</a> page.
        </p>

        <ol className="timeline">
          {DATA.roles.map((r) => {
            const linked = (r.projectIds || [])
              .map((id) => DATA.projects.find((p) => p.id === id))
              .filter(Boolean);
            return (
              <li className="timeline__row" key={r.id}>
                <div className="timeline__when">
                  <div className="timeline__period">{r.period}</div>
                  <div className="timeline__loc">{r.location}</div>
                  <div className="timeline__roleTitle">{r.title}</div>
                </div>
                <div className="timeline__main">
                  <h2 className="timeline__org">
                    {r.org}
                    {r.orgMeta && <span className="timeline__orgMeta"> · {r.orgMeta}</span>}
                  </h2>
                  <p className="timeline__summary">{r.summary}</p>
                  {r.bullets && r.bullets.length > 0 && (
                    <ul className="timeline__bullets">
                      {r.bullets.map((b, i) => (
                        <li key={i}>{b}</li>
                      ))}
                    </ul>
                  )}
                  {linked.length > 0 && (
                    <div className="timeline__projects">
                      <span className="label">Shipped</span>
                      <div className="timeline__projectList">
                        {linked.map((p) => (
                          <a
                            key={p.id}
                            className="timeline__projectChip"
                            href={p.external || ("#/projects?focus=" + p.id)}
                            target={p.external ? "_blank" : undefined}
                            rel={p.external ? "noopener" : undefined}
                          >
                            <span className="timeline__projectName">{p.title}</span>
                            <span className="timeline__projectKick">{p.kicker}</span>
                            <span className="timeline__projectArrow">{p.external ? "↗" : "→"}</span>
                          </a>
                        ))}
                      </div>
                    </div>
                  )}
                </div>
              </li>
            );
          })}
        </ol>

        <div className="timeline__edu">
          <div className="label" style={{marginBottom:"1rem"}}>Education</div>
          <ul className="edu">
            {DATA.education.map((e) => (
              <li className="edu__row" key={e.id}>
                <div className="edu__year">{e.year}</div>
                <div className="edu__main">
                  <div className="edu__school">{e.school}</div>
                  <div className="edu__degree">{e.degree} · {e.location}</div>
                </div>
              </li>
            ))}
          </ul>
        </div>

        <p style={{marginTop: "3rem", color: "var(--ink-3)", fontFamily: "var(--sans)", fontSize: "13px"}}>
          <ObfuscatedEmail label="Email for resume PDF →" />
        </p>
      </section>
    </div>
  );
}

// ============================================================
// /about
// ============================================================
function About() {
  return (
    <div className="shell--narrow">
      <section className="reader" style={{paddingTop:"2rem"}}>
        <div className="label" style={{marginBottom:"1rem"}}>About</div>
        <h1 className="reader__title" style={{fontSize:"clamp(2rem,4vw,2.6rem)"}}>I’m Sid.</h1>
        <div className="reader__body" style={{marginTop:"2rem"}}>
          <p className="lede">
            Industrial engineer who likes watching how things actually get
            made — and then making the operations around them less awful.
          </p>
          <p>
            I started on the floor at Ford in Dearborn, walking paper checklists
            between assembly stations during F-150 launches. I ended up
            pitching a digital replacement to executives at HQ. That became
            LaunchCentral, which landed in the top 10 of fifty-odd ideas in
            Ford’s internal “Shark Tank” and got funded.
          </p>
          <p>
            From there: a YC manufacturing startup (Pashi, W20) where I built
            the MES + early analytics suite and helped land $3M in funding;
            then Fyusion / Cox Automotive, leading the admin software behind a
            fleet of AI-powered vehicle imaging tunnels — a system projected
            to save $60M a year in inspection efficiency.
          </p>
          <p>
            In 2023 I went in the other direction: bought into a
            home-remodeling franchise in Austin and ran it as Owner Operator
            through April 2026. We grew from $0 to $500K in revenue, delivered
            sixty-plus bathrooms and kitchens, collected thirty-plus 5-star
            reviews, and earned five Project-of-the-Month awards from the
            national franchisor. Behind the scenes was a steady amount of
            OpenAI + Zapier automation holding the marketing, sales, and
            operations together.
          </p>
          <p>
            Currently on sabbatical and building.{" "}
            <a href="https://openpts-api.onrender.com/docs" target="_blank" rel="noopener">OpenPTS</a>{" "}
            is the first open REST API for a 60-year-old industrial standard.{" "}
            <a href="https://gujarat.siddh.it" target="_blank" rel="noopener">Gujarat — Across Time</a>{" "}
            is an interactive map of Gujarati literature across thirteen
            centuries. Open to the next thing.
          </p>
          <h2>How I work</h2>
          <p>
            I’m happiest at the intersection of physical systems and
            software. Domain knowledge isn’t optional. The best insights
            come from being on the floor, in the truck, or in the customer’s
            kitchen. Most “data problems” turn out to be
            information-architecture problems wearing a costume — and most
            “AI problems” are really operations problems with a fancier hat.
          </p>
          <p>
            I’m not actively looking for anything. But I love talking shop —
            manufacturing, launch programs, weird APIs, home-services
            operations, and where the AI wave actually lands in industries
            that still run on paper.
          </p>
          <h2>Elsewhere</h2>
          <p>
            <a href="https://github.com/siddhit" target="_blank" rel="noopener">GitHub</a> ·{" "}
            <a href="https://www.linkedin.com/in/siddhit/" target="_blank" rel="noopener">LinkedIn</a> ·{" "}
            <ObfuscatedEmail />
          </p>
        </div>
      </section>
    </div>
  );
}

// ---------------- Mount ----------------
const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(<App />);