/* global React, ReactDOM, Icon, Wordmark */
// ============================================================
// Coming soon — standalone marketing page template.
// Reuses the shared design tokens (styles.css) + Wordmark/Icon so it
// stays on-brand. Swap copy / launch date freely; this is a template.
// ============================================================
const { useState: useStateCS } = React;
// Launch target — change this date to drive the countdown.
const LAUNCH_TS = new Date('2026-08-15T17:00:00Z').getTime();
function useCountdown(target) {
const [now, setNow] = useStateCS(Date.now());
React.useEffect(() => {
const id = setInterval(() => setNow(Date.now()), 1000);
return () => clearInterval(id);
}, []);
const diff = Math.max(0, target - now);
const d = Math.floor(diff / 86400000);
const h = Math.floor((diff % 86400000) / 3600000);
const m = Math.floor((diff % 3600000) / 60000);
const s = Math.floor((diff % 60000) / 1000);
return { d, h, m, s, done: diff === 0 };
}
function CountUnit({ value, label }) {
return (
{String(value).padStart(2, '0')}
{label}
);
}
function ComingSoon() {
const t = useCountdown(LAUNCH_TS);
const [email, setEmail] = useStateCS('');
const [sent, setSent] = useStateCS(false);
const valid = /.+@.+\..+/.test(email);
function submit(e) {
e.preventDefault();
if (!valid) return;
setSent(true);
}
return (
Beta coming soon
A calmer home for your characters, grinds & static.
Crystaltide ties together what's scattered across spreadsheets and single-purpose
sites; synced from public data, tracked the way your group actually plays.
We're putting on the finishing touches.