// Ulicraft landing — pixel components, live status, copy-IP, scroll reveals, tweaks
const { useState, useEffect, useRef, useCallback } = React;

/* ---------- pixel art helpers ---------- */
// 8x8 creeper face
const CREEPER = [
  "00000000",
  "01100110",
  "01100110",
  "00011000",
  "00111100",
  "00111100",
  "00100100",
  "00000000",
];
function Creeper() {
  const cells = CREEPER.join("").split("");
  return (
    <div className="creeper" aria-hidden="true">
      {cells.map((c, i) => <i key={i} className={c === "1" ? "f" : ""} />)}
    </div>
  );
}

// 7x7 feature glyphs
const GLYPHS = {
  shield: ["0111110","1111111","1111111","1111111","0111110","0011100","0001000"],
  diamond:["0001000","0011100","0111110","1111111","0111110","0011100","0001000"],
  orb:    ["0011100","0111110","1111111","1111111","1111111","0111110","0011100"],
  heart:  ["0110110","1111111","1111111","1111111","0111110","0011100","0001000"],
};
function PixelIcon({ glyph, gold }) {
  const cells = GLYPHS[glyph].join("").split("");
  return (
    <div className="picon" aria-hidden="true">
      {cells.map((c, i) => (
        <i key={i} className={c === "1" ? (gold ? "go" : "on") : ""} />
      ))}
    </div>
  );
}

/* ---------- copy to clipboard ---------- */
function copyText(text) {
  try {
    if (navigator.clipboard && window.isSecureContext) {
      navigator.clipboard.writeText(text);
      return;
    }
  } catch (e) {}
  const ta = document.createElement("textarea");
  ta.value = text;
  ta.style.position = "fixed";
  ta.style.opacity = "0";
  document.body.appendChild(ta);
  ta.select();
  try { document.execCommand("copy"); } catch (e) {}
  document.body.removeChild(ta);
}

function IpChip({ ip }) {
  const [copied, setCopied] = useState(false);
  const onCopy = () => {
    copyText(ip);
    setCopied(true);
    clearTimeout(onCopy._t);
    onCopy._t = setTimeout(() => setCopied(false), 1600);
  };
  return (
    <div className="ip-chip">
      <span className="ip-val"><span className="pin">▸</span>{ip}</span>
      <button className={copied ? "copied" : ""} onClick={onCopy}>
        {copied ? "Copied!" : "Copy IP"}
      </button>
    </div>
  );
}

/* ---------- live player count ---------- */
function useLivePlayers(base = 37, max = 100) {
  const [n, setN] = useState(base);
  useEffect(() => {
    if (window.matchMedia("(prefers-reduced-motion: reduce)").matches) return;
    const id = setInterval(() => {
      setN((p) => {
        const step = Math.floor(Math.random() * 5) - 2;
        return Math.max(base - 6, Math.min(max - 4, p + step));
      });
    }, 2600);
    return () => clearInterval(id);
  }, [base, max]);
  return n;
}

/* ---------- floating pixel dust ---------- */
function Dust({ on }) {
  if (!on) return null;
  const bits = Array.from({ length: 16 }, (_, i) => i);
  return (
    <div className="dust" aria-hidden="true">
      {bits.map((i) => {
        const size = 3 + (i % 3) * 2;
        const st = {
          position: "absolute",
          left: ((i * 61) % 100) + "%",
          bottom: "-20px",
          width: size + "px",
          height: size + "px",
          background: i % 4 === 0 ? "var(--gold)" : "var(--accent)",
          opacity: 0.18 + (i % 3) * 0.06,
          imageRendering: "pixelated",
          animation: `rise ${13 + (i % 7) * 3}s linear ${i * 0.7}s infinite`,
        };
        return <i key={i} style={st} />;
      })}
    </div>
  );
}

/* ---------- server-list status panel ---------- */
function ServerListPanel({ players, max, version }) {
  return (
    <div className="serverlist">
      <div className="icon"><Creeper /></div>
      <div className="meta">
        <div className="row1">
          <span className="title">Ulicraft</span>
          <span className="ver">Java {version}</span>
        </div>
        <p className="motd">
          <span className="a">⛏ Season 3</span> · Survival SMP · <span className="g">whitelist open</span>
        </p>
      </div>
      <div className="stat">
        <div className="players">
          <span className="bars" aria-hidden="true"><i /><i /><i /><i /><i /></span>
          <span><b>{players}</b>/{max}</span>
        </div>
      </div>
    </div>
  );
}

/* ---------- scroll reveal (fail-safe: visible at rest, .anim added when in view) ---------- */
function useReveal() {
  useEffect(() => {
    if (window.matchMedia("(prefers-reduced-motion: reduce)").matches) return;
    let els = [...document.querySelectorAll(".reveal")];
    let stop = false;
    const tick = () => {
      if (stop) return;
      const vh = window.innerHeight;
      for (let i = els.length - 1; i >= 0; i--) {
        const r = els[i].getBoundingClientRect();
        if (r.top < vh * 0.9 && r.bottom > 0) {
          els[i].classList.add("anim");
          els.splice(i, 1);
        }
      }
      if (els.length) requestAnimationFrame(tick);
      else stop = true;
    };
    requestAnimationFrame(tick);
    return () => { stop = true; };
  }, []);
}

/* ============================================================ */
const TWEAK_DEFAULTS = /*EDITMODE-BEGIN*/{
  "heroLayout": "centered",
  "mood": "grass",
  "headFont": "pixelify",
  "serverIp": "play.ulicraft.net",
  "tagline": "Hardcore survival, built to last.",
  "particles": true
}/*EDITMODE-END*/;

const HEAD_FONTS = {
  pixelify: "'Pixelify Sans', system-ui, sans-serif",
  "8bit": "'Press Start 2P', monospace",
  silkscreen: "'Silkscreen', system-ui, sans-serif",
};

const FEATURES = [
  { glyph: "shield", gold: false, h: "Grief-proof claims",
    p: "Lock down your base with golden-shovel land claims. Your builds stay yours — even while you're offline." },
  { glyph: "diamond", gold: true, h: "Zero pay-to-win",
    p: "The store sells cosmetics and nothing else. Every diamond is earned in-game, never bought." },
  { glyph: "orb", gold: false, h: "A living world",
    p: "Seasonal map resets, custom bosses, and community events keep the overworld worth logging into." },
  { glyph: "heart", gold: true, h: "Real community",
    p: "A whitelisted, moderated server with an active Discord. Toxicity meets the ban hammer, fast." },
];

function App() {
  const [t, setTweak] = useTweaks(TWEAK_DEFAULTS);
  const players = useLivePlayers(37, 100);
  const peak = 84;
  const version = "1.21.4";

  // guarantee pixel head fonts are downloaded before first paint settles
  useEffect(() => {
    if (!document.fonts || !document.fonts.load) return;
    ["600 32px 'Pixelify Sans'", "700 32px 'Pixelify Sans'",
     "400 32px 'Press Start 2P'", "400 32px 'Silkscreen'", "700 32px 'Silkscreen'"]
      .forEach((f) => document.fonts.load(f).catch(() => {}));
  }, []);

  // apply mood / hero / font to <html>
  useEffect(() => {
    const r = document.documentElement;
    r.setAttribute("data-mood", t.mood);
    r.setAttribute("data-hero", t.heroLayout);
    r.setAttribute("data-head", t.headFont);
    r.style.setProperty("--font-head", HEAD_FONTS[t.headFont] || HEAD_FONTS.pixelify);
  }, [t.mood, t.heroLayout, t.headFont]);

  useReveal();

  return (
    <>
      {/* NAV */}
      <header className="nav">
        <div className="wrap nav-in">
          <a className="brand" href="#top">
            <Creeper />
            <span className="name">ULICRAFT</span>
          </a>
          <nav className="nav-links">
            <a href="#status">Status</a>
            <a href="#features">Features</a>
            <a href="#join">How to Join</a>
          </nav>
          <span className="nav-spacer" />
          <a className="mc-btn primary sm" href="#join">Play Now</a>
        </div>
      </header>

      {/* HERO */}
      <main id="top">
        <section className="hero" data-screen-label="Hero">
          <Dust on={t.particles} />
          <div className="wrap hero-grid">
            <div className="hero-logo">
              <img src="assets/ulicraft-logo.png" alt="Ulicraft" width="707" height="148" />
            </div>
            <div className="hero-copy">
              <span className="eyebrow">Java Edition · Survival SMP · Season 3</span>
              <h1 className="hero-tagline">{t.tagline}</h1>
              <p className="hero-sub">
                A whitelisted Java SMP with land claims, seasonal events, and zero pay-to-win.
                Grab the IP, fire up your launcher, and stake your claim.
              </p>
              <div className="hero-ip-row">
                <IpChip ip={t.serverIp} />
                <a className="mc-btn" href="#join">How to Join</a>
              </div>
              <div className="hero-meta">
                <span className="live-pill">
                  <span className="live-dot" />
                  <span><b>{players}</b> playing now</span>
                </span>
                <span>Java {version}</span>
                <span className="dot" />
                <span>No mods required</span>
              </div>
            </div>
            <div className="hero-status">
              <ServerListPanel players={players} max={100} version={version} />
            </div>
          </div>
        </section>

        {/* STATUS */}
        <section id="status" className="pad" data-screen-label="Status">
          <div className="wrap">
            <div className="sec-head reveal">
              <span className="eyebrow">Server Status</span>
              <h2 className="section-title">Live, and waiting for you.</h2>
              <p className="lead">This is exactly what you'll see in your multiplayer list.</p>
            </div>
            <div className="reveal">
              <ServerListPanel players={players} max={100} version={version} />
            </div>
            <div className="stat-grid">
              {[
                { k: <>{players}<span className="u">/100</span></>, l: "Players Online" },
                { k: <>{peak}</>, l: "Peak Today" },
                { k: <>99.9<span className="u">%</span></>, l: "Uptime" },
                { k: <>20.0<span className="u"> tps</span></>, l: "Performance" },
              ].map((s, i) => (
                <div className="tile reveal" key={i} style={{ transitionDelay: i * 60 + "ms" }}>
                  <div className="k">{s.k}</div>
                  <div className="l">{s.l}</div>
                </div>
              ))}
            </div>
          </div>
        </section>

        {/* FEATURES */}
        <section id="features" className="pad" data-screen-label="Features" style={{ background: "var(--bg-2)" }}>
          <div className="wrap">
            <div className="sec-head reveal">
              <span className="eyebrow">What makes it Ulicraft</span>
              <h2 className="section-title">Built for players who stay.</h2>
              <p className="lead">No reset roulette, no whales buying god gear. Just a server that respects your time.</p>
            </div>
            <div className="feat-grid">
              {FEATURES.map((f, i) => (
                <div className="feat reveal" key={i} style={{ transitionDelay: (i % 2) * 80 + "ms" }}>
                  <PixelIcon glyph={f.glyph} gold={f.gold} />
                  <div>
                    <h3>{f.h}</h3>
                    <p>{f.p}</p>
                  </div>
                </div>
              ))}
            </div>
          </div>
        </section>

        {/* HOW TO JOIN */}
        <section id="join" className="pad" data-screen-label="How to Join">
          <div className="wrap">
            <div className="sec-head reveal">
              <span className="eyebrow">How to Join · 3 Steps</span>
              <h2 className="section-title">From zero to spawning in.</h2>
              <p className="lead">Ulicraft runs on Minecraft: Java Edition. Here's the whole path, start to finish.</p>
            </div>

            <div className="steps">
              {/* STEP 1 */}
              <div className="step reveal">
                <div className="num">1</div>
                <div className="body">
                  <span className="kicker">Account</span>
                  <h3>Get Minecraft: Java Edition</h3>
                  <p>
                    Create a free Microsoft account, then buy and download Minecraft: Java &amp; Bedrock
                    Edition from minecraft.net. Already own Java Edition? Skip straight to step&nbsp;2.
                  </p>
                  <div className="actions">
                    <a className="mc-btn gold sm" href="https://www.minecraft.net/get-minecraft" target="_blank" rel="noopener">Get Java Edition →</a>
                    <span className="hint">Microsoft account required</span>
                  </div>
                </div>
              </div>

              {/* STEP 2 */}
              <div className="step reveal">
                <div className="num">2</div>
                <div className="body">
                  <span className="kicker">Launcher</span>
                  <h3>Download &amp; set up the launcher</h3>
                  <p>
                    Install the official Minecraft Launcher, sign in with your Microsoft account, and select
                    the <strong style={{ color: "var(--text)" }}>Latest Release ({version})</strong> profile.
                  </p>
                  <ul>
                    <li>Download the launcher for Windows, macOS, or Linux.</li>
                    <li>Sign in → pick <strong style={{ color: "var(--text)" }}>Latest Release</strong> → press <strong style={{ color: "var(--text)" }}>Play</strong> once to finish installing.</li>
                    <li>Optional: allocate 4–6&nbsp;GB RAM under Installations → More Options for smoother play.</li>
                  </ul>
                  <div className="actions">
                    <a className="mc-btn sm" href="https://www.minecraft.net/download" target="_blank" rel="noopener">Download launcher →</a>
                    <span className="hint">No mods or modpack needed</span>
                  </div>
                </div>
              </div>

              {/* STEP 3 */}
              <div className="step reveal">
                <div className="num">3</div>
                <div className="body">
                  <span className="kicker">Connect</span>
                  <h3>Join the Ulicraft server</h3>
                  <p>
                    In Minecraft, open <kbd>Multiplayer</kbd> → <kbd>Add Server</kbd>. Name it Ulicraft,
                    paste the address below, hit <kbd>Done</kbd>, then double-click the server to join.
                  </p>
                  <div className="actions" style={{ marginBottom: "14px" }}>
                    <IpChip ip={t.serverIp} />
                  </div>
                  <span className="hint">Whitelisted server — apply in our Discord first to get added.</span>
                </div>
              </div>
            </div>
          </div>
        </section>
      </main>

      {/* FOOTER */}
      <footer className="footer">
        <div className="wrap footer-in">
          <a className="brand" href="#top">
            <Creeper />
            <span className="name">ULICRAFT</span>
          </a>
          <div className="footer-links">
            <a className="mc-btn primary sm" href="#join">Copy IP &amp; Play</a>
            <a className="mc-btn sm" href="#" onClick={(e) => e.preventDefault()}>Discord</a>
          </div>
          <p className="disc">
            Not affiliated with Mojang or Microsoft. Minecraft is a trademark of Mojang AB.
            © 2026 Ulicraft.
          </p>
        </div>
      </footer>

      {/* TWEAKS */}
      <TweaksPanel title="Tweaks">
        <TweakSection label="Layout" />
        <TweakRadio label="Hero" value={t.heroLayout}
          options={[{ value: "centered", label: "Centered" }, { value: "split", label: "Split" }, { value: "spotlight", label: "Spotlight" }]}
          onChange={(v) => setTweak("heroLayout", v)} />
        <TweakSection label="Mood" />
        <TweakRadio label="Palette" value={t.mood}
          options={[{ value: "grass", label: "Grass" }, { value: "nether", label: "Nether" }, { value: "end", label: "End" }]}
          onChange={(v) => setTweak("mood", v)} />
        <TweakSection label="Type" />
        <TweakSelect label="Headline font" value={t.headFont}
          options={[{ value: "pixelify", label: "Pixelify (readable)" }, { value: "8bit", label: "Press Start (8-bit)" }, { value: "silkscreen", label: "Silkscreen" }]}
          onChange={(v) => setTweak("headFont", v)} />
        <TweakSection label="Content" />
        <TweakText label="Tagline" value={t.tagline} onChange={(v) => setTweak("tagline", v)} />
        <TweakText label="Server IP" value={t.serverIp} onChange={(v) => setTweak("serverIp", v)} />
        <TweakToggle label="Floating dust" value={t.particles} onChange={(v) => setTweak("particles", v)} />
      </TweaksPanel>
    </>
  );
}

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