/* App shell + router (Bastion-styled) */
const { useState, useEffect, useRef, useMemo, useCallback } = React;
const ROUTES = [
{ id: "home", label: "首頁", en: "INDEX" },
{ id: "courses", label: "課程", en: "PROGRAMS" },
{ id: "schedule", label: "課表", en: "SCHEDULE" },
{ id: "pricing", label: "費用", en: "MEMBERSHIP"},
{ id: "about", label: "關於", en: "MANIFESTO" },
{ id: "contact", label: "聯絡", en: "CONTACT" },
];
function useHashRoute() {
const [route, setRoute] = useState(() => (window.location.hash.slice(1) || "home"));
useEffect(() => {
const onHash = () => {
setRoute(window.location.hash.slice(1) || "home");
window.scrollTo({ top: 0, behavior: "instant" });
};
window.addEventListener("hashchange", onHash);
return () => window.removeEventListener("hashchange", onHash);
}, []);
const navigate = useCallback((id) => { window.location.hash = id; }, []);
return [route, navigate];
}
// ============ SHIELD MONOGRAM ============
function Shield({ size = 40 }) {
// Hand-drawn shield monogram for "AF" — Attack First
return (
);
}
// ============ TWEAKS ============
const TWEAK_DEFAULTS = /*EDITMODE-BEGIN*/{
"gold": "#a8804f",
"displayFont": "vanguard"
}/*EDITMODE-END*/;
function applyTweaks(t) {
const root = document.documentElement;
root.style.setProperty("--gold", t.gold);
// soft variants derived from primary
const hex = t.gold.replace("#", "");
const r = parseInt(hex.slice(0, 2), 16), g = parseInt(hex.slice(2, 4), 16), b = parseInt(hex.slice(4, 6), 16);
root.style.setProperty("--gold-soft", `rgba(${r},${g},${b},0.5)`);
root.style.setProperty("--gold-mute", `rgba(${r},${g},${b},0.3)`);
root.style.setProperty("--gold-faint", `rgba(${r},${g},${b},0.12)`);
root.style.setProperty("--hairline", t.gold);
root.style.setProperty("--hairline-soft", `rgba(${r},${g},${b},0.25)`);
if (t.displayFont === "vanguard") {
root.style.setProperty("--display", '"Vanguard", "Bebas Neue", "Oswald", "Archivo Narrow", "Noto Sans TC", sans-serif');
} else if (t.displayFont === "bebas") {
root.style.setProperty("--display", '"Bebas Neue", "Noto Sans TC", sans-serif');
} else if (t.displayFont === "oswald") {
root.style.setProperty("--display", '"Oswald", "Noto Sans TC", sans-serif');
} else if (t.displayFont === "anton") {
root.style.setProperty("--display", '"Anton", "Noto Sans TC", sans-serif');
}
}
function TweaksApp() {
const [tweaks, setTweak] = useTweaks(TWEAK_DEFAULTS);
useEffect(() => { applyTweaks(tweaks); }, [tweaks]);
return (