// Supernormal Minecraft — landing page (dark mode only)
// Layout: fixed header + footer, scrolling middle (sidebar + main) inside wood frame.
// Sections flow: about → how to join → mini timeline preview (click-through to timeline.html).

// Production config. anchorWallClock + anchorVersion are placeholders — the
// real values are fetched from /status.json at mount (regenerated by
// refresh-status.sh on every timeline upgrade). Other fields are static.
const SITE_CONFIG = {
  tagline: "Minecraft as it was intended",
  serverAddress: "mc.supernormalsolutions.com",
  accentColor: "#8FB05A",
  wordmarkLine1: "SUPERNORMAL",
  wordmarkLine2: "MINECRAFT",
  anchorWallClock: "2026-03-01",
  anchorVersion: "0.1.2_01",
};

// --- mini timeline helpers ---------------------------------------------
function miniRealDateFor(canonicalDateStr, anchorWallClockStr, anchorVersion) {
  const anchorEntry = MANIFEST.find(m => m.v === anchorVersion) || MANIFEST[0];
  const canonicalAnchor = parseDate(anchorEntry.d);
  const canonicalTarget = parseDate(canonicalDateStr);
  const gap = daysBetween(canonicalAnchor, canonicalTarget);
  const wall = parseDate(anchorWallClockStr);
  const out = new Date(wall);
  out.setUTCDate(out.getUTCDate() + gap);
  return out;
}
function miniEraOf(v) {
  if (v.startsWith('0.')) return 'alpha';
  if (['b1.0','b1.0_01','b1.1','b1.1_01','b1.1_02','b1.2','b1.2_01'].includes(v)) return 'early-beta';
  if (['b1.3','b1.4','b1.4_01','b1.5','b1.5_01','b1.5_02'].includes(v)) return 'mid-beta';
  return 'late-beta';
}

function MiniTimeline({ anchorWallClock, anchorVersion, accent }) {
  const ALPHA_C = '#A07A4F', EARLY_BETA = '#8FB05A', MID_BETA = '#b89a54', LATE_BETA = '#c26a6a';
  const eraColor = (era) => era === 'alpha' ? ALPHA_C : era === 'early-beta' ? EARLY_BETA
    : era === 'mid-beta' ? MID_BETA : LATE_BETA;
  const ink = '#EADFC4', muted = '#9A8F74', rule = '#463c28';

  const enriched = MANIFEST.map(m => ({
    ...m,
    wallDate: miniRealDateFor(m.d, anchorWallClock, anchorVersion),
  }));
  const now = new Date();
  const nowUTC = new Date(Date.UTC(now.getUTCFullYear(), now.getUTCMonth(), now.getUTCDate()));
  let liveIdx = -1;
  for (let i = 0; i < enriched.length; i++) {
    if (enriched[i].wallDate.getTime() <= nowUTC.getTime()) liveIdx = i;
  }
  const live = liveIdx >= 0 ? enriched[liveIdx] : null;

  const firstD = parseDate(MANIFEST[0].d);
  const lastD = parseDate(MANIFEST[MANIFEST.length-1].d);
  const totalDays = daysBetween(firstD, lastD);
  const W = 640; // compact rail width
  const xFor = (ds) => (daysBetween(firstD, parseDate(ds)) / totalDays) * W;

  // Era bands for mini
  const bands = [
    { from: '2010-08-12', to: '2010-12-03', color: ALPHA_C, label: 'alpha' },
    { from: '2010-12-20', to: '2011-01-14', color: EARLY_BETA, label: 'early beta' },
    { from: '2011-02-22', to: '2011-04-20', color: MID_BETA, label: 'mid beta' },
    { from: '2011-05-26', to: '2011-07-08', color: LATE_BETA, label: 'late beta' },
  ];

  // now marker
  const nowDayOff = (nowUTC - enriched[0].wallDate) / 86400000;
  const clampedNow = Math.max(0, Math.min(totalDays, nowDayOff));
  const nowX = (clampedNow / totalDays) * W;
  const nowInRange = nowDayOff >= 0 && nowDayOff <= totalDays;

  return (
    <a href="timeline.html" className="mini-tl" style={{
      display: 'block', textDecoration: 'none', color: 'inherit',
      border: `1px solid ${rule}`, background: '#15110b',
      padding: '14px 16px 10px',
      position: 'relative',
      cursor: 'pointer',
    }}>
      {/* caption row */}
      <div style={{ display: 'flex', alignItems: 'baseline', justifyContent: 'space-between', marginBottom: 10, gap: 12 }}>
        <div>
          <div className="pstart" style={{ fontSize: 10, color: accent, letterSpacing: 1 }}>THE WORLDLINE</div>
          <div className="vt" style={{ fontSize: 15, color: muted, marginTop: 2 }}>
            {live ? <>live: <b style={{ color: ink }}>{live.v}</b></> : <>not yet anchored</>}
          </div>
        </div>
        <div className="vt open-hint" style={{ fontSize: 15, color: muted, whiteSpace: 'nowrap' }}>
          open timeline <span style={{ color: accent }}>&rarr;</span>
        </div>
      </div>

      {/* rail */}
      <div style={{ position: 'relative', width: W, maxWidth: '100%', height: 64, margin: '0 auto' }}>
        {/* base rail */}
        <div style={{
          position: 'absolute', left: 0, right: 0, top: 28, height: 4,
          background: '#15110b', border: `1px solid ${rule}`,
        }}/>
        {/* progress fill */}
        {nowX > 0 && (
          <div style={{
            position: 'absolute', left: 0, top: 28, width: nowX, height: 4,
            backgroundImage: `repeating-linear-gradient(45deg, ${accent} 0 4px, ${SN_PALETTE.grassDark} 4px 7px)`,
            border: `1px solid #0a0906`, boxSizing: 'border-box',
          }}/>
        )}

        {/* era bands under the rail */}
        {bands.map((b, i) => {
          const x1 = xFor(b.from), x2 = xFor(b.to);
          const w = Math.max(2, x2 - x1);
          return (
            <React.Fragment key={i}>
              <div style={{ position: 'absolute', left: x1, top: 40, width: 2, height: 5, background: b.color }}/>
              <div style={{ position: 'absolute', left: x2 - 2, top: 40, width: 2, height: 5, background: b.color }}/>
              <div style={{ position: 'absolute', left: x1, top: 44, width: w, height: 1, background: b.color }}/>
              <div className="vt" style={{
                position: 'absolute', left: (x1+x2)/2 - 50, top: 48, width: 100,
                color: b.color, fontSize: 11, textAlign: 'center', textTransform: 'uppercase', letterSpacing: 1,
              }}>{b.label}</div>
            </React.Fragment>
          );
        })}

        {/* nodes */}
        {enriched.map((e, i) => {
          const x = xFor(e.d);
          const isLive = i === liveIdx;
          const isPast = i < liveIdx;
          const c = eraColor(miniEraOf(e.v));
          const size = isLive ? 10 : 5;
          const bg = (isLive || isPast) ? c : '#0a0906';
          const borderCol = (isLive || isPast) ? ink : `${c}88`;
          return (
            <div key={i} style={{
              position: 'absolute', left: x - size/2, top: 30 - size/2 + 2,
              width: size, height: size, background: bg,
              border: `1px solid ${borderCol}`,
              opacity: (!isLive && !isPast) ? 0.7 : 1,
              zIndex: isLive ? 6 : isPast ? 4 : 3,
              boxShadow: isLive ? `0 0 0 2px ${ink}` : 'none',
            }}/>
          );
        })}

        {/* now marker */}
        {nowInRange && (
          <>
            <div style={{
              position: 'absolute', left: nowX - 1, top: 12, width: 2, height: 28,
              background: ink, boxShadow: '0 0 0 1px #0a0906',
            }}/>
            <div className="vt" style={{
              position: 'absolute', left: nowX - 32, top: 0, width: 64,
              color: ink, fontSize: 11, textAlign: 'center',
              background: '#0a0906', border: `1px solid ${rule}`, padding: '1px 0',
            }}>you are here</div>
          </>
        )}
      </div>

      <div className="vt" style={{ fontSize: 14, color: muted, marginTop: 8, textAlign: 'center', fontStyle: 'italic' }}>
        41 versions &middot; 331 canonical days &middot; 1:1 scale
      </div>
    </a>
  );
}
// ----------------------------------------------------------------------

function Landing() {
  const containerRef = React.useRef(null);
  const [copied, setCopied] = React.useState(false);
  const [tweaks, setTweaks] = React.useState(SITE_CONFIG);
  useCursorTrail(containerRef, { color: tweaks.accentColor });

  // Pull the live anchor (current server version + wall-clock install date)
  // from refresh-status.sh's output. If the fetch fails (offline / local dev),
  // fall back to the baked-in SITE_CONFIG values.
  React.useEffect(() => {
    fetch('/status.json')
      .then(r => r.ok ? r.json() : null)
      .then(s => {
        if (!s || !s.anchorVersion || !s.anchorWallClock) return;
        setTweaks(t => ({ ...t,
          anchorVersion: s.anchorVersion,
          anchorWallClock: s.anchorWallClock,
        }));
      })
      .catch(() => {});
  }, []);

  const col = '#221d14', ink = '#EADFC4', muted = '#9A8F74';
  const rule = '#463c28', link = '#9ac6ff', linkV = '#c6aaff';
  const accent = tweaks.accentColor;

  // Compute the currently-live version from the manifest + anchor tweaks.
  // Same logic as MiniTimeline / timeline page so the whole site stays in sync.
  const { live, next } = React.useMemo(() => {
    const enriched = MANIFEST.map(m => ({
      ...m,
      wallDate: miniRealDateFor(m.d, tweaks.anchorWallClock, tweaks.anchorVersion),
    }));
    const now = new Date();
    const nowUTC = new Date(Date.UTC(now.getUTCFullYear(), now.getUTCMonth(), now.getUTCDate()));
    let idx = -1;
    for (let i = 0; i < enriched.length; i++) {
      if (enriched[i].wallDate.getTime() <= nowUTC.getTime()) idx = i;
    }
    return {
      live: idx >= 0 ? enriched[idx] : null,
      next: idx + 1 < enriched.length ? enriched[idx + 1] : null,
    };
  }, [tweaks.anchorWallClock, tweaks.anchorVersion]);

  const copy = () => {
    if (navigator.clipboard) navigator.clipboard.writeText(tweaks.serverAddress).catch(() => {});
    setCopied(true);
    setTimeout(() => setCopied(false), 1600);
  };

  return (
    <div ref={containerRef} style={{
      width: '100%', height: '100%',
      backgroundImage: 'url(assets/bg_main.png)',
      backgroundRepeat: 'repeat',
      backgroundColor: '#0a0906',
      imageRendering: 'pixelated',
      color: ink,
      fontFamily: '"Cambria", "Hoefler Text", Georgia, "Times New Roman", serif',
      fontSize: 16, lineHeight: 1.6,
      display: 'flex', flexDirection: 'column',
      position: 'relative',
    }}>
      <style>{`
        .merged a { color: ${link}; text-decoration: underline; }
        .merged a:visited { color: ${linkV}; }
        .merged a:hover { background: #3a3428; }
        .merged h2 { font-family: "VT323", "Courier New", monospace; font-weight: normal; font-size: 28px; margin: 0 0 8px; color: ${ink}; letter-spacing: 0.5px; border-bottom: 1px solid ${rule}; padding-bottom: 4px; }
        .merged h3 { font-family: "VT323", "Courier New", monospace; font-weight: normal; font-size: 22px; margin: 18px 0 4px; color: ${muted}; }
        .merged h2:not(:first-child) { margin-top: 30px; }
        .merged hr { border: 0; border-top: 1px dashed ${rule}; margin: 22px 0; }
        .merged .vt { font-family: "VT323", "Courier New", monospace; font-size: 18px; line-height: 1.25; }
        .merged .pstart { font-family: "Press Start 2P", monospace; }
        .merged code { font-family: "VT323", "Courier New", monospace; font-size: 18px; background: #0f0c08; padding: 0 4px; }
        .merged .nav a { text-decoration: none; display: block; padding: 2px 10px; border-left: 3px solid transparent; }
        .merged .nav a:hover { background: #2a2318; border-left-color: ${accent}; text-decoration: none; }
        .merged .middle { display: grid; grid-template-columns: 170px 1fr; gap: 20px; }
        .mid-scroll::-webkit-scrollbar { width: 12px; }
        .mid-scroll::-webkit-scrollbar-track { background: #0f0c08; }
        .mid-scroll::-webkit-scrollbar-thumb { background: ${rule}; border: 2px solid #0f0c08; }
        .mini-tl { transition: border-color 120ms, background 120ms; }
        .mini-tl:hover { border-color: ${accent} !important; background: #1a150d !important; text-decoration: none !important; }
        .mini-tl:hover .open-hint { color: ${ink} !important; }
      `}</style>

      {/* FIXED HEADER — compact, single row */}
      <header style={{ flexShrink: 0 }}>
        <div style={{
          background: 'linear-gradient(180deg, #2a2015 0%, #1e1710 100%)',
          borderBottom: `1px solid ${rule}`,
          padding: '10px 0',
          boxShadow: 'inset 0 -1px 0 #000',
        }}>
          <div style={{ maxWidth: 1100, margin: '0 auto', display: 'flex', alignItems: 'center', justifyContent: 'space-between', padding: '0 24px', gap: 24 }}>
            <div style={{ display: 'flex', alignItems: 'baseline', gap: 14 }}>
              <span className="pstart" style={{ fontSize: 22, color: accent, textShadow: '2px 2px 0 #0a0906', letterSpacing: 1 }}>
                {tweaks.wordmarkLine1}
              </span>
              <span className="pstart" style={{ fontSize: 22, color: '#EADFC4', textShadow: '2px 2px 0 #0a0906', letterSpacing: 1 }}>
                {tweaks.wordmarkLine2}
              </span>
              <span className="vt" style={{ color: muted, fontSize: 14, marginLeft: 6, fontStyle: 'italic' }}>
                &mdash; {tweaks.tagline}
              </span>
            </div>
            <div className="vt" style={{ color: muted, fontSize: 16 }}>
              <span style={{ color: accent }}>&#9679;</span> online &middot; <b style={{ color: ink }}>{tweaks.serverAddress}</b>
            </div>
          </div>
        </div>
        {/* thin plank trim */}
        <div style={{
          backgroundImage: 'url(assets/bg_top.png)',
          backgroundRepeat: 'repeat-x',
          backgroundSize: 'auto 24px',
          height: 24,
          imageRendering: 'pixelated',
          borderTop: '1px solid #000',
          borderBottom: '2px solid #000',
        }}/>
      </header>

      {/* SCROLLING MIDDLE */}
      <div className="merged" style={{
        flex: 1, overflow: 'hidden',
        display: 'flex', justifyContent: 'center',
        padding: '20px 20px',
      }}>
        <div style={{
          flex: 1, maxWidth: 1100,
          background: col,
          border: `2px solid ${SN_PALETTE.dirtDark}`,
          boxShadow: '0 0 0 2px #0a0906, 0 8px 18px rgba(0,0,0,0.45)',
          display: 'flex', flexDirection: 'column',
          minHeight: 0,
        }}>
          <div className="middle" style={{ flex: 1, minHeight: 0, padding: 24 }}>

            {/* SIDEBAR */}
            <aside style={{ borderRight: `1px solid ${rule}`, paddingRight: 14, display: 'flex', flexDirection: 'column', gap: 18, overflow: 'auto' }}>
              <nav className="nav vt" style={{ fontSize: 18 }}>
                <a href="#home" style={{ color: accent }}>home</a>
                <a href="#about">about</a>
                <a href="#connect">how to join</a>
                <a href="#worldline">worldline</a>
                <a href="timeline.html">&rarr; full timeline</a>
              </nav>

              <div>
                <div className="pstart" style={{ fontSize: 10, color: accent, marginBottom: 8 }}>SERVER</div>
                <div className="vt" style={{ fontSize: 16, color: ink }}>
                  <div><span style={{ color: accent }}>&#9679;</span> online</div>
                  {live ? (
                    <>
                      <div style={{ color: muted, marginTop: 2 }}>running <b style={{ color: ink }}>{live.v}</b></div>
                      <div style={{ color: muted, marginTop: 2 }}>client <code style={{ fontSize: 14, background: '#0f0c08', padding: '0 4px' }}>{live.c}</code></div>
                    </>
                  ) : (
                    <div style={{ color: muted, marginTop: 2 }}>not yet anchored</div>
                  )}
                </div>
              </div>

              <div>
                <div className="pstart" style={{ fontSize: 10, color: accent, marginBottom: 8 }}>LINKS</div>
                <div className="vt" style={{ fontSize: 16 }}>
                  <div><a href="#">discord</a></div>
                </div>
              </div>

              <div style={{ marginTop: 'auto', color: muted, fontSize: 12, fontStyle: 'italic' }}>
                hand-rolled html. no trackers.
              </div>
            </aside>

            {/* MAIN SCROLL */}
            <main className="mid-scroll" style={{ overflow: 'auto', paddingRight: 20, minWidth: 0 }}>

              <a id="home"/>
              <a id="about"/>
              <h2>about the server</h2>
              <p><em>Hi.</em> This is a private server for a dozen or so friends that boots every Alpha and Beta server jar from <code>0.1.2_01</code> (Aug 12, 2010) to <code>b1.7.3</code> (Jul 8, 2011), <em>on a 1:1 real-world calendar</em>. The server upgrades itself at exactly the same cadence Mojang shipped the originals, so we&rsquo;re walking through eleven months of early Minecraft history in real time.</p>
              <p>No mods, no plugins &mdash; just the original jars, unmodified, running the protocol they shipped with. Clients have to match the current server version exactly (see the sidebar for what&rsquo;s live right now). Expect hurt animations to arrive late, the Nether to open a few weeks in, PvP to not exist until <code>a1.2.3</code>, pistons not to land until summer, and the occasional 12-minute-long hotfix jar. When the worldline reaches <code>b1.7.3</code>, that&rsquo;s it &mdash; the Adventure Update is a different game.</p>

              <a id="connect"/>
              <h2>how to join</h2>
              <p style={{ color: muted, fontStyle: 'italic', marginTop: 0 }}>Four steps. The server is Tailscale-only and runs historical Beta jars, so the vanilla launcher won&rsquo;t work.</p>

              <ol className="join-steps" style={{ listStyle: 'none', padding: 0, margin: '14px 0 18px', counterReset: 'step' }}>
                <li style={{ display: 'grid', gridTemplateColumns: '34px 1fr', gap: 14, marginBottom: 14 }}>
                  <div className="pstart" style={{ fontSize: 14, color: accent, paddingTop: 2 }}>01</div>
                  <div>
                    <h3 style={{ margin: '0 0 2px' }}>join the tailnet</h3>
                    <div>Install <a href="https://tailscale.com/download" target="_blank" rel="noreferrer">Tailscale</a>, accept the invite I sent you, and sign in. You should see <code>mjr-server</code> in your machine list.</div>
                  </div>
                </li>
                <li style={{ display: 'grid', gridTemplateColumns: '34px 1fr', gap: 14, marginBottom: 14 }}>
                  <div className="pstart" style={{ fontSize: 14, color: accent, paddingTop: 2 }}>02</div>
                  <div>
                    <h3 style={{ margin: '0 0 2px' }}>install betacraft</h3>
                    <div>The official launcher can&rsquo;t boot Alpha/Beta jars. Grab <a href="https://betacraft.uk/" target="_blank" rel="noreferrer">Betacraft</a> for your OS and run it.</div>
                  </div>
                </li>
                <li style={{ display: 'grid', gridTemplateColumns: '34px 1fr', gap: 14, marginBottom: 14 }}>
                  <div className="pstart" style={{ fontSize: 14, color: accent, paddingTop: 2 }}>03</div>
                  <div>
                    <h3 style={{ margin: '0 0 2px' }}>sign in &amp; pick the live version</h3>
                    <div>In Betacraft, click the profile icon and sign in with the Microsoft account tied to your Minecraft profile. Select the client version listed in the sidebar &mdash; it must match the server exactly.</div>
                  </div>
                </li>
                <li style={{ display: 'grid', gridTemplateColumns: '34px 1fr', gap: 14, marginBottom: 4 }}>
                  <div className="pstart" style={{ fontSize: 14, color: accent, paddingTop: 2 }}>04</div>
                  <div>
                    <h3 style={{ margin: '0 0 6px' }}>connect</h3>
                    <div style={{ marginBottom: 8 }}>Multiplayer &rarr; Add Server, paste the address below, save, and join. You should spawn in.</div>
                    <div style={{
                      fontFamily: '"VT323", monospace', fontSize: 26,
                      background: '#0a0906', color: '#b0e665',
                      padding: '10px 12px', border: '2px solid #3a3020',
                      display: 'flex', alignItems: 'center', justifyContent: 'space-between', gap: 10,
                    }}>
                      <span>{tweaks.serverAddress}</span>
                      <button onClick={copy} style={{
                        fontFamily: '"VT323", monospace', fontSize: 15,
                        background: copied ? SN_PALETTE.grassDark : '#3a3020',
                        color: '#fff', border: '2px solid #000', padding: '3px 10px', cursor: 'pointer',
                        textTransform: 'uppercase', letterSpacing: 1,
                      }}>{copied ? 'copied!' : 'copy'}</button>
                    </div>

                    {/* inline live-version row */}
                    <div className="vt" style={{
                      display: 'flex', flexWrap: 'wrap', gap: '4px 18px',
                      fontSize: 17, color: muted, marginTop: 8,
                    }}>
                      <span><span style={{ color: muted }}>server</span> {live ? <code>{live.v}</code> : <span style={{ fontStyle: 'italic' }}>pre-launch</span>}</span>
                      <span style={{ color: rule }}>&middot;</span>
                      <span><span style={{ color: muted }}>client</span> {live ? <code>{live.c}</code> : <span style={{ fontStyle: 'italic' }}>&mdash;</span>}</span>
                      {next && (
                        <>
                          <span style={{ color: rule }}>&middot;</span>
                          <span><span style={{ color: muted }}>next</span> <code>{next.v}</code> <span>&mdash; {(() => {
                            const now = new Date();
                            const nowUTC = new Date(Date.UTC(now.getUTCFullYear(), now.getUTCMonth(), now.getUTCDate()));
                            const du = Math.round((next.wallDate - nowUTC) / 86400000);
                            if (du <= 0) return 'due now';
                            if (du === 1) return 'tomorrow';
                            return `in ${du} days`;
                          })()}</span></span>
                        </>
                      )}
                    </div>
                  </div>
                </li>
              </ol>

              <div className="vt" style={{ fontSize: 16, color: muted, background: '#15110b', border: `1px dashed ${rule}`, padding: '10px 12px', margin: '0 0 10px' }}>
                <b style={{ color: ink }}>won&rsquo;t connect?</b> check the Tailscale tray icon is green and that <code>tailscale ping mjr-server</code> works. if Tailscale&rsquo;s fine, you&rsquo;ve almost certainly got the wrong Beta version selected in Betacraft.
              </div>

              <a id="worldline"/>
              <h2>the worldline</h2>
              <p>
                The server walks a <em>1:1 real-world calendar</em> through every Alpha and Beta
                release from <code>0.1.2_01</code> (Aug 12, 2010) to <code>b1.7.3</code> (Jul 8, 2011).
              </p>
              <div style={{ marginTop: 10 }}>
                <MiniTimeline
                  anchorWallClock={tweaks.anchorWallClock}
                  anchorVersion={tweaks.anchorVersion}
                  accent={accent}
                />
              </div>
            </main>
          </div>
        </div>
      </div>

      {/* FIXED FOOTER — plank trim over solid panel */}
      <footer style={{ flexShrink: 0 }}>
        <div style={{
          backgroundImage: 'url(assets/bg_top.png)',
          backgroundRepeat: 'repeat-x',
          backgroundSize: 'auto 24px',
          height: 24,
          imageRendering: 'pixelated',
          borderTop: '2px solid #000',
          borderBottom: '1px solid #000',
        }}/>
        <div style={{
          background: 'linear-gradient(180deg, #1e1710 0%, #14100a 100%)',
          padding: '12px 24px',
        }}>
          <div style={{ maxWidth: 1100, margin: '0 auto', display: 'flex', alignItems: 'center', justifyContent: 'space-between', gap: 16 }}>
            <div style={{ display: 'flex', alignItems: 'center', gap: 10 }}>
              <PixelGrassBlock size={28}/>
              <div className="vt" style={{ fontSize: 18, color: '#EADFC4' }}>
                server ip: <b>{tweaks.serverAddress}</b>
              </div>
            </div>
            <div className="vt" style={{ fontSize: 15, color: muted }}>
              supernormal minecraft 2026 &middot; a private server
            </div>
          </div>
        </div>
      </footer>

    </div>
  );
}

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(<Landing/>);
