// app.jsx — Main page: nav, sections, footer, Tweaks panel.
// Depends on hero.jsx and portfolio.jsx (loaded before this script).

// Palettes — bright, airy, neutral. Backgrounds sit just under warm white;
// "ink" is a soft warm grey rather than near-black so nothing on the page
// competes with the illustrations. Primary/accent are luminous but still
// dusty — pulled from the artwork.
const PALETTES = {
  // Near-white cream + dusty coral + powder blue (polar-bear hero)
  shore: { name: "Powder & Cream", bg: "#F8F4EB", frame: "#F8F4EB", ink: "#6A6055", muted: "#A8A095", line: "#E8E1D2", primary: "#E6A67F", accent: "#BFD2D9" },
  // Bright buttermilk + faded honey + soft sage (kitchen scene)
  sage: { name: "Buttermilk", bg: "#FAF5E4", frame: "#F3ECD3", ink: "#6A6050", muted: "#A89F8C", line: "#E5DCC0", primary: "#DFC290", accent: "#C7DBCC" },
  // Pale cream + bright peach + buttercup (night-star piece)
  mustard: { name: "Stargazer", bg: "#F4F0E2", frame: "#ECE6D2", ink: "#6B6770", muted: "#A6A2AB", line: "#DCD6C4", primary: "#E1B19E", accent: "#DFD194" },
  // Warm linen + bright seaglass + shell pink (ocean spread)
  lavender: { name: "Shoreline", bg: "#F6F2E8", frame: "#EDE8D8", ink: "#6A6760", muted: "#A6A39A", line: "#DFD9CB", primary: "#B5C8CD", accent: "#DCBFB1" }
};

const TYPE_PAIRINGS = {
  editorial: { name: "Editorial", display: "'DM Serif Display', serif", body: "'Work Sans', system-ui, sans-serif" },
  storybook: { name: "Storybook", display: "'Lora', serif", body: "'Nunito', system-ui, sans-serif" },
  romantic: { name: "Romantic", display: "'Cormorant Garamond', serif", body: "'Public Sans', system-ui, sans-serif" }
};

const TWEAK_DEFAULTS = /*EDITMODE-BEGIN*/{
  "palette": "shore",
  "typography": "editorial",
  "heroVariant": "magazine",
  "galleryLayout": "masonry",
  "paperTexture": false,
  "tape": false
} /*EDITMODE-END*/;

// ── small UI ────────────────────────────────────────────────────────────────

function Nav({ palette }) {
  return (
    <nav data-vg-nav="true" style={{ ...{
        display: "flex", alignItems: "center", justifyContent: "flex-end",
        padding: "28px 80px 0", background: palette.bg, fontFamily: "var(--vg-body)"
      }, background: "rgb(255, 253, 247)", justifyContent: "flex-start", alignItems: "center" }}>
      <div style={{ display: "flex", gap: 36, alignItems: "center" }}>
        {[
        { href: "#work", label: "Work" },
        { href: "#about", label: "About" },
        { href: "#contact", label: "Contact" }].
        map((l) =>
        <a key={l.href} href={l.href} style={{
          color: palette.ink, textDecoration: "none", fontSize: 13,
          letterSpacing: ".14em", textTransform: "uppercase"
        }}>{l.label}</a>
        )}
      </div>
    </nav>);

}

const CLIENTS = [];


function About({ palette }) {
  return (
    <section id="about" data-vg-section="about" style={{ ...{
        padding: "120px 80px",
        background: palette.frame,
        borderTop: `1px solid ${palette.line}`,
        borderBottom: `1px solid ${palette.line}`
      }, background: "rgb(255, 253, 247)" }}>
      <div data-vg-grid="about-2col" style={{ display: "grid", gridTemplateColumns: "1fr 1.3fr", gap: 80, alignItems: "start", height: "677px" }}>
        <div>
          <div data-vg-about-portrait="true" style={{ background: palette.bg, boxShadow: "0 20px 40px -28px rgba(60,40,20,.5)", width: "544px", padding: "5px", height: "345px" }}>
            <image-slot id="about-portrait" shape="rect" fit="contain" placeholder="Drop a studio portrait"
            style={{ display: "block", width: "100%", height: "329px" }}></image-slot>
          </div>
          <div style={{ fontFamily: "var(--vg-body)", fontSize: 12, letterSpacing: ".18em", textTransform: "uppercase", color: palette.muted, marginTop: 18, textAlign: "center" }}> 

          </div>
        </div>
        <div>
          <div style={{ fontFamily: "var(--vg-body)", fontSize: 12, letterSpacing: ".24em", textTransform: "uppercase", color: palette.muted }}>
            About the studio
          </div>
          <h2 style={{ lineHeight: 1.05, margin: "16px 0 28px", color: palette.ink, letterSpacing: "1.7px", fontFamily: "\"Playfair Display\"", fontWeight: "500", width: "760px", fontSize: "35px" }}>
            Drawing the world <em style={{ color: palette.primary, fontStyle: "italic", fontWeight: "500", fontSize: "39px", fontFamily: "\"DM Serif Display\"" }}>as children see it</em>.
          </h2>
          <div style={{ fontFamily: "var(--vg-body)", fontSize: 17, lineHeight: 1.7, color: palette.ink, opacity: .85, maxWidth: 620, display: "flex", flexDirection: "column", gap: 18 }}>
            <p style={{ margin: 0 }}>I'm Virginia, a Singapore-based children's illustrator.

Inspired by my two young children and their love of dinosaurs, animals, vehicles, and all things small and furry, I create illustrations that are joyful and intentional — designed to spark imagination and bring lasting charm to a child's world.</p>
            <p style={{ margin: 0 }}>My work spans children's book illustration, art prints, and licensed character design. I'm available for illustration commissions and art licensing enquiries.

            </p>
            <p style={{ margin: 0 }}>When I'm not illustrating, I work as an interior designer.

            </p>
          </div>
        </div>
      </div>
    </section>);

}

function Contact({ palette }) {
  const [form, setForm] = React.useState({ name: "", email: "", kind: "Picture book", message: "" });
  const [sent, setSent] = React.useState(false);

  const update = (k) => (e) => setForm({ ...form, [k]: e.target.value });

  const submit = (e) => {
    e.preventDefault();
    if (!form.name || !form.email || !form.message) return;
    setSent(true);
  };

  return (
    <section id="contact" data-vg-section="contact" style={{ ...{ padding: "96px 80px 120px", background: palette.bg }, background: "rgb(241, 230, 210)" }}>
      <div data-vg-grid="contact-2col" style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: 96, alignItems: "start" }}>
        <div>
          <div style={{ fontFamily: "var(--vg-body)", fontSize: 12, letterSpacing: ".24em", textTransform: "uppercase", color: palette.muted }}>
            Get in touch
          </div>
          <h2 style={{ lineHeight: 1.02, margin: "16px 0 28px", color: palette.ink, letterSpacing: "-0.025em", fontSize: "43px", fontFamily: "\"Playfair Display\"", fontWeight: "500" }}>
            Tell me about your <em style={{ color: palette.primary, fontStyle: "italic", fontSize: "55px", fontWeight: "500", fontFamily: "serif" }}>story</em>.
          </h2>
          <p style={{ fontFamily: "var(--vg-body)", fontSize: 18, lineHeight: 1.6, color: palette.ink, opacity: .85, maxWidth: 440 }}>Currently booking picture-book and editorial commissions for autumn 2026 onwards.

          </p>

          <div style={{ marginTop: 48, display: "flex", flexDirection: "column", gap: 24, maxWidth: 440 }}>
            <ContactRow palette={palette} label="Direct" value="hello@virginiagohillustration.com" href="mailto:hello@virginiagohillustration.com" />
            <ContactRow palette={palette} label="Instagram" value="@virginia.draws" href="https://instagram.com" />
            <ContactRow palette={palette} label="Studio" value="Singapore" />
          </div>
        </div>

        <form onSubmit={submit} style={{ ...{
            background: palette.frame, padding: 40,
            border: `1px solid ${palette.line}`,
            display: "flex", flexDirection: "column", gap: 18
          }, background: "rgb(255, 253, 247)" }}>
          {sent ?
          <div style={{ padding: "40px 0", textAlign: "center" }}>
              <div style={{ fontFamily: "var(--vg-display)", fontSize: 40, lineHeight: 1.1, color: palette.ink, marginBottom: 16 }}>
                Thank you, {form.name.split(" ")[0]}.
              </div>
              <div style={{ fontFamily: "var(--vg-body)", fontSize: 16, lineHeight: 1.55, color: palette.ink, opacity: .8 }}>
                Your note has landed in the studio. I'll write back within a week — usually on a Sunday morning, over coffee.
              </div>
              <button type="button" onClick={() => {setSent(false);setForm({ name: "", email: "", kind: "Picture book", message: "" });}}
            style={{ marginTop: 28, ...btnGhost(palette), cursor: "pointer" }}>
                Send another
              </button>
            </div> :

          <React.Fragment>
              <FormField label="Your name" palette={palette}>
                <input type="text" value={form.name} onChange={update("name")} required
              style={inputStyle(palette)} placeholder="Eleanor Wren" />
              </FormField>
              <FormField label="Email" palette={palette}>
                <input type="email" value={form.email} onChange={update("email")} required
              style={inputStyle(palette)} placeholder="eleanor@pebbleplum.co" />
              </FormField>
              <FormField label="Project type" palette={palette}>
                <select value={form.kind} onChange={update("kind")} style={inputStyle(palette)}>
                  <option>Picture book</option>
                  <option>Book cover</option>
                  <option>Magazine / editorial</option>
                  <option>Brand / advertising</option>
                  <option>Toy / product</option>
                  <option>Something else</option>
                </select>
              </FormField>
              <FormField label="Tell me a little about it" palette={palette}>
                <textarea value={form.message} onChange={update("message")} required rows={5}
              style={{ ...inputStyle(palette), height: "auto", padding: "12px 14px", lineHeight: 1.5, resize: "vertical" }}
              placeholder="A picture book about a sleepy hedgehog who keeps a lighthouse…" />
              </FormField>
              <button type="submit" style={{ ...btnPrimary(palette), border: "0", cursor: "pointer", marginTop: 8, padding: "16px 22px" }}>
                Send a note
              </button>
            </React.Fragment>
          }
        </form>
      </div>
    </section>);

}

function ContactRow({ palette, label, value, href }) {
  const content =
  <div>
      <div style={{ fontFamily: "var(--vg-body)", fontSize: 11, letterSpacing: ".2em", textTransform: "uppercase", color: palette.muted, marginBottom: 4 }}>
        {label}
      </div>
      <div style={{ fontSize: 22, color: palette.ink, letterSpacing: "-0.005em", fontFamily: "\"Playfair Display\"", fontWeight: "500" }}>
        {value}
      </div>
    </div>;

  if (href) return <a href={href} style={{ textDecoration: "none", color: "inherit", borderBottom: `1px solid ${palette.line}`, paddingBottom: 14, display: "block" }}>{content}</a>;
  return <div style={{ borderBottom: `1px solid ${palette.line}`, paddingBottom: 14 }}>{content}</div>;
}

function FormField({ label, palette, children }) {
  return (
    <label style={{ display: "flex", flexDirection: "column", gap: 8 }}>
      <span style={{ fontFamily: "var(--vg-body)", fontSize: 11, letterSpacing: ".2em", textTransform: "uppercase", color: palette.muted }}>
        {label}
      </span>
      {children}
    </label>);

}
function inputStyle(palette) {
  return {
    appearance: "none",
    background: palette.bg,
    border: `1px solid ${palette.line}`,
    padding: "14px 14px",
    fontFamily: "var(--vg-body)", fontSize: 15, color: palette.ink,
    outline: "none",
    width: "100%",
    boxSizing: "border-box"
  };
}

function Footer({ palette }) {
  return (
    <footer data-vg-section="footer" style={{ background: palette.frame, color: palette.ink, padding: "56px 80px 40px", fontFamily: "var(--vg-body)", borderTop: `1px solid ${palette.line}` }}>
      <div style={{ display: "flex", justifyContent: "space-between", alignItems: "baseline", flexWrap: "wrap", gap: 24 }}>
        <div style={{ marginBottom: 8, width: "132px" }}>
          <image-slot id="logo" shape="rect" placeholder="Logo"
          style={{ display: "block", width: "143px", height: "87px" }}></image-slot>
        </div>
        <div style={{ display: "flex", gap: 28, fontSize: 12, letterSpacing: ".14em", textTransform: "uppercase", opacity: .8 }}>
          <a href="https://instagram.com" style={{ color: "inherit", textDecoration: "none" }}>Instagram</a>
          <a href="#" style={{ color: "inherit", textDecoration: "none" }}>Are.na</a>
          <a href="mailto:hello@virginiagohillustration.com" style={{ color: "inherit", textDecoration: "none" }}>Email</a>
        </div>
      </div>
      <div style={{ marginTop: 40, display: "flex", justifyContent: "space-between", fontSize: 12, opacity: .55 }}>
        <span>© 2026 Virginia Goh. All illustrations are her own.</span>
        <span>Made with watercolour and patience.</span>
      </div>
    </footer>);

}

// ── Tweaks panel ────────────────────────────────────────────────────────────

function StudioTweaks({ t, setTweak }) {
  return (
    <TweaksPanel title="Tweaks">
      <TweakSection label="Hero treatment" />
      <TweakRadio
        value={t.heroVariant}
        options={[
        { value: "magazine", label: "Magazine" },
        { value: "scrapbook", label: "Scrapbook" },
        { value: "spread", label: "Spread" },
        { value: "stamp", label: "Stamps" }]
        }
        onChange={(v) => setTweak("heroVariant", v)} />
      
      <TweakSection label="Gallery layout" />
      <TweakRadio
        value={t.galleryLayout}
        options={[
        { value: "editorial", label: "Editorial" },
        { value: "masonry", label: "Masonry" },
        { value: "uniform", label: "Uniform" }]
        }
        onChange={(v) => setTweak("galleryLayout", v)} />
      
      <TweakSection label="Palette" />
      <TweakSelect
        value={t.palette}
        options={Object.keys(PALETTES).map((k) => ({ value: k, label: PALETTES[k].name }))}
        onChange={(v) => setTweak("palette", v)} />
      
      <TweakColor
        value={[PALETTES[t.palette].bg, PALETTES[t.palette].frame, PALETTES[t.palette].primary, PALETTES[t.palette].ink]}
        options={Object.keys(PALETTES).map((k) => [PALETTES[k].bg, PALETTES[k].frame, PALETTES[k].primary, PALETTES[k].ink])}
        onChange={(val) => {
          const key = Object.keys(PALETTES).find((k) => PALETTES[k].bg === val[0]);
          if (key) setTweak("palette", key);
        }} />
      
      <TweakSection label="Typography" />
      <TweakSelect
        value={t.typography}
        options={Object.keys(TYPE_PAIRINGS).map((k) => ({ value: k, label: TYPE_PAIRINGS[k].name }))}
        onChange={(v) => setTweak("typography", v)} />
      
      <TweakSection label="Texture" />
      <TweakToggle label="Paper texture" value={t.paperTexture} onChange={(v) => setTweak("paperTexture", v)} />
      <TweakToggle label="Washi tape accents" value={t.tape} onChange={(v) => setTweak("tape", v)} />
    </TweaksPanel>);

}

// ── App ─────────────────────────────────────────────────────────────────────

function App() {
  const [t, setTweak] = useTweaks(TWEAK_DEFAULTS);
  const [filter, setFilter] = React.useState("All work");
  const [openWork, setOpenWork] = React.useState(null);

  const palette = PALETTES[t.palette] || PALETTES.shore;
  const type = TYPE_PAIRINGS[t.typography] || TYPE_PAIRINGS.editorial;

  React.useEffect(() => {
    document.documentElement.style.setProperty("--vg-display", type.display);
    document.documentElement.style.setProperty("--vg-body", type.body);
    document.body.style.background = palette.bg;
    document.body.style.color = palette.ink;
    document.body.style.fontFamily = type.body;
  }, [type, palette]);

  // Strip the image-slot's default frame bg + dashed ring from logo slots so
  // the logo can sit transparently on the cream page. The component uses a
  // shadow DOM with hardcoded styles, so we reach in via shadowRoot. Re-run
  // whenever the hero variant changes (different DOM nodes get mounted).
  React.useEffect(() => {
    const apply = () => {
      document.querySelectorAll('image-slot[id="logo"]').forEach((slot) => {
        const root = slot.shadowRoot;
        if (!root) return;
        const frame = root.querySelector(".frame");
        const ring = root.querySelector(".ring");
        if (frame) frame.style.background = "transparent";
        if (ring) ring.style.border = "1.5px dashed rgba(0,0,0,.15)";
      });
    };
    apply();
    // Also catch slow mounts (web components register their shadow on connect)
    const t1 = setTimeout(apply, 50);
    const t2 = setTimeout(apply, 200);
    return () => {clearTimeout(t1);clearTimeout(t2);};
  }, [t.heroVariant]);

  // Paper texture (subtle SVG noise)
  const paper = t.paperTexture ?
  `url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='220' height='220'><filter id='n'><feTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='2' stitchTiles='stitch'/><feColorMatrix values='0 0 0 0 0.4  0 0 0 0 0.35  0 0 0 0 0.28  0 0 0 0.04 0'/></filter><rect width='100%' height='100%' filter='url(%23n)'/></svg>")` :
  "none";

  const Hero =
  t.heroVariant === "scrapbook" ? HeroScrapbook :
  t.heroVariant === "spread" ? HeroSpread :
  t.heroVariant === "stamp" ? HeroStamp :
  HeroMagazine;

  return (
    <div id="top" style={{
      minHeight: "100vh",
      backgroundImage: paper,
      backgroundColor: palette.bg,
      backgroundBlendMode: "multiply",
      position: "relative"
    }}>
      <Nav palette={palette} />
      <Hero palette={palette} />
      <Gallery
        layout={t.galleryLayout}
        filter={filter}
        setFilter={setFilter}
        palette={palette}
        onOpen={setOpenWork}
        tape={t.tape} />
      
      <About palette={palette} />
      <Contact palette={palette} />
      <Footer palette={palette} />
      <Lightbox work={openWork} onClose={() => setOpenWork(null)} palette={palette} />
      <StudioTweaks t={t} setTweak={setTweak} />
    </div>);

}

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