// Main site — single-page portfolio with hash routing for legal pages.
// Editorial / portfolio feel: type-led, lots of whitespace, no marketing copy.
const { useState, useEffect } = React;

const TWEAK_DEFAULTS = /*EDITMODE-BEGIN*/{
  "theme": "light",
  "accent": ["#7c8cff", "#b08cff"],
  "fontPair": "geist-grotesk",
  "density": "comfortable",
  "ambientGlow": true,
  "showGrain": true
}/*EDITMODE-END*/;

const ACCENT_OPTIONS = [
  ["#7c8cff", "#b08cff"], // Indigo
  ["#22d3ee", "#8b5cf6"], // Cyan + Violet
  ["#fb923c", "#f43f5e"], // Ember
  ["#4ade80", "#22d3ee"], // Matrix
  ["#f472b6", "#fb7185"], // Rose
  ["#a3a3a3", "#737373"], // Paper
];

const FONT_PAIRS = {
  'geist-grotesk':  { display: "'Space Grotesk', system-ui, sans-serif", body: "'Geist', system-ui, sans-serif" },
  'grotesk-only':   { display: "'Space Grotesk', system-ui, sans-serif", body: "'Space Grotesk', system-ui, sans-serif" },
  'geist-only':     { display: "'Geist', system-ui, sans-serif",         body: "'Geist', system-ui, sans-serif" },
  'mono-display':   { display: "'Geist Mono', ui-monospace, monospace",  body: "'Geist', system-ui, sans-serif" },
};

const APPS = [
  {
    id: 'peppal',
    n: '01',
    name: 'PepPal',
    tag: 'Peptide Tracker',
    blurb: 'A focused tracker for peptide schedules, dosages, and notes.',
    url: 'https://touchgrass-screentime.my.canva.site/peppal/',
    year: '2025',
  },
  {
    id: 'touchgrass',
    n: '02',
    name: 'Touch Grass',
    tag: 'Screentime Control',
    blurb: 'A gentle but firm screen time tool. Set windows, schedule breaks, reclaim attention.',
    url: 'https://touchgrass-screentime.my.canva.site/',
    year: '2025',
  },
  {
    id: 'potterypal',
    n: '03',
    name: 'Pottery Pal',
    tag: 'Studio Companion',
    blurb: 'A pottery companion for tracking pieces, glazes, and firings.',
    url: 'https://potterypal.my.canva.site/',
    year: '2026',
  },
];

// ---------- Nav ----------
function Nav({ theme, onToggleTheme }) {
  const [scrolled, setScrolled] = useState(false);
  useEffect(() => {
    const onScroll = () => setScrolled(window.scrollY > 16);
    window.addEventListener('scroll', onScroll, { passive: true });
    return () => window.removeEventListener('scroll', onScroll);
  }, []);

  const links = [
    { label: 'About', href: '#about' },
    { label: 'Work',  href: '#work' },
    { label: 'Contact', href: '#contact' },
  ];

  return (
    <nav
      style={{
        position: 'sticky', top: 0, zIndex: 50,
        backdropFilter: scrolled ? 'blur(14px) saturate(140%)' : 'blur(0px)',
        WebkitBackdropFilter: scrolled ? 'blur(14px) saturate(140%)' : 'blur(0px)',
        background: scrolled ? 'color-mix(in srgb, var(--bg) 80%, transparent)' : 'transparent',
        borderBottom: scrolled ? '1px solid var(--border)' : '1px solid transparent',
        transition: 'all 0.25s ease',
      }}
    >
      <div style={{
        maxWidth: 1180, margin: '0 auto',
        padding: 'clamp(16px, 2vw, 22px) clamp(20px, 5vw, 56px)',
        display: 'flex', alignItems: 'center', gap: 24,
      }}>
        <a href="#" style={{
          textDecoration: 'none', color: 'var(--text)',
          fontFamily: 'var(--mono)', fontSize: 13, letterSpacing: '0.02em',
          fontWeight: 500,
        }}>
          Joseph Grzyb
        </a>
        <div style={{ flex: 1 }}/>
        <div style={{ display: 'flex', gap: 'clamp(6px, 1vw, 14px)', alignItems: 'center' }}>
          {links.map(l => (
            <a key={l.href} href={l.href} style={{
              textDecoration: 'none', color: 'var(--text-muted)',
              fontFamily: 'var(--mono)', fontSize: 13, letterSpacing: '0.02em',
              padding: '8px 10px', borderRadius: 6,
              transition: 'color 0.15s',
            }}
              onMouseEnter={(e)=>{ e.currentTarget.style.color='var(--text)'; }}
              onMouseLeave={(e)=>{ e.currentTarget.style.color='var(--text-muted)'; }}
            >{l.label}</a>
          ))}
          <button
            onClick={onToggleTheme}
            aria-label="Toggle theme"
            style={{
              width: 32, height: 32, marginLeft: 4,
              background: 'transparent', border: '1px solid var(--border)',
              borderRadius: 999,
              cursor: 'pointer', display: 'grid', placeItems: 'center',
              color: 'var(--text-muted)',
              transition: 'color 0.15s, border-color 0.15s',
            }}
            onMouseEnter={(e)=>{ e.currentTarget.style.color='var(--text)'; e.currentTarget.style.borderColor='var(--border-strong)';}}
            onMouseLeave={(e)=>{ e.currentTarget.style.color='var(--text-muted)'; e.currentTarget.style.borderColor='var(--border)';}}
          >
            {theme === 'dark'
              ? <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.8"><circle cx="12" cy="12" r="4"/><path d="M12 2v2M12 20v2M4.93 4.93l1.41 1.41M17.66 17.66l1.41 1.41M2 12h2M20 12h2M4.93 19.07l1.41-1.41M17.66 6.34l1.41-1.41"/></svg>
              : <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.8"><path d="M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79z"/></svg>
            }
          </button>
        </div>
      </div>
    </nav>
  );
}

// ---------- Hero ----------
function Hero() {
  return (
    <section style={{
      padding: 'clamp(80px, 14vw, 180px) clamp(20px, 5vw, 56px) clamp(40px, 6vw, 80px)',
      maxWidth: 1180, margin: '0 auto',
    }}>
      <div style={{
        fontFamily: 'var(--mono)', fontSize: 12.5, color: 'var(--text-dim)',
        letterSpacing: '0.1em', textTransform: 'uppercase', marginBottom: 36,
      }}>
        Joseph Grzyb · Independent app developer · San Francisco
      </div>

      <h1 style={{
        fontSize: 'clamp(32px, 4.8vw, 60px)',
        lineHeight: 1.15,
        letterSpacing: '-0.022em',
        fontWeight: 500,
        marginBottom: 28,
        maxWidth: '22ch',
        color: 'var(--text)',
      }}>
        I design and build small, focused mobile apps.
        <span style={{ color: 'var(--text-muted)' }}> Tools for tracking, attention, and making things by hand.</span>
      </h1>

      <p style={{
        fontSize: 16,
        color: 'var(--text-muted)',
        maxWidth: '52ch',
        lineHeight: 1.65,
      }}>
        Three apps live so far; more in progress. Everything is operated as a sole proprietor.
        No team, no investors, no analytics. <a href="#work" style={{ color: 'var(--text)', textDecoration: 'none', borderBottom: '1px solid var(--border-strong)' }}>See the work</a>.
      </p>
    </section>
  );
}

// ---------- Section label ----------
function SectionLabel({ index, children }) {
  return (
    <div style={{
      display: 'flex', alignItems: 'baseline', gap: 14,
      marginBottom: 40,
    }}>
      <span style={{
        fontFamily: 'var(--mono)', fontSize: 12, color: 'var(--text-dim)',
        letterSpacing: '0.06em',
      }}>{index}</span>
      <span style={{
        fontFamily: 'var(--mono)', fontSize: 12, color: 'var(--text-muted)',
        letterSpacing: '0.14em', textTransform: 'uppercase', fontWeight: 500,
      }}>{children}</span>
      <span style={{ flex: 1, height: 1, background: 'var(--border)', alignSelf: 'center' }}/>
    </div>
  );
}

// ---------- About ----------
function About() {
  return (
    <section id="about" style={{
      padding: 'clamp(50px, 6vw, 90px) clamp(20px, 5vw, 56px)',
      maxWidth: 1180, margin: '0 auto',
    }}>
      <SectionLabel index="01">About</SectionLabel>
      <div style={{
        display: 'grid', gridTemplateColumns: 'minmax(0, 0.7fr) minmax(0, 1.3fr)',
        gap: 'clamp(24px, 5vw, 80px)', alignItems: 'start',
      }} className="about-grid">
        <div>
          <h2 style={{
            fontSize: 17, lineHeight: 1.5, marginBottom: 0,
            fontFamily: 'var(--mono)', fontWeight: 500,
            color: 'var(--text-muted)', letterSpacing: '0.01em',
          }}>
            Operator
          </h2>
        </div>
        <div style={{ fontSize: 17, lineHeight: 1.7, color: 'var(--text)', maxWidth: '54ch' }}>
          <p style={{ marginBottom: 18 }}>
            Independent app designer and developer, based in San Francisco. Each app is designed,
            coded, and operated by Joseph Grzyb as a sole proprietor.
          </p>
          <p style={{ color: 'var(--text-muted)' }}>
            No accounts, no analytics, no advertising trackers. Data stays on your device.
            Apps are built to disappear into a daily routine, not pull you back in.
          </p>
        </div>
      </div>
      <style>{`
        @media (max-width: 720px) {
          .about-grid { grid-template-columns: 1fr !important; gap: 12px !important; }
        }
      `}</style>
    </section>
  );
}

// ---------- Work (apps as list) ----------
function WorkRow({ app, hovered, onHover, onLeave }) {
  return (
    <a
      href={app.url}
      target="_blank"
      rel="noopener noreferrer"
      onMouseEnter={onHover}
      onMouseLeave={onLeave}
      style={{
        display: 'grid',
        gridTemplateColumns: '56px minmax(0, 1.4fr) minmax(0, 1.6fr) 80px 28px',
        gap: 'clamp(12px, 2vw, 28px)',
        alignItems: 'baseline',
        padding: 'clamp(22px, 3vw, 32px) clamp(8px, 1vw, 16px)',
        borderTop: '1px solid var(--border)',
        textDecoration: 'none', color: 'inherit',
        transition: 'background 0.25s ease, padding-left 0.25s ease',
        background: hovered ? 'color-mix(in srgb, var(--accent) 5%, transparent)' : 'transparent',
        paddingLeft: hovered ? 'clamp(20px, 2vw, 28px)' : 'clamp(8px, 1vw, 16px)',
      }}
      className="work-row"
    >
      <span style={{
        fontFamily: 'var(--mono)', fontSize: 12, color: 'var(--text-dim)',
        letterSpacing: '0.04em',
      }}>{app.n}</span>

      <div>
        <h3 style={{
          fontSize: 'clamp(22px, 2.6vw, 30px)', lineHeight: 1.1,
          letterSpacing: '-0.02em', fontWeight: 500,
          color: hovered ? 'transparent' : 'var(--text)',
          background: hovered ? 'linear-gradient(120deg, var(--accent), var(--accent-2))' : 'none',
          WebkitBackgroundClip: hovered ? 'text' : 'initial',
          backgroundClip: hovered ? 'text' : 'initial',
          transition: 'color 0.25s ease',
        }}>{app.name}</h3>
        <div style={{
          fontFamily: 'var(--mono)', fontSize: 11.5, color: 'var(--text-muted)',
          letterSpacing: '0.08em', textTransform: 'uppercase', marginTop: 6,
        }}>{app.tag}</div>
      </div>

      <p style={{
        color: 'var(--text-muted)', fontSize: 15, lineHeight: 1.55,
        margin: 0, maxWidth: '48ch',
      }}>{app.blurb}</p>

      <span style={{
        fontFamily: 'var(--mono)', fontSize: 12, color: 'var(--text-dim)',
        letterSpacing: '0.04em', textAlign: 'right',
      }}>{app.year}</span>

      <span style={{
        fontSize: 18, color: hovered ? 'var(--text)' : 'var(--text-dim)',
        transform: hovered ? 'translate(2px, -2px)' : 'translate(0, 0)',
        transition: 'transform 0.25s ease, color 0.25s ease',
        textAlign: 'right',
      }}>↗</span>

      <style>{`
        @media (max-width: 720px) {
          .work-row {
            grid-template-columns: 32px 1fr 28px !important;
            grid-template-rows: auto auto !important;
            row-gap: 8px !important;
          }
          .work-row > :nth-child(3) { grid-column: 2 / 3; grid-row: 2; }
          .work-row > :nth-child(4) { display: none; }
        }
      `}</style>
    </a>
  );
}

function Work() {
  const [hoveredIdx, setHoveredIdx] = useState(null);

  return (
    <section id="work" style={{
      padding: 'clamp(50px, 6vw, 90px) clamp(20px, 5vw, 56px)',
      maxWidth: 1180, margin: '0 auto',
    }}>
      <SectionLabel index="02">Work</SectionLabel>

      <div>
        {APPS.map((app, i) => (
          <WorkRow
            key={app.id}
            app={app}
            hovered={hoveredIdx === i}
            onHover={() => setHoveredIdx(i)}
            onLeave={() => setHoveredIdx(null)}
          />
        ))}
        <div style={{ borderTop: '1px solid var(--border)' }}/>
      </div>
    </section>
  );
}

// ---------- Contact ----------
function Contact() {
  return (
    <section id="contact" style={{
      padding: 'clamp(50px, 6vw, 90px) clamp(20px, 5vw, 56px) clamp(80px, 8vw, 120px)',
      maxWidth: 1180, margin: '0 auto',
    }}>
      <SectionLabel index="03">Contact</SectionLabel>

      <div style={{
        display: 'grid', gridTemplateColumns: 'minmax(0, 0.7fr) minmax(0, 1.3fr)',
        gap: 'clamp(24px, 5vw, 80px)', alignItems: 'start',
      }} className="contact-grid">
        <div>
          <h2 style={{
            fontSize: 17, lineHeight: 1.5, marginBottom: 0,
            fontFamily: 'var(--mono)', fontWeight: 500,
            color: 'var(--text-muted)', letterSpacing: '0.01em',
          }}>
            For inquiries
          </h2>
        </div>

        <div>
          <div style={{
            display: 'grid', gap: 4,
            fontFamily: 'var(--mono)', fontSize: 15.5,
            color: 'var(--text)',
          }}>
            <div style={{ display: 'grid', gridTemplateColumns: '90px 1fr', gap: 16 }}>
              <span style={{ color: 'var(--text-dim)', fontSize: 12, letterSpacing: '0.08em', textTransform: 'uppercase', paddingTop: 5 }}>Email</span>
              <a href="mailto:joegrzyb24@gmail.com" style={{ color: 'var(--text)', textDecoration: 'none', borderBottom: '1px solid var(--border-strong)', justifySelf: 'start', paddingBottom: 1 }}>
                joegrzyb24@gmail.com
              </a>
            </div>
            <div style={{ display: 'grid', gridTemplateColumns: '90px 1fr', gap: 16, marginTop: 14 }}>
              <span style={{ color: 'var(--text-dim)', fontSize: 12, letterSpacing: '0.08em', textTransform: 'uppercase', paddingTop: 5 }}>Based</span>
              <span style={{ color: 'var(--text-muted)', paddingTop: 4 }}>San Francisco, CA</span>
            </div>
          </div>
        </div>
      </div>

      <style>{`
        @media (max-width: 720px) {
          .contact-grid { grid-template-columns: 1fr !important; gap: 12px !important; }
        }
      `}</style>
    </section>
  );
}

// ---------- Footer ----------
function Footer() {
  return (
    <footer style={{
      padding: 'clamp(28px, 3vw, 40px) clamp(20px, 5vw, 56px) 32px',
      maxWidth: 1180, margin: '0 auto',
      borderTop: '1px solid var(--border)',
    }}>
      <div style={{
        display: 'flex', flexWrap: 'wrap', gap: 16,
        justifyContent: 'space-between', alignItems: 'baseline',
        fontFamily: 'var(--mono)', fontSize: 12, color: 'var(--text-muted)',
        letterSpacing: '0.02em',
      }}>
        <div>
          © 2026 Joseph Grzyb
        </div>
        <div style={{ display: 'flex', gap: 18 }}>
          <a href="#privacy" style={{ color: 'var(--text-muted)', textDecoration: 'none' }}>Privacy Policy</a>
          <a href="#terms" style={{ color: 'var(--text-muted)', textDecoration: 'none' }}>Terms</a>
          <a href="#data-deletion" style={{ color: 'var(--text-muted)', textDecoration: 'none' }}>Data Deletion</a>
        </div>
      </div>
    </footer>
  );
}

// ---------- Tweaks ----------
function Tweaks() {
  const [t, setTweak] = useTweaks(TWEAK_DEFAULTS);

  useEffect(() => {
    document.documentElement.setAttribute('data-theme', t.theme);
    const accent = Array.isArray(t.accent) ? t.accent : ['#7c8cff', '#b08cff'];
    document.documentElement.style.setProperty('--accent', accent[0]);
    document.documentElement.style.setProperty('--accent-2', accent[1] || accent[0]);
    const fp = FONT_PAIRS[t.fontPair] || FONT_PAIRS['geist-grotesk'];
    document.documentElement.style.setProperty('--display', fp.display);
    document.documentElement.style.setProperty('--body', fp.body);
    document.body.style.fontSize = t.density === 'compact' ? '15px' : t.density === 'spacious' ? '17px' : '16px';
    const glow = document.querySelector('.bg-glow');
    const grain = document.querySelector('.bg-grain');
    if (glow)  glow.style.opacity  = t.ambientGlow ? '1' : '0';
    if (grain) grain.style.opacity = t.showGrain   ? '' : '0';
  }, [t]);

  return (
    <>
      <SiteRoot
        theme={t.theme}
        onToggleTheme={() => setTweak('theme', t.theme === 'dark' ? 'light' : 'dark')}
      />
      <TweaksPanel title="Tweaks">
        <TweakSection label="Theme"/>
        <TweakRadio label="Mode" value={t.theme} options={[
          { label: 'Dark', value: 'dark' },
          { label: 'Light', value: 'light' },
        ]} onChange={(v) => setTweak('theme', v)}/>
        <TweakColor
          label="Accent"
          value={t.accent}
          options={ACCENT_OPTIONS}
          onChange={(v) => setTweak('accent', v)}
        />

        <TweakSection label="Type"/>
        <TweakSelect label="Font pair" value={t.fontPair} options={[
          { label: 'Space Grotesk + Geist',  value: 'geist-grotesk' },
          { label: 'Space Grotesk only',     value: 'grotesk-only' },
          { label: 'Geist only',             value: 'geist-only' },
          { label: 'Mono display + Geist',   value: 'mono-display' },
        ]} onChange={(v) => setTweak('fontPair', v)}/>
        <TweakRadio label="Density" value={t.density} options={[
          { label: 'Compact',     value: 'compact' },
          { label: 'Comfortable', value: 'comfortable' },
          { label: 'Spacious',    value: 'spacious' },
        ]} onChange={(v) => setTweak('density', v)}/>

        <TweakSection label="Background"/>
        <TweakToggle label="Ambient glow"  value={t.ambientGlow} onChange={(v) => setTweak('ambientGlow', v)}/>
        <TweakToggle label="Film grain"    value={t.showGrain}   onChange={(v) => setTweak('showGrain', v)}/>
      </TweaksPanel>
    </>
  );
}

// ---------- Root with hash routing ----------
function SiteRoot({ theme, onToggleTheme }) {
  const [hash, setHash] = useState(window.location.hash);
  useEffect(() => {
    const onHash = () => {
      setHash(window.location.hash);
      if (['#privacy', '#terms', '#data-deletion'].includes(window.location.hash)) {
        window.scrollTo(0, 0);
      }
    };
    window.addEventListener('hashchange', onHash);
    return () => window.removeEventListener('hashchange', onHash);
  }, []);

  const closeLegal = () => {
    history.pushState('', document.title, window.location.pathname + window.location.search);
    setHash('');
    window.scrollTo(0, 0);
  };

  if (hash === '#privacy')       return <PrivacyPolicy onClose={closeLegal}/>;
  if (hash === '#terms')         return <TermsOfService onClose={closeLegal}/>;
  if (hash === '#data-deletion') return <DataDeletion onClose={closeLegal}/>;

  return (
    <>
      <Nav theme={theme} onToggleTheme={onToggleTheme}/>
      <Hero/>
      <About/>
      <Work/>
      <Contact/>
      <Footer/>
    </>
  );
}

ReactDOM.createRoot(document.getElementById('app')).render(<Tweaks/>);
