/* ============================================================
   DESIGN: Dark Baroque meets Celestial Codex
   - Asymmetric two-column layout (portrait left, content right)
   - Deep midnight navy, silver, pale blue, warm gold palette
   - Cinzel Decorative for display, EB Garamond for body, Courier Prime for data
   - Manuscript-inspired with rune dividers and corner ornaments
   ============================================================ */

import { useEffect, useRef, useState, useCallback } from "react";
import StarCanvas from "@/components/StarCanvas";
import StatRadarChart from "@/components/StatRadarChart";
import { trpc } from "@/lib/trpc";
import { useAuth } from "@/_core/hooks/useAuth";
import { getLoginUrl } from "@/const";

const PORTRAIT_URL = "https://d2xsxph8kpxj0f.cloudfront.net/310519663392130193/2fZBTokfc7TnqrVZUwLhM2/lyra_portrait_e0cebace.png";
const BANNER_URL = "https://d2xsxph8kpxj0f.cloudfront.net/310519663392130193/2fZBTokfc7TnqrVZUwLhM2/lyra_banner_6f01d4ce.png";

// ── Stat bar ────────────────────────────────────────────────
function StatBar({ label, value, max = 100, color = "blue" }: { label: string; value: number; max?: number; color?: "blue" | "gold" }) {
  const [width, setWidth] = useState(0);
  const ref = useRef<HTMLDivElement>(null);

  useEffect(() => {
    const observer = new IntersectionObserver(
      ([entry]) => { if (entry.isIntersecting) setWidth((value / max) * 100); },
      { threshold: 0.3 }
    );
    if (ref.current) observer.observe(ref.current);
    return () => observer.disconnect();
  }, [value, max]);

  return (
    <div ref={ref} style={{ marginBottom: "0.75rem" }}>
      <div style={{ display: "flex", justifyContent: "space-between", marginBottom: "0.3rem" }}>
        <span style={{ fontFamily: "'Courier Prime', monospace", fontSize: "0.78rem", letterSpacing: "0.08em", color: "oklch(0.72 0.12 75)" }}>
          {label}
        </span>
        <span style={{ fontFamily: "'Courier Prime', monospace", fontSize: "0.78rem", color: "oklch(0.60 0.01 240)" }}>
          {value}
        </span>
      </div>
      <div className="stat-bar-track">
        <div
          className={`stat-bar-fill ${color === "gold" ? "gold" : ""}`}
          style={{ width: `${width}%` }}
        />
      </div>
    </div>
  );
}

// ── Rune divider ─────────────────────────────────────────────
function RuneDivider({ label }: { label?: string }) {
  return (
    <div className="rune-divider">
      {label && (
        <span style={{
          fontFamily: "'Cinzel', serif",
          fontSize: "0.65rem",
          letterSpacing: "0.2em",
          color: "oklch(0.72 0.12 75 / 70%)",
          textTransform: "uppercase",
          whiteSpace: "nowrap",
        }}>
          {label}
        </span>
      )}
    </div>
  );
}

// ── Corner ornaments ─────────────────────────────────────────
function CornerOrnaments() {
  return (
    <>
      <div className="corner-ornament tl" />
      <div className="corner-ornament tr" />
      <div className="corner-ornament bl" />
      <div className="corner-ornament br" />
    </>
  );
}

// ── Section wrapper with reveal animation ────────────────────
function RevealSection({ children, delay = 0, style }: { children: React.ReactNode; delay?: number; style?: React.CSSProperties }) {
  const ref = useRef<HTMLDivElement>(null);
  const [visible, setVisible] = useState(false);

  useEffect(() => {
    const observer = new IntersectionObserver(
      ([entry]) => { if (entry.isIntersecting) setVisible(true); },
      { threshold: 0.1 }
    );
    if (ref.current) observer.observe(ref.current);
    return () => observer.disconnect();
  }, []);

  return (
    <div
      ref={ref}
      className={`reveal ${visible ? "visible" : ""}`}
      style={{ transitionDelay: `${delay}ms`, ...style }}
    >
      {children}
    </div>
  );
}

// ── Ability card ─────────────────────────────────────────────
function AbilityCard({ icon, name, description, type }: { icon: string; name: string; description: string; type: string }) {
  return (
    <div className="lore-card ability-card" style={{ padding: "1rem 1.25rem", position: "relative", marginBottom: "0.75rem" }}>
      <CornerOrnaments />
      <div style={{ display: "flex", alignItems: "flex-start", gap: "0.75rem" }}>
        <div style={{
          fontSize: "1.5rem",
          lineHeight: 1,
          flexShrink: 0,
          width: "2.5rem",
          height: "2.5rem",
          display: "flex",
          alignItems: "center",
          justifyContent: "center",
          background: "oklch(0.18 0.04 260)",
          border: "1px solid oklch(0.72 0.12 240 / 30%)",
        }}>
          {icon}
        </div>
        <div style={{ flex: 1 }}>
          <div style={{ display: "flex", alignItems: "baseline", gap: "0.5rem", marginBottom: "0.25rem" }}>
            <span style={{ fontFamily: "'Cinzel', serif", fontSize: "0.9rem", fontWeight: 600, color: "oklch(0.82 0.01 240)" }}>
              {name}
            </span>
            <span className="trait-badge" style={{ fontSize: "0.65rem" }}>{type}</span>
          </div>
          <p style={{ fontSize: "0.875rem", color: "oklch(0.65 0.01 240)", lineHeight: 1.6, margin: 0 }}>
            {description}
          </p>
        </div>
      </div>
    </div>
  );
}

// ── Equipment item ────────────────────────────────────────────
function EquipmentItem({ icon, name, description }: { icon: string; name: string; description: string }) {
  return (
    <div className="equipment-item">
      <div style={{ fontSize: "1.25rem", flexShrink: 0, marginTop: "0.1rem" }}>{icon}</div>
      <div>
        <div style={{ fontFamily: "'Cinzel', serif", fontSize: "0.85rem", fontWeight: 600, color: "oklch(0.72 0.12 75)", marginBottom: "0.2rem" }}>
          {name}
        </div>
        <p style={{ fontSize: "0.85rem", color: "oklch(0.60 0.01 240)", margin: 0, lineHeight: 1.5 }}>
          {description}
        </p>
      </div>
    </div>
  );
}

// ── Personality trait ─────────────────────────────────────────
function TraitBadge({ label }: { label: string }) {
  return (
    <span className="trait-badge" style={{ marginRight: "0.5rem", marginBottom: "0.5rem" }}>
      ✦ {label}
    </span>
  );
}

// ── Main page ─────────────────────────────────────────────────
export default function Home() {
  const { user, isAuthenticated } = useAuth();
  const [activeTab, setActiveTab] = useState<"lore" | "stats" | "abilities" | "equipment" | "relationships" | "generate">("lore");

  // ── Saved Characters (database) state ───────────────────────────
  const [saveSessionTag, setSaveSessionTag] = useState("");
  const [savedFilter, setSavedFilter] = useState<"all" | "forge" | "randomiser" | "pinned">("all");
  const [deleteConfirmId, setDeleteConfirmId] = useState<number | null>(null);
  const [saveSuccessId, setSaveSuccessId] = useState<number | null>(null);
  const [randSaveSuccess, setRandSaveSuccess] = useState(false);

  const utils = trpc.useUtils();

  const { data: savedChars, isLoading: savedLoading } = trpc.character.listSavedCharacters.useQuery(
    undefined,
    { enabled: isAuthenticated }
  );

  const saveCharMutation = trpc.character.saveCharacter.useMutation({
    onSuccess: (data) => {
      setSaveSuccessId(data.id);
      setTimeout(() => setSaveSuccessId(null), 3000);
      utils.character.listSavedCharacters.invalidate();
    },
  });

  const saveRandMutation = trpc.character.saveCharacter.useMutation({
    onSuccess: () => {
      setRandSaveSuccess(true);
      setTimeout(() => setRandSaveSuccess(false), 3000);
      utils.character.listSavedCharacters.invalidate();
    },
  });

  const deleteCharMutation = trpc.character.deleteCharacter.useMutation({
    onSuccess: () => {
      setDeleteConfirmId(null);
      utils.character.listSavedCharacters.invalidate();
    },
  });

  const togglePinMutation = trpc.character.togglePin.useMutation({
    onSuccess: () => utils.character.listSavedCharacters.invalidate(),
  });

  // ── Rune / Grace fluctuating ticker ────────────────────────
  const [runeCount, setRuneCount] = useState(() => Math.floor(Math.random() * 80000) + 20000);
  const [graceCount, setGraceCount] = useState(() => Math.floor(Math.random() * 12) + 3);
  const [runeFlash, setRuneFlash] = useState<"up" | "down" | null>(null);

  useEffect(() => {
    // Runes fluctuate every 3-7 seconds with a random gain/loss
    const fluctuate = () => {
      const delta = Math.floor(Math.random() * 4800) - 1800; // -1800 to +3000
      setRuneCount(prev => Math.max(0, prev + delta));
      setRuneFlash(delta >= 0 ? "up" : "down");
      setTimeout(() => setRuneFlash(null), 800);
    };
    const id = setInterval(fluctuate, Math.random() * 4000 + 3000);
    return () => clearInterval(id);
  }, []);

  useEffect(() => {
    // Grace count occasionally increments (discovery) or rarely decrements
    const graceFluctuate = () => {
      const delta = Math.random() < 0.75 ? 1 : -1;
      setGraceCount(prev => Math.max(1, Math.min(30, prev + delta)));
    };
    const id = setInterval(graceFluctuate, Math.random() * 12000 + 8000);
    return () => clearInterval(id);
  }, []);

  // ── Generate Character state ───────────────────────────────
  const [genGender, setGenGender] = useState<"female" | "male" | "any">("any");
  const [genAge, setGenAge] = useState("18-40");
  const [genFaction, setGenFaction] = useState("");
  const [genArchetype, setGenArchetype] = useState("");
  const [genTone, setGenTone] = useState<"heroic" | "tragic" | "mysterious" | "neutral">("neutral");
  const [genContext, setGenContext] = useState("");
  const [generatedChar, setGeneratedChar] = useState<null | Record<string, unknown>>(null);
  const [genHistory, setGenHistory] = useState<Array<Record<string, unknown>>>([]);
  const [historyIndex, setHistoryIndex] = useState(-1);
  // New generation controls
  const [genBackstoryDepth, setGenBackstoryDepth] = useState<"brief" | "standard" | "detailed" | "epic">("standard");
  const [genRelationshipSeed, setGenRelationshipSeed] = useState("");
  const [genNarrativeSeed, setGenNarrativeSeed] = useState("");
  const [genVariantCount, setGenVariantCount] = useState(1);
  const [genVariants, setGenVariants] = useState<Array<Record<string, unknown>>>([]);
  const [activeVariantIndex, setActiveVariantIndex] = useState(0);
  // Portrait style
  const [portraitStyle, setPortraitStyle] = useState<"oil_painting" | "ink_sketch" | "stained_glass" | "manuscript">("oil_painting");
  // Pinned/favourite characters
  const [pinnedChars, setPinnedChars] = useState<Set<string>>(() => {
    try { return new Set(JSON.parse(localStorage.getItem("lyra_pinned_chars") ?? "[]") as string[]); }
    catch { return new Set(); }
  });
  // Regenerate field mutation
  const regenFieldMutation = trpc.character.regenerateField.useMutation({
    onSuccess: (data) => {
      if (!generatedChar) return;
      const updated = { ...generatedChar, [data.field]: data.value };
      setGeneratedChar(updated);
      setActiveCharacter(updated);
      setGenHistory(prev => prev.map((c, i) => i === historyIndex ? updated : c));
    },
  });

  // ── Active display character (null = show Lyra, set = show generated) ──
  const [activeCharacter, setActiveCharacter] = useState<null | Record<string, unknown>>(null);

  // ── Cooldown state (5 min, persisted in localStorage) ──────
  const COOLDOWN_MS = 5 * 60 * 1000; // 5 minutes
  const COOLDOWN_KEY = "lyra_forge_cooldown_until";

  const getCooldownRemaining = () => {
    const until = parseInt(localStorage.getItem(COOLDOWN_KEY) ?? "0", 10);
    return Math.max(0, until - Date.now());
  };

  const [cooldownRemaining, setCooldownRemaining] = useState<number>(() => getCooldownRemaining());

  // Tick the cooldown down every second
  useEffect(() => {
    if (cooldownRemaining <= 0) return;
    const id = setInterval(() => {
      const remaining = getCooldownRemaining();
      setCooldownRemaining(remaining);
      if (remaining <= 0) clearInterval(id);
    }, 1000);
    return () => clearInterval(id);
  }, [cooldownRemaining]);

  const formatCooldown = (ms: number) => {
    const totalSec = Math.ceil(ms / 1000);
    const m = Math.floor(totalSec / 60);
    const s = totalSec % 60;
    return `${m}:${String(s).padStart(2, "0")}`;
  };

  // ── Portrait generation state ──────────────────────────────
  const [generatedPortraitUrl, setGeneratedPortraitUrl] = useState<string | null>(null);
  const [portraitGenerating, setPortraitGenerating] = useState(false);
  const [portraitError, setPortraitError] = useState<string | null>(null);
  // Track which character the portrait belongs to (by name) to avoid re-generating
  const [portraitForChar, setPortraitForChar] = useState<string | null>(null);
  // Ref to track if portrait generation has been triggered for the current cooldown cycle
  const portraitTriggeredRef = useRef(false);

  const portraitMutation = trpc.character.generatePortrait.useMutation({
    onSuccess: (data) => {
      setGeneratedPortraitUrl(data.portraitUrl);
      setPortraitGenerating(false);
      setPortraitError(null);
    },
    onError: (err) => {
      setPortraitGenerating(false);
      setPortraitError(err.message);
    },
  });

  // ── Randomiser token-bucket state ────────────────────────
  const RAND_TOKEN_KEY = "lyra_rand_tokens";
  const RAND_REFILL_KEY = "lyra_rand_last_refill";
  const MAX_RAND_TOKENS = 3;
  const RAND_REFILL_MS = 60 * 60 * 1000; // 1 hour per token

  const getTokenState = () => {
    const stored = parseInt(localStorage.getItem(RAND_TOKEN_KEY) ?? String(MAX_RAND_TOKENS), 10);
    const lastRefill = parseInt(localStorage.getItem(RAND_REFILL_KEY) ?? String(Date.now()), 10);
    const elapsed = Date.now() - lastRefill;
    const tokensToAdd = Math.floor(elapsed / RAND_REFILL_MS);
    const tokens = Math.min(MAX_RAND_TOKENS, stored + tokensToAdd);
    const newLastRefill = lastRefill + tokensToAdd * RAND_REFILL_MS;
    if (tokensToAdd > 0) {
      localStorage.setItem(RAND_TOKEN_KEY, String(tokens));
      localStorage.setItem(RAND_REFILL_KEY, String(newLastRefill));
    }
    const msUntilNext = RAND_REFILL_MS - (Date.now() - newLastRefill);
    return { tokens, msUntilNext: tokens < MAX_RAND_TOKENS ? Math.max(0, msUntilNext) : 0 };
  };

  const [randTokens, setRandTokens] = useState<number>(() => getTokenState().tokens);
  const [randNextRefill, setRandNextRefill] = useState<number>(() => getTokenState().msUntilNext);
  const [randResult, setRandResult] = useState<null | {
    name: string; race: string; gender: string; age: string;
    archetype: string; faction: string; hook: string;
    traits: string[]; suggestedRole: string; flavorQuote: string;
  }>(null);
  const [randContext, setRandContext] = useState("");

  // Tick refill timer
  useEffect(() => {
    const id = setInterval(() => {
      const { tokens, msUntilNext } = getTokenState();
      setRandTokens(tokens);
      setRandNextRefill(msUntilNext);
    }, 5000);
    return () => clearInterval(id);
  }, []);

  const formatRefill = (ms: number) => {
    const totalSec = Math.ceil(ms / 1000);
    const m = Math.floor(totalSec / 60);
    const s = totalSec % 60;
    return `${m}:${String(s).padStart(2, "0")}`;
  };

  const randomiseMutation = trpc.character.randomise.useMutation({
    onSuccess: (data) => {
      setRandResult(data);
      const newTokens = Math.max(0, randTokens - 1);
      localStorage.setItem(RAND_TOKEN_KEY, String(newTokens));
      if (newTokens < MAX_RAND_TOKENS && parseInt(localStorage.getItem(RAND_REFILL_KEY) ?? "0", 10) === 0) {
        localStorage.setItem(RAND_REFILL_KEY, String(Date.now()));
      }
      const { tokens, msUntilNext } = getTokenState();
      setRandTokens(tokens);
      setRandNextRefill(msUntilNext);
    },
  });

  const generateMutation = trpc.character.generate.useMutation({
    onSuccess: (data) => {
      const variants = data.variants ?? [data.character];
      setGenVariants(variants);
      setActiveVariantIndex(0);
      setGeneratedChar(data.character);
      setGenHistory(prev => [data.character, ...prev].slice(0, 10));
      setHistoryIndex(0);
      // Set active display to the generated character
      setActiveCharacter(data.character);
      // Reset portrait state for the new character
      setGeneratedPortraitUrl(null);
      setPortraitError(null);
      setPortraitForChar(null);
      portraitTriggeredRef.current = false;
      // Start cooldown
      const until = Date.now() + COOLDOWN_MS;
      localStorage.setItem(COOLDOWN_KEY, String(until));
      setCooldownRemaining(COOLDOWN_MS);
    },
  });

  // Auto-trigger portrait generation when cooldown expires and we have a generated character
  useEffect(() => {
    if (
      cooldownRemaining <= 0 &&
      generatedChar &&
      !portraitTriggeredRef.current &&
      portraitForChar !== String(generatedChar.name)
    ) {
      portraitTriggeredRef.current = true;
      setPortraitGenerating(true);
      setPortraitForChar(String(generatedChar.name));
      portraitMutation.mutate({
        name: String(generatedChar.name),
        race: String(generatedChar.race),
        gender: String(generatedChar.gender),
        archetype: String(generatedChar.archetype),
        faction: String(generatedChar.faction),
        appearance: String(generatedChar.appearance),
        age: Number(generatedChar.age),
        style: portraitStyle,
      });
    }
  }, [cooldownRemaining, generatedChar, portraitForChar]);

  // ── Relationships state ───────────────────────────────────
  type RelType = "ally" | "rival" | "neutral" | "unknown";
  interface Relationship {
    id: string;
    name: string;
    type: RelType;
    faction: string;
    trustLevel: number; // 0–100
    firstMet: string;
    notes: string;
    isExpanded: boolean;
  }

  const defaultRelationships: Relationship[] = [
    {
      id: "r1",
      name: "Serath the Wanderer",
      type: "ally",
      faction: "Tarnished",
      trustLevel: 72,
      firstMet: "Session 1 — Limgrave crossroads",
      notes: "A grizzled Tarnished warrior who shared his campfire with Lyra on her first night on the surface. He taught her the difference between a real sunrise and the false dawn of Nokstella. She has given him a Starlight Shard.",
      isExpanded: false,
    },
    {
      id: "r2",
      name: "Mireth of the Glintstone",
      type: "ally",
      faction: "Academy of Raya Lucaria",
      trustLevel: 55,
      firstMet: "Session 2 — Liurnia of the Lakes",
      notes: "A young Academy sorcerer fascinated by Nox night sorceries. She and Lyra exchange knowledge cautiously — Mireth wants Lyra's secrets, and Lyra wants access to the Academy's star charts. A transactional friendship that may deepen.",
      isExpanded: false,
    },
    {
      id: "r3",
      name: "The Pale Confessor",
      type: "rival",
      faction: "Golden Order",
      trustLevel: 8,
      firstMet: "Session 2 — Church of Irith",
      notes: "A Golden Order Confessor who recognized Lyra's Nox Mirrorhelm as a symbol of heresy against the Greater Will. He has vowed to 'correct her path.' His methods are cold and methodical. Lyra suspects he is following her.",
      isExpanded: false,
    },
  ];

  const [relationships, setRelationships] = useState<Relationship[]>(defaultRelationships);
  const [showAddForm, setShowAddForm] = useState(false);
  const [editingId, setEditingId] = useState<string | null>(null);
  const emptyForm = { name: "", type: "neutral" as RelType, faction: "", trustLevel: 50, firstMet: "", notes: "" };
  const [formData, setFormData] = useState(emptyForm);

  const openAdd = () => { setFormData(emptyForm); setEditingId(null); setShowAddForm(true); };
  const openEdit = (r: Relationship) => {
    setFormData({ name: r.name, type: r.type, faction: r.faction, trustLevel: r.trustLevel, firstMet: r.firstMet, notes: r.notes });
    setEditingId(r.id);
    setShowAddForm(true);
  };
  const closeForm = () => { setShowAddForm(false); setEditingId(null); };
  const saveForm = useCallback(() => {
    if (!formData.name.trim()) return;
    if (editingId) {
      setRelationships(prev => prev.map(r => r.id === editingId ? { ...r, ...formData } : r));
    } else {
      const newR: Relationship = { ...formData, id: `r${Date.now()}`, isExpanded: false };
      setRelationships(prev => [...prev, newR]);
    }
    closeForm();
  }, [formData, editingId]);
  const deleteRel = (id: string) => setRelationships(prev => prev.filter(r => r.id !== id));
  const toggleExpand = (id: string) => setRelationships(prev => prev.map(r => r.id === id ? { ...r, isExpanded: !r.isExpanded } : r));

  // ── Mini-Relationships state ─────────────────────────────────────────
  const [miniRelOpen, setMiniRelOpen] = useState(false);
  const [miniRelFigures, setMiniRelFigures] = useState<Array<{
    name: string; race: string; gender: string; age: number;
    archetype: string; faction: string; relationshipType: string;
    trustLevel: number; hook: string; firstMet: string;
  }>>([]);
  const [miniRelSentIds, setMiniRelSentIds] = useState<Set<number>>(new Set());

  const miniRelMutation = trpc.character.generateMiniRelationships.useMutation({
    onSuccess: (data) => {
      setMiniRelFigures(data.figures);
    },
  });

  const sendToRelationships = (fig: typeof miniRelFigures[0], idx: number) => {
    const newRel: Relationship = {
      id: `mini_${Date.now()}_${idx}`,
      name: fig.name,
      type: fig.relationshipType === "ally" ? "ally" : fig.relationshipType === "rival" ? "rival" : "neutral",
      faction: fig.faction,
      trustLevel: fig.trustLevel,
      firstMet: fig.firstMet,
      notes: fig.hook,
      isExpanded: false,
    };
    setRelationships(prev => [...prev, newRel]);
    setMiniRelSentIds(prev => new Set(Array.from(prev).concat(idx)));
  };

  return (
    <div style={{ minHeight: "100vh", position: "relative", background: "oklch(0.10 0.025 260)" }}>
      <StarCanvas />

      {/* ── HERO BANNER ─────────────────────────────────────── */}
      <div style={{ position: "relative", height: "clamp(220px, 35vw, 420px)", overflow: "hidden", zIndex: 1 }}>
        <img
          src={BANNER_URL}
          alt="Elden Ring & Nightreign Character Codex"
          style={{ width: "100%", height: "100%", objectFit: "cover", objectPosition: "center 40%" }}
        />
        {/* Gradient overlay */}
        <div style={{
          position: "absolute", inset: 0,
          background: "linear-gradient(to bottom, oklch(0.10 0.025 260 / 20%) 0%, oklch(0.10 0.025 260 / 60%) 60%, oklch(0.10 0.025 260) 100%)"
        }} />
        {/* Title overlay */}
        <div style={{
          position: "absolute", bottom: "2rem", left: "50%", transform: "translateX(-50%)",
          textAlign: "center", width: "100%", padding: "0 1rem",
        }}>
          <div style={{
            fontFamily: "'Courier Prime', monospace",
            fontSize: "clamp(0.6rem, 1.5vw, 0.75rem)",
            letterSpacing: "0.4em",
            color: "oklch(0.72 0.12 240 / 80%)",
            textTransform: "uppercase",
            marginBottom: "0.5rem",
          }}>
            {activeCharacter ? "Elden Ring · Character Codex" : "Elden Ring & Nightreign"}
          </div>
          <h1 style={{
            fontFamily: "'Cinzel Decorative', serif",
            fontSize: "clamp(1.8rem, 5vw, 3.5rem)",
            fontWeight: 700,
            color: "oklch(0.92 0.01 240)",
            textShadow: "0 0 30px oklch(0.72 0.12 240 / 40%), 0 0 60px oklch(0.72 0.12 240 / 20%)",
            margin: 0,
            lineHeight: 1.1,
            transition: "opacity 0.4s ease",
          }}>
            {activeCharacter ? String(activeCharacter.name) : "Character Codex"}
          </h1>
          <div style={{
            fontFamily: "'Cinzel', serif",
            fontSize: "clamp(0.75rem, 2vw, 1rem)",
            letterSpacing: "0.25em",
            color: "oklch(0.72 0.12 75)",
            textTransform: "uppercase",
            marginTop: "0.4rem",
            transition: "opacity 0.4s ease",
          }}>
            {activeCharacter
              ? `${String(activeCharacter.archetype)} · ${String(activeCharacter.faction)}`
              : "Forge · Randomise · Archive"}
          </div>
          {/* ── Rune / Grace ticker ────────────────────────────────── */}
          <div style={{
            display: "flex",
            justifyContent: "center",
            gap: "1.5rem",
            marginTop: "0.9rem",
            flexWrap: "wrap",
          }}>
            {/* Runes */}
            <div style={{
              display: "flex", alignItems: "center", gap: "0.4rem",
              background: "oklch(0.10 0.025 260 / 70%)",
              border: `1px solid ${runeFlash === "up" ? "oklch(0.72 0.12 75 / 60%)" : runeFlash === "down" ? "oklch(0.65 0.20 25 / 60%)" : "oklch(0.30 0.04 240 / 40%)"}`,
              padding: "0.3rem 0.8rem",
              transition: "border-color 0.3s ease",
            }}>
              <span style={{ fontSize: "0.85rem" }}>💎</span>
              <div>
                <div style={{
                  fontFamily: "'Courier Prime', monospace",
                  fontSize: "0.65rem",
                  letterSpacing: "0.12em",
                  color: "oklch(0.50 0.01 240)",
                  textTransform: "uppercase",
                  lineHeight: 1,
                  marginBottom: "0.1rem",
                }}>Runes</div>
                <div style={{
                  fontFamily: "'Cinzel', serif",
                  fontSize: "0.9rem",
                  fontWeight: 700,
                  color: runeFlash === "up" ? "oklch(0.72 0.12 75)" : runeFlash === "down" ? "oklch(0.65 0.20 25)" : "oklch(0.85 0.01 240)",
                  transition: "color 0.3s ease",
                  letterSpacing: "0.05em",
                }}>
                  {runeFlash === "up" ? "+" : runeFlash === "down" ? "−" : ""}{runeCount.toLocaleString()}
                </div>
              </div>
            </div>
            {/* Sites of Grace */}
            <div style={{
              display: "flex", alignItems: "center", gap: "0.4rem",
              background: "oklch(0.10 0.025 260 / 70%)",
              border: "1px solid oklch(0.72 0.12 75 / 25%)",
              padding: "0.3rem 0.8rem",
            }}>
              <span style={{ fontSize: "0.85rem" }}>✨</span>
              <div>
                <div style={{
                  fontFamily: "'Courier Prime', monospace",
                  fontSize: "0.65rem",
                  letterSpacing: "0.12em",
                  color: "oklch(0.50 0.01 240)",
                  textTransform: "uppercase",
                  lineHeight: 1,
                  marginBottom: "0.1rem",
                }}>Sites of Grace</div>
                <div style={{
                  fontFamily: "'Cinzel', serif",
                  fontSize: "0.9rem",
                  fontWeight: 700,
                  color: "oklch(0.72 0.12 75)",
                  letterSpacing: "0.05em",
                }}>{graceCount}</div>
              </div>
            </div>
          </div>

          {activeCharacter && (
            <button
              onClick={() => setActiveCharacter(null)}
              style={{
                marginTop: "0.75rem",
                fontFamily: "'Cinzel', serif",
                fontSize: "0.6rem",
                letterSpacing: "0.18em",
                textTransform: "uppercase",
                padding: "0.3rem 0.8rem",
                background: "transparent",
                border: "1px solid oklch(0.72 0.12 240 / 40%)",
                color: "oklch(0.72 0.12 240 / 70%)",
                cursor: "pointer",
              }}
            >
              ← Return to Codex Hub
            </button>
          )}
        </div>
      </div>

      {/* ── MAIN CONTENT ────────────────────────────────────── */}
      <div style={{ position: "relative", zIndex: 1, maxWidth: "1200px", margin: "0 auto", padding: "0 1.5rem 4rem" }}>

        {/* ── TWO-COLUMN LAYOUT ─────────────────────────────── */}
        <div style={{
          display: "grid",
          gridTemplateColumns: "clamp(220px, 28%, 320px) 1fr",
          gap: "2rem",
          alignItems: "start",
          marginTop: "-2rem",
        }} className="responsive-grid">

          {/* ── LEFT COLUMN: Portrait + Quick Info ─────────── */}
          <RevealSection delay={0}>
            <div style={{ position: "sticky", top: "1.5rem" }}>

              {/* Portrait */}
              <div style={{ position: "relative", marginBottom: "1.5rem" }}>
                <div style={{
                  border: activeCharacter ? "1px solid oklch(0.72 0.12 240 / 50%)" : "1px solid oklch(0.72 0.12 240 / 30%)",
                  overflow: "hidden",
                  position: "relative",
                  transition: "border-color 0.4s ease",
                }}>
                  <CornerOrnaments />

                  {/* Portrait display: generated > loading shimmer > Lyra default */}
                  {activeCharacter && generatedPortraitUrl ? (
                    <img
                      src={generatedPortraitUrl}
                      alt={String(activeCharacter.name)}
                      className="portrait-glow"
                      style={{ width: "100%", display: "block", filter: "brightness(0.95) contrast(1.05)", transition: "opacity 0.6s ease" }}
                    />
                  ) : activeCharacter && portraitGenerating ? (
                    <div style={{
                      width: "100%",
                      aspectRatio: "3/4",
                      background: "linear-gradient(135deg, oklch(0.15 0.04 260) 0%, oklch(0.20 0.06 240) 50%, oklch(0.15 0.04 260) 100%)",
                      backgroundSize: "200% 200%",
                      animation: "shimmer 2s ease-in-out infinite",
                      display: "flex",
                      flexDirection: "column",
                      alignItems: "center",
                      justifyContent: "center",
                      gap: "0.75rem",
                    }}>
                      <span style={{ fontSize: "2rem", animation: "spin 3s linear infinite" }}>✦</span>
                      <span style={{ fontFamily: "'Cinzel', serif", fontSize: "0.7rem", letterSpacing: "0.15em", color: "oklch(0.72 0.12 240)", textTransform: "uppercase" }}>Painting portrait...</span>
                    </div>
                  ) : (
                    // No active character — show a welcome placeholder
                    <div style={{
                      width: "100%",
                      aspectRatio: "3/4",
                      background: "linear-gradient(160deg, oklch(0.12 0.04 260) 0%, oklch(0.08 0.02 240) 100%)",
                      display: "flex",
                      flexDirection: "column",
                      alignItems: "center",
                      justifyContent: "center",
                      gap: "0.75rem",
                      padding: "1.5rem",
                      textAlign: "center",
                    }}>
                      <div style={{ fontSize: "2.5rem", opacity: 0.4, lineHeight: 1 }}>✦</div>
                      <div style={{ fontFamily: "'Cinzel', serif", fontSize: "0.72rem", letterSpacing: "0.18em", color: "oklch(0.45 0.05 240)", textTransform: "uppercase", lineHeight: 1.6 }}>
                        No character<br />loaded
                      </div>
                      <div style={{ fontFamily: "'EB Garamond', serif", fontSize: "0.78rem", color: "oklch(0.35 0.02 240)", fontStyle: "italic", lineHeight: 1.5, marginTop: "0.25rem" }}>
                        Generate or load a<br />character to begin
                      </div>
                    </div>
                  )}

                  {/* Badge */}
                  {activeCharacter && (
                    <div style={{
                      position: "absolute", top: "0.5rem", right: "0.5rem",
                      background: generatedPortraitUrl ? "oklch(0.72 0.12 75 / 20%)" : "oklch(0.72 0.12 240 / 20%)",
                      border: `1px solid ${generatedPortraitUrl ? "oklch(0.72 0.12 75 / 40%)" : "oklch(0.72 0.12 240 / 40%)"}`,
                      padding: "0.2rem 0.5rem",
                      fontFamily: "'Courier Prime', monospace",
                      fontSize: "0.6rem",
                      letterSpacing: "0.1em",
                      color: generatedPortraitUrl ? "oklch(0.72 0.12 75)" : "oklch(0.72 0.12 240)",
                      textTransform: "uppercase",
                    }}>{generatedPortraitUrl ? "AI Portrait" : portraitGenerating ? "Painting..." : "Generated"}</div>
                  )}

                  {/* Portrait error */}
                  {portraitError && activeCharacter && (
                    <div style={{
                      position: "absolute", bottom: "2.5rem", left: "0.5rem", right: "0.5rem",
                      background: "oklch(0.65 0.20 25 / 15%)",
                      border: "1px solid oklch(0.65 0.20 25 / 30%)",
                      padding: "0.3rem 0.5rem",
                      fontFamily: "'Courier Prime', monospace",
                      fontSize: "0.6rem",
                      color: "oklch(0.65 0.20 25)",
                      textAlign: "center",
                    }}>Portrait unavailable</div>
                  )}
                  {/* Portrait gradient overlay */}
                  <div style={{
                    position: "absolute", bottom: 0, left: 0, right: 0, height: "30%",
                    background: "linear-gradient(to top, oklch(0.10 0.025 260) 0%, transparent 100%)"
                  }} />
                </div>
              </div>

              {/* Quick Stats Card — dynamic */}
              <div className="lore-card" style={{ padding: "1.25rem", position: "relative", marginBottom: "1rem" }}>
                <CornerOrnaments />
                <div style={{ fontFamily: "'Cinzel', serif", fontSize: "0.7rem", letterSpacing: "0.2em", color: "oklch(0.72 0.12 75)", textTransform: "uppercase", marginBottom: "0.75rem" }}>
                  Identity
                </div>
                {(activeCharacter ? [
                  ["Age", String(activeCharacter.age)],
                  ["Origin", String(activeCharacter.origin)],
                  ["Race", String(activeCharacter.race)],
                  ["Role", String(activeCharacter.archetype)],
                  ["Allegiance", String(activeCharacter.faction)],
                  ["Gender", String(activeCharacter.gender)],
                ] : [
                  ["Age", "—"],
                  ["Origin", "—"],
                  ["Race", "—"],
                  ["Role", "—"],
                  ["Allegiance", "—"],
                  ["Status", "—"],
                ]).map(([key, val]) => (
                  <div key={key} style={{ display: "flex", justifyContent: "space-between", marginBottom: "0.5rem", borderBottom: "1px solid oklch(0.30 0.04 240 / 20%)", paddingBottom: "0.5rem" }}>
                    <span style={{ fontFamily: "'Courier Prime', monospace", fontSize: "0.72rem", color: "oklch(0.55 0.01 240)", letterSpacing: "0.05em" }}>{key}</span>
                    <span style={{ fontFamily: "'Courier Prime', monospace", fontSize: "0.72rem", color: "oklch(0.80 0.01 240)", textAlign: "right", maxWidth: "55%" }}>{val}</span>
                  </div>
                ))}
              </div>

              {/* Personality Traits — dynamic */}
              <div className="lore-card" style={{ padding: "1.25rem", position: "relative" }}>
                <CornerOrnaments />
                <div style={{ fontFamily: "'Cinzel', serif", fontSize: "0.7rem", letterSpacing: "0.2em", color: "oklch(0.72 0.12 75)", textTransform: "uppercase", marginBottom: "0.75rem" }}>
                  Traits
                </div>
                <div style={{ display: "flex", flexWrap: "wrap" }}>
                  {(activeCharacter && Array.isArray(activeCharacter.traits)
                    ? (activeCharacter.traits as string[])
                    : []
                  ).length === 0 && !activeCharacter ? (
                    <div style={{ fontFamily: "'EB Garamond', serif", fontSize: "0.8rem", color: "oklch(0.35 0.02 240)", fontStyle: "italic" }}>No character loaded</div>
                  ) : null}
                  {(activeCharacter && Array.isArray(activeCharacter.traits)
                    ? (activeCharacter.traits as string[])
                    : []
                  ).map(t => (
                    <TraitBadge key={t} label={t} />
                  ))}
                </div>
              </div>

            </div>
          </RevealSection>

          {/* ── RIGHT COLUMN: Tabs + Content ───────────────── */}
          <div>

            {/* Tab navigation */}
            <RevealSection delay={100}>
              <div style={{
                display: "flex",
                gap: "0",
                borderBottom: "1px solid oklch(0.30 0.04 240 / 40%)",
                marginBottom: "1.5rem",
                overflowX: "auto",
              }}>
                {(["lore", "stats", "abilities", "equipment", "relationships", "generate"] as const).map(tab => (
                  <button
                    key={tab}
                    onClick={() => setActiveTab(tab)}
                    style={{
                      fontFamily: "'Cinzel', serif",
                      fontSize: "0.75rem",
                      letterSpacing: "0.15em",
                      textTransform: "uppercase",
                      padding: "0.75rem 1.25rem",
                      background: "transparent",
                      border: "none",
                      borderBottom: activeTab === tab ? "2px solid oklch(0.72 0.12 75)" : "2px solid transparent",
                      color: activeTab === tab ? "oklch(0.72 0.12 75)" : "oklch(0.55 0.01 240)",
                      cursor: "pointer",
                      transition: "color 0.2s ease, border-color 0.2s ease",
                      whiteSpace: "nowrap",
                    }}
                  >
                    {tab}
                  </button>
                ))}
              </div>
            </RevealSection>

            {/* ── LORE TAB ──────────────────────────────────── */}
            {activeTab === "lore" && (
              <div>
                {activeCharacter ? (
                  <>
                    <RevealSection delay={0}>
                      <div className="lore-card" style={{ padding: "1.75rem", position: "relative", marginBottom: "1.25rem" }}>
                        <CornerOrnaments />
                        <h2 style={{ fontFamily: "'Cinzel Decorative', serif", fontSize: "1.1rem", color: "oklch(0.72 0.12 75)", marginBottom: "1rem", fontWeight: 700 }}>Origin · {String(activeCharacter.origin)}</h2>
                        <p style={{ fontSize: "0.95rem", lineHeight: 1.85, color: "oklch(0.72 0.01 240)" }}>{String(activeCharacter.backstory)}</p>
                      </div>
                    </RevealSection>
                    <RevealSection delay={100}>
                      <div className="lore-card" style={{ padding: "1.75rem", position: "relative", marginBottom: "1.25rem" }}>
                        <CornerOrnaments />
                        <h2 style={{ fontFamily: "'Cinzel Decorative', serif", fontSize: "1.1rem", color: "oklch(0.72 0.12 75)", marginBottom: "1rem", fontWeight: 700 }}>Appearance</h2>
                        <p style={{ fontSize: "0.95rem", lineHeight: 1.85, color: "oklch(0.72 0.01 240)" }}>{String(activeCharacter.appearance)}</p>
                      </div>
                    </RevealSection>
                    <RevealSection delay={200}>
                      <div className="lore-card" style={{ padding: "1.75rem", position: "relative", marginBottom: "1.25rem" }}>
                        <CornerOrnaments />
                        <h2 style={{ fontFamily: "'Cinzel Decorative', serif", fontSize: "1.1rem", color: "oklch(0.72 0.12 75)", marginBottom: "1rem", fontWeight: 700 }}>Personality</h2>
                        <p style={{ fontSize: "0.95rem", lineHeight: 1.85, color: "oklch(0.72 0.01 240)" }}>{String(activeCharacter.personality)}</p>
                        <RuneDivider label="Defining Flaw" />
                        <p style={{ fontSize: "0.95rem", lineHeight: 1.85, color: "oklch(0.65 0.20 25)", fontStyle: "italic" }}>{String(activeCharacter.definingFlaw)}</p>
                      </div>
                    </RevealSection>
                    <RevealSection delay={300}>
                      <div className="lore-card" style={{ padding: "1.75rem", position: "relative", border: "1px solid oklch(0.72 0.12 75 / 25%)" }}>
                        <CornerOrnaments />
                        <h2 style={{ fontFamily: "'Cinzel Decorative', serif", fontSize: "1.1rem", color: "oklch(0.72 0.12 75)", marginBottom: "1rem", fontWeight: 700 }}>Motivation</h2>
                        <p style={{ fontSize: "0.95rem", lineHeight: 1.85, color: "oklch(0.72 0.01 240)" }}>{String(activeCharacter.motivation)}</p>
                        <RuneDivider label="Connection to Party" />
                        <p style={{ fontSize: "0.95rem", lineHeight: 1.85, color: "oklch(0.72 0.01 240)", fontStyle: "italic" }}>{String(activeCharacter.connectionToLyra ?? activeCharacter.connectionToParty ?? "")}</p>
                      </div>
                    </RevealSection>
                  </>
                ) : (
                  <>
                <RevealSection delay={0}>
                  <div className="lore-card" style={{ padding: "2.5rem", position: "relative", marginBottom: "1.25rem", textAlign: "center" }}>
                    <CornerOrnaments />
                    <div style={{ fontSize: "3rem", marginBottom: "1rem", opacity: 0.3 }}>✦</div>
                    <h2 style={{ fontFamily: "'Cinzel Decorative', serif", fontSize: "1.2rem", color: "oklch(0.72 0.12 75)", marginBottom: "1rem", fontWeight: 700 }}>
                      No Character Loaded
                    </h2>
                    <p style={{ fontSize: "0.95rem", lineHeight: 1.85, color: "oklch(0.55 0.01 240)", fontStyle: "italic", maxWidth: "480px", margin: "0 auto 1.25rem" }}>
                      The Codex awaits a soul to chronicle. Head to the <strong style={{ color: "oklch(0.72 0.12 75)" }}>Generate</strong> tab to forge a new character from the lore of the Lands Between and Nightreign, or load one from your Codex Archive.
                    </p>
                    <RuneDivider />
                    <p style={{ fontSize: "0.8rem", lineHeight: 1.7, color: "oklch(0.40 0.02 240)", fontFamily: "'Courier Prime', monospace", letterSpacing: "0.05em", marginTop: "1rem" }}>
                      "Arise, Tarnished. Thy grace long lost, thou art yet called."<br />
                      <span style={{ opacity: 0.5 }}>— The Two Fingers</span>
                    </p>
                  </div>
                </RevealSection>
                  </>
                )}
              </div>
            )}

            {/* ── STATS TAB ─────────────────────────────────── */}
            {activeTab === "stats" && (
              <div>
                <RevealSection delay={0}>
                  <div className="lore-card" style={{ padding: "1.75rem", position: "relative", marginBottom: "1.25rem" }}>
                    <CornerOrnaments />
                    <h2 style={{ fontFamily: "'Cinzel Decorative', serif", fontSize: "1.1rem", color: "oklch(0.72 0.12 75)", marginBottom: "0.5rem", fontWeight: 700 }}>
                      Attribute Spread
                    </h2>
                    <p style={{ fontSize: "0.85rem", color: "oklch(0.55 0.01 240)", marginBottom: "1.25rem", fontFamily: "'Courier Prime', monospace" }}>
                      {activeCharacter ? `${String(activeCharacter.name)}'s attributes` : "Hover over the chart to inspect individual values."}
                    </p>
                    {activeCharacter && activeCharacter.stats && typeof activeCharacter.stats === "object" ? (
                      (() => {
                        const statsObj = activeCharacter.stats as Record<string, unknown>;
                        const statKeys = Object.keys(statsObj);
                        return statKeys.map(stat => (
                          <div key={stat} style={{ display: "flex", alignItems: "center", gap: "0.5rem", marginBottom: "0.5rem" }}>
                            <span style={{ fontFamily: "'Courier Prime', monospace", fontSize: "0.68rem", letterSpacing: "0.08em", color: "oklch(0.55 0.01 240)", textTransform: "uppercase", width: "90px", flexShrink: 0 }}>{stat}</span>
                            <div style={{ flex: 1, height: "6px", background: "oklch(0.20 0.03 260)", borderRadius: "3px", overflow: "hidden" }}>
                              <div style={{ width: `${(Number(statsObj[stat]) / 99) * 100}%`, height: "100%", background: "oklch(0.72 0.12 240)", borderRadius: "3px", boxShadow: "0 0 6px oklch(0.72 0.12 240 / 50%)", transition: "width 1s ease" }} />
                            </div>
                            <span style={{ fontFamily: "'Courier Prime', monospace", fontSize: "0.72rem", color: "oklch(0.72 0.12 240)", width: "28px", textAlign: "right" }}>{Number(statsObj[stat])}</span>
                          </div>
                        ));
                      })()
                    ) : (
                      <StatRadarChart />
                    )}
                  </div>
                </RevealSection>

                <RevealSection delay={100}>
                  <div className="lore-card" style={{ padding: "1.75rem", position: "relative", marginBottom: "1.25rem" }}>
                    <CornerOrnaments />
                    <h2 style={{ fontFamily: "'Cinzel Decorative', serif", fontSize: "1.1rem", color: "oklch(0.72 0.12 75)", marginBottom: "1.25rem", fontWeight: 700 }}>
                      Primary Attributes
                    </h2>
                    {activeCharacter && activeCharacter.stats && typeof activeCharacter.stats === "object" ? (
                      (() => {
                        const s = activeCharacter.stats as Record<string, unknown>;
                        return [
                          ["DEXTERITY", "dexterity"], ["INTELLIGENCE", "intelligence"],
                          ["MIND", "mind"], ["ENDURANCE", "endurance"],
                          ["STRENGTH", "strength"], ["FAITH", "faith"],
                        ].map(([label, key]) => (
                          <StatBar key={label} label={label} value={Number(s[key] ?? s[label.toLowerCase()] ?? 20)} color={["DEXTERITY","INTELLIGENCE","MIND"].includes(label) ? "blue" : "gold"} />
                        ));
                      })()
                    ) : (
                      <>
                        <StatBar label="DEXTERITY" value={88} color="blue" />
                        <StatBar label="INTELLIGENCE" value={82} color="blue" />
                        <StatBar label="MIND" value={65} color="blue" />
                        <StatBar label="ENDURANCE" value={55} color="gold" />
                        <StatBar label="STRENGTH" value={30} color="gold" />
                        <StatBar label="FAITH" value={20} color="gold" />
                      </>
                    )}
                  </div>
                </RevealSection>

                <RevealSection delay={200}>
                  <div className="lore-card" style={{ padding: "1.75rem", position: "relative" }}>
                    <CornerOrnaments />
                    <h2 style={{ fontFamily: "'Cinzel Decorative', serif", fontSize: "1.1rem", color: "oklch(0.72 0.12 75)", marginBottom: "1.25rem", fontWeight: 700 }}>
                      Derived Values
                    </h2>
                    <div style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: "0.75rem" }}>
                      {[
                        ["HP", activeCharacter ? "—" : "1,240"],
                        ["FP (Focus)", activeCharacter ? "—" : "860"],
                        ["Stamina", activeCharacter ? "—" : "720"],
                        ["Equip Load", activeCharacter ? "—" : "Light"],
                        ["Discovery", activeCharacter ? "—" : "High"],
                        ["Poise", activeCharacter ? "—" : "Low"],
                      ].map(([k, v]) => (
                        <div key={k} style={{
                          background: "oklch(0.18 0.04 260)",
                          border: "1px solid oklch(0.30 0.04 240 / 30%)",
                          padding: "0.75rem 1rem",
                          display: "flex",
                          flexDirection: "column",
                          gap: "0.25rem",
                        }}>
                          <span style={{ fontFamily: "'Courier Prime', monospace", fontSize: "0.65rem", letterSpacing: "0.1em", color: "oklch(0.55 0.01 240)", textTransform: "uppercase" }}>{k}</span>
                          <span style={{ fontFamily: "'Cinzel', serif", fontSize: "1rem", fontWeight: 600, color: "oklch(0.82 0.01 240)" }}>{v}</span>
                        </div>
                      ))}
                    </div>
                  </div>
                </RevealSection>
              </div>
            )}

            {/* ── ABILITIES TAB ─────────────────────────────── */}
            {activeTab === "abilities" && (
              <div>
                <RevealSection delay={0}>
                  <div style={{ marginBottom: "1rem" }}>
                    <div style={{ fontFamily: "'Cinzel', serif", fontSize: "0.7rem", letterSpacing: "0.2em", color: "oklch(0.72 0.12 75)", textTransform: "uppercase", marginBottom: "0.75rem" }}>
                      Combat Arts
                    </div>
                    <AbilityCard
                      icon="⚔️"
                      name="Flowing Form"
                      type="Passive"
                      description="Lyra's fighting style is fluid and unpredictable, drawn from the ancient Nox Swordstress tradition. She can seamlessly transition between offensive and defensive postures mid-combination, making her movements difficult to read and harder to counter."
                    />
                    <AbilityCard
                      icon="🌊"
                      name="Silver Tide"
                      type="Active · Weapon Art"
                      description="Lyra channels liquid silver through her blade, sending a rippling wave of metallic force in a wide arc. Enemies struck are slowed as the silver briefly coats their limbs. Costs 18 FP."
                    />
                  </div>
                </RevealSection>

                <RevealSection delay={100}>
                  <div style={{ marginBottom: "1rem" }}>
                    <div style={{ fontFamily: "'Cinzel', serif", fontSize: "0.7rem", letterSpacing: "0.2em", color: "oklch(0.72 0.12 75)", textTransform: "uppercase", marginBottom: "0.75rem" }}>
                      Sorceries
                    </div>
                    <AbilityCard
                      icon="✨"
                      name="Starlight Shard"
                      type="Sorcery · INT 28"
                      description="Conjures a shard of crystallized starlight and hurls it at a target. The shard explodes on impact, releasing a burst of pale blue radiance that can briefly blind enemies caught in its radius. Costs 12 FP."
                    />
                    <AbilityCard
                      icon="🌌"
                      name="Eternal Darkness"
                      type="Sorcery · INT 35"
                      description="The signature sorcery of the Nox, a sphere of absolute darkness that devours all light and sound within its radius. Enemies inside cannot see or hear, and sorceries cast within it are absorbed. Costs 32 FP. This spell is said to symbolize the downfall of the Eternal Cities."
                    />
                    <AbilityCard
                      icon="🔮"
                      name="Night Comet"
                      type="Sorcery · INT 38"
                      description="Fires a comet of condensed night-sorcery that travels silently, without the telltale glow of glintstone magic. Enemies rarely detect it until impact. Costs 24 FP."
                    />
                  </div>
                </RevealSection>

                <RevealSection delay={200}>
                  <div>
                    <div style={{ fontFamily: "'Cinzel', serif", fontSize: "0.7rem", letterSpacing: "0.2em", color: "oklch(0.72 0.12 75)", textTransform: "uppercase", marginBottom: "0.75rem" }}>
                      Innate Gifts
                    </div>
                    <AbilityCard
                      icon="🌙"
                      name="Child of the Stars"
                      type="Innate · Racial"
                      description="As a Nox born under a celestial alignment, Lyra possesses natural resistance to sleep and madness effects. She can see clearly in near-total darkness and instinctively senses the position of celestial bodies, even underground."
                    />
                    <AbilityCard
                      icon="🪬"
                      name="Cold Blood"
                      type="Innate · Racial"
                      description="The Nox are cold-blooded, running cooler than surface-dwellers. Lyra has heightened resistance to fire damage but is more susceptible to frost. Her body temperature also makes her harder to detect by creatures that hunt by heat."
                    />
                  </div>
                </RevealSection>
              </div>
            )}

            {/* ── EQUIPMENT TAB ─────────────────────────────── */}
            {activeTab === "equipment" && (
              <div>
                <RevealSection delay={0}>
                  <div className="lore-card" style={{ padding: "1.5rem", position: "relative", marginBottom: "1.25rem" }}>
                    <CornerOrnaments />
                    <h2 style={{ fontFamily: "'Cinzel Decorative', serif", fontSize: "1.1rem", color: "oklch(0.72 0.12 75)", marginBottom: "1.25rem", fontWeight: 700 }}>
                      Armaments
                    </h2>
                    <div style={{ display: "flex", flexDirection: "column", gap: "0.5rem" }}>
                      <EquipmentItem
                        icon="⚔️"
                        name="Nox Flowing Sword"
                        description="A unique weapon forged from liquid silver metal. The blade can extend and retract, flowing like water to strike at unexpected angles. It is both a sword and a whip, depending on the wielder's intent. Scales with DEX and INT."
                      />
                      <EquipmentItem
                        icon="🔮"
                        name="Nox Sorcerer's Staff"
                        description="A slender staff carved from the crystalline stone of the Eternal Cities. It channels night sorceries with exceptional efficiency, reducing FP costs for Nox-origin spells."
                      />
                    </div>
                  </div>
                </RevealSection>

                <RevealSection delay={100}>
                  <div className="lore-card" style={{ padding: "1.5rem", position: "relative", marginBottom: "1.25rem" }}>
                    <CornerOrnaments />
                    <h2 style={{ fontFamily: "'Cinzel Decorative', serif", fontSize: "1.1rem", color: "oklch(0.72 0.12 75)", marginBottom: "1.25rem", fontWeight: 700 }}>
                      Armor
                    </h2>
                    <div style={{ display: "flex", flexDirection: "column", gap: "0.5rem" }}>
                      <EquipmentItem
                        icon="👑"
                        name="Nox Mirrorhelm"
                        description="A crystalline helmet fashioned from glass, designed to ward off the intervention of the Two Fingers. It is said that wearing it severs one's connection to the Greater Will — a deliberate act of defiance by the Nox people."
                      />
                      <EquipmentItem
                        icon="🥻"
                        name="Nox Swordstress Garb"
                        description="Flowing silk garments of deep midnight blue, adorned with silver thread in patterns that map the false stars of Nokstella. Light and elegant, offering surprising resistance to magic damage."
                      />
                      <EquipmentItem
                        icon="💠"
                        name="Silver Tear Bracelets"
                        description="Bracelets formed from hardened Silver Tear liquid metal. They can briefly liquefy and reform, allowing Lyra to slip out of grapples or reshape them into makeshift weapons in a pinch."
                      />
                    </div>
                  </div>
                </RevealSection>

                <RevealSection delay={200}>
                  <div className="lore-card" style={{ padding: "1.5rem", position: "relative" }}>
                    <CornerOrnaments />
                    <h2 style={{ fontFamily: "'Cinzel Decorative', serif", fontSize: "1.1rem", color: "oklch(0.72 0.12 75)", marginBottom: "1.25rem", fontWeight: 700 }}>
                      Keepsakes & Tools
                    </h2>
                    <div style={{ display: "flex", flexDirection: "column", gap: "0.5rem" }}>
                      <EquipmentItem
                        icon="🔭"
                        name="Astrolabe of Nokstella"
                        description="An intricate device used for navigating by the stars. In the underground, it reads the false stars of the Eternal City. On the surface, it reads the real ones. Lyra uses it to orient herself and to perform celestial calculations for her sorceries."
                      />
                      <EquipmentItem
                        icon="💎"
                        name="Starlight Shards"
                        description="Small, crystalline shards that emit a soft, calming pale blue light. Lyra carries a pouch of them. They have no combat use, but she gives them to people she trusts — a Nox gesture of friendship."
                      />
                      <EquipmentItem
                        icon="📜"
                        name="The Elders' Mandate"
                        description="A sealed scroll given to Lyra by the elders of Nokstella. She has been instructed not to open it until she has 'seen the true stars for the first time.' She does not know what it contains."
                      />
                    </div>
                  </div>
                </RevealSection>
              </div>
            )}

            {/* ── RELATIONSHIPS TAB ──────────────────────── */}
            {activeTab === "relationships" && (
              <div>
                {/* Header row */}
                <RevealSection delay={0}>
                  <div style={{ display: "flex", justifyContent: "space-between", alignItems: "center", marginBottom: "1.25rem" }}>
                    <div>
                      <div style={{ fontFamily: "'Cinzel Decorative', serif", fontSize: "1rem", color: "oklch(0.72 0.12 75)", fontWeight: 700 }}>Known Figures</div>
                      <div style={{ fontFamily: "'Courier Prime', monospace", fontSize: "0.72rem", color: "oklch(0.50 0.01 240)", marginTop: "0.25rem" }}>
                        {relationships.filter(r => r.type === "ally").length} allies · {relationships.filter(r => r.type === "rival").length} rivals · {relationships.filter(r => r.type === "neutral" || r.type === "unknown").length} others
                      </div>
                    </div>
                    <button
                      onClick={openAdd}
                      style={{
                        fontFamily: "'Cinzel', serif",
                        fontSize: "0.7rem",
                        letterSpacing: "0.12em",
                        textTransform: "uppercase",
                        padding: "0.5rem 1rem",
                        background: "transparent",
                        border: "1px solid oklch(0.72 0.12 75 / 60%)",
                        color: "oklch(0.72 0.12 75)",
                        cursor: "pointer",
                        transition: "background 0.2s ease, border-color 0.2s ease",
                      }}
                      onMouseEnter={e => (e.currentTarget.style.background = "oklch(0.72 0.12 75 / 10%)")}
                      onMouseLeave={e => (e.currentTarget.style.background = "transparent")}
                    >
                      + Add Figure
                    </button>
                  </div>
                </RevealSection>

                {/* Add / Edit form */}
                {showAddForm && (
                  <RevealSection delay={0}>
                    <div className="lore-card" style={{ padding: "1.5rem", position: "relative", marginBottom: "1.25rem", border: "1px solid oklch(0.72 0.12 75 / 40%)" }}>
                      <CornerOrnaments />
                      <div style={{ fontFamily: "'Cinzel Decorative', serif", fontSize: "0.9rem", color: "oklch(0.72 0.12 75)", marginBottom: "1rem", fontWeight: 700 }}>
                        {editingId ? "Edit Figure" : "New Figure"}
                      </div>
                      <div style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: "0.75rem", marginBottom: "0.75rem" }}>
                        {/* Name */}
                        <div style={{ gridColumn: "1 / -1" }}>
                          <label style={formLabelStyle}>Name</label>
                          <input
                            value={formData.name}
                            onChange={e => setFormData(p => ({ ...p, name: e.target.value }))}
                            placeholder="Character name..."
                            style={formInputStyle}
                          />
                        </div>
                        {/* Type */}
                        <div>
                          <label style={formLabelStyle}>Relationship</label>
                          <select
                            value={formData.type}
                            onChange={e => setFormData(p => ({ ...p, type: e.target.value as RelType }))}
                            style={formInputStyle}
                          >
                            <option value="ally">Ally</option>
                            <option value="rival">Rival</option>
                            <option value="neutral">Neutral</option>
                            <option value="unknown">Unknown</option>
                          </select>
                        </div>
                        {/* Faction */}
                        <div>
                          <label style={formLabelStyle}>Faction / Origin</label>
                          <input
                            value={formData.faction}
                            onChange={e => setFormData(p => ({ ...p, faction: e.target.value }))}
                            placeholder="e.g. Golden Order..."
                            style={formInputStyle}
                          />
                        </div>
                        {/* Trust level */}
                        <div style={{ gridColumn: "1 / -1" }}>
                          <label style={formLabelStyle}>Trust Level — {formData.trustLevel} / 100</label>
                          <input
                            type="range" min={0} max={100}
                            value={formData.trustLevel}
                            onChange={e => setFormData(p => ({ ...p, trustLevel: Number(e.target.value) }))}
                            style={{ width: "100%", accentColor: "oklch(0.72 0.12 240)", cursor: "pointer" }}
                          />
                        </div>
                        {/* First met */}
                        <div style={{ gridColumn: "1 / -1" }}>
                          <label style={formLabelStyle}>First Encountered</label>
                          <input
                            value={formData.firstMet}
                            onChange={e => setFormData(p => ({ ...p, firstMet: e.target.value }))}
                            placeholder="Session X — location..."
                            style={formInputStyle}
                          />
                        </div>
                        {/* Notes */}
                        <div style={{ gridColumn: "1 / -1" }}>
                          <label style={formLabelStyle}>Notes</label>
                          <textarea
                            value={formData.notes}
                            onChange={e => setFormData(p => ({ ...p, notes: e.target.value }))}
                            placeholder="Describe the relationship, key events, motivations..."
                            rows={4}
                            style={{ ...formInputStyle, resize: "vertical", minHeight: "80px" }}
                          />
                        </div>
                      </div>
                      <div style={{ display: "flex", gap: "0.75rem", justifyContent: "flex-end" }}>
                        <button onClick={closeForm} style={{ ...formBtnStyle, color: "oklch(0.55 0.01 240)", borderColor: "oklch(0.30 0.04 240 / 40%)" }}>Cancel</button>
                        <button onClick={saveForm} style={{ ...formBtnStyle, color: "oklch(0.72 0.12 75)", borderColor: "oklch(0.72 0.12 75 / 60%)", background: "oklch(0.72 0.12 75 / 8%)" }}>
                          {editingId ? "Save Changes" : "Add Figure"}
                        </button>
                      </div>
                    </div>
                  </RevealSection>
                )}

                {/* Filter sections: Allies → Rivals → Others */}
                {(["ally", "rival", "neutral", "unknown"] as RelType[]).map(section => {
                  const group = relationships.filter(r => r.type === section);
                  if (group.length === 0) return null;
                  const sectionLabel = section === "ally" ? "Allies" : section === "rival" ? "Rivals" : section === "neutral" ? "Neutral" : "Unknown";
                  const sectionColor = section === "ally" ? "oklch(0.72 0.12 240)" : section === "rival" ? "oklch(0.65 0.20 25)" : "oklch(0.72 0.12 75)";
                  return (
                    <RevealSection key={section} delay={0}>
                      <div style={{ marginBottom: "1.5rem" }}>
                        <div style={{ fontFamily: "'Cinzel', serif", fontSize: "0.7rem", letterSpacing: "0.2em", color: sectionColor, textTransform: "uppercase", marginBottom: "0.75rem", display: "flex", alignItems: "center", gap: "0.75rem" }}>
                          <span>{sectionLabel}</span>
                          <span style={{ flex: 1, height: "1px", background: `linear-gradient(90deg, ${sectionColor}40, transparent)` }} />
                        </div>
                        {group.map(rel => (
                          <div key={rel.id} className="lore-card" style={{ position: "relative", marginBottom: "0.75rem", border: `1px solid ${sectionColor}25` }}>
                            <CornerOrnaments />
                            {/* Card header row */}
                            <div
                              style={{ padding: "1rem 1.25rem", cursor: "pointer", display: "flex", alignItems: "center", gap: "1rem" }}
                              onClick={() => toggleExpand(rel.id)}
                            >
                              {/* Type icon */}
                              <div style={{
                                width: "2.25rem", height: "2.25rem", flexShrink: 0,
                                display: "flex", alignItems: "center", justifyContent: "center",
                                background: `${sectionColor}15`,
                                border: `1px solid ${sectionColor}40`,
                                fontSize: "1rem",
                              }}>
                                {section === "ally" ? "🤝" : section === "rival" ? "⚔️" : section === "neutral" ? "⚖️" : "❓"}
                              </div>
                              <div style={{ flex: 1, minWidth: 0 }}>
                                <div style={{ fontFamily: "'Cinzel', serif", fontSize: "0.9rem", fontWeight: 600, color: "oklch(0.85 0.01 240)", marginBottom: "0.2rem" }}>
                                  {rel.name}
                                </div>
                                <div style={{ display: "flex", alignItems: "center", gap: "0.75rem", flexWrap: "wrap" }}>
                                  {rel.faction && (
                                    <span style={{ fontFamily: "'Courier Prime', monospace", fontSize: "0.68rem", color: "oklch(0.55 0.01 240)", letterSpacing: "0.05em" }}>
                                      {rel.faction}
                                    </span>
                                  )}
                                  {/* Trust bar inline */}
                                  <div style={{ display: "flex", alignItems: "center", gap: "0.4rem" }}>
                                    <span style={{ fontFamily: "'Courier Prime', monospace", fontSize: "0.65rem", color: "oklch(0.50 0.01 240)" }}>Trust</span>
                                    <div style={{ width: "60px", height: "4px", background: "oklch(0.20 0.03 260)", borderRadius: "2px", overflow: "hidden" }}>
                                      <div style={{ width: `${rel.trustLevel}%`, height: "100%", background: sectionColor, borderRadius: "2px", boxShadow: `0 0 6px ${sectionColor}60`, transition: "width 0.8s ease" }} />
                                    </div>
                                    <span style={{ fontFamily: "'Courier Prime', monospace", fontSize: "0.65rem", color: sectionColor }}>{rel.trustLevel}</span>
                                  </div>
                                </div>
                              </div>
                              {/* Expand chevron */}
                              <div style={{ color: "oklch(0.45 0.01 240)", fontSize: "0.75rem", transition: "transform 0.3s ease", transform: rel.isExpanded ? "rotate(180deg)" : "rotate(0deg)" }}>▼</div>
                            </div>

                            {/* Expanded details */}
                            {rel.isExpanded && (
                              <div style={{ padding: "0 1.25rem 1.25rem", borderTop: "1px solid oklch(0.25 0.03 240 / 40%)" }}>
                                {rel.firstMet && (
                                  <div style={{ marginTop: "0.75rem", marginBottom: "0.5rem" }}>
                                    <span style={{ fontFamily: "'Courier Prime', monospace", fontSize: "0.68rem", color: "oklch(0.55 0.01 240)", letterSpacing: "0.08em", textTransform: "uppercase" }}>First Encountered · </span>
                                    <span style={{ fontFamily: "'Courier Prime', monospace", fontSize: "0.72rem", color: "oklch(0.72 0.12 75)" }}>{rel.firstMet}</span>
                                  </div>
                                )}
                                {rel.notes && (
                                  <p style={{ fontSize: "0.875rem", lineHeight: 1.75, color: "oklch(0.68 0.01 240)", margin: "0.5rem 0 0.75rem" }}>
                                    {rel.notes}
                                  </p>
                                )}
                                <div style={{ display: "flex", gap: "0.5rem", justifyContent: "flex-end" }}>
                                  <button
                                    onClick={() => openEdit(rel)}
                                    style={{ ...formBtnStyle, fontSize: "0.65rem", padding: "0.3rem 0.75rem", color: "oklch(0.72 0.12 240)", borderColor: "oklch(0.72 0.12 240 / 40%)" }}
                                  >Edit</button>
                                  <button
                                    onClick={() => deleteRel(rel.id)}
                                    style={{ ...formBtnStyle, fontSize: "0.65rem", padding: "0.3rem 0.75rem", color: "oklch(0.65 0.20 25)", borderColor: "oklch(0.65 0.20 25 / 40%)" }}
                                  >Remove</button>
                                </div>
                              </div>
                            )}
                          </div>
                        ))}
                      </div>
                    </RevealSection>
                  );
                })}

                {relationships.length === 0 && (
                  <RevealSection delay={0}>
                    <div className="lore-card" style={{ padding: "2.5rem", textAlign: "center", position: "relative" }}>
                      <CornerOrnaments />
                      <div style={{ fontSize: "2rem", marginBottom: "0.75rem" }}>✦</div>
                      <div style={{ fontFamily: "'Cinzel', serif", fontSize: "0.85rem", color: "oklch(0.50 0.01 240)" }}>No figures recorded yet.</div>
                      <div style={{ fontFamily: "'EB Garamond', serif", fontSize: "0.85rem", color: "oklch(0.40 0.01 240)", marginTop: "0.4rem", fontStyle: "italic" }}>Add allies and rivals as your sessions unfold.</div>
                    </div>
                  </RevealSection>
                )}
              </div>
            )}

            {/* ── GENERATE CHARACTER TAB ─────────────────────── */}
            {activeTab === "generate" && (
              <div>
                <RevealSection delay={0}>
                  <div style={{ marginBottom: "1.25rem" }}>
                    <div style={{ fontFamily: "'Cinzel Decorative', serif", fontSize: "1rem", color: "oklch(0.72 0.12 75)", fontWeight: 700, marginBottom: "0.35rem" }}>Character Forge</div>
                    <div style={{ fontFamily: "'EB Garamond', serif", fontSize: "0.9rem", color: "oklch(0.55 0.01 240)", fontStyle: "italic" }}>
                      Describe the kind of character you need and the Forge will weave them from the lore of the Lands Between.
                    </div>
                  </div>
                </RevealSection>

                {/* ── RANDOMISER PANEL ── */}
                <RevealSection delay={25}>
                  <div className="lore-card" style={{ padding: "1.5rem", position: "relative", marginBottom: "1.5rem", border: "1px solid oklch(0.55 0.15 270 / 40%)", background: "oklch(0.11 0.03 270 / 60%)" }}>
                    <CornerOrnaments />
                    {/* Header row */}
                    <div style={{ display: "flex", justifyContent: "space-between", alignItems: "flex-start", marginBottom: "0.75rem" }}>
                      <div>
                        <div style={{ fontFamily: "'Cinzel Decorative', serif", fontSize: "0.85rem", color: "oklch(0.75 0.18 270)", fontWeight: 700, marginBottom: "0.2rem" }}>✦ Quick Randomiser</div>
                        <div style={{ fontFamily: "'EB Garamond', serif", fontSize: "0.85rem", color: "oklch(0.52 0.01 240)", fontStyle: "italic" }}>Roll a quick-start concept — a spark, not a saga.</div>
                      </div>
                      {/* Token bucket display */}
                      <div style={{ display: "flex", flexDirection: "column", alignItems: "flex-end", gap: "0.2rem", flexShrink: 0, marginLeft: "1rem" }}>
                        <div style={{ display: "flex", gap: "0.35rem" }}>
                          {[0, 1, 2].map(i => (
                            <div key={i} style={{
                              width: "14px", height: "14px", borderRadius: "50%",
                              background: i < randTokens ? "oklch(0.72 0.18 270)" : "oklch(0.22 0.03 270)",
                              boxShadow: i < randTokens ? "0 0 6px oklch(0.72 0.18 270 / 70%)" : "none",
                              transition: "background 0.4s, box-shadow 0.4s",
                            }} />
                          ))}
                        </div>
                        <div style={{ fontFamily: "'Courier Prime', monospace", fontSize: "0.6rem", color: "oklch(0.42 0.01 240)", letterSpacing: "0.06em" }}>
                          {randTokens}/{MAX_RAND_TOKENS} charges
                          {randNextRefill > 0 && ` · +1 in ${formatRefill(randNextRefill)}`}
                        </div>
                      </div>
                    </div>

                    {/* Optional lore context */}
                    <div style={{ marginBottom: "0.75rem" }}>
                      <label style={{ fontFamily: "'Courier Prime', monospace", fontSize: "0.65rem", letterSpacing: "0.1em", color: "oklch(0.50 0.01 240)", textTransform: "uppercase", display: "block", marginBottom: "0.3rem" }}>Session Context (optional)</label>
                      <textarea
                        value={randContext}
                        onChange={e => setRandContext(e.target.value)}
                        placeholder="Paste a note from your last session to ground the concept in your story..."
                        rows={2}
                        style={{ width: "100%", background: "oklch(0.10 0.02 260)", border: "1px solid oklch(0.25 0.03 240 / 50%)", borderRadius: "4px", color: "oklch(0.75 0.01 240)", fontFamily: "'EB Garamond', serif", fontSize: "0.88rem", padding: "0.5rem 0.65rem", resize: "vertical", outline: "none", boxSizing: "border-box" }}
                      />
                    </div>

                    {/* Roll button */}
                    <button
                      onClick={() => {
                        if (randTokens <= 0 || randomiseMutation.isPending) return;
                        randomiseMutation.mutate({ sessionContext: randContext || undefined });
                      }}
                      disabled={randTokens <= 0 || randomiseMutation.isPending}
                      style={{
                        width: "100%", padding: "0.6rem 1rem",
                        background: randTokens > 0 ? "oklch(0.22 0.06 270)" : "oklch(0.15 0.02 270)",
                        border: `1px solid ${randTokens > 0 ? "oklch(0.55 0.18 270 / 60%)" : "oklch(0.25 0.03 270 / 30%)"}`,
                        borderRadius: "4px",
                        color: randTokens > 0 ? "oklch(0.82 0.15 270)" : "oklch(0.40 0.03 270)",
                        fontFamily: "'Cinzel', serif", fontSize: "0.78rem", letterSpacing: "0.15em", textTransform: "uppercase",
                        cursor: randTokens > 0 ? "pointer" : "not-allowed",
                        transition: "all 0.2s",
                      }}
                    >
                      {randomiseMutation.isPending ? "Rolling the dice..." : randTokens <= 0 ? `No charges — next in ${formatRefill(randNextRefill)}` : "✦ Roll the Dice"}
                    </button>

                    {/* Result card */}
                    {randResult && !randomiseMutation.isPending && (
                      <div className="char-card" style={{ marginTop: "1rem", padding: "1.1rem", background: "oklch(0.10 0.03 270 / 80%)", border: "1px solid oklch(0.45 0.15 270 / 40%)", borderRadius: "6px" }}>
                        {/* Name + archetype header */}
                        <div style={{ display: "flex", justifyContent: "space-between", alignItems: "flex-start", marginBottom: "0.6rem" }}>
                          <div>
                            <div style={{ fontFamily: "'Cinzel Decorative', serif", fontSize: "1.05rem", color: "oklch(0.88 0.12 75)", fontWeight: 700 }}>{randResult.name}</div>
                            <div style={{ fontFamily: "'Courier Prime', monospace", fontSize: "0.65rem", letterSpacing: "0.12em", color: "oklch(0.55 0.01 240)", textTransform: "uppercase", marginTop: "0.15rem" }}>
                              {randResult.race} · {randResult.archetype} · {randResult.age} · {randResult.gender}
                            </div>
                          </div>
                          <div style={{ fontFamily: "'Courier Prime', monospace", fontSize: "0.6rem", letterSpacing: "0.08em", color: "oklch(0.72 0.15 270)", background: "oklch(0.18 0.05 270 / 60%)", border: "1px solid oklch(0.45 0.15 270 / 40%)", borderRadius: "3px", padding: "0.2rem 0.5rem", flexShrink: 0, marginLeft: "0.75rem" }}>
                            {randResult.suggestedRole}
                          </div>
                        </div>

                        {/* Faction */}
                        <div style={{ fontFamily: "'EB Garamond', serif", fontSize: "0.78rem", color: "oklch(0.50 0.01 240)", marginBottom: "0.5rem" }}>
                          <span style={{ fontFamily: "'Courier Prime', monospace", fontSize: "0.6rem", color: "oklch(0.42 0.01 240)", textTransform: "uppercase", letterSpacing: "0.08em" }}>Faction · </span>
                          {randResult.faction}
                        </div>

                        {/* Hook */}
                        <div style={{ fontFamily: "'EB Garamond', serif", fontSize: "0.92rem", color: "oklch(0.78 0.01 240)", lineHeight: 1.65, marginBottom: "0.65rem", paddingLeft: "0.75rem", borderLeft: "2px solid oklch(0.55 0.18 270 / 50%)", fontStyle: "italic" }}>
                          {randResult.hook}
                        </div>

                        {/* Traits */}
                        <div style={{ display: "flex", gap: "0.4rem", flexWrap: "wrap", marginBottom: "0.65rem" }}>
                          {randResult.traits.map((t, i) => (
                            <span key={i} style={{ fontFamily: "'Courier Prime', monospace", fontSize: "0.62rem", letterSpacing: "0.08em", color: "oklch(0.72 0.15 270)", background: "oklch(0.16 0.05 270 / 50%)", border: "1px solid oklch(0.40 0.12 270 / 40%)", borderRadius: "3px", padding: "0.15rem 0.45rem", textTransform: "uppercase" }}>
                              {t}
                            </span>
                          ))}
                        </div>

                        {/* Flavor quote */}
                        <div style={{ fontFamily: "'EB Garamond', serif", fontSize: "0.82rem", color: "oklch(0.48 0.01 240)", fontStyle: "italic", marginBottom: "0.75rem" }}>
                          "{randResult.flavorQuote}"
                        </div>

                        {/* Action buttons row */}
                        <div style={{ display: "flex", gap: "0.5rem" }}>
                          {/* Expand in Forge button */}
                          <button
                            onClick={() => {
                              setGenGender(randResult.gender === "female" ? "female" : randResult.gender === "male" ? "male" : "any");
                              setGenFaction(randResult.faction);
                              setGenArchetype(randResult.archetype);
                              setGenNarrativeSeed(randResult.hook);
                              setGenContext(randContext);
                              setTimeout(() => {
                                document.getElementById("forge-form")?.scrollIntoView({ behavior: "smooth", block: "start" });
                              }, 100);
                            }}
                            style={{ flex: 1, padding: "0.5rem 0.75rem", background: "oklch(0.18 0.04 75)", border: "1px solid oklch(0.72 0.12 75 / 40%)", borderRadius: "4px", color: "oklch(0.82 0.12 75)", fontFamily: "'Cinzel', serif", fontSize: "0.68rem", letterSpacing: "0.12em", textTransform: "uppercase", cursor: "pointer" }}
                          >
                            ⚒ Expand in Forge
                          </button>
                          {/* Save Concept button */}
                          {isAuthenticated ? (
                            <button
                              onClick={() => {
                                if (saveRandMutation.isPending) return;
                                saveRandMutation.mutate({
                                  characterJson: JSON.stringify(randResult),
                                  sessionTag: randContext ? randContext.slice(0, 64) : undefined,
                                  source: "randomiser",
                                });
                              }}
                              disabled={saveRandMutation.isPending}
                              style={{ flex: 1, padding: "0.5rem 0.75rem", background: randSaveSuccess ? "oklch(0.22 0.08 145)" : "oklch(0.14 0.04 145)", border: `1px solid ${randSaveSuccess ? "oklch(0.55 0.15 145 / 70%)" : "oklch(0.35 0.10 145 / 50%)"}`, color: randSaveSuccess ? "oklch(0.78 0.15 145)" : "oklch(0.60 0.12 145)", fontFamily: "'Cinzel', serif", fontSize: "0.68rem", letterSpacing: "0.12em", textTransform: "uppercase", cursor: saveRandMutation.isPending ? "not-allowed" : "pointer", borderRadius: "4px", transition: "all 0.2s" }}
                            >
                              {saveRandMutation.isPending ? "Saving..." : randSaveSuccess ? "✓ Saved!" : "⊕ Save Concept"}
                            </button>
                          ) : (
                            <button
                              onClick={() => { window.location.href = getLoginUrl(); }}
                              style={{ flex: 1, padding: "0.5rem 0.75rem", background: "oklch(0.14 0.03 240)", border: "1px solid oklch(0.30 0.05 240 / 50%)", color: "oklch(0.55 0.05 240)", fontFamily: "'Cinzel', serif", fontSize: "0.68rem", letterSpacing: "0.12em", textTransform: "uppercase", cursor: "pointer", borderRadius: "4px" }}
                            >
                              Sign in to Save
                            </button>
                          )}
                        </div>
                      </div>
                    )}
                  </div>
                </RevealSection>

                {/* ── GENERATION FORM ── */}
                <RevealSection delay={50}>
                  <div id="forge-form" className="lore-card" style={{ padding: "1.5rem", position: "relative", marginBottom: "1.25rem", border: "1px solid oklch(0.72 0.12 75 / 30%)" }}>
                    <CornerOrnaments />
                    <div style={{ fontFamily: "'Cinzel', serif", fontSize: "0.7rem", letterSpacing: "0.2em", color: "oklch(0.72 0.12 75)", textTransform: "uppercase", marginBottom: "1rem" }}>Forge Parameters</div>

                    <div style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: "0.75rem", marginBottom: "0.75rem" }}>
                      {/* Gender */}
                      <div>
                        <label style={formLabelStyle}>Gender</label>
                        <select value={genGender} onChange={e => setGenGender(e.target.value as typeof genGender)} style={formInputStyle}>
                          <option value="any">Any</option>
                          <option value="female">Female</option>
                          <option value="male">Male</option>
                        </select>
                      </div>
                      {/* Age */}
                      <div>
                        <label style={formLabelStyle}>Age Range</label>
                        <select value={genAge} onChange={e => setGenAge(e.target.value)} style={formInputStyle}>
                          <option value="18-25">18 – 25 (Young)</option>
                          <option value="18-40">18 – 40 (Adult)</option>
                          <option value="25-45">25 – 45 (Experienced)</option>
                          <option value="40-60">40 – 60 (Veteran)</option>
                          <option value="60-120">60+ (Elder / Ancient)</option>
                        </select>
                      </div>
                      {/* Tone */}
                      <div>
                        <label style={formLabelStyle}>Narrative Tone</label>
                        <select value={genTone} onChange={e => setGenTone(e.target.value as typeof genTone)} style={formInputStyle}>
                          <option value="neutral">Neutral</option>
                          <option value="heroic">Heroic</option>
                          <option value="tragic">Tragic</option>
                          <option value="mysterious">Mysterious</option>
                        </select>
                      </div>
                      {/* Faction */}
                      <div>
                        <label style={formLabelStyle}>Faction (optional)</label>
                        <input
                          value={genFaction}
                          onChange={e => setGenFaction(e.target.value)}
                          placeholder="e.g. Golden Order, Nox, Volcano Manor..."
                          style={formInputStyle}
                        />
                      </div>
                      {/* Archetype */}
                      <div style={{ gridColumn: "1 / -1" }}>
                        <label style={formLabelStyle}>Archetype / Class (optional)</label>
                        <input
                          value={genArchetype}
                          onChange={e => setGenArchetype(e.target.value)}
                          placeholder="e.g. Sorcerer, Knight, Assassin, Prophet, Wanderer..."
                          style={formInputStyle}
                        />
                      </div>
                      {/* Backstory Depth */}
                      <div>
                        <label style={formLabelStyle}>Backstory Depth</label>
                        <select value={genBackstoryDepth} onChange={e => setGenBackstoryDepth(e.target.value as typeof genBackstoryDepth)} style={formInputStyle}>
                          <option value="brief">Brief (1-2 sentences)</option>
                          <option value="standard">Standard (3-4 sentences)</option>
                          <option value="detailed">Detailed (5-7 sentences)</option>
                          <option value="epic">Epic (full paragraphs)</option>
                        </select>
                      </div>
                      {/* Variant Count */}
                      <div>
                        <label style={formLabelStyle}>Variants to Generate</label>
                        <select value={genVariantCount} onChange={e => setGenVariantCount(Number(e.target.value))} style={formInputStyle}>
                          <option value={1}>1 — Single character</option>
                          <option value={2}>2 — Side by side</option>
                          <option value={3}>3 — Full spread</option>
                        </select>
                      </div>
                      {/* Portrait Style */}
                      <div>
                        <label style={formLabelStyle}>Portrait Style</label>
                        <select value={portraitStyle} onChange={e => setPortraitStyle(e.target.value as typeof portraitStyle)} style={formInputStyle}>
                          <option value="oil_painting">Oil Painting</option>
                          <option value="ink_sketch">Ink Sketch</option>
                          <option value="stained_glass">Stained Glass</option>
                          <option value="manuscript">Manuscript Illumination</option>
                        </select>
                      </div>
                      {/* Relationship Seed */}
                      <div style={{ gridColumn: "1 / -1" }}>
                        <label style={formLabelStyle}>Relationship Seed (optional)</label>
                        <input
                          value={genRelationshipSeed}
                          onChange={e => setGenRelationshipSeed(e.target.value)}
                          placeholder="Name of an existing character — the generated character will have a pre-written connection to them..."
                          style={formInputStyle}
                        />
                      </div>
                      {/* Narrative Seed */}
                      <div style={{ gridColumn: "1 / -1" }}>
                        <label style={formLabelStyle}>Narrative Seed (optional)</label>
                        <input
                          value={genNarrativeSeed}
                          onChange={e => setGenNarrativeSeed(e.target.value)}
                          placeholder="A story hook to weave in, e.g. she was a soldier who deserted after witnessing a massacre..."
                          style={formInputStyle}
                        />
                      </div>
                      {/* Session context */}
                      <div style={{ gridColumn: "1 / -1" }}>
                        <label style={formLabelStyle}>Session Lore Context (optional)</label>
                        <textarea
                          value={genContext}
                          onChange={e => setGenContext(e.target.value)}
                          placeholder="Paste notes from your session log or describe recent events. The Forge will use this to create a character that feels connected to your story..."
                          rows={4}
                          style={{ ...formInputStyle, resize: "vertical", minHeight: "80px" }}
                        />
                      </div>
                    </div>

                    <div style={{ display: "flex", justifyContent: "space-between", alignItems: "center", flexWrap: "wrap", gap: "0.75rem" }}>
                      {/* Cooldown status */}
                      {cooldownRemaining > 0 && !generateMutation.isPending && (
                        <div style={{ display: "flex", alignItems: "center", gap: "0.5rem" }}>
                          <div style={{ width: "120px", height: "4px", background: "oklch(0.20 0.03 260)", borderRadius: "2px", overflow: "hidden" }}>
                            <div style={{
                              width: `${((COOLDOWN_MS - cooldownRemaining) / COOLDOWN_MS) * 100}%`,
                              height: "100%",
                              background: "oklch(0.72 0.12 240)",
                              borderRadius: "2px",
                              transition: "width 1s linear",
                            }} />
                          </div>
                          <span style={{ fontFamily: "'Courier Prime', monospace", fontSize: "0.68rem", color: "oklch(0.55 0.01 240)", letterSpacing: "0.08em" }}>
                            Forge cools in {formatCooldown(cooldownRemaining)}
                          </span>
                        </div>
                      )}
                      {cooldownRemaining <= 0 && !generateMutation.isPending && (
                        <span style={{ fontFamily: "'Courier Prime', monospace", fontSize: "0.68rem", color: "oklch(0.50 0.01 240)", fontStyle: "italic" }}>
                          The Forge is ready.
                        </span>
                      )}
                      <button
                        onClick={() => {
                          if (cooldownRemaining > 0) return;
                          generateMutation.mutate({
                            gender: genGender,
                            ageRange: genAge,
                            faction: genFaction || undefined,
                            archetype: genArchetype || undefined,
                            tone: genTone,
                            sessionContext: genContext || undefined,
                            backstoryDepth: genBackstoryDepth,
                            relationshipSeed: genRelationshipSeed || undefined,
                            narrativeSeed: genNarrativeSeed || undefined,
                            variantCount: genVariantCount,
                          });
                        }}
                        disabled={generateMutation.isPending || cooldownRemaining > 0}
                        style={{
                          fontFamily: "'Cinzel', serif",
                          fontSize: "0.75rem",
                          letterSpacing: "0.15em",
                          textTransform: "uppercase",
                          padding: "0.65rem 1.5rem",
                          background: (generateMutation.isPending || cooldownRemaining > 0) ? "oklch(0.72 0.12 75 / 8%)" : "oklch(0.72 0.12 75 / 12%)",
                          border: `1px solid oklch(0.72 0.12 75 / ${cooldownRemaining > 0 ? "25%" : "60%"})`,
                          color: (generateMutation.isPending || cooldownRemaining > 0) ? "oklch(0.45 0.01 240)" : "oklch(0.72 0.12 75)",
                          cursor: (generateMutation.isPending || cooldownRemaining > 0) ? "not-allowed" : "pointer",
                          transition: "background 0.2s ease, color 0.2s ease, border-color 0.2s ease",
                          display: "flex",
                          alignItems: "center",
                          gap: "0.5rem",
                          marginLeft: "auto",
                        }}
                      >
                        {generateMutation.isPending ? (
                          <>
                            <span style={{ display: "inline-block", animation: "spin 1s linear infinite", fontSize: "0.9rem" }}>✦</span>
                            Forging...
                          </>
                        ) : cooldownRemaining > 0 ? (
                          <>⏳ Cooldown {formatCooldown(cooldownRemaining)}</>
                        ) : (
                          <>✦ Forge Character</>
                        )}
                      </button>
                    </div>

                    {generateMutation.isError && (
                      <div style={{ marginTop: "0.75rem", padding: "0.75rem", background: "oklch(0.65 0.20 25 / 10%)", border: "1px solid oklch(0.65 0.20 25 / 30%)", fontFamily: "'Courier Prime', monospace", fontSize: "0.75rem", color: "oklch(0.65 0.20 25)" }}>
                        Forging failed: {generateMutation.error?.message ?? "Unknown error"}
                      </div>
                    )}
                  </div>
                </RevealSection>

                {/* ── GENERATED CHARACTER RESULT ── */}
                {generatedChar && (
                  <RevealSection delay={0}>
                    {/* Variant selector tabs */}
                    {genVariants.length > 1 && (
                      <div style={{ display: "flex", gap: "0.5rem", marginBottom: "1rem", flexWrap: "wrap" }}>
                        {genVariants.map((v, i) => (
                          <button
                            key={i}
                            onClick={() => {
                              setActiveVariantIndex(i);
                              setGeneratedChar(genVariants[i]);
                              setActiveCharacter(genVariants[i]);
                              setGeneratedPortraitUrl(null);
                              setPortraitForChar(null);
                              portraitTriggeredRef.current = false;
                            }}
                            style={{
                              fontFamily: "'Cinzel', serif",
                              fontSize: "0.65rem",
                              letterSpacing: "0.12em",
                              textTransform: "uppercase",
                              padding: "0.3rem 0.8rem",
                              background: activeVariantIndex === i ? "oklch(0.72 0.12 240 / 15%)" : "transparent",
                              border: `1px solid oklch(0.72 0.12 240 / ${activeVariantIndex === i ? "60%" : "25%"})`,
                              color: activeVariantIndex === i ? "oklch(0.72 0.12 240)" : "oklch(0.50 0.01 240)",
                              cursor: "pointer",
                              transition: "all 0.2s ease",
                            }}
                          >
                            Variant {i + 1} — {String(v.name).split(" ")[0]}
                          </button>
                        ))}
                      </div>
                    )}

                    {/* History navigation */}
                    {genHistory.length > 1 && (
                      <div style={{ display: "flex", alignItems: "center", gap: "0.75rem", marginBottom: "1rem" }}>
                        <span style={{ fontFamily: "'Courier Prime', monospace", fontSize: "0.68rem", color: "oklch(0.50 0.01 240)", letterSpacing: "0.08em" }}>
                          RECORD {historyIndex + 1} / {genHistory.length}
                        </span>
                        <button
                          onClick={() => { const i = Math.min(historyIndex + 1, genHistory.length - 1); setHistoryIndex(i); setGeneratedChar(genHistory[i]); }}
                          disabled={historyIndex >= genHistory.length - 1}
                          style={{ ...formBtnStyle, fontSize: "0.65rem", padding: "0.25rem 0.6rem", color: "oklch(0.55 0.01 240)", borderColor: "oklch(0.30 0.04 240 / 40%)", opacity: historyIndex >= genHistory.length - 1 ? 0.4 : 1 }}
                        >← Older</button>
                        <button
                          onClick={() => { const i = Math.max(historyIndex - 1, 0); setHistoryIndex(i); setGeneratedChar(genHistory[i]); }}
                          disabled={historyIndex <= 0}
                          style={{ ...formBtnStyle, fontSize: "0.65rem", padding: "0.25rem 0.6rem", color: "oklch(0.55 0.01 240)", borderColor: "oklch(0.30 0.04 240 / 40%)", opacity: historyIndex <= 0 ? 0.4 : 1 }}
                        >Newer →</button>
                      </div>
                    )}

                    {/* Character header card */}
                    <div className={`lore-card char-card char-card-enter${pinnedChars.has(String(generatedChar.name)) ? " pinned" : ""}`} style={{ padding: "1.5rem", position: "relative", marginBottom: "1rem", border: "1px solid oklch(0.72 0.12 240 / 30%)" }}>
                      <CornerOrnaments />
                      <div style={{ display: "flex", alignItems: "flex-start", justifyContent: "space-between", gap: "1rem", flexWrap: "wrap" }}>
                        <div style={{ flex: 1 }}>
                          <div style={{ fontFamily: "'Cinzel Decorative', serif", fontSize: "1.3rem", color: "oklch(0.88 0.01 240)", fontWeight: 700, marginBottom: "0.25rem" }}>
                            {String(generatedChar.name)}
                          </div>
                          <div style={{ fontFamily: "'Cinzel', serif", fontSize: "0.75rem", letterSpacing: "0.2em", color: "oklch(0.72 0.12 75)", textTransform: "uppercase" }}>
                            {String(generatedChar.archetype)} · {String(generatedChar.faction)}
                          </div>
                        </div>
                        <div style={{ display: "flex", flexDirection: "column", alignItems: "flex-end", gap: "0.5rem" }}>
                          <div style={{ display: "flex", gap: "0.4rem", flexWrap: "wrap", justifyContent: "flex-end" }}>
                            {[String(generatedChar.race), `Age ${generatedChar.age}`, String(generatedChar.gender)].map(tag => (
                              <span key={tag} className="trait-badge">{tag}</span>
                            ))}
                          </div>
                          {/* Save to Codex */}
                          <div style={{ display: "flex", gap: "0.4rem", alignItems: "center", marginBottom: "0.3rem" }}>
                            <input
                              value={saveSessionTag}
                              onChange={e => setSaveSessionTag(e.target.value)}
                              placeholder="Session tag (optional)"
                              maxLength={64}
                              style={{ background: "oklch(0.10 0.02 260)", border: "1px solid oklch(0.25 0.03 240 / 50%)", borderRadius: "4px", color: "oklch(0.75 0.01 240)", fontFamily: "'EB Garamond', serif", fontSize: "0.78rem", padding: "0.25rem 0.5rem", outline: "none", width: "140px" }}
                            />
                            {isAuthenticated ? (
                              <button
                                onClick={() => {
                                  if (saveCharMutation.isPending) return;
                                  saveCharMutation.mutate({
                                    characterJson: JSON.stringify(generatedChar),
                                    portraitUrl: generatedPortraitUrl ?? undefined,
                                    paramsJson: JSON.stringify({ gender: genGender, ageRange: genAge, faction: genFaction, archetype: genArchetype, tone: genTone, backstoryDepth: genBackstoryDepth }),
                                    sessionTag: saveSessionTag || undefined,
                                    source: "forge",
                                  });
                                }}
                                disabled={saveCharMutation.isPending}
                                style={{ background: saveSuccessId ? "oklch(0.22 0.08 145)" : "oklch(0.18 0.05 145)", border: `1px solid ${saveSuccessId ? "oklch(0.55 0.15 145 / 70%)" : "oklch(0.40 0.12 145 / 50%)"}`, color: saveSuccessId ? "oklch(0.78 0.15 145)" : "oklch(0.65 0.12 145)", cursor: saveCharMutation.isPending ? "not-allowed" : "pointer", padding: "0.25rem 0.65rem", fontSize: "0.72rem", fontFamily: "'Cinzel', serif", letterSpacing: "0.1em", borderRadius: "4px", transition: "all 0.2s", whiteSpace: "nowrap" }}
                              >
                                {saveCharMutation.isPending ? "Saving..." : saveSuccessId ? "✓ Saved!" : "⊕ Save to Codex"}
                              </button>
                            ) : (
                              <button
                                onClick={() => { window.location.href = getLoginUrl(); }}
                                style={{ background: "oklch(0.16 0.04 75)", border: "1px solid oklch(0.45 0.10 75 / 50%)", color: "oklch(0.72 0.12 75)", cursor: "pointer", padding: "0.25rem 0.65rem", fontSize: "0.72rem", fontFamily: "'Cinzel', serif", letterSpacing: "0.1em", borderRadius: "4px", whiteSpace: "nowrap" }}
                              >
                                Sign in to Save
                              </button>
                            )}
                          </div>
                          <div style={{ display: "flex", gap: "0.4rem" }}>
                            {/* Pin / Favourite button */}
                            <button
                              onClick={() => {
                                const name = String(generatedChar.name);
                                setPinnedChars(prev => {
                                  const next = new Set(prev);
                                  if (next.has(name)) next.delete(name); else next.add(name);
                                  localStorage.setItem("lyra_pinned_chars", JSON.stringify(Array.from(next)));
                                  return next;
                                });
                              }}
                              title={pinnedChars.has(String(generatedChar.name)) ? "Unpin character" : "Pin / Favourite"}
                              style={{ background: "transparent", border: "1px solid oklch(0.72 0.12 75 / 30%)", color: pinnedChars.has(String(generatedChar.name)) ? "oklch(0.72 0.12 75)" : "oklch(0.45 0.01 240)", cursor: "pointer", padding: "0.2rem 0.5rem", fontSize: "0.8rem", transition: "all 0.2s ease" }}
                            >
                              {pinnedChars.has(String(generatedChar.name)) ? "★ Pinned" : "☆ Pin"}
                            </button>
                            {/* Regenerate portrait button */}
                            <button
                              onClick={() => {
                                setGeneratedPortraitUrl(null);
                                setPortraitError(null);
                                setPortraitGenerating(true);
                                setPortraitForChar(String(generatedChar.name) + "_regen");
                                portraitTriggeredRef.current = true;
                                portraitMutation.mutate({
                                  name: String(generatedChar.name),
                                  race: String(generatedChar.race),
                                  gender: String(generatedChar.gender),
                                  archetype: String(generatedChar.archetype),
                                  faction: String(generatedChar.faction),
                                  appearance: String(generatedChar.appearance),
                                  age: Number(generatedChar.age),
                                  style: portraitStyle,
                                });
                              }}
                              disabled={portraitGenerating}
                              title="Regenerate portrait"
                              style={{ background: "transparent", border: "1px solid oklch(0.72 0.12 240 / 30%)", color: portraitGenerating ? "oklch(0.40 0.01 240)" : "oklch(0.60 0.08 240)", cursor: portraitGenerating ? "not-allowed" : "pointer", padding: "0.2rem 0.5rem", fontSize: "0.75rem", transition: "all 0.2s ease" }}
                            >
                              {portraitGenerating ? "⧗ Painting..." : "🎨 New Portrait"}
                            </button>
                          </div>
                        </div>
                      </div>
                    </div>

                    {/* Portrait status banner */}
                    {generatedChar && (
                      <div style={{
                        marginBottom: "1rem",
                        padding: "0.75rem 1.25rem",
                        background: generatedPortraitUrl
                          ? "oklch(0.72 0.12 75 / 8%)"
                          : portraitGenerating
                          ? "oklch(0.72 0.12 240 / 8%)"
                          : cooldownRemaining > 0
                          ? "oklch(0.18 0.04 260)"
                          : "oklch(0.18 0.04 260)",
                        border: `1px solid ${
                          generatedPortraitUrl
                            ? "oklch(0.72 0.12 75 / 30%)"
                            : portraitGenerating
                            ? "oklch(0.72 0.12 240 / 30%)"
                            : "oklch(0.30 0.04 240 / 25%)"
                        }`,
                        display: "flex",
                        alignItems: "center",
                        gap: "0.75rem",
                      }}>
                        {generatedPortraitUrl ? (
                          <>
                            <img src={generatedPortraitUrl} alt="portrait thumbnail" style={{ width: "40px", height: "40px", objectFit: "cover", border: "1px solid oklch(0.72 0.12 75 / 40%)" }} />
                            <div>
                              <div style={{ fontFamily: "'Cinzel', serif", fontSize: "0.72rem", color: "oklch(0.72 0.12 75)", letterSpacing: "0.1em", textTransform: "uppercase" }}>AI Portrait Ready</div>
                              <div style={{ fontFamily: "'Courier Prime', monospace", fontSize: "0.65rem", color: "oklch(0.50 0.01 240)", marginTop: "0.2rem" }}>Visible in the portrait panel on the left.</div>
                            </div>
                          </>
                        ) : portraitGenerating ? (
                          <>
                            <span style={{ fontSize: "1.25rem", animation: "spin 2s linear infinite", flexShrink: 0 }}>✦</span>
                            <div>
                              <div style={{ fontFamily: "'Cinzel', serif", fontSize: "0.72rem", color: "oklch(0.72 0.12 240)", letterSpacing: "0.1em", textTransform: "uppercase" }}>Painting Portrait...</div>
                              <div style={{ fontFamily: "'Courier Prime', monospace", fontSize: "0.65rem", color: "oklch(0.50 0.01 240)", marginTop: "0.2rem" }}>The Forge is rendering a portrait. This may take 10–20 seconds.</div>
                            </div>
                          </>
                        ) : cooldownRemaining > 0 ? (
                          <>
                            <div style={{ width: "80px", height: "4px", background: "oklch(0.20 0.03 260)", borderRadius: "2px", overflow: "hidden", flexShrink: 0 }}>
                              <div style={{ width: `${((COOLDOWN_MS - cooldownRemaining) / COOLDOWN_MS) * 100}%`, height: "100%", background: "oklch(0.72 0.12 240)", borderRadius: "2px", transition: "width 1s linear" }} />
                            </div>
                            <div>
                              <div style={{ fontFamily: "'Cinzel', serif", fontSize: "0.72rem", color: "oklch(0.55 0.01 240)", letterSpacing: "0.1em", textTransform: "uppercase" }}>Portrait Pending</div>
                              <div style={{ fontFamily: "'Courier Prime', monospace", fontSize: "0.65rem", color: "oklch(0.45 0.01 240)", marginTop: "0.2rem" }}>Portrait will be painted when the Forge cools — {formatCooldown(cooldownRemaining)} remaining.</div>
                            </div>
                          </>
                        ) : portraitError ? (
                          <>
                            <span style={{ fontSize: "1rem", flexShrink: 0 }}>⚠️</span>
                            <div style={{ fontFamily: "'Courier Prime', monospace", fontSize: "0.68rem", color: "oklch(0.65 0.20 25)" }}>Portrait generation failed. The character data is still available.</div>
                          </>
                        ) : null}
                      </div>
                    )}

                    {/* Two-column detail grid */}
                    <div style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: "0.75rem", marginBottom: "0.75rem" }} className="responsive-grid">
                      {/* Backstory */}
                      <div className="lore-card char-card" style={{ padding: "1.25rem", position: "relative", gridColumn: "1 / -1" }}>
                        <CornerOrnaments />
                        <div style={{ fontFamily: "'Cinzel', serif", fontSize: "0.68rem", letterSpacing: "0.18em", color: "oklch(0.72 0.12 75)", textTransform: "uppercase", marginBottom: "0.6rem" }}>Origin · {String(generatedChar.origin)}</div>
                        <p style={{ fontSize: "0.9rem", lineHeight: 1.8, color: "oklch(0.72 0.01 240)", margin: 0 }}>{String(generatedChar.backstory)}</p>
                      </div>

                      {/* Appearance */}
                      <div className="lore-card char-card" style={{ padding: "1.25rem", position: "relative" }}>
                        <CornerOrnaments />
                        <div style={{ display: "flex", justifyContent: "space-between", alignItems: "center", marginBottom: "0.6rem" }}>
                          <div style={{ fontFamily: "'Cinzel', serif", fontSize: "0.68rem", letterSpacing: "0.18em", color: "oklch(0.72 0.12 75)", textTransform: "uppercase" }}>Appearance</div>
                          <button onClick={() => regenFieldMutation.mutate({ field: "appearance", currentCharacter: generatedChar, backstoryDepth: genBackstoryDepth })} disabled={regenFieldMutation.isPending} style={{ background: "transparent", border: "none", color: "oklch(0.45 0.01 240)", cursor: "pointer", fontSize: "0.65rem", fontFamily: "'Courier Prime', monospace", letterSpacing: "0.08em", padding: "0" }}>{regenFieldMutation.isPending ? "..." : "↻ Reroll"}</button>
                        </div>
                        <p style={{ fontSize: "0.875rem", lineHeight: 1.75, color: "oklch(0.68 0.01 240)", margin: 0 }}>{String(generatedChar.appearance)}</p>
                      </div>

                      {/* Personality */}
                      <div className="lore-card char-card" style={{ padding: "1.25rem", position: "relative" }}>
                        <CornerOrnaments />
                        <div style={{ display: "flex", justifyContent: "space-between", alignItems: "center", marginBottom: "0.6rem" }}>
                          <div style={{ fontFamily: "'Cinzel', serif", fontSize: "0.68rem", letterSpacing: "0.18em", color: "oklch(0.72 0.12 75)", textTransform: "uppercase" }}>Personality</div>
                          <button onClick={() => regenFieldMutation.mutate({ field: "personality", currentCharacter: generatedChar, backstoryDepth: genBackstoryDepth })} disabled={regenFieldMutation.isPending} style={{ background: "transparent", border: "none", color: "oklch(0.45 0.01 240)", cursor: "pointer", fontSize: "0.65rem", fontFamily: "'Courier Prime', monospace", letterSpacing: "0.08em", padding: "0" }}>{regenFieldMutation.isPending ? "..." : "↻ Reroll"}</button>
                        </div>
                        <p style={{ fontSize: "0.875rem", lineHeight: 1.75, color: "oklch(0.68 0.01 240)", margin: 0 }}>{String(generatedChar.personality)}</p>
                        <div style={{ marginTop: "0.75rem", paddingTop: "0.75rem", borderTop: "1px solid oklch(0.25 0.03 240 / 40%)", display: "flex", justifyContent: "space-between", alignItems: "flex-start" }}>
                          <div>
                            <span style={{ fontFamily: "'Courier Prime', monospace", fontSize: "0.65rem", color: "oklch(0.55 0.01 240)", textTransform: "uppercase", letterSpacing: "0.1em" }}>Defining Flaw · </span>
                            <span style={{ fontFamily: "'EB Garamond', serif", fontSize: "0.85rem", color: "oklch(0.65 0.20 25)", fontStyle: "italic" }}>{String(generatedChar.definingFlaw)}</span>
                          </div>
                          <button onClick={() => regenFieldMutation.mutate({ field: "definingFlaw", currentCharacter: generatedChar, backstoryDepth: genBackstoryDepth })} disabled={regenFieldMutation.isPending} style={{ background: "transparent", border: "none", color: "oklch(0.45 0.01 240)", cursor: "pointer", fontSize: "0.65rem", fontFamily: "'Courier Prime', monospace", letterSpacing: "0.08em", padding: "0", flexShrink: 0 }}>{regenFieldMutation.isPending ? "..." : "↻ Reroll"}</button>
                        </div>
                      </div>

                      {/* Motivation */}
                      <div className="lore-card char-card" style={{ padding: "1.25rem", position: "relative" }}>
                        <CornerOrnaments />
                        <div style={{ display: "flex", justifyContent: "space-between", alignItems: "center", marginBottom: "0.6rem" }}>
                          <div style={{ fontFamily: "'Cinzel', serif", fontSize: "0.68rem", letterSpacing: "0.18em", color: "oklch(0.72 0.12 75)", textTransform: "uppercase" }}>Motivation</div>
                          <button onClick={() => regenFieldMutation.mutate({ field: "motivation", currentCharacter: generatedChar, backstoryDepth: genBackstoryDepth })} disabled={regenFieldMutation.isPending} style={{ background: "transparent", border: "none", color: "oklch(0.45 0.01 240)", cursor: "pointer", fontSize: "0.65rem", fontFamily: "'Courier Prime', monospace", letterSpacing: "0.08em", padding: "0" }}>{regenFieldMutation.isPending ? "..." : "↻ Reroll"}</button>
                        </div>
                        <p style={{ fontSize: "0.875rem", lineHeight: 1.75, color: "oklch(0.68 0.01 240)", margin: 0 }}>{String(generatedChar.motivation)}</p>
                      </div>

                      {/* Stats */}
                      <div className="lore-card char-card" style={{ padding: "1.25rem", position: "relative" }}>
                        <CornerOrnaments />
                        <div style={{ fontFamily: "'Cinzel', serif", fontSize: "0.68rem", letterSpacing: "0.18em", color: "oklch(0.72 0.12 75)", textTransform: "uppercase", marginBottom: "0.75rem" }}>Attributes</div>
                        {(() => {
                          if (!generatedChar.stats || typeof generatedChar.stats !== "object") return null;
                          const statsObj = generatedChar.stats as Record<string, unknown>;
                          const justifications = (generatedChar.statJustifications ?? {}) as Record<string, string>;
                          return Object.entries(statsObj).map(([stat, rawVal]) => {
                            const val = Number(rawVal);
                            const justification = justifications[stat];
                            return (
                              <div key={stat} style={{ marginBottom: "0.6rem" }}>
                                <div style={{ display: "flex", alignItems: "center", gap: "0.5rem" }}>
                                  <span style={{ fontFamily: "'Courier Prime', monospace", fontSize: "0.65rem", letterSpacing: "0.08em", color: "oklch(0.55 0.01 240)", textTransform: "uppercase", width: "80px", flexShrink: 0 }}>{stat}</span>
                                  <div style={{ flex: 1, height: "4px", background: "oklch(0.20 0.03 260)", borderRadius: "2px", overflow: "hidden" }}>
                                    <div style={{ width: `${(val / 99) * 100}%`, height: "100%", background: "oklch(0.72 0.12 240)", borderRadius: "2px", boxShadow: "0 0 6px oklch(0.72 0.12 240 / 50%)" }} />
                                  </div>
                                  <span style={{ fontFamily: "'Courier Prime', monospace", fontSize: "0.68rem", color: "oklch(0.72 0.12 240)", width: "24px", textAlign: "right" }}>{val}</span>
                                </div>
                                {justification && (
                                  <div style={{ marginLeft: "88px", marginTop: "0.15rem", fontFamily: "'EB Garamond', serif", fontSize: "0.75rem", color: "oklch(0.48 0.01 240)", fontStyle: "italic", lineHeight: 1.4 }}>
                                    {justification}
                                  </div>
                                )}
                              </div>
                            );
                          });
                        })()}
                      </div>

                      {/* Equipment */}
                      <div className="lore-card char-card" style={{ padding: "1.25rem", position: "relative" }}>
                        <CornerOrnaments />
                        <div style={{ fontFamily: "'Cinzel', serif", fontSize: "0.68rem", letterSpacing: "0.18em", color: "oklch(0.72 0.12 75)", textTransform: "uppercase", marginBottom: "0.75rem" }}>Equipment</div>
                        <div style={{ display: "flex", flexDirection: "column", gap: "0.5rem" }}>
                          <div style={{ display: "flex", gap: "0.5rem", alignItems: "flex-start" }}>
                            <span style={{ fontSize: "0.9rem", flexShrink: 0 }}>⚔️</span>
                            <div>
                              <div style={{ fontFamily: "'Cinzel', serif", fontSize: "0.78rem", color: "oklch(0.80 0.01 240)" }}>{String(generatedChar.primaryWeapon)}</div>
                              {generatedChar.secondaryWeapon != null && generatedChar.secondaryWeapon !== "null" && <div style={{ fontFamily: "'Cinzel', serif", fontSize: "0.75rem", color: "oklch(0.65 0.01 240)", marginTop: "0.2rem" }}>{String(generatedChar.secondaryWeapon)}</div>}
                            </div>
                          </div>
                          <div style={{ display: "flex", gap: "0.5rem", alignItems: "flex-start" }}>
                            <span style={{ fontSize: "0.9rem", flexShrink: 0 }}>📜</span>
                            <div style={{ fontFamily: "'EB Garamond', serif", fontSize: "0.85rem", color: "oklch(0.65 0.01 240)" }}>{String(generatedChar.keepsake)}</div>
                          </div>
                        </div>
                        {/* Traits */}
                        <div style={{ marginTop: "0.75rem", paddingTop: "0.75rem", borderTop: "1px solid oklch(0.25 0.03 240 / 40%)", display: "flex", flexWrap: "wrap", gap: "0.25rem" }}>
                          {Array.isArray(generatedChar.traits) && (generatedChar.traits as string[]).map((t: string) => (
                            <span key={t} className="trait-badge" style={{ marginRight: 0, marginBottom: 0 }}>✦ {t}</span>
                          ))}
                        </div>
                      </div>

                      {/* Connection to Party */}
                      <div className="lore-card char-card" style={{ padding: "1.25rem", position: "relative", gridColumn: "1 / -1", border: "1px solid oklch(0.72 0.12 75 / 25%)" }}>
                        <CornerOrnaments />
                        <div style={{ fontFamily: "'Cinzel', serif", fontSize: "0.68rem", letterSpacing: "0.18em", color: "oklch(0.72 0.12 75)", textTransform: "uppercase", marginBottom: "0.6rem" }}>Connection to Party</div>
                        <p style={{ fontSize: "0.9rem", lineHeight: 1.8, color: "oklch(0.72 0.01 240)", margin: 0, fontStyle: "italic" }}>{String(generatedChar.connectionToLyra ?? generatedChar.connectionToParty ?? "")}</p>
                      </div>
                    </div>
                  </RevealSection>
                )}

                {/* Empty state */}
                {!generatedChar && !generateMutation.isPending && (
                  <RevealSection delay={100}>
                    <div className="lore-card" style={{ padding: "2.5rem", textAlign: "center", position: "relative" }}>
                      <CornerOrnaments />
                      <div style={{ fontSize: "2rem", marginBottom: "0.75rem" }}>⚗️</div>
                      <div style={{ fontFamily: "'Cinzel', serif", fontSize: "0.85rem", color: "oklch(0.50 0.01 240)" }}>The Forge awaits.</div>
                      <div style={{ fontFamily: "'EB Garamond', serif", fontSize: "0.85rem", color: "oklch(0.40 0.01 240)", marginTop: "0.4rem", fontStyle: "italic" }}>Set your parameters above and strike the Forge to breathe life into a new denizen of the Lands Between.</div>
                    </div>
                  </RevealSection>
                )}

                {/* ── SAVED CHARACTERS GALLERY ──────────────────────────────── */}
                <RevealSection delay={0}>
                  <div className="lore-card" style={{ padding: "1.5rem", marginBottom: "1.5rem", position: "relative" }}>
                    <CornerOrnaments />
                    <div style={{ display: "flex", alignItems: "center", justifyContent: "space-between", marginBottom: "1rem", flexWrap: "wrap", gap: "0.5rem" }}>
                      <div style={{ fontFamily: "'Cinzel Decorative', serif", fontSize: "0.9rem", color: "oklch(0.72 0.12 75)", fontWeight: 700 }}>⊕ Codex Archive</div>
                      {!isAuthenticated && (
                        <button onClick={() => { window.location.href = getLoginUrl(); }} style={{ background: "oklch(0.14 0.04 75)", border: "1px solid oklch(0.45 0.10 75 / 50%)", color: "oklch(0.72 0.12 75)", cursor: "pointer", padding: "0.25rem 0.65rem", fontSize: "0.72rem", fontFamily: "'Cinzel', serif", letterSpacing: "0.1em", borderRadius: "4px" }}>Sign in to view saved characters</button>
                      )}
                      {isAuthenticated && (
                        <div style={{ display: "flex", gap: "0.35rem" }}>
                          {(["all", "forge", "randomiser", "pinned"] as const).map(f => (
                            <button key={f} onClick={() => setSavedFilter(f)} style={{ background: savedFilter === f ? "oklch(0.20 0.05 240)" : "transparent", border: `1px solid ${savedFilter === f ? "oklch(0.55 0.10 240 / 60%)" : "oklch(0.25 0.03 240 / 40%)"}`, color: savedFilter === f ? "oklch(0.80 0.08 240)" : "oklch(0.45 0.01 240)", cursor: "pointer", padding: "0.2rem 0.5rem", fontSize: "0.68rem", fontFamily: "'Cinzel', serif", letterSpacing: "0.1em", borderRadius: "3px", textTransform: "capitalize" }}>{f}</button>
                          ))}
                        </div>
                      )}
                    </div>

                    {isAuthenticated && savedLoading && (
                      <div style={{ textAlign: "center", padding: "1.5rem", color: "oklch(0.45 0.01 240)", fontFamily: "'EB Garamond', serif", fontStyle: "italic" }}>Loading archive...</div>
                    )}

                    {isAuthenticated && !savedLoading && (() => {
                      const filtered = (savedChars ?? []).filter(c => {
                        if (savedFilter === "pinned") return c.pinned;
                        if (savedFilter === "forge") return c.source === "forge";
                        if (savedFilter === "randomiser") return c.source === "randomiser";
                        return true;
                      });
                      if (filtered.length === 0) return (
                        <div style={{ textAlign: "center", padding: "2rem", color: "oklch(0.40 0.01 240)", fontFamily: "'EB Garamond', serif", fontStyle: "italic" }}>
                          {savedFilter === "pinned" ? "No pinned characters yet. Pin a generated character to see it here." : "No saved characters yet. Generate a character and click \u2295 Save to Codex."}
                        </div>
                      );
                      return (
                        <div style={{ display: "grid", gridTemplateColumns: "repeat(auto-fill, minmax(260px, 1fr))", gap: "0.75rem" }}>
                          {filtered.map(row => {
                            const char = (() => { try { return JSON.parse(row.characterJson); } catch { return {}; } })();
                            const isDeleting = deleteConfirmId === row.id;
                            return (
                              <div key={row.id} className="char-card" style={{ background: "oklch(0.09 0.02 260)", border: "1px solid oklch(0.22 0.04 240 / 50%)", borderRadius: "6px", padding: "1rem", position: "relative", transition: "border-color 0.2s" }}>
                                {/* Portrait thumbnail */}
                                {row.portraitUrl && (
                                  <img src={row.portraitUrl} alt={String(char.name ?? "")} style={{ width: "100%", height: "120px", objectFit: "cover", borderRadius: "4px", marginBottom: "0.6rem", border: "1px solid oklch(0.25 0.04 240 / 40%)" }} />
                                )}
                                {!row.portraitUrl && (
                                  <div style={{ width: "100%", height: "60px", background: "oklch(0.12 0.03 260)", borderRadius: "4px", marginBottom: "0.6rem", display: "flex", alignItems: "center", justifyContent: "center", color: "oklch(0.30 0.02 240)", fontSize: "1.2rem" }}>✦</div>
                                )}
                                {/* Name + archetype */}
                                <div style={{ fontFamily: "'Cinzel', serif", fontSize: "0.82rem", color: "oklch(0.85 0.01 240)", fontWeight: 700, marginBottom: "0.15rem", lineHeight: 1.3 }}>{String(char.name ?? "Unknown")}</div>
                                <div style={{ fontFamily: "'Cinzel', serif", fontSize: "0.62rem", letterSpacing: "0.12em", color: "oklch(0.72 0.12 75)", textTransform: "uppercase", marginBottom: "0.4rem" }}>{String(char.archetype ?? char.suggestedRole ?? "")}</div>
                                {/* Tags */}
                                <div style={{ display: "flex", gap: "0.3rem", flexWrap: "wrap", marginBottom: "0.5rem" }}>
                                  {[char.race, char.faction, row.source === "randomiser" ? "Concept" : "Forged"].filter(Boolean).map((t, i) => (
                                    <span key={i} className="trait-badge" style={{ fontSize: "0.6rem", padding: "0.1rem 0.4rem" }}>{String(t)}</span>
                                  ))}
                                  {row.sessionTag && <span className="trait-badge" style={{ fontSize: "0.6rem", padding: "0.1rem 0.4rem", background: "oklch(0.18 0.05 270 / 40%)", borderColor: "oklch(0.45 0.10 270 / 40%)", color: "oklch(0.70 0.10 270)" }}>{row.sessionTag}</span>}
                                </div>
                                {/* Hook / backstory preview */}
                                {(char.hook || char.backstory) && (
                                  <div style={{ fontFamily: "'EB Garamond', serif", fontSize: "0.75rem", color: "oklch(0.50 0.01 240)", fontStyle: "italic", marginBottom: "0.5rem", lineHeight: 1.4, overflow: "hidden", display: "-webkit-box", WebkitLineClamp: 2, WebkitBoxOrient: "vertical" }}>"{String(char.hook ?? char.backstory).slice(0, 120)}{String(char.hook ?? char.backstory).length > 120 ? "..." : ""}"</div>
                                )}
                                {/* Date */}
                                <div style={{ fontFamily: "'Courier Prime', monospace", fontSize: "0.62rem", color: "oklch(0.35 0.01 240)", marginBottom: "0.5rem" }}>{new Date(row.createdAt).toLocaleDateString()}</div>
                                {/* Action buttons */}
                                <div style={{ display: "flex", gap: "0.35rem" }}>
                                  <button
                                    onClick={() => togglePinMutation.mutate({ id: row.id, pinned: !row.pinned })}
                                    title={row.pinned ? "Unpin" : "Pin"}
                                    style={{ flex: 1, background: "transparent", border: `1px solid ${row.pinned ? "oklch(0.55 0.12 75 / 50%)" : "oklch(0.25 0.03 240 / 40%)"}`, color: row.pinned ? "oklch(0.72 0.12 75)" : "oklch(0.40 0.01 240)", cursor: "pointer", padding: "0.2rem", fontSize: "0.7rem", borderRadius: "3px", transition: "all 0.2s" }}
                                  >{row.pinned ? "★" : "☆"}</button>
                                  <button
                                    onClick={() => {
                                      setActiveCharacter(char);
                                      setActiveTab("lore");
                                      window.scrollTo({ top: 0, behavior: "smooth" });
                                    }}
                                    title="Load as active character"
                                    style={{ flex: 3, background: "oklch(0.14 0.03 240)", border: "1px solid oklch(0.30 0.06 240 / 40%)", color: "oklch(0.60 0.06 240)", cursor: "pointer", padding: "0.2rem 0.4rem", fontSize: "0.65rem", fontFamily: "'Cinzel', serif", letterSpacing: "0.08em", borderRadius: "3px", transition: "all 0.2s" }}
                                  >Load</button>
                                  {!isDeleting ? (
                                    <button onClick={() => setDeleteConfirmId(row.id)} title="Delete" style={{ flex: 1, background: "transparent", border: "1px solid oklch(0.30 0.08 15 / 40%)", color: "oklch(0.45 0.10 15)", cursor: "pointer", padding: "0.2rem", fontSize: "0.7rem", borderRadius: "3px", transition: "all 0.2s" }}>✕</button>
                                  ) : (
                                    <button onClick={() => deleteCharMutation.mutate({ id: row.id })} style={{ flex: 2, background: "oklch(0.18 0.08 15)", border: "1px solid oklch(0.50 0.15 15 / 60%)", color: "oklch(0.70 0.15 15)", cursor: "pointer", padding: "0.2rem 0.4rem", fontSize: "0.62rem", fontFamily: "'Cinzel', serif", letterSpacing: "0.06em", borderRadius: "3px" }}>Confirm</button>
                                  )}
                                </div>
                              </div>
                            );
                          })}
                        </div>
                      );
                    })()}
                  </div>
                </RevealSection>

                {/* Loading state */}
                {generateMutation.isPending && (
                  <RevealSection delay={0}>
                    <div className="lore-card" style={{ padding: "2.5rem", textAlign: "center", position: "relative" }}>
                      <CornerOrnaments />
                      <div style={{ fontSize: "2rem", marginBottom: "0.75rem", animation: "spin 2s linear infinite", display: "inline-block" }}>✦</div>
                      <div style={{ fontFamily: "'Cinzel', serif", fontSize: "0.85rem", color: "oklch(0.72 0.12 75)" }}>The Forge burns...</div>
                      <div style={{ fontFamily: "'EB Garamond', serif", fontSize: "0.85rem", color: "oklch(0.50 0.01 240)", marginTop: "0.4rem", fontStyle: "italic" }}>Weaving fate from the lore of the Lands Between.</div>
                    </div>
                  </RevealSection>
                )}
              </div>
            )}

          </div>
        </div>

        {/* ── FOOTER ──────────────────────────────────────── */}
        <RevealSection delay={0}>
          <div style={{
            marginTop: "3rem",
            paddingTop: "1.5rem",
            borderTop: "1px solid oklch(0.30 0.04 240 / 30%)",
            textAlign: "center",
          }}>
            <div style={{ fontFamily: "'Cinzel', serif", fontSize: "0.65rem", letterSpacing: "0.3em", color: "oklch(0.40 0.01 240)", textTransform: "uppercase" }}>
              Codex of the Eternal Cities · Nokstella Archive · Character Record
            </div>
            <div style={{ fontFamily: "'Courier Prime', monospace", fontSize: "0.7rem", color: "oklch(0.35 0.01 240)", marginTop: "0.5rem" }}>
              "In eternal anticipation of the coming Age of the Stars."
            </div>
          </div>
        </RevealSection>

      </div>

      {/* Responsive grid style */}
      <style>{`
        @media (max-width: 768px) {
          .responsive-grid {
            grid-template-columns: 1fr !important;
          }
        }
      `}</style>
    </div>
  );
}

// ── Shared form styles ────────────────────────────────────────
const formLabelStyle: React.CSSProperties = {
  display: "block",
  fontFamily: "'Courier Prime', monospace",
  fontSize: "0.68rem",
  letterSpacing: "0.1em",
  textTransform: "uppercase",
  color: "oklch(0.55 0.01 240)",
  marginBottom: "0.35rem",
};

const formInputStyle: React.CSSProperties = {
  width: "100%",
  background: "oklch(0.18 0.04 260)",
  border: "1px solid oklch(0.30 0.04 240 / 40%)",
  color: "oklch(0.82 0.01 240)",
  padding: "0.5rem 0.75rem",
  fontFamily: "'EB Garamond', serif",
  fontSize: "0.9rem",
  outline: "none",
  boxSizing: "border-box" as const,
};

const formBtnStyle: React.CSSProperties = {
  fontFamily: "'Cinzel', serif",
  fontSize: "0.7rem",
  letterSpacing: "0.12em",
  textTransform: "uppercase",
  padding: "0.4rem 0.9rem",
  background: "transparent",
  border: "1px solid",
  cursor: "pointer",
  transition: "background 0.2s ease",
};
