// Korico Dashboard — logged-in home

const { useState, useEffect, useRef, useMemo } = React;

/* ============================================================
   ROOT APP
   ============================================================ */

function App() {
  const [navOpen, setNavOpen] = useState(false);
  const [active, setActive] = useState("home");

  // Tax state lifted so sub-pages share it
  const [taxStatus, setTaxStatus] = useState("parttime");
  const [jobs, setJobs] = useState(SEED_JOBS);
  const [editingJob, setEditingJob] = useState(null);
  const [toast, setToast] = useState("");
  const flash = (m) => { setToast(m); setTimeout(() => setToast(""), 3200); };

  const taxState = { taxStatus, setTaxStatus, jobs, setJobs, editingJob, setEditingJob, flash };

  // Forms state
  const [selectedFormId, setSelectedFormId] = useState(null);
  const [savedFormIds, setSavedFormIds] = useState(new Set());
  const formsState = { selectedFormId, setSelectedFormId, savedFormIds, setSavedFormIds, flash };

  // Chat state — shared between floating button and full chat page
  const [conversations, setConversations] = useState(SEED_CONVERSATIONS);
  const [activeConvId, setActiveConvId] = useState(SEED_CONVERSATIONS[0]?.id || null);
  const [chatContext, setChatContext] = useState(null);
  const chatState = {
    conversations, setConversations,
    activeConvId, setActiveConvId,
    chatContext, setChatContext,
    flash,
  };

  // Map sub-page → parent nav key for sidebar highlight
  const parentKey = ({
    "tax-newjob": "tax", "tax-checklist": "tax", "tax-tasks": "tax", "tax-guides": "tax",
    "forms-detail": "forms",
    "form-fill-d2": "forms",
    "form-fill-occupation": "forms",
    "visa-plan-d2-d10": "visa",
    "visa-f2-calc": "visa",
  })[active] || active;

  return (
    <div style={{ minHeight: "100vh", background: "var(--bg-canvas)" }}>
      <TopNav
        active={parentKey}
        onSelect={(k) => { setActive(k); setNavOpen(false); }}
        onMenu={() => setNavOpen(true)}
        navOpen={navOpen}
        onCloseMobile={() => setNavOpen(false)}
      />
      <Main
        onMenu={() => setNavOpen(true)}
        active={active}
        onNavigate={setActive}
        taxState={taxState}
        formsState={formsState}
        chatState={chatState}
      />
      <Toast text={toast} />
      <FloatingChat onOpenFullPage={() => setActive("chat")} hidden={active === "chat"} />
    </div>
  );
}

/* ============================================================
   TOP NAV  (new shell — replaces the thick left sidebar)
   ============================================================ */

const TOP_NAV = [
  { key: "home", label: "Dashboard" },
  {
    label: "Visa & ARC",
    children: [
      { key: "visa", label: "Visa & status", icon: "id" },
      { key: "arc",  label: "ARC",            icon: "credit-card" },
    ],
  },
  {
    label: "Life in Korea",
    children: [
      { key: "tax",     label: "Tax & work",       icon: "report-money" },
      { key: "housing", label: "Housing & moving", icon: "home" },
      { key: "legal",   label: "Legal & 행정사",   icon: "scale" },
    ],
  },
  { key: "forms", label: "Forms" },
  { key: "chat",  label: "Korico chat" },
];

function TopNav({ active, onSelect, navOpen, onCloseMobile }) {
  const [openMenu, setOpenMenu] = useState(null);
  const ref = useRef(null);

  useEffect(() => {
    const h = (e) => {
      if (ref.current && !ref.current.contains(e.target)) setOpenMenu(null);
    };
    document.addEventListener("mousedown", h);
    return () => document.removeEventListener("mousedown", h);
  }, []);

  const isActive = (item) => {
    if (item.key) return active === item.key;
    if (item.children) return item.children.some((c) => c.key === active);
    return false;
  };

  return (
    <>
      <header style={{
        position: "sticky", top: 0, zIndex: 40,
        background: "rgba(255,255,255,0.85)",
        backdropFilter: "saturate(180%) blur(14px)",
        WebkitBackdropFilter: "saturate(180%) blur(14px)",
        borderBottom: "1px solid var(--border-soft)",
        padding: "12px clamp(20px, 4vw, 40px)",
      }} ref={ref}>
        <div style={{
          maxWidth: 1280, margin: "0 auto",
          display: "grid",
          gridTemplateColumns: "auto 1fr auto",
          alignItems: "center",
          gap: 18,
        }}>
          {/* Logo */}
          <a href="../" style={{
            display: "inline-flex", alignItems: "center",
            textDecoration: "none",
          }}>
            <img src="../docs/images/logo.png" alt="Korico" style={{ height: 32, width: "auto" }} />
          </a>

          {/* Primary nav (center-left, hidden on mobile) */}
          <nav className="tn-primary" style={{
            display: "flex", alignItems: "center", gap: 4,
            justifyContent: "center",
          }}>
            {TOP_NAV.map((item, i) => (
              <TopNavItem
                key={item.label}
                item={item}
                index={i}
                isActive={isActive(item)}
                openMenu={openMenu}
                setOpenMenu={setOpenMenu}
                onSelect={(k) => { onSelect(k); setOpenMenu(null); }}
              />
            ))}
          </nav>

          {/* Right: visa pill + language + profile */}
          <div style={{ display: "flex", alignItems: "center", gap: 10 }}>
            <div className="tn-status" style={{
              display: "inline-flex", alignItems: "center", gap: 8,
              padding: "7px 12px 7px 7px", borderRadius: 99,
              background: "white", border: "1px solid var(--border)",
              fontSize: 11.5, color: "var(--ink)", fontWeight: 500,
            }}>
              <span style={{
                fontSize: 10, fontWeight: 700, letterSpacing: "0.1em",
                background: "var(--ink)", color: "var(--lime)",
                padding: "3px 7px", borderRadius: 6,
              }}>D-2</span>
              <span>ARC · 2026.03.15</span>
            </div>
            <span className="tn-lang" style={{
              padding: "6px 10px", borderRadius: 8,
              background: "var(--bg-soft)", color: "var(--ink)",
              fontSize: 10.5, fontWeight: 700, letterSpacing: "0.12em",
            }}>EN</span>
            <button className="tn-profile" title="Profile" style={{
              width: 34, height: 34, borderRadius: "50%",
              background: "linear-gradient(135deg, #2E8BFF, #7BC0FF)",
              color: "white",
              fontFamily: "var(--font-body)", fontWeight: 700, fontSize: 12,
              display: "inline-flex", alignItems: "center", justifyContent: "center",
              border: "2px solid white",
              boxShadow: "0 4px 10px rgba(11,27,44,0.12)",
            }}>NM</button>
            <button className="tn-hamburger" aria-label="Menu"
              onClick={() => setOpenMenu(openMenu === "mobile" ? null : "mobile")}
              style={{
                display: "none",
                width: 36, height: 36, borderRadius: 10,
                background: "var(--bg-soft)", color: "var(--ink)",
                alignItems: "center", justifyContent: "center",
              }}>
              <i className="ti ti-menu-2" style={{ fontSize: 18 }} />
            </button>
          </div>
        </div>

        {/* Mobile menu sheet */}
        {openMenu === "mobile" && (
          <div className="tn-mobile-sheet" style={{
            background: "white",
            borderTop: "1px solid var(--border-soft)",
            padding: "10px 16px 14px",
            display: "none",
            animation: "fade-up 0.2s ease-out both",
          }}>
            {TOP_NAV.map((item) => (
              <div key={item.label} style={{ borderBottom: "1px solid var(--border-soft)", padding: "8px 0" }}>
                {item.key ? (
                  <button onClick={() => onSelect(item.key)} style={{
                    display: "flex", alignItems: "center", width: "100%",
                    padding: "8px 4px",
                    fontSize: 13, fontWeight: 600,
                    color: active === item.key ? "var(--ink)" : "var(--text-soft)",
                    textAlign: "left",
                  }}>{item.label}</button>
                ) : (
                  <>
                    <div style={{
                      fontSize: 10, fontWeight: 700, color: "var(--text-mute)",
                      letterSpacing: "0.16em", textTransform: "uppercase",
                      padding: "6px 4px 2px",
                    }}>{item.label}</div>
                    {item.children.map((c) => (
                      <button key={c.key} onClick={() => onSelect(c.key)} style={{
                        display: "flex", alignItems: "center", gap: 10, width: "100%",
                        padding: "8px 10px", borderRadius: 8,
                        background: active === c.key ? "var(--bg-soft)" : "transparent",
                        fontSize: 13, fontWeight: 500, color: "var(--ink)",
                        textAlign: "left",
                      }}>
                        <i className={`ti ti-${c.icon}`} style={{ fontSize: 14, color: "var(--text-mute)" }} />
                        {c.label}
                      </button>
                    ))}
                  </>
                )}
              </div>
            ))}
          </div>
        )}

        <style>{`
          @media (max-width: 920px) {
            .tn-primary { display: none !important; }
            .tn-status { display: none !important; }
            .tn-hamburger { display: inline-flex !important; }
            .tn-mobile-sheet { display: block !important; }
          }
          @media (max-width: 560px) {
            .tn-lang { display: none !important; }
          }
        `}</style>
      </header>
    </>
  );
}

function TopNavItem({ item, isActive, openMenu, setOpenMenu, onSelect }) {
  const hasKids = !!item.children;
  const open = hasKids && openMenu === item.label;
  const closeTimer = useRef(null);

  const scheduleClose = () => {
    if (closeTimer.current) clearTimeout(closeTimer.current);
    closeTimer.current = setTimeout(() => setOpenMenu(null), 120);
  };
  const cancelClose = () => {
    if (closeTimer.current) { clearTimeout(closeTimer.current); closeTimer.current = null; }
  };
  useEffect(() => () => { if (closeTimer.current) clearTimeout(closeTimer.current); }, []);

  if (!hasKids) {
    return (
      <button onClick={() => onSelect(item.key)} style={{
        padding: "8px 14px", borderRadius: 99,
        background: isActive ? "var(--ink)" : "transparent",
        color: isActive ? "var(--lime)" : "var(--ink)",
        fontSize: 12.5, fontWeight: isActive ? 600 : 500,
        letterSpacing: "-0.005em",
        transition: "background 0.18s ease, color 0.18s ease",
      }}
        onMouseEnter={(e) => { if (!isActive) e.currentTarget.style.background = "var(--bg-soft)"; }}
        onMouseLeave={(e) => { if (!isActive) e.currentTarget.style.background = "transparent"; }}
      >{item.label}</button>
    );
  }

  return (
    <div
      style={{ position: "relative" }}
      onMouseEnter={() => { cancelClose(); setOpenMenu(item.label); }}
      onMouseLeave={scheduleClose}
    >
      <button
        onClick={() => (open ? setOpenMenu(null) : setOpenMenu(item.label))}
        onFocus={() => { cancelClose(); setOpenMenu(item.label); }}
        style={{
          display: "inline-flex", alignItems: "center", gap: 6,
          padding: "8px 14px", borderRadius: 99,
          background: isActive ? "var(--ink)" : (open ? "var(--bg-soft)" : "transparent"),
          color: isActive ? "var(--lime)" : "var(--ink)",
          fontSize: 12.5, fontWeight: isActive ? 600 : 500,
          letterSpacing: "-0.005em",
          transition: "background 0.18s ease, color 0.18s ease",
        }}
      >
        {item.label}
        <i className={`ti ti-chevron-${open ? "up" : "down"}`} style={{ fontSize: 13, opacity: 0.7 }} />
      </button>

      {/* Invisible bridge so the cursor can travel from button to menu without dropping hover */}
      {open && (
        <div aria-hidden style={{
          position: "absolute", top: "100%", left: 0, right: 0, height: 10,
        }} />
      )}

      {open && (
        <div style={{
          position: "absolute", top: "calc(100% + 8px)", left: 0,
          minWidth: 220,
          background: "white",
          border: "1px solid var(--border-soft)",
          borderRadius: 14,
          padding: 6,
          boxShadow: "0 24px 60px rgba(11,27,44,0.12)",
          zIndex: 50,
          animation: "fade-up 0.18s ease-out both",
        }}>
          {item.children.map((c) => (
            <button key={c.key} onClick={() => { onSelect(c.key); setOpenMenu(null); }} style={{
              display: "flex", alignItems: "center", gap: 10, width: "100%",
              padding: "9px 12px", borderRadius: 10,
              background: "transparent",
              color: "var(--ink)", textAlign: "left",
              fontSize: 13, fontWeight: 500,
              transition: "background 0.15s ease",
            }}
              onMouseEnter={(e) => e.currentTarget.style.background = "var(--bg-soft)"}
              onMouseLeave={(e) => e.currentTarget.style.background = "transparent"}
            >
              <i className={`ti ti-${c.icon}`} style={{ fontSize: 15, color: "var(--text-mute)" }} />
              {c.label}
            </button>
          ))}
        </div>
      )}
    </div>
  );
}

/* ============================================================
   LEGACY SIDEBAR (kept for compatibility — no longer rendered)
   ============================================================ */

const NAV = [
  {
    group: null,
    items: [
      { key: "home",  label: "Overview", icon: "layout-grid" },
      { key: "files", label: "My files", icon: "user-circle" },
    ],
  },
  {
    group: "Visa & ARC",
    items: [
      { key: "visa", label: "Visa & status", icon: "id" },
      { key: "arc", label: "ARC", icon: "credit-card" },
    ],
  },
  {
    group: "Life in Korea",
    items: [
      { key: "tax", label: "Tax & work", icon: "report-money" },
      { key: "housing", label: "Housing & moving", icon: "home" },
      { key: "legal", label: "Legal & 행정사", icon: "scale" },
    ],
  },
  {
    group: "Tools",
    items: [
      { key: "forms", label: "Forms & templates", icon: "file-text" },
      { key: "chat", label: "Korico chat", icon: "message-circle" },
    ],
  },
  {
    group: null,
    items: [
      { key: "settings", label: "Settings", icon: "settings" },
    ],
  },
];

function Sidebar({ open, onClose, active, onSelect }) {
  return (
    <>
      {/* mobile overlay */}
      <div
        onClick={onClose}
        style={{
          position: "fixed", inset: 0, background: "rgba(11,27,44,0.5)",
          opacity: open ? 1 : 0,
          pointerEvents: open ? "auto" : "none",
          transition: "opacity 0.25s ease",
          zIndex: 49,
        }}
        className="sb-overlay"
      />
      <aside style={{
        width: 260, flexShrink: 0,
        background: "var(--side-bg)",
        color: "var(--side-text)",
        padding: "26px 18px 22px",
        display: "flex", flexDirection: "column",
        position: "sticky", top: 0,
        alignSelf: "flex-start",
        height: "100vh",
        zIndex: 50,
      }} className="sb">
        {/* Logo */}
        <a href="../" style={{
          display: "flex", alignItems: "center",
          padding: "0 4px 18px",
          textDecoration: "none",
          borderBottom: "1px solid rgba(255,255,255,0.06)",
          marginBottom: 18,
        }}>
          <img
            src="../docs/images/logo.png"
            alt="Korico"
            style={{
              height: 56, width: "auto",
              filter: "drop-shadow(0 2px 8px rgba(0,0,0,0.35))",
            }}
          />
        </a>

        {/* Nav groups */}
        <nav style={{
          display: "flex", flexDirection: "column", gap: 18,
          flex: 1, overflowY: "auto", paddingRight: 4,
        }}>
          {NAV.map((g, i) => (
            <div key={i}>
              {g.group && (
                <div style={{
                  fontSize: 10, fontWeight: 600,
                  color: "var(--side-mute)",
                  letterSpacing: "0.18em", textTransform: "uppercase",
                  padding: "6px 10px 8px",
                }}>{g.group}</div>
              )}
              <div style={{ display: "flex", flexDirection: "column", gap: 2 }}>
                {g.items.map((it) => (
                  <SideLink key={it.key} item={it} active={active === it.key}
                    onClick={() => onSelect(it.key)} />
                ))}
              </div>
            </div>
          ))}
        </nav>

        {/* User chip */}
        <div style={{
          marginTop: 18, padding: "12px 12px",
          background: "rgba(255,255,255,0.04)",
          borderRadius: 14,
          display: "flex", alignItems: "center", gap: 12,
        }}>
          <div style={{
            width: 36, height: 36, borderRadius: "50%",
            background: "linear-gradient(135deg, #2E8BFF, #7BC0FF)",
            display: "grid", placeItems: "center",
            color: "white", fontWeight: 700, fontSize: 14,
            letterSpacing: "-0.02em",
          }}>NM</div>
          <div style={{ minWidth: 0, flex: 1 }}>
            <div style={{ fontSize: 13, fontWeight: 600, color: "white" }}>Nguyễn M. Anh</div>
            <div style={{ fontSize: 11, color: "var(--side-mute)", marginTop: 1 }}>D-2 student</div>
          </div>
        </div>

        <style>{`
          @media (max-width: 860px) {
            .sb {
              position: fixed !important;
              left: 0; top: 0;
              transform: translateX(${open ? '0' : '-100%'});
              transition: transform 0.3s cubic-bezier(0.2,0.7,0.2,1);
              width: 80vw; max-width: 320px;
            }
          }
          @media (min-width: 861px) {
            .sb-overlay { display: none; }
          }
        `}</style>
      </aside>
    </>
  );
}

function SideLink({ item, active, onClick }) {
  return (
    <button onClick={onClick} style={{
      display: "flex", alignItems: "center", gap: 12,
      padding: "9px 12px",
      borderRadius: 10,
      background: active ? "rgba(212,255,79,0.10)" : "transparent",
      color: active ? "white" : "var(--side-text)",
      fontSize: 13, fontWeight: active ? 600 : 500,
      letterSpacing: "-0.005em",
      textAlign: "left",
      position: "relative",
      transition: "background 0.18s ease, color 0.18s ease",
    }}
      onMouseEnter={(e) => { if (!active) e.currentTarget.style.background = "rgba(255,255,255,0.04)"; }}
      onMouseLeave={(e) => { if (!active) e.currentTarget.style.background = "transparent"; }}>
      {active && (
        <span style={{
          position: "absolute", left: -18, top: 8, bottom: 8,
          width: 3, borderRadius: 3, background: "var(--lime)",
        }} />
      )}
      <i className={`ti ti-${item.icon}`} style={{
        fontSize: 17, color: active ? "var(--lime)" : "var(--side-mute)",
      }} />
      <span>{item.label}</span>
    </button>
  );
}

/* ============================================================
   MAIN
   ============================================================ */

function Main({ onMenu, active, onNavigate, taxState, formsState, chatState }) {
  const page =
    active === "files"   ? <MyFiles />
    : active === "visa"  ? <VisaPage onNavigate={onNavigate} />
    : active === "visa-plan-d2-d10" ? <VisaPlanD2D10Page onNavigate={onNavigate} />
    : active === "visa-f2-calc"     ? <F2CalculatorPage onNavigate={onNavigate} />
    : active === "arc"   ? <ArcPage />
    : active === "tax"            ? <TaxPage onNavigate={onNavigate} taxState={taxState} />
    : active === "tax-newjob"     ? <NewJobPage onNavigate={onNavigate} taxState={taxState} />
    : active === "tax-checklist"  ? <WorkChecklistPage onNavigate={onNavigate} />
    : active === "tax-tasks"      ? <TaxTasksPage onNavigate={onNavigate} />
    : active === "tax-guides"     ? <TaxGuidesPage onNavigate={onNavigate} />
    : active === "housing" ? <HousingPage />
    : active === "legal"   ? <LegalPage />
    : active === "forms"        ? <FormsPage onNavigate={onNavigate} formsState={formsState} />
    : active === "forms-detail" ? <FormDetailPage onNavigate={onNavigate} formsState={formsState} />
    : active === "form-fill-d2" ? <FillD2Page onNavigate={onNavigate} formsState={formsState} />
    : active === "form-fill-occupation" ? <FillOccupationPage onNavigate={onNavigate} formsState={formsState} />
    : active === "chat"  ? <ChatPage onNavigate={onNavigate} chatState={chatState} />
    : <Grid onNavigate={onNavigate} chatState={chatState} />;

  const hideTopBar = active === "form-fill-d2" || active === "form-fill-occupation";
  const isHome = active === "home";
  return (
    <main style={{
      minWidth: 0,
      padding: hideTopBar ? 0 : "clamp(18px, 2.4vh, 28px) clamp(16px, 4vw, 40px) 72px",
      background: "var(--bg-canvas)",
    }}>
      <div style={{ maxWidth: 1280, margin: "0 auto" }}>
        {!hideTopBar && !isHome && <TopBar onMenu={onMenu} active={active} />}
        {page}
      </div>
    </main>
  );
}

function TopBar({ onMenu, active }) {
  const headings = {
    files: { title: "My files", sub: "Everything we know about you — pre-filled and reusable across visa applications." },
    visa:  { title: "Visa & status", sub: "See your current visa, key dates, and Korico's suggested next steps." },
    "visa-plan-d2-d10": { title: "D-2 → D-10 transition plan", sub: "A guided 5-step plan so the switch from student to job-seeker visa never blocks you." },
    "visa-f2-calc": { title: "F-2 points calculator", sub: "Estimate your F-2 long-term residence score based on age, education, Korean ability, income, and family situation." },
    arc:   { title: "ARC", sub: "Keep your foreign registration up to date to avoid fines and immigration problems." },
    tax:   { title: "Tax & work", sub: "Track your jobs, contracts, and basic tax obligations in Korea — Korico gives general guidance only." },
    "tax-newjob":    { title: "Add a job", sub: "Save a new role so Korico can track contracts and tax events for you." },
    "tax-checklist": { title: "Work basics checklist", sub: "Quick checks that the fundamentals of working in Korea are covered." },
    "tax-tasks":     { title: "Tax tasks & deadlines", sub: "Every task Korico has lined up for your tax year." },
    "tax-guides":    { title: "Tax guides for Korea", sub: "Short, plain-language explainers — pick the one closest to your situation." },
    housing: { title: "Housing & moving", sub: "Keep track of your home in Korea, from contracts to address changes." },
    legal:   { title: "Legal & 행정사", sub: "Browse immigration and administrative professionals and save the ones that fit your needs. Korico does not rank or recommend any specific office." },
    forms:   { title: "Forms & templates", sub: "Find the forms you need for visas, ARC, work, housing, and taxes. Korico links to official sources and adds plain-language helper notes." },
    "forms-detail": { title: "Forms & templates", sub: "Read the helper notes, then open the official form or fill it with Korico." },
    chat:    { title: "Korico chat", sub: "A focused workspace for everything you want to ask Korico — visas, housing, tax, contracts." },
  };
  const heading = headings[active] || { title: "Hi, Minh Anh.", sub: "Here's where you are in your Korea journey today." };

  return (
    <div style={{
      display: "flex", alignItems: "center", justifyContent: "space-between",
      gap: 16, marginBottom: 24,
      animation: "fade-up 0.5s cubic-bezier(0.2,0.7,0.2,1) both",
    }}>
      <div style={{ display: "flex", alignItems: "center", gap: 12, minWidth: 0 }}>
        <button onClick={onMenu} className="sb-toggle" style={{
          display: "none",
          width: 40, height: 40, borderRadius: 12,
          background: "white", border: "1px solid var(--border)",
          alignItems: "center", justifyContent: "center",
          color: "var(--ink)",
        }}>
          <i className="ti ti-menu-2" style={{ fontSize: 18 }} />
        </button>
        <div style={{ minWidth: 0 }}>
          <div style={{
            fontSize: "clamp(20px, 2.4vw, 28px)",
            fontWeight: 600, letterSpacing: "-0.02em",
            color: "var(--ink)",
          }}>{heading.title}</div>
          <div style={{
            fontSize: 13, color: "var(--text-mute)", marginTop: 4,
          }}>{heading.sub}</div>
        </div>
      </div>

      <div style={{ display: "flex", alignItems: "center", gap: 10 }}>
        <div style={{
          display: "inline-flex", alignItems: "center", gap: 10,
          padding: "8px 14px 8px 8px",
          borderRadius: 99,
          background: "white", border: "1px solid var(--border)",
          fontSize: 12, color: "var(--ink)", fontWeight: 500,
        }} className="hide-sm">
          <span style={{
            fontSize: 10, fontWeight: 700, letterSpacing: "0.1em",
            background: "var(--ink)", color: "var(--lime)",
            padding: "3px 8px", borderRadius: 6,
          }}>D-2</span>
          <span>Student · ARC valid to 2026.03.15</span>
        </div>
        <button style={{
          width: 40, height: 40, borderRadius: "50%",
          background: "white", border: "1px solid var(--border)",
          display: "inline-flex", alignItems: "center", justifyContent: "center",
        }} title="Profile">
          <i className="ti ti-user" style={{ fontSize: 18, color: "var(--ink)" }} />
        </button>
      </div>

      <style>{`
        @media (max-width: 860px) { .sb-toggle { display: inline-flex !important; }}
        @media (max-width: 720px) { .hide-sm { display: none !important; }}
      `}</style>
    </div>
  );
}

function Grid({ onNavigate, chatState }) {
  return (
    <div style={{
      animation: "fade-up 0.6s cubic-bezier(0.2,0.7,0.2,1) both",
      animationDelay: "0.05s",
    }}>
      {/* Soft greeting strip — replaces the old TopBar inside the new shell */}
      <div style={{
        display: "flex", flexWrap: "wrap", alignItems: "flex-end",
        justifyContent: "space-between", gap: 16, marginBottom: 22,
      }}>
        <div style={{ minWidth: 0 }}>
          <div style={{
            fontSize: 11, fontWeight: 600, color: "var(--text-mute)",
            letterSpacing: "0.18em", textTransform: "uppercase",
          }}>Welcome back</div>
          <div style={{
            fontSize: "clamp(24px, 3vw, 32px)",
            fontWeight: 600, letterSpacing: "-0.025em",
            color: "var(--ink)", marginTop: 6,
            fontFamily: "var(--font-body)",
          }}>
            Hi, Minh Anh — <span style={{
              fontFamily: "var(--font-display)", fontStyle: "italic",
              fontWeight: 400, color: "var(--ink-soft, #4A5A6D)",
            }}>here's your Korea snapshot.</span>
          </div>
        </div>
        <div style={{ display: "flex", alignItems: "center", gap: 8 }}>
          <button
            onClick={() => onNavigate?.("chat")}
            style={{
              display: "inline-flex", alignItems: "center", gap: 8,
              padding: "10px 16px", borderRadius: 99,
              background: "var(--ink)", color: "var(--lime)",
              fontFamily: "var(--font-body)", fontWeight: 700, fontSize: 11,
              letterSpacing: "0.14em", textTransform: "uppercase",
              border: "none", cursor: "pointer",
              transition: "transform 0.18s ease",
            }}
            onMouseEnter={(e) => e.currentTarget.style.transform = "translateY(-1px)"}
            onMouseLeave={(e) => e.currentTarget.style.transform = "translateY(0)"}
          >
            <i className="ti ti-sparkles" style={{ fontSize: 13 }} />
            Open Korico chat
          </button>
        </div>
      </div>

      {/* Two-column Lambda-style layout */}
      <div style={{
        display: "grid",
        gridTemplateColumns: "minmax(0, 0.55fr) minmax(0, 1fr)",
        gap: 22,
        alignItems: "flex-start",
      }} className="dash-2col">
        {/* LEFT — Context / filters card (sticky) */}
        <aside style={{
          position: "sticky", top: 88,
          display: "flex", flexDirection: "column", gap: 14,
          minWidth: 0,
        }} className="dash-left">
          <ContextCard onNavigate={onNavigate} />
        </aside>

        {/* RIGHT — Card stack */}
        <div style={{ display: "flex", flexDirection: "column", gap: 18, minWidth: 0 }}>
          <SlimAskKorico onNavigate={onNavigate} chatState={chatState} />
          <SnapshotRow />
          <JourneyCard />
          <TodoList />
          <DocsStrip />
        </div>

        <style>{`
          @media (max-width: 980px) {
            .dash-2col { grid-template-columns: 1fr !important; }
            .dash-left { position: static !important; }
          }
        `}</style>
      </div>
    </div>
  );
}

/* ------------------------------------------------------------
   CONTEXT CARD — left sticky column for Dashboard (new)
   ------------------------------------------------------------ */
function ContextCard({ onNavigate }) {
  const [focusFilter, setFocusFilter] = useState("all");

  const focusItems = [
    { id: "arc",   label: "ARC renewal",        when: "in 132 days",  tone: "warn",    route: "arc",  icon: "credit-card" },
    { id: "tax",   label: "Year-end tax filing", when: "Jan 2026",     tone: "neutral", route: "tax",  icon: "report-money" },
    { id: "visa",  label: "D-2 → D-10 plan",     when: "Plan ahead",   tone: "info",    route: "visa-plan-d2-d10", icon: "id" },
    { id: "house", label: "전입신고 reminder",     when: "Within 14 days", tone: "warn",  route: "housing", icon: "home" },
  ];
  const filters = [
    { id: "all",   label: "All" },
    { id: "warn",  label: "Soon" },
    { id: "info",  label: "Planning" },
    { id: "neutral", label: "Routine" },
  ];
  const filtered = focusFilter === "all" ? focusItems : focusItems.filter((f) => f.tone === focusFilter);

  return (
    <div style={{
      background: "white",
      border: "1px solid var(--border-soft)",
      borderRadius: 22,
      padding: 20,
      display: "flex", flexDirection: "column", gap: 18,
    }}>
      {/* Profile row */}
      <div style={{ display: "flex", alignItems: "center", gap: 12 }}>
        <div style={{
          width: 46, height: 46, borderRadius: "50%",
          background: "linear-gradient(135deg, #0B1B2C 0%, #1f3a55 100%)",
          color: "var(--lime)",
          display: "inline-flex", alignItems: "center", justifyContent: "center",
          fontWeight: 700, fontSize: 14, letterSpacing: "0.04em",
          flexShrink: 0,
        }}>MA</div>
        <div style={{ minWidth: 0 }}>
          <div style={{
            fontSize: 14, fontWeight: 600, color: "var(--ink)",
            letterSpacing: "-0.01em",
          }}>Minh Anh Nguyễn</div>
          <div style={{
            fontSize: 11.5, color: "var(--text-mute)", marginTop: 2,
          }}>Hanoi, VN · Studying at SNU</div>
        </div>
      </div>

      {/* Visa pill row */}
      <div style={{
        display: "flex", flexWrap: "wrap", gap: 6,
      }}>
        <span style={{
          display: "inline-flex", alignItems: "center", gap: 6,
          padding: "5px 10px", borderRadius: 99,
          background: "var(--ink)", color: "var(--lime)",
          fontSize: 10, fontWeight: 700, letterSpacing: "0.1em",
        }}>D-2 STUDENT</span>
        <span style={{
          display: "inline-flex", alignItems: "center", gap: 6,
          padding: "5px 10px", borderRadius: 99,
          background: "var(--bg-soft)", color: "var(--ink)",
          fontSize: 11, fontWeight: 500,
        }}>
          <i className="ti ti-calendar-event" style={{ fontSize: 12, color: "var(--text-mute)" }} />
          ARC to 2026.03.15
        </span>
      </div>

      <div style={{ height: 1, background: "var(--border-soft)" }} />

      {/* Focus filters */}
      <div>
        <div style={{
          fontSize: 10, fontWeight: 600, color: "var(--text-mute)",
          letterSpacing: "0.18em", textTransform: "uppercase",
          marginBottom: 8,
        }}>Upcoming focus</div>
        <div style={{ display: "flex", flexWrap: "wrap", gap: 6, marginBottom: 12 }}>
          {filters.map((f) => {
            const isOn = focusFilter === f.id;
            return (
              <button
                key={f.id}
                onClick={() => setFocusFilter(f.id)}
                style={{
                  padding: "5px 11px", borderRadius: 99,
                  background: isOn ? "var(--ink)" : "white",
                  color: isOn ? "var(--lime)" : "var(--ink)",
                  border: "1px solid " + (isOn ? "var(--ink)" : "var(--border)"),
                  fontSize: 11, fontWeight: 600, letterSpacing: "-0.005em",
                  cursor: "pointer", transition: "all 0.18s ease",
                }}
              >{f.label}</button>
            );
          })}
        </div>

        {/* Focus list */}
        <div style={{ display: "flex", flexDirection: "column", gap: 6 }}>
          {filtered.length === 0 ? (
            <div style={{ fontSize: 12, color: "var(--text-mute)", padding: "8px 2px" }}>
              Nothing here for this filter.
            </div>
          ) : filtered.map((f) => {
            const toneColors = {
              warn:    { bg: "#FEF3E0", fg: "#A35A00" },
              info:    { bg: "#E8F0FE", fg: "#1A50B8" },
              neutral: { bg: "var(--bg-soft)", fg: "var(--ink)" },
            }[f.tone];
            return (
              <button
                key={f.id}
                onClick={() => onNavigate?.(f.route)}
                style={{
                  display: "flex", alignItems: "center", gap: 10,
                  padding: "10px 12px", borderRadius: 12,
                  background: "white",
                  border: "1px solid var(--border-soft)",
                  textAlign: "left", cursor: "pointer",
                  transition: "all 0.18s ease",
                }}
                onMouseEnter={(e) => {
                  e.currentTarget.style.borderColor = "var(--ink)";
                  e.currentTarget.style.transform = "translateX(2px)";
                }}
                onMouseLeave={(e) => {
                  e.currentTarget.style.borderColor = "var(--border-soft)";
                  e.currentTarget.style.transform = "translateX(0)";
                }}
              >
                <div style={{
                  width: 30, height: 30, borderRadius: 9,
                  background: toneColors.bg, color: toneColors.fg,
                  display: "inline-flex", alignItems: "center", justifyContent: "center",
                  flexShrink: 0,
                }}>
                  <i className={`ti ti-${f.icon}`} style={{ fontSize: 14 }} />
                </div>
                <div style={{ flex: 1, minWidth: 0 }}>
                  <div style={{
                    fontSize: 12.5, fontWeight: 600, color: "var(--ink)",
                    letterSpacing: "-0.005em",
                  }}>{f.label}</div>
                  <div style={{ fontSize: 11, color: "var(--text-mute)", marginTop: 1 }}>{f.when}</div>
                </div>
                <i className="ti ti-arrow-right" style={{ fontSize: 14, color: "var(--text-mute)" }} />
              </button>
            );
          })}
        </div>
      </div>

      <div style={{ height: 1, background: "var(--border-soft)" }} />

      {/* Quick actions */}
      <div>
        <div style={{
          fontSize: 10, fontWeight: 600, color: "var(--text-mute)",
          letterSpacing: "0.18em", textTransform: "uppercase",
          marginBottom: 8,
        }}>Quick actions</div>
        <div style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: 6 }}>
          {[
            { icon: "file-text",     label: "Forms",   route: "forms" },
            { icon: "folder",        label: "My files", route: "files" },
            { icon: "scale",         label: "Legal",   route: "legal" },
            { icon: "report-money",  label: "Tax",     route: "tax" },
          ].map((q) => (
            <button
              key={q.label}
              onClick={() => onNavigate?.(q.route)}
              style={{
                display: "inline-flex", alignItems: "center", gap: 8,
                padding: "10px 12px", borderRadius: 12,
                background: "var(--bg-soft)", color: "var(--ink)",
                border: "1px solid transparent",
                fontSize: 12, fontWeight: 500,
                cursor: "pointer", transition: "all 0.18s ease",
              }}
              onMouseEnter={(e) => {
                e.currentTarget.style.background = "white";
                e.currentTarget.style.borderColor = "var(--ink)";
              }}
              onMouseLeave={(e) => {
                e.currentTarget.style.background = "var(--bg-soft)";
                e.currentTarget.style.borderColor = "transparent";
              }}
            >
              <i className={`ti ti-${q.icon}`} style={{ fontSize: 14, color: "var(--text-mute)" }} />
              {q.label}
            </button>
          ))}
        </div>
      </div>
    </div>
  );
}

/* ------------------------------------------------------------
   SLIM ASK KORICO — compact bar for the right column
   ------------------------------------------------------------ */
function SlimAskKorico({ onNavigate, chatState }) {
  const [text, setText] = useState("");
  const [focused, setFocused] = useState(false);
  const { setConversations, setActiveConvId, setChatContext } = chatState || {};

  const submit = (raw) => {
    const value = (raw ?? text).trim();
    if (!value || !chatState) return;
    const id = "c" + (Date.now() % 100000);
    setConversations((arr) => [
      { id, title: value.length > 42 ? value.slice(0, 42) + "…" : value,
        contexts: [], updated: "Just now",
        messages: [{ who: "user", text: value }] },
      ...arr,
    ]);
    setActiveConvId(id);
    setChatContext(null);
    setText("");
    onNavigate?.("chat");
    setTimeout(() => {
      setConversations((arr) => arr.map((c) => c.id !== id ? c : {
        ...c, messages: [...c.messages, { who: "bot", text: replyFor(value) }],
      }));
    }, 900);
  };

  return (
    <section style={{
      position: "relative",
      background: "linear-gradient(135deg, #FFFFFF 0%, #F7F8FA 100%)",
      border: "1px solid var(--border-soft)",
      borderRadius: 20,
      padding: 18,
      overflow: "hidden",
    }}>
      <span aria-hidden style={{
        position: "absolute", right: -40, top: -40,
        width: 160, height: 160, borderRadius: "50%",
        background: "radial-gradient(circle, rgba(212,255,79,0.22), transparent 70%)",
        pointerEvents: "none",
      }} />
      <div style={{
        display: "flex", alignItems: "center", gap: 8, marginBottom: 10,
        position: "relative",
      }}>
        <i className="ti ti-sparkles" style={{ fontSize: 14, color: "var(--ink)" }} />
        <span style={{
          fontSize: 10, fontWeight: 700, color: "var(--text-mute)",
          letterSpacing: "0.18em", textTransform: "uppercase",
        }}>Ask Korico</span>
      </div>
      <form
        onSubmit={(e) => { e.preventDefault(); submit(); }}
        style={{
          display: "flex", alignItems: "center", gap: 8,
          padding: "5px 5px 5px 16px",
          borderRadius: 99,
          background: "white",
          border: "1.5px solid " + (focused ? "var(--ink)" : "var(--border)"),
          boxShadow: focused ? "0 0 0 4px rgba(212,255,79,0.30)" : "none",
          transition: "border-color 0.2s ease, box-shadow 0.2s ease",
          position: "relative",
        }}
      >
        <input
          value={text}
          onChange={(e) => setText(e.target.value)}
          onFocus={() => setFocused(true)}
          onBlur={() => setFocused(false)}
          placeholder="Ask about visas, housing, tax, contracts…"
          style={{
            flex: 1, border: "none", outline: "none",
            background: "transparent",
            fontFamily: "var(--font-body)",
            fontSize: 14, color: "var(--ink)",
            padding: "10px 4px",
            minWidth: 0,
          }}
        />
        <button
          type="submit" aria-label="Ask Korico"
          disabled={!text.trim()}
          style={{
            display: "inline-flex", alignItems: "center", gap: 6,
            padding: "9px 14px", borderRadius: 99,
            background: text.trim() ? "var(--ink)" : "var(--bg-soft)",
            color: text.trim() ? "var(--lime)" : "var(--text-mute)",
            fontFamily: "var(--font-body)", fontWeight: 700, fontSize: 10.5,
            letterSpacing: "0.16em", textTransform: "uppercase",
            cursor: text.trim() ? "pointer" : "not-allowed",
            border: "none", flexShrink: 0,
          }}
        >
          Ask
          <i className="ti ti-arrow-up" style={{ fontSize: 12 }} />
        </button>
      </form>
      <div style={{
        display: "flex", flexWrap: "wrap", gap: 6, marginTop: 10,
        position: "relative",
      }}>
        {ASK_QUICK_PROMPTS.slice(0, 3).map((q) => (
          <button
            key={q.label}
            onClick={() => submit(q.prompt)}
            style={{
              display: "inline-flex", alignItems: "center", gap: 6,
              padding: "6px 10px", borderRadius: 99,
              background: "white", color: "var(--ink)",
              border: "1px solid var(--border)",
              fontSize: 11, fontWeight: 500,
              cursor: "pointer", transition: "all 0.18s ease",
            }}
            onMouseEnter={(e) => {
              e.currentTarget.style.background = "var(--bg-soft)";
              e.currentTarget.style.borderColor = "var(--ink)";
            }}
            onMouseLeave={(e) => {
              e.currentTarget.style.background = "white";
              e.currentTarget.style.borderColor = "var(--border)";
            }}
          >
            <i className={`ti ti-${q.icon}`} style={{ fontSize: 12, color: "var(--text-mute)" }} />
            {q.label}
          </button>
        ))}
      </div>
    </section>
  );
}

const ASK_QUICK_PROMPTS = [
  { icon: "id",            label: "Check my D-2 deadline",          prompt: "When does my D-2 expire and what should I start preparing now?" },
  { icon: "credit-card",   label: "Update ARC address",             prompt: "I just moved — how do I update my ARC address?" },
  { icon: "report-money",  label: "Year-end tax (연말정산)",         prompt: "How does 연말정산 work for me as a D-2 student with a part-time job?" },
  { icon: "home",          label: "전입신고 quick guide",            prompt: "Do I need 전입신고 for a wolse one-room? Walk me through it." },
];

function AskKoricoHero({ onNavigate, chatState }) {
  const [text, setText] = useState("");
  const [focused, setFocused] = useState(false);
  const { conversations, setConversations, setActiveConvId, setChatContext } = chatState || {};

  const submit = (raw) => {
    const value = (raw ?? text).trim();
    if (!value || !chatState) return;

    // Start a fresh conversation seeded with the user's question
    const id = "c" + (Date.now() % 100000);
    setConversations((arr) => [
      {
        id,
        title: value.length > 42 ? value.slice(0, 42) + "…" : value,
        contexts: [],
        updated: "Just now",
        messages: [{ who: "user", text: value }],
      },
      ...arr,
    ]);
    setActiveConvId(id);
    setChatContext(null);
    setText("");
    onNavigate?.("chat");

    // Schedule the bot reply so it lands shortly after the chat page mounts
    setTimeout(() => {
      setConversations((arr) => arr.map((c) => c.id !== id ? c : {
        ...c,
        messages: [...c.messages, { who: "bot", text: replyFor(value) }],
      }));
    }, 900);
  };

  return (
    <section style={{
      position: "relative",
      background: "linear-gradient(135deg, #FFFFFF 0%, #F6F6F7 100%)",
      border: "1px solid var(--border-soft)",
      borderRadius: 22,
      padding: "clamp(18px, 2.4vh, 24px) clamp(20px, 2.6vw, 28px)",
      overflow: "hidden",
    }}>
      {/* soft lime glow in corner */}
      <span aria-hidden style={{
        position: "absolute", right: -50, top: -50,
        width: 220, height: 220, borderRadius: "50%",
        background: "radial-gradient(circle, rgba(212,255,79,0.25), transparent 70%)",
        pointerEvents: "none",
      }} />

      <div style={{ display: "flex", alignItems: "center", gap: 10, marginBottom: 14, position: "relative" }}>
        <div style={{
          width: 30, height: 30, borderRadius: 9,
          background: "var(--ink)", color: "var(--lime)",
          display: "inline-flex", alignItems: "center", justifyContent: "center",
          flexShrink: 0,
        }}>
          <i className="ti ti-sparkles" style={{ fontSize: 15 }} />
        </div>
        <div style={{ minWidth: 0 }}>
          <div style={{
            fontSize: 10, fontWeight: 600, color: "var(--text-mute)",
            letterSpacing: "0.18em", textTransform: "uppercase",
          }}>Ask Korico</div>
          <div style={{
            fontSize: 13.5, fontWeight: 600, color: "var(--ink)",
            letterSpacing: "-0.005em", marginTop: 1,
          }}>What's on your mind today, Minh Anh?</div>
        </div>
      </div>

      {/* Big search-like pill */}
      <form
        onSubmit={(e) => { e.preventDefault(); submit(); }}
        style={{
          display: "flex", alignItems: "center", gap: 10,
          padding: "6px 6px 6px 18px",
          borderRadius: 99,
          background: "white",
          border: "1.5px solid " + (focused ? "var(--ink)" : "var(--border)"),
          boxShadow: focused ? "0 0 0 4px rgba(212,255,79,0.30)" : "0 1px 0 var(--border-soft)",
          transition: "border-color 0.2s ease, box-shadow 0.2s ease",
          position: "relative",
        }}
      >
        <input
          value={text}
          onChange={(e) => setText(e.target.value)}
          onFocus={() => setFocused(true)}
          onBlur={() => setFocused(false)}
          placeholder="Ask about visas, housing, tax, contracts…"
          style={{
            flex: 1, border: "none", outline: "none",
            background: "transparent",
            fontFamily: "var(--font-body)",
            fontSize: 15, color: "var(--ink)",
            padding: "12px 4px",
            minWidth: 0,
          }}
        />
        <button
          type="submit"
          aria-label="Ask Korico"
          disabled={!text.trim()}
          style={{
            display: "inline-flex", alignItems: "center", gap: 8,
            padding: "11px 18px 11px 16px", borderRadius: 99,
            background: text.trim() ? "var(--ink)" : "var(--bg-soft)",
            color: text.trim() ? "var(--lime)" : "var(--text-mute)",
            fontFamily: "var(--font-body)", fontWeight: 700, fontSize: 11,
            letterSpacing: "0.16em", textTransform: "uppercase",
            cursor: text.trim() ? "pointer" : "not-allowed",
            transition: "background 0.18s ease, color 0.18s ease, transform 0.18s ease",
            flexShrink: 0,
          }}
          onMouseEnter={(e) => { if (text.trim()) e.currentTarget.style.transform = "translateY(-1px)"; }}
          onMouseLeave={(e) => e.currentTarget.style.transform = "translateY(0)"}
        >
          Ask
          <span style={{
            width: 22, height: 22, borderRadius: "50%",
            background: text.trim() ? "var(--lime)" : "white",
            color: text.trim() ? "var(--ink)" : "var(--text-mute)",
            display: "inline-flex", alignItems: "center", justifyContent: "center",
          }}><i className="ti ti-arrow-up" style={{ fontSize: 12 }} /></span>
        </button>
      </form>

      {/* Quick prompt chips */}
      <div style={{
        display: "flex", flexWrap: "wrap", gap: 6, marginTop: 12,
        position: "relative",
      }}>
        {ASK_QUICK_PROMPTS.map((q) => (
          <button
            key={q.label}
            onClick={() => submit(q.prompt)}
            style={{
              display: "inline-flex", alignItems: "center", gap: 7,
              padding: "7px 12px 7px 10px", borderRadius: 99,
              background: "white", color: "var(--ink)",
              border: "1px solid var(--border)",
              fontSize: 11.5, fontWeight: 500, letterSpacing: "-0.005em",
              transition: "background 0.18s ease, border-color 0.18s ease, transform 0.18s ease",
              cursor: "pointer",
            }}
            onMouseEnter={(e) => {
              e.currentTarget.style.background = "var(--bg-soft)";
              e.currentTarget.style.borderColor = "var(--ink)";
              e.currentTarget.style.transform = "translateY(-1px)";
            }}
            onMouseLeave={(e) => {
              e.currentTarget.style.background = "white";
              e.currentTarget.style.borderColor = "var(--border)";
              e.currentTarget.style.transform = "translateY(0)";
            }}
          >
            <i className={`ti ti-${q.icon}`} style={{ fontSize: 13, color: "var(--text-mute)" }} />
            {q.label}
          </button>
        ))}
      </div>
    </section>
  );
}

/* ============================================================
   JOURNEY CARD
   ============================================================ */

const JOURNEY = [
  { id: "arrival", label: "Arrival & ARC", status: "done", icon: "plane-arrival", date: "2024.03" },
  { id: "current", label: "Current visa", status: "active", icon: "id", date: "D-2 · valid to 2026.03" },
  { id: "next",    label: "Next step",     status: "todo",   icon: "arrows-exchange", date: "Prepare D-10" },
  { id: "long",    label: "Long-term goal", status: "todo",  icon: "flag-2", date: "F-2 in 2–3 years" },
];

function JourneyCard() {
  return (
    <SurfaceCard>
      <CardHead
        eyebrow="Journey"
        title="Your Korico journey"
        subtitle="From first visa to long-term stay, track all your steps here."
      />
      <div style={{
        display: "grid", gridTemplateColumns: `repeat(${JOURNEY.length}, 1fr)`,
        gap: 14, alignItems: "stretch",
      }} className="journey-grid">
        {JOURNEY.map((s, i) => (
          <JourneyStep key={s.id} step={s} index={i} last={i === JOURNEY.length - 1} />
        ))}
      </div>

      <style>{`
        @media (max-width: 720px) { .journey-grid { grid-template-columns: 1fr !important; }}
      `}</style>
    </SurfaceCard>
  );
}

function JourneyStep({ step, index, last }) {
  const palette = {
    done:   { bg: "var(--success-soft)",  fg: "var(--success)" },
    active: { bg: "var(--lime)",          fg: "var(--ink)"     },
    todo:   { bg: "var(--bg-soft)",       fg: "var(--text-mute)" },
  }[step.status];

  const statusLabel = { done: "Done", active: "In progress", todo: "Not started" }[step.status];

  return (
    <div style={{
      position: "relative",
      padding: "16px 16px 18px",
      background: step.status === "active" ? "rgba(212,255,79,0.08)" : "var(--bg-soft)",
      borderRadius: 14,
      border: step.status === "active" ? "1px solid rgba(11,27,44,0.10)" : "1px solid var(--border-soft)",
      display: "flex", flexDirection: "column", gap: 10,
      animation: "step-in 0.6s cubic-bezier(0.2,0.7,0.2,1) both",
      animationDelay: `${0.1 + index * 0.1}s`,
    }}>
      <div style={{
        width: 38, height: 38, borderRadius: 10,
        background: palette.bg, color: palette.fg,
        display: "inline-flex", alignItems: "center", justifyContent: "center",
        boxShadow: step.status === "active" ? "0 6px 14px rgba(184,230,60,0.45)" : "none",
      }}>
        <i className={`ti ti-${step.icon}`} style={{ fontSize: 18 }} />
      </div>
      <div style={{
        fontSize: 13, fontWeight: 600, color: "var(--ink)", letterSpacing: "-0.01em",
      }}>{step.label}</div>
      <div style={{ fontSize: 11.5, color: "var(--text-mute)" }}>{step.date}</div>
      <div style={{
        marginTop: "auto", paddingTop: 6,
        display: "inline-flex", alignItems: "center", gap: 6,
        fontSize: 10, fontWeight: 600,
        color: step.status === "done" ? "var(--success)"
              : step.status === "active" ? "var(--ink)"
              : "var(--text-mute)",
        letterSpacing: "0.12em", textTransform: "uppercase",
      }}>
        <span style={{
          width: 6, height: 6, borderRadius: "50%",
          background: step.status === "done" ? "var(--success)"
                    : step.status === "active" ? "var(--ink)"
                    : "var(--border)",
        }} />
        {statusLabel}
      </div>
    </div>
  );
}

/* ============================================================
   SNAPSHOT ROW (3 mini cards)
   ============================================================ */

function SnapshotRow() {
  return (
    <div style={{
      display: "grid", gridTemplateColumns: "repeat(3, 1fr)", gap: 14,
    }} className="snap-grid">
      <SnapshotCard
        eyebrow="Current visa"
        title="D-2 Student"
        sub="Valid until 2026.03.15"
        chip={{ label: "On track", tone: "success" }}
        icon="id"
      />
      <SnapshotCard
        eyebrow="Next deadline"
        title="ARC renewal"
        sub="2026.02.01 · in 132 days"
        chip={{ label: "Plan ahead", tone: "warn" }}
        icon="calendar-event"
      />
      <SnapshotCard
        eyebrow="Risk level"
        title="Low"
        sub="All key documents uploaded"
        chip={{ label: "Healthy", tone: "success" }}
        icon="shield-check"
      />

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

function SnapshotCard({ eyebrow, title, sub, chip, icon }) {
  const chipPalette = {
    success: { bg: "var(--success-soft)", fg: "var(--success)" },
    warn:    { bg: "var(--warning-soft)", fg: "var(--warning)" },
    danger:  { bg: "var(--danger-soft)",  fg: "var(--danger)"  },
  }[chip.tone];

  return (
    <button style={{
      textAlign: "left", padding: 20,
      background: "white",
      borderRadius: 18,
      border: "1px solid var(--border-soft)",
      display: "flex", flexDirection: "column", gap: 10,
      transition: "transform 0.22s ease, box-shadow 0.22s ease, border-color 0.22s ease",
    }}
      onMouseEnter={(e) => {
        e.currentTarget.style.transform = "translateY(-3px)";
        e.currentTarget.style.boxShadow = "var(--shadow-md)";
        e.currentTarget.style.borderColor = "var(--border)";
      }}
      onMouseLeave={(e) => {
        e.currentTarget.style.transform = "translateY(0)";
        e.currentTarget.style.boxShadow = "none";
        e.currentTarget.style.borderColor = "var(--border-soft)";
      }}
    >
      <div style={{
        display: "flex", alignItems: "center", justifyContent: "space-between",
      }}>
        <div style={{
          width: 32, height: 32, borderRadius: 9,
          background: "var(--bg-soft)", color: "var(--ink)",
          display: "inline-flex", alignItems: "center", justifyContent: "center",
        }}>
          <i className={`ti ti-${icon}`} style={{ fontSize: 16 }} />
        </div>
        <span style={{
          padding: "3px 9px", borderRadius: 99,
          background: chipPalette.bg, color: chipPalette.fg,
          fontSize: 10, fontWeight: 700, letterSpacing: "0.08em",
          textTransform: "uppercase",
        }}>{chip.label}</span>
      </div>
      <div>
        <div style={{
          fontSize: 10, fontWeight: 600, color: "var(--text-mute)",
          letterSpacing: "0.18em", textTransform: "uppercase",
        }}>{eyebrow}</div>
        <div style={{
          fontSize: 20, fontWeight: 600, color: "var(--ink)",
          letterSpacing: "-0.015em", marginTop: 4,
        }}>{title}</div>
        <div style={{ fontSize: 12.5, color: "var(--text-mute)", marginTop: 4 }}>{sub}</div>
      </div>
    </button>
  );
}

/* ============================================================
   PROFILE FORM
   ============================================================ */

const CONCERNS = [
  "I'm confused about options",
  "I'm worried about deadlines",
  "Documents are hard",
  "Housing",
  "Work contract",
];

function ProfileForm() {
  const [form, setForm] = useState({
    visa: "D-2",
    country: "VN",
    purpose: "Study",
    goal: "Long-term residence",
    concerns: ["I'm worried about deadlines", "Documents are hard"],
  });
  const [saving, setSaving] = useState(false);
  const [saved, setSaved] = useState(false);

  const toggleConcern = (c) => {
    setForm((f) => ({
      ...f,
      concerns: f.concerns.includes(c)
        ? f.concerns.filter((x) => x !== c)
        : [...f.concerns, c],
    }));
  };

  const submit = (e) => {
    e.preventDefault();
    setSaving(true);
    setTimeout(() => {
      setSaving(false);
      setSaved(true);
      setTimeout(() => setSaved(false), 1800);
    }, 700);
  };

  return (
    <SurfaceCard>
      <CardHead
        eyebrow="Profile"
        title="Tell us about your situation"
        subtitle="Answer a few questions so Korico can guide you better."
      />
      <form onSubmit={submit} style={{ display: "flex", flexDirection: "column", gap: 18 }}>
        <div style={{
          display: "grid", gridTemplateColumns: "1fr 1fr", gap: 14,
        }} className="form-grid">
          <Field label="Current visa type">
            <Select value={form.visa} onChange={(v) => setForm({ ...form, visa: v })}
              options={["D-2", "D-4", "D-10", "E-7", "F-2", "F-6"]} />
          </Field>
          <Field label="Country of citizenship">
            <Select value={form.country} onChange={(v) => setForm({ ...form, country: v })}
              options={["VN", "MN", "ZH", "US", "RU", "TH", "PH", "Other"]} />
          </Field>
          <Field label="Purpose in Korea">
            <Select value={form.purpose} onChange={(v) => setForm({ ...form, purpose: v })}
              options={["Study", "Work", "Job search", "Startup", "Family"]} />
          </Field>
          <Field label="Long-term goal">
            <Select value={form.goal} onChange={(v) => setForm({ ...form, goal: v })}
              options={["Stay 1–2 years", "Long-term residence", "Permanent (F-5)", "Not sure yet"]} />
          </Field>
        </div>

        <Field label="Main concerns">
          <div style={{ display: "flex", flexWrap: "wrap", gap: 8 }}>
            {CONCERNS.map((c) => {
              const on = form.concerns.includes(c);
              return (
                <button key={c} type="button" onClick={() => toggleConcern(c)} style={{
                  padding: "8px 14px", borderRadius: 99,
                  fontSize: 12, fontWeight: 600,
                  background: on ? "var(--ink)" : "white",
                  color: on ? "var(--lime)" : "var(--ink)",
                  border: `1px solid ${on ? "var(--ink)" : "var(--border)"}`,
                  transition: "all 0.18s ease",
                  letterSpacing: "-0.005em",
                }}>{c}</button>
              );
            })}
          </div>
        </Field>

        <div style={{ display: "flex", alignItems: "center", justifyContent: "space-between", gap: 12 }}>
          <div style={{
            fontSize: 12, color: saved ? "var(--success)" : "var(--text-mute)",
            transition: "color 0.25s ease",
          }}>
            {saved ? "Saved. Korico will tailor your next steps." : "We never share your answers with third parties."}
          </div>
          <button type="submit" disabled={saving} style={{
            display: "inline-flex", alignItems: "center", gap: 10,
            padding: "11px 20px", borderRadius: 99,
            background: "var(--lime)", color: "var(--ink)",
            fontFamily: "var(--font-body)", fontWeight: 700, fontSize: 12,
            letterSpacing: "0.16em", textTransform: "uppercase",
            boxShadow: "0 10px 22px rgba(184,230,60,0.35)",
            opacity: saving ? 0.65 : 1, cursor: saving ? "wait" : "pointer",
            transition: "transform 0.18s ease, opacity 0.2s ease",
          }}
            onMouseEnter={(e) => !saving && (e.currentTarget.style.transform = "translateY(-1px)")}
            onMouseLeave={(e) => e.currentTarget.style.transform = "translateY(0)"}
          >
            {saving ? "Saving…" : "Save profile"}
            <span style={{
              width: 20, height: 20, borderRadius: "50%",
              background: "var(--ink)", color: "var(--lime)",
              display: "inline-flex", alignItems: "center", justifyContent: "center",
            }}><i className="ti ti-arrow-up-right" style={{ fontSize: 11 }} /></span>
          </button>
        </div>

        <style>{`
          @media (max-width: 640px) { .form-grid { grid-template-columns: 1fr !important; }}
        `}</style>
      </form>
    </SurfaceCard>
  );
}

function Field({ label, children }) {
  return (
    <label style={{ display: "flex", flexDirection: "column", gap: 8 }}>
      <span style={{
        fontSize: 10, fontWeight: 600, color: "var(--text-mute)",
        letterSpacing: "0.18em", textTransform: "uppercase",
      }}>{label}</span>
      {children}
    </label>
  );
}

function Select({ value, onChange, options }) {
  return (
    <div style={{ position: "relative" }}>
      <select value={value} onChange={(e) => onChange(e.target.value)} style={{
        width: "100%",
        padding: "11px 38px 11px 14px",
        borderRadius: 12,
        border: "1px solid var(--border)",
        background: "white",
        fontSize: 14, color: "var(--ink)",
        appearance: "none", WebkitAppearance: "none",
      }}>
        {options.map((o) => <option key={o} value={o}>{o}</option>)}
      </select>
      <i className="ti ti-chevron-down" style={{
        position: "absolute", right: 12, top: "50%", transform: "translateY(-50%)",
        fontSize: 16, color: "var(--text-mute)", pointerEvents: "none",
      }} />
    </div>
  );
}

/* ============================================================
   CHAT CARD
   ============================================================ */

const SEED_MESSAGES = [
  { who: "bot", text: "Hi Minh Anh — what's on your mind today?" },
  { who: "user", text: "I'm on D-2 now but thinking about D-10. What should I prepare?" },
  { who: "bot", text: "Great timing. You'll typically want: graduation certificate, recent transcript, your ARC, and proof of job search activity. Want me to add a checklist to your todo?" },
];

const QUICK = [
  "Check my next deadline",
  "What documents am I missing?",
  "Help with housing contract",
];

function FloatingChat({ onOpenFullPage, hidden }) {
  const [open, setOpen] = useState(false);
  const [unread, setUnread] = useState(1);
  const [msgs, setMsgs] = useState(SEED_MESSAGES);
  const [text, setText] = useState("");
  const [typing, setTyping] = useState(false);
  const scrollRef = useRef(null);

  useEffect(() => {
    if (open && scrollRef.current) {
      scrollRef.current.scrollTop = scrollRef.current.scrollHeight;
    }
  }, [msgs, typing, open]);

  useEffect(() => {
    if (open) setUnread(0);
  }, [open]);

  // close on Escape
  useEffect(() => {
    if (!open) return;
    const h = (e) => { if (e.key === "Escape") setOpen(false); };
    window.addEventListener("keydown", h);
    return () => window.removeEventListener("keydown", h);
  }, [open]);

  // listen for external "open chat with prefilled text" events
  useEffect(() => {
    const h = (e) => {
      const prefill = e.detail?.prefill || "";
      setOpen(true);
      if (prefill) setText(prefill);
    };
    window.addEventListener("korico:ask", h);
    return () => window.removeEventListener("korico:ask", h);
  }, []);

  const send = (raw) => {
    const value = (raw ?? text).trim();
    if (!value) return;
    setMsgs((m) => [...m, { who: "user", text: value }]);
    setText("");
    setTyping(true);
    setTimeout(() => {
      setTyping(false);
      setMsgs((m) => [...m, { who: "bot", text: replyFor(value) }]);
    }, 900);
  };

  if (hidden) return null;

  return (
    <>
      {/* Floating launcher button */}
      <button
        onClick={() => setOpen((o) => !o)}
        aria-label={open ? "Close Korico chat" : "Open Korico chat"}
        style={{
          position: "fixed",
          right: 24, bottom: 24,
          width: 60, height: 60,
          borderRadius: "50%",
          background: open ? "var(--ink)" : "var(--lime)",
          color: open ? "var(--lime)" : "var(--ink)",
          display: "inline-flex", alignItems: "center", justifyContent: "center",
          boxShadow: open
            ? "0 18px 40px rgba(11,27,44,0.30)"
            : "0 18px 40px rgba(184,230,60,0.50)",
          transition: "background 0.22s ease, color 0.22s ease, transform 0.22s ease, box-shadow 0.22s ease",
          zIndex: 60,
        }}
        onMouseEnter={(e) => e.currentTarget.style.transform = "translateY(-2px) scale(1.03)"}
        onMouseLeave={(e) => e.currentTarget.style.transform = "translateY(0) scale(1)"}
      >
        <i className={open ? "ti ti-x" : "ti ti-message-circle"} style={{ fontSize: 24 }} />
        {!open && unread > 0 && (
          <span style={{
            position: "absolute", top: 4, right: 4,
            width: 18, height: 18, borderRadius: "50%",
            background: "var(--ink)", color: "var(--lime)",
            fontSize: 10, fontWeight: 700,
            display: "inline-flex", alignItems: "center", justifyContent: "center",
            boxShadow: "0 4px 10px rgba(11,27,44,0.25)",
          }}>{unread}</span>
        )}
      </button>

      {/* Floating panel */}
      <div
        role="dialog"
        aria-label="Korico chat"
        aria-hidden={!open}
        style={{
          position: "fixed",
          right: 24, bottom: 100,
          width: "min(380px, calc(100vw - 32px))",
          height: "min(560px, calc(100vh - 140px))",
          background: "white",
          border: "1px solid var(--border)",
          borderRadius: 22,
          boxShadow: "0 32px 80px rgba(11,27,44,0.25), 0 8px 24px rgba(11,27,44,0.08)",
          display: "flex", flexDirection: "column",
          overflow: "hidden",
          zIndex: 59,
          transformOrigin: "bottom right",
          transform: open ? "translateY(0) scale(1)" : "translateY(12px) scale(0.96)",
          opacity: open ? 1 : 0,
          pointerEvents: open ? "auto" : "none",
          transition: "transform 0.28s cubic-bezier(0.2,0.7,0.2,1), opacity 0.24s ease",
        }}
      >
        {/* Header */}
        <div style={{
          padding: "16px 18px",
          background: "var(--ink)",
          color: "white",
          display: "flex", alignItems: "center", gap: 12,
        }}>
          <div style={{
            width: 36, height: 36, borderRadius: 10,
            background: "var(--lime)", color: "var(--ink)",
            display: "inline-flex", alignItems: "center", justifyContent: "center",
            fontWeight: 700, fontSize: 14, letterSpacing: "-0.04em",
          }}>K</div>
          <div style={{ flex: 1, minWidth: 0 }}>
            <div style={{ fontSize: 14, fontWeight: 600, letterSpacing: "-0.01em" }}>
              Korico chat
            </div>
            <div style={{
              fontSize: 11, color: "rgba(255,255,255,0.6)",
              marginTop: 2, display: "inline-flex", alignItems: "center", gap: 6,
            }}>
              <span style={{
                width: 6, height: 6, borderRadius: "50%", background: "var(--lime)",
                animation: "pulse-dot 1.6s ease-in-out infinite",
              }} />
              Online · usually replies instantly
            </div>
          </div>
          {onOpenFullPage && (
            <button onClick={() => { setOpen(false); onOpenFullPage(); }}
              aria-label="Open in full page"
              title="Open in full page"
              style={{
                width: 32, height: 32, borderRadius: 8,
                background: "rgba(255,255,255,0.06)", color: "white",
                display: "inline-flex", alignItems: "center", justifyContent: "center",
                marginRight: 6,
              }}
              onMouseEnter={(e) => e.currentTarget.style.background = "rgba(255,255,255,0.12)"}
              onMouseLeave={(e) => e.currentTarget.style.background = "rgba(255,255,255,0.06)"}
            >
              <i className="ti ti-arrow-up-right" style={{ fontSize: 14 }} />
            </button>
          )}
          <button onClick={() => setOpen(false)} aria-label="Close" style={{
            width: 32, height: 32, borderRadius: 8,
            background: "rgba(255,255,255,0.06)", color: "white",
            display: "inline-flex", alignItems: "center", justifyContent: "center",
          }}
            onMouseEnter={(e) => e.currentTarget.style.background = "rgba(255,255,255,0.12)"}
            onMouseLeave={(e) => e.currentTarget.style.background = "rgba(255,255,255,0.06)"}
          >
            <i className="ti ti-minus" style={{ fontSize: 16 }} />
          </button>
        </div>

        {/* Messages */}
        <div ref={scrollRef} style={{
          flex: 1, overflowY: "auto",
          padding: "16px 16px 8px",
          background: "var(--bg-canvas)",
          display: "flex", flexDirection: "column", gap: 10,
        }}>
          {msgs.map((m, i) => <Bubble key={i} m={m} />)}
          {typing && (
            <div style={{
              alignSelf: "flex-start",
              padding: "10px 14px", borderRadius: "16px 16px 16px 6px",
              background: "white", border: "1px solid var(--border-soft)",
              display: "inline-flex", gap: 6, alignItems: "center",
            }}>
              <Dot delay={0} /><Dot delay={0.15} /><Dot delay={0.3} />
            </div>
          )}
        </div>

        {/* Quick chips */}
        <div style={{
          display: "flex", flexWrap: "wrap", gap: 6,
          padding: "10px 14px 4px",
          background: "var(--bg-canvas)",
        }}>
          {QUICK.map((q) => (
            <button key={q} onClick={() => send(q)} style={{
              padding: "6px 12px", borderRadius: 99,
              background: "white", color: "var(--ink)",
              fontSize: 11.5, fontWeight: 500,
              border: "1px solid var(--border)",
              transition: "background 0.18s ease, border-color 0.18s ease",
            }}
              onMouseEnter={(e) => { e.currentTarget.style.background = "var(--lime)"; e.currentTarget.style.borderColor = "var(--lime)"; }}
              onMouseLeave={(e) => { e.currentTarget.style.background = "white"; e.currentTarget.style.borderColor = "var(--border)"; }}
            >{q}</button>
          ))}
        </div>

        {/* Input */}
        <form onSubmit={(e) => { e.preventDefault(); send(); }} style={{
          padding: "10px 14px 14px",
          background: "var(--bg-canvas)",
        }}>
          <div style={{
            display: "flex", alignItems: "center", gap: 8,
            padding: "6px 6px 6px 16px",
            borderRadius: 99,
            background: "white",
            border: "1px solid var(--border)",
            transition: "box-shadow 0.2s ease, border-color 0.2s ease",
          }}
            onFocus={(e) => {
              e.currentTarget.style.borderColor = "var(--ink)";
              e.currentTarget.style.boxShadow = "0 0 0 3px rgba(212,255,79,0.25)";
            }}
            onBlur={(e) => {
              e.currentTarget.style.borderColor = "var(--border)";
              e.currentTarget.style.boxShadow = "none";
            }}
          >
            <input
              type="text"
              value={text}
              onChange={(e) => setText(e.target.value)}
              placeholder="Ask about visas, housing, or contracts…"
              style={{
                flex: 1, border: "none", outline: "none",
                background: "transparent",
                fontSize: 14, color: "var(--ink)",
                padding: "9px 4px",
              }}
            />
            <button type="submit" aria-label="Send" style={{
              width: 34, height: 34, borderRadius: "50%",
              background: "var(--ink)", color: "var(--lime)",
              display: "inline-flex", alignItems: "center", justifyContent: "center",
              flexShrink: 0,
              transition: "transform 0.18s ease",
            }}
              onMouseEnter={(e) => e.currentTarget.style.transform = "translateY(-1px)"}
              onMouseLeave={(e) => e.currentTarget.style.transform = "translateY(0)"}
            >
              <i className="ti ti-arrow-up" style={{ fontSize: 15 }} />
            </button>
          </div>
        </form>
      </div>
    </>
  );
}

function Bubble({ m }) {
  const isUser = m.who === "user";
  return (
    <div style={{
      alignSelf: isUser ? "flex-end" : "flex-start",
      maxWidth: "82%",
      padding: "10px 14px",
      borderRadius: isUser ? "16px 16px 6px 16px" : "16px 16px 16px 6px",
      background: isUser ? "var(--ink)" : "var(--bg-soft)",
      color: isUser ? "white" : "var(--ink)",
      fontSize: 13.5, lineHeight: 1.5,
      animation: "fade-up 0.32s cubic-bezier(0.2,0.7,0.2,1) both",
    }}>{m.text}</div>
  );
}

function Dot({ delay }) {
  return (
    <span style={{
      width: 6, height: 6, borderRadius: "50%",
      background: "var(--text-mute)",
      animation: "typing 1s ease-in-out infinite",
      animationDelay: `${delay}s`,
    }} />
  );
}

function StatusDot() {
  return (
    <span style={{
      display: "inline-flex", alignItems: "center", gap: 6,
      fontSize: 11, color: "var(--success)", fontWeight: 600,
    }}>
      <span style={{
        width: 7, height: 7, borderRadius: "50%", background: "var(--success)",
        animation: "pulse-dot 1.6s ease-in-out infinite",
      }} />
      Online
    </span>
  );
}

function replyFor(q) {
  const low = q.toLowerCase();
  if (low.includes("deadline")) return "Your closest deadline is ARC renewal on 2026.02.01 — 132 days away. I'll remind you 30 days before.";
  if (low.includes("document") || low.includes("missing")) return "You're at 7 of 12 documents. The two most important to add next: passport scan and university enrollment letter.";
  if (low.includes("housing") || low.includes("contract")) return "Send me a photo of the contract and I'll flag the deposit, term, and exit clauses in your language.";
  if (low.includes("d-10") || low.includes("d10")) return "For D-2 → D-10 you'll need a graduation certificate, transcript, ARC, and proof of job search. Want me to add it as a checklist?";
  return "Got it. I'll prep a short answer with the documents and timing — give me a second.";
}

/* ============================================================
   TODO LIST
   ============================================================ */

const SEED_TODOS = [
  { id: "passport", label: "Upload passport scan (D-2 docs)", due: "Recommended this week", done: false },
  { id: "arc",      label: "Add ARC expiration date",         due: "Quick · 2 min",          done: true },
  { id: "house",    label: "Scan housing contract",           due: "Before 2026.02.01",      done: false },
  { id: "guide",    label: "Read guide: First visit to immigration office", due: "When you can", done: false },
];

function TodoList() {
  const [items, setItems] = useState(SEED_TODOS);
  const toggle = (id) => setItems((arr) => arr.map((x) => x.id === id ? { ...x, done: !x.done } : x));
  const done = items.filter((x) => x.done).length;

  return (
    <SurfaceCard>
      <CardHead
        eyebrow="Today"
        title="Today's tasks"
        subtitle="Small steps add up. Korico keeps the order for you."
        right={
          <span style={{
            fontSize: 11, color: "var(--text-mute)", fontWeight: 500,
          }}>{done}/{items.length} done</span>
        }
      />
      <div style={{ display: "flex", flexDirection: "column", gap: 8 }}>
        {items.map((it) => (
          <TodoRow key={it.id} item={it} onToggle={() => toggle(it.id)} />
        ))}
      </div>
    </SurfaceCard>
  );
}

function TodoRow({ item, onToggle }) {
  return (
    <button onClick={onToggle} style={{
      display: "flex", alignItems: "center", gap: 12,
      padding: "12px 14px", borderRadius: 14,
      background: item.done ? "var(--bg-soft)" : "white",
      border: "1px solid " + (item.done ? "var(--border-soft)" : "var(--border)"),
      textAlign: "left", width: "100%",
      transition: "background 0.2s ease, border-color 0.2s ease",
    }}>
      <span style={{
        width: 22, height: 22, borderRadius: 7,
        background: item.done ? "var(--ink)" : "white",
        border: item.done ? "none" : "1.5px solid var(--border)",
        display: "inline-flex", alignItems: "center", justifyContent: "center",
        color: "var(--lime)",
        flexShrink: 0,
        transition: "background 0.2s ease, border-color 0.2s ease",
      }}>
        {item.done && (
          <i className="ti ti-check" style={{
            fontSize: 14, animation: "check-pop 0.3s cubic-bezier(0.2,1.4,0.4,1) both",
          }} />
        )}
      </span>
      <div style={{ flex: 1, minWidth: 0 }}>
        <div style={{
          fontSize: 13.5, fontWeight: 500,
          color: item.done ? "var(--text-mute)" : "var(--ink)",
          textDecoration: item.done ? "line-through" : "none",
          letterSpacing: "-0.005em",
        }}>{item.label}</div>
        <div style={{ fontSize: 11, color: "var(--text-mute)", marginTop: 2 }}>{item.due}</div>
      </div>
    </button>
  );
}

/* ============================================================
   DOCS STRIP
   ============================================================ */

function DocsStrip() {
  const total = 12, done = 7;
  const pct = Math.round((done / total) * 100);
  return (
    <SurfaceCard style={{ display: "flex", flexDirection: "column", gap: 14 }}>
      <div style={{ display: "flex", alignItems: "center", justifyContent: "space-between" }}>
        <div>
          <div style={{
            fontSize: 10, fontWeight: 600, color: "var(--text-mute)",
            letterSpacing: "0.18em", textTransform: "uppercase",
          }}>Documents</div>
          <div style={{
            fontSize: 16, fontWeight: 600, color: "var(--ink)",
            letterSpacing: "-0.015em", marginTop: 4,
          }}>{done} of {total} uploaded</div>
        </div>
        <a href="#docs" style={{
          fontSize: 12, fontWeight: 600, color: "var(--ink)",
          textDecoration: "none", display: "inline-flex", alignItems: "center", gap: 6,
        }}>
          Open documents
          <i className="ti ti-arrow-up-right" style={{ fontSize: 14 }} />
        </a>
      </div>
      <div style={{
        height: 8, background: "var(--bg-soft)",
        borderRadius: 99, overflow: "hidden",
      }}>
        <div style={{
          width: `${pct}%`, height: "100%",
          background: "linear-gradient(90deg, var(--lime), var(--lime-deep))",
          borderRadius: 99,
          transition: "width 0.6s cubic-bezier(0.2,0.7,0.2,1)",
        }} />
      </div>
    </SurfaceCard>
  );
}

/* ============================================================
   MY FILES — pre-filled profile vault
   ============================================================ */

const FILE_DATA = {
  identity: {
    title: "Core identity",
    icon: "user",
    note: "Reused across every visa type.",
    rows: [
      ["Full legal name", "Nguyễn Minh Anh"],
      ["Date of birth", "2002.05.14"],
      ["Nationality", "Vietnam"],
      ["Country of birth", "Vietnam"],
      ["Passport number", "N12345678"],
      ["Passport issue date", "2022.01.10"],
      ["Passport expiry", "2032.01.09"],
      ["Gender", "Female"],
      ["Profile photo", { kind: "file", label: "passport-photo.jpg", meta: "2.4 MB · verified" }],
      ["Current country of residence", "South Korea"],
      ["Phone", "+82 10-1234-5678"],
      ["Email", "minh.anh@yonsei.ac.kr"],
    ],
  },
  immigration: {
    title: "Immigration status",
    icon: "stamp",
    note: "Current Korean visa snapshot.",
    rows: [
      ["Current visa type", { kind: "pill", label: "D-2", tone: "ink" }],
      ["Visa expiry date", "2026.03.15"],
      ["Alien Registration Number", "020514-6XXXXXX"],
      ["Entry date to Korea", "2024.03.04"],
      ["Previous Korean visas", "D-4 (2023.09 – 2024.02)"],
      ["Prior deportation / overstay", { kind: "pill", label: "No", tone: "success" }],
    ],
  },
  education: {
    title: "Education",
    icon: "school",
    note: "Used for D-2, D-10, E-1, E-7, F-5 eligibility.",
    rows: [
      ["Highest degree", "Bachelor's (in progress)"],
      ["Field of study", "Computer Science"],
      ["University", "Yonsei University · Seoul"],
      ["Graduation (expected)", "2026.02"],
      ["GPA", "3.78 / 4.30"],
      ["TOPIK level", { kind: "pill", label: "Level 4", tone: "lime" }],
      ["TOPIK test date", "2025.04.21"],
      ["Other languages", "English (IELTS 7.0), Vietnamese (native)"],
    ],
  },
  employment: {
    title: "Employment & work history",
    icon: "briefcase",
    note: "Used for E-series, D-10, F-series qualification.",
    rows: [
      ["Current status", { kind: "pill", label: "Student · part-time", tone: "ink" }],
      ["Current employer", "Naver Labs (internship)"],
      ["Industry", "Software · R&D"],
      ["Job title", "ML Research Intern"],
      ["Employment start", "2025.06.02"],
      ["Contract type", "Internship · 20 hrs/wk"],
      ["Annual income", "₩18,000,000 (projected)"],
      ["Past experience", "Tutor at Yonsei CS Lab (2024.09 – 2025.05)"],
      ["Business registration no.", "—"],
    ],
  },
  finance: {
    title: "Financial info",
    icon: "wallet",
    note: "Used for D-10, F-series, C-3, D-8 sufficiency checks.",
    rows: [
      ["Bank account balance", "₩12,840,000 (Woori, as of 2025.10.20)"],
      ["Monthly average income", "₩1,500,000"],
      ["Sponsor", "Mother — Nguyễn Thi Hoa (relation: parent)"],
      ["Sponsor contact", "+84 24-555-1212"],
    ],
  },
  family: {
    title: "Family & relationship",
    icon: "users",
    note: "Used for F-1, F-3, F-6, F-2 routes.",
    rows: [
      ["Marital status", "Single"],
      ["Spouse nationality", "—"],
      ["Spouse visa status", "—"],
      ["Children", "None"],
      ["Korean family member", "—"],
    ],
  },
};

const DOCUMENTS = [
  { name: "Passport scan",                 file: "passport.pdf",        size: "1.2 MB", status: "verified",  date: "2024.03.05" },
  { name: "ARC scan",                      file: "arc-front-back.pdf",  size: "0.8 MB", status: "verified",  date: "2024.03.22" },
  { name: "Degree certificate",            file: "high-school-cert.pdf",size: "2.1 MB", status: "verified",  date: "2024.03.10" },
  { name: "Transcript",                    file: "transcript-2025s.pdf",size: "0.9 MB", status: "uploaded",  date: "2025.09.12" },
  { name: "Employment certificate",        file: "naver-letter.pdf",    size: "0.4 MB", status: "uploaded",  date: "2025.06.05" },
  { name: "Bank statement",                file: "woori-2025-10.pdf",   size: "1.5 MB", status: "uploaded",  date: "2025.10.20" },
  { name: "Proof of residence (lease)",    file: "sinchon-room.pdf",    size: "3.2 MB", status: "uploaded",  date: "2024.04.02" },
  { name: "Health insurance certificate",  file: "nhis-card.pdf",       size: "0.3 MB", status: "verified",  date: "2024.05.18" },
  { name: "TB test result",                file: "tb-2025-09.pdf",      size: "0.6 MB", status: "uploaded",  date: "2025.09.30" },
  { name: "TOPIK certificate",             file: "topik-lvl4.pdf",      size: "0.5 MB", status: "verified",  date: "2025.05.10" },
];

const MAPPING = [
  { field: "Nationality + education",         used: "D-10-1 eligibility check" },
  { field: "Current visa + graduation date",  used: "D-2 → D-10 transition suggestion" },
  { field: "Employment + income",             used: "E-7, F-2, F-5 qualification" },
  { field: "Marital status + spouse visa",    used: "F-3, F-6 eligibility" },
  { field: "Financial balance",               used: "D-10, C-3, D-8 financial sufficiency" },
  { field: "Work history abroad",             used: "D-10 points scoring (experience)" },
  { field: "TOPIK level",                     used: "D-10 bonus points, F-2 eligibility" },
];

function MyFiles() {
  return (
    <div style={{
      display: "flex", flexDirection: "column", gap: 22,
      animation: "fade-up 0.5s cubic-bezier(0.2,0.7,0.2,1) both",
      animationDelay: "0.05s",
      maxWidth: 1180,
    }}>
      <FilesSummary />

      {Object.entries(FILE_DATA).map(([key, section]) => (
        <ProfileSection key={key} section={section} />
      ))}

      <DocumentsVault />
      <ProfileMapping />
    </div>
  );
}

function FilesSummary() {
  const total = 47, filled = 47;
  const docsDone = DOCUMENTS.filter((d) => d.status === "verified" || d.status === "uploaded").length;
  return (
    <SurfaceCard>
      <div style={{
        display: "grid", gridTemplateColumns: "1fr auto", gap: 24,
        alignItems: "center",
      }} className="files-summary-grid">
        <div>
          <div style={{
            fontSize: 10, fontWeight: 600, color: "var(--text-mute)",
            letterSpacing: "0.18em", textTransform: "uppercase",
          }}>Profile completeness</div>
          <h2 style={{
            fontSize: 22, fontWeight: 600, color: "var(--ink)",
            letterSpacing: "-0.02em", marginTop: 6,
          }}>Your file vault is ready.</h2>
          <p style={{ fontSize: 13.5, color: "var(--text-mute)", marginTop: 6, lineHeight: 1.55, maxWidth: 540 }}>
            All sections below are filled. Korico reuses them automatically when you apply for D-10, E-7, F-2, or any other visa — so you never type the same thing twice.
          </p>
        </div>
        <div style={{
          display: "flex", gap: 12,
        }} className="files-summary-pills">
          <SummaryPill label="Profile fields" value={`${filled}/${total}`} tone="success" />
          <SummaryPill label="Documents" value={`${docsDone}/${DOCUMENTS.length}`} tone="ink" />
        </div>
      </div>
      <style>{`
        @media (max-width: 720px) {
          .files-summary-grid { grid-template-columns: 1fr !important; }
          .files-summary-pills { width: 100%; }
        }
      `}</style>
    </SurfaceCard>
  );
}

function SummaryPill({ label, value, tone }) {
  const tones = {
    ink:     { bg: "var(--ink)",         fg: "var(--lime)" },
    success: { bg: "var(--success-soft)",fg: "var(--success)" },
    warn:    { bg: "var(--warning-soft)",fg: "var(--warning)" },
  }[tone] || { bg: "var(--bg-soft)", fg: "var(--ink)" };
  return (
    <div style={{
      padding: "10px 16px", borderRadius: 14,
      background: tones.bg, color: tones.fg,
      minWidth: 130,
    }}>
      <div style={{ fontSize: 10, fontWeight: 600, letterSpacing: "0.16em", textTransform: "uppercase", opacity: 0.75 }}>{label}</div>
      <div style={{ fontSize: 22, fontWeight: 700, letterSpacing: "-0.02em", marginTop: 2 }}>{value}</div>
    </div>
  );
}

function ProfileSection({ section }) {
  return (
    <SurfaceCard>
      <header style={{ marginBottom: 18, display: "flex", alignItems: "center", gap: 12 }}>
        <div style={{
          width: 38, height: 38, borderRadius: 11,
          background: "var(--bg-soft)", color: "var(--ink)",
          display: "inline-flex", alignItems: "center", justifyContent: "center",
        }}>
          <i className={`ti ti-${section.icon}`} style={{ fontSize: 18 }} />
        </div>
        <div style={{ flex: 1, minWidth: 0 }}>
          <h2 style={{
            fontSize: 17, fontWeight: 600, color: "var(--ink)",
            letterSpacing: "-0.015em",
          }}>{section.title}</h2>
          <p style={{ fontSize: 12, color: "var(--text-mute)", marginTop: 2 }}>{section.note}</p>
        </div>
        <button style={{
          padding: "6px 12px", borderRadius: 99,
          background: "white", color: "var(--ink)",
          border: "1px solid var(--border)",
          fontSize: 11, fontWeight: 600, letterSpacing: "0.04em",
          display: "inline-flex", alignItems: "center", gap: 6,
        }}
          onMouseEnter={(e) => e.currentTarget.style.background = "var(--bg-soft)"}
          onMouseLeave={(e) => e.currentTarget.style.background = "white"}
        >
          <i className="ti ti-pencil" style={{ fontSize: 13 }} />
          Edit
        </button>
      </header>

      <dl style={{
        display: "grid", gridTemplateColumns: "minmax(180px, 1fr) 2fr",
        rowGap: 0, columnGap: 22,
        margin: 0,
      }} className="kv-grid">
        {section.rows.map(([label, value], i) => (
          <KVRow key={label} label={label} value={value} last={i === section.rows.length - 1} />
        ))}
      </dl>
      <style>{`
        @media (max-width: 640px) {
          .kv-grid { grid-template-columns: 1fr !important; }
          .kv-grid dt { padding-bottom: 0 !important; }
          .kv-grid dd { padding-top: 4px !important; }
        }
      `}</style>
    </SurfaceCard>
  );
}

function KVRow({ label, value, last }) {
  const border = last ? "none" : "1px solid var(--border-soft)";
  return (
    <>
      <dt style={{
        padding: "12px 0",
        borderBottom: border,
        fontSize: 12, fontWeight: 500,
        color: "var(--text-mute)",
        letterSpacing: "-0.005em",
      }}>{label}</dt>
      <dd style={{
        padding: "12px 0",
        borderBottom: border,
        margin: 0,
        fontSize: 13.5, color: "var(--ink)",
        fontWeight: 500, letterSpacing: "-0.005em",
        display: "flex", alignItems: "center", gap: 10, flexWrap: "wrap",
      }}>
        {renderValue(value)}
      </dd>
    </>
  );
}

function renderValue(v) {
  if (typeof v === "string") return v || "—";
  if (v?.kind === "pill") {
    const tones = {
      ink:     { bg: "var(--ink)",          fg: "var(--lime)" },
      lime:    { bg: "var(--lime)",         fg: "var(--ink)"  },
      success: { bg: "var(--success-soft)", fg: "var(--success)" },
      warn:    { bg: "var(--warning-soft)", fg: "var(--warning)" },
    }[v.tone] || { bg: "var(--bg-soft)", fg: "var(--ink)" };
    return (
      <span style={{
        padding: "4px 10px", borderRadius: 99,
        background: tones.bg, color: tones.fg,
        fontSize: 11, fontWeight: 700, letterSpacing: "0.08em",
        textTransform: "uppercase",
      }}>{v.label}</span>
    );
  }
  if (v?.kind === "file") {
    return (
      <span style={{
        display: "inline-flex", alignItems: "center", gap: 8,
        padding: "5px 10px 5px 7px", borderRadius: 10,
        background: "var(--bg-soft)", color: "var(--ink)",
        fontSize: 12, fontWeight: 500,
      }}>
        <span style={{
          width: 20, height: 20, borderRadius: 5,
          background: "var(--ink)", color: "var(--lime)",
          display: "inline-flex", alignItems: "center", justifyContent: "center",
        }}><i className="ti ti-photo" style={{ fontSize: 12 }} /></span>
        {v.label}
        <span style={{ fontSize: 10.5, color: "var(--text-mute)" }}>· {v.meta}</span>
      </span>
    );
  }
  return "—";
}

function DocumentsVault() {
  return (
    <SurfaceCard>
      <header style={{ marginBottom: 18, display: "flex", alignItems: "center", gap: 12 }}>
        <div style={{
          width: 38, height: 38, borderRadius: 11,
          background: "var(--lime)", color: "var(--ink)",
          display: "inline-flex", alignItems: "center", justifyContent: "center",
        }}>
          <i className="ti ti-folder" style={{ fontSize: 18 }} />
        </div>
        <div style={{ flex: 1, minWidth: 0 }}>
          <h2 style={{
            fontSize: 17, fontWeight: 600, color: "var(--ink)",
            letterSpacing: "-0.015em",
          }}>Documents vault</h2>
          <p style={{ fontSize: 12, color: "var(--text-mute)", marginTop: 2 }}>
            Upload once. Korico attaches the right files to each application automatically.
          </p>
        </div>
        <button style={{
          padding: "6px 12px", borderRadius: 99,
          background: "var(--ink)", color: "var(--lime)",
          fontSize: 11, fontWeight: 700, letterSpacing: "0.12em",
          display: "inline-flex", alignItems: "center", gap: 6,
        }}>
          <i className="ti ti-upload" style={{ fontSize: 13 }} />
          UPLOAD
        </button>
      </header>

      <div style={{
        display: "grid", gridTemplateColumns: "repeat(2, 1fr)", gap: 10,
      }} className="docs-grid">
        {DOCUMENTS.map((d) => <DocRow key={d.name} d={d} />)}
      </div>
      <style>{`
        @media (max-width: 720px) { .docs-grid { grid-template-columns: 1fr !important; }}
      `}</style>
    </SurfaceCard>
  );
}

function DocRow({ d }) {
  const tones = {
    verified: { bg: "var(--success-soft)", fg: "var(--success)" },
    uploaded: { bg: "var(--bg-soft)",      fg: "var(--ink)" },
    missing:  { bg: "var(--warning-soft)", fg: "var(--warning)" },
  }[d.status];
  return (
    <div style={{
      display: "flex", alignItems: "center", gap: 12,
      padding: "12px 14px", borderRadius: 14,
      background: "white", border: "1px solid var(--border-soft)",
      transition: "border-color 0.18s ease, background 0.18s ease",
    }}
      onMouseEnter={(e) => { e.currentTarget.style.borderColor = "var(--border)"; e.currentTarget.style.background = "var(--bg-soft)"; }}
      onMouseLeave={(e) => { e.currentTarget.style.borderColor = "var(--border-soft)"; e.currentTarget.style.background = "white"; }}
    >
      <div style={{
        width: 36, height: 36, borderRadius: 9,
        background: "var(--bg-soft)", color: "var(--ink)",
        display: "inline-flex", alignItems: "center", justifyContent: "center",
        flexShrink: 0,
      }}>
        <i className="ti ti-file-text" style={{ fontSize: 18 }} />
      </div>
      <div style={{ flex: 1, minWidth: 0 }}>
        <div style={{
          fontSize: 13, fontWeight: 600, color: "var(--ink)",
          letterSpacing: "-0.005em",
          overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap",
        }}>{d.name}</div>
        <div style={{ fontSize: 11, color: "var(--text-mute)", marginTop: 2 }}>
          {d.file} · {d.size} · {d.date}
        </div>
      </div>
      <span style={{
        padding: "3px 9px", borderRadius: 99,
        background: tones.bg, color: tones.fg,
        fontSize: 10, fontWeight: 700, letterSpacing: "0.08em",
        textTransform: "uppercase",
        flexShrink: 0,
      }}>{d.status}</span>
    </div>
  );
}

function ProfileMapping() {
  return (
    <SurfaceCard>
      <header style={{ marginBottom: 16 }}>
        <div style={{
          fontSize: 10, fontWeight: 600, color: "var(--text-mute)",
          letterSpacing: "0.18em", textTransform: "uppercase",
        }}>How Korico uses your file</div>
        <h2 style={{
          fontSize: 17, fontWeight: 600, color: "var(--ink)",
          letterSpacing: "-0.015em", marginTop: 4,
        }}>Profile → visa mapping</h2>
        <p style={{ fontSize: 12.5, color: "var(--text-mute)", marginTop: 4, lineHeight: 1.5 }}>
          The fields you filled above feed directly into the eligibility checks below.
        </p>
      </header>
      <div style={{
        border: "1px solid var(--border-soft)", borderRadius: 14, overflow: "hidden",
      }}>
        {MAPPING.map((row, i) => (
          <div key={i} style={{
            display: "grid", gridTemplateColumns: "1fr 1.4fr", gap: 16,
            padding: "12px 16px",
            borderTop: i === 0 ? "none" : "1px solid var(--border-soft)",
            background: i % 2 === 0 ? "white" : "var(--bg-canvas)",
            fontSize: 13,
          }} className="map-row">
            <div style={{ color: "var(--ink)", fontWeight: 500 }}>{row.field}</div>
            <div style={{ color: "var(--text-mute)" }}>{row.used}</div>
          </div>
        ))}
      </div>
      <style>{`
        @media (max-width: 640px) { .map-row { grid-template-columns: 1fr !important; gap: 4px !important; }}
      `}</style>
    </SurfaceCard>
  );
}

/* ============================================================
   VISA & STATUS PAGE
   ============================================================ */

const VISA_TIMELINE = [
  { id: "arrival", label: "Arrival in Korea", date: "2024.03.04", state: "past" },
  { id: "arc",     label: "ARC issued",        date: "2024.03.22", state: "past" },
  { id: "today",   label: "Today",             date: "2025.10.20", state: "today" },
  { id: "ext",     label: "Extension window opens", date: "2026.02.13", state: "future" },
  { id: "expiry",  label: "D-2 expires",        date: "2026.03.15", state: "future" },
  { id: "target",  label: "Target: D-10",       date: "~2026.05",   state: "future" },
];

function VisaPage({ onNavigate }) {
  return (
    <div style={{
      display: "grid", gridTemplateColumns: "1.5fr 1fr", gap: 22,
      animation: "fade-up 0.5s cubic-bezier(0.2,0.7,0.2,1) both",
      animationDelay: "0.05s",
      maxWidth: 1280,
    }} className="page-grid">
      <div style={{ display: "flex", flexDirection: "column", gap: 22, minWidth: 0 }}>
        <VisaSummaryCard />
        <F2CalculatorBanner onNavigate={onNavigate} />
        <VisaTimelineCard />
        <KoricoSuggestionCard onNavigate={onNavigate} />
      </div>
      <div style={{ display: "flex", flexDirection: "column", gap: 22, minWidth: 0 }}>
        <VisaPreferencesCard />
        <AskShortcutCard
          eyebrow="Ask Korico"
          title="Talk through your visa options"
          prefill="Given my D-2 visa expiring on 2026.03.15 and my goal to work in Korea, what are my best visa options?"
        />
      </div>

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

function VisaSummaryCard() {
  return (
    <SurfaceCard style={{ position: "relative" }}>
      <header style={{
        display: "flex", alignItems: "flex-start", gap: 14, marginBottom: 18,
      }}>
        <div style={{
          width: 48, height: 48, borderRadius: 14,
          background: "var(--ink)", color: "var(--lime)",
          display: "inline-flex", alignItems: "center", justifyContent: "center",
          flexShrink: 0,
        }}>
          <i className="ti ti-id" style={{ fontSize: 22 }} />
        </div>
        <div style={{ flex: 1, minWidth: 0 }}>
          <div style={{
            fontSize: 10, fontWeight: 600, color: "var(--text-mute)",
            letterSpacing: "0.18em", textTransform: "uppercase",
          }}>Current visa</div>
          <h2 style={{
            fontSize: 28, fontWeight: 600, letterSpacing: "-0.02em",
            color: "var(--ink)", marginTop: 4,
          }}>D-2 <span style={{ color: "var(--text-mute)", fontWeight: 400 }}>Student</span></h2>
          <div style={{ fontSize: 13, color: "var(--text-mute)", marginTop: 6 }}>
            Valid from 2024.03.04 to <strong style={{ color: "var(--ink)" }}>2026.03.15</strong>
          </div>
        </div>
        <span style={{
          padding: "5px 12px", borderRadius: 99,
          background: "var(--success-soft)", color: "var(--success)",
          fontSize: 10, fontWeight: 700, letterSpacing: "0.14em", textTransform: "uppercase",
        }}>Low risk</span>
        <button title="Edit" style={{
          width: 34, height: 34, borderRadius: 10,
          background: "var(--bg-soft)", color: "var(--ink)",
          display: "inline-flex", alignItems: "center", justifyContent: "center",
        }}
          onMouseEnter={(e) => e.currentTarget.style.background = "var(--border-soft)"}
          onMouseLeave={(e) => e.currentTarget.style.background = "var(--bg-soft)"}
        ><i className="ti ti-pencil" style={{ fontSize: 16 }} /></button>
      </header>

      <div style={{
        padding: "14px 16px", borderRadius: 14,
        background: "var(--bg-soft)",
        display: "grid", gridTemplateColumns: "1fr 1fr", gap: 16,
      }} className="vs-kv">
        <div>
          <div style={{ fontSize: 10, color: "var(--text-mute)", fontWeight: 600, letterSpacing: "0.16em", textTransform: "uppercase" }}>ARC</div>
          <div style={{ fontSize: 13.5, color: "var(--ink)", marginTop: 4, fontWeight: 500 }}>Registered · ****-1234</div>
        </div>
        <div>
          <div style={{ fontSize: 10, color: "var(--text-mute)", fontWeight: 600, letterSpacing: "0.16em", textTransform: "uppercase" }}>Days remaining</div>
          <div style={{ fontSize: 13.5, color: "var(--ink)", marginTop: 4, fontWeight: 500 }}>146 days</div>
        </div>
      </div>

      <div style={{ display: "flex", flexWrap: "wrap", gap: 6, marginTop: 14 }}>
        {["Full-time student", "Seoul", "Yonsei University", "Computer Science"].map((c) => (
          <span key={c} style={{
            padding: "5px 11px", borderRadius: 99,
            background: "white", border: "1px solid var(--border)",
            fontSize: 11, fontWeight: 500, color: "var(--ink)",
          }}>{c}</span>
        ))}
      </div>

      <style>{`
        @media (max-width: 560px) { .vs-kv { grid-template-columns: 1fr !important; }}
      `}</style>
    </SurfaceCard>
  );
}

function VisaTimelineCard() {
  return (
    <SurfaceCard>
      <CardHead
        eyebrow="Timeline"
        title="Timeline & key dates"
        subtitle="A quick view of where you are and what's coming next."
      />

      <div style={{ position: "relative", padding: "8px 0 16px" }}>
        {/* Track */}
        <div style={{
          position: "absolute", left: 12, right: 12, top: 24, height: 2,
          background: "var(--border-soft)", borderRadius: 99,
        }} />
        <div style={{
          display: "grid",
          gridTemplateColumns: `repeat(${VISA_TIMELINE.length}, 1fr)`,
          position: "relative",
        }} className="vt-grid">
          {VISA_TIMELINE.map((n, i) => (
            <TimelineNode key={n.id} n={n} delay={i * 0.08} />
          ))}
        </div>
      </div>

      <ul style={{
        listStyle: "none", margin: 0, padding: 0,
        display: "flex", flexDirection: "column", gap: 8,
        marginTop: 4,
      }}>
        <TimelineHint icon="calendar-event" text="Extension window opens in 120 days." />
        <TimelineHint icon="building-bank" text="Immigration office may require an appointment 30 days before expiry." />
        <TimelineHint icon="alert-circle" text="Apply for a status change at least 2 weeks before D-2 ends." tone="warn" />
      </ul>

      <style>{`
        @media (max-width: 720px) {
          .vt-grid { grid-template-columns: 1fr !important; gap: 18px; }
          .vt-grid > * { padding-left: 0 !important; }
        }
      `}</style>
    </SurfaceCard>
  );
}

function TimelineNode({ n, delay }) {
  const tones = {
    past:   { dot: "var(--border)",       fg: "var(--text-mute)" },
    today:  { dot: "var(--lime)",         fg: "var(--ink)",       ring: true },
    future: { dot: "var(--sky-2)",        fg: "var(--ink)" },
  }[n.state];

  return (
    <div style={{
      textAlign: "center",
      padding: "0 6px",
      animation: "step-in 0.5s cubic-bezier(0.2,0.7,0.2,1) both",
      animationDelay: `${0.1 + delay}s`,
    }}>
      <div style={{
        width: 14, height: 14, borderRadius: "50%",
        background: tones.dot,
        margin: "16px auto 10px",
        boxShadow: tones.ring ? "0 0 0 6px rgba(212,255,79,0.30)" : "none",
        animation: n.state === "today" ? "pulse-dot 2s ease-in-out infinite" : "none",
      }} />
      <div style={{ fontSize: 11.5, fontWeight: 600, color: tones.fg, letterSpacing: "-0.005em" }}>{n.label}</div>
      <div style={{ fontSize: 10.5, color: "var(--text-mute)", marginTop: 2 }}>{n.date}</div>
    </div>
  );
}

function TimelineHint({ icon, text, tone }) {
  const palette = tone === "warn"
    ? { bg: "var(--warning-soft)", fg: "var(--warning)" }
    : { bg: "var(--bg-soft)", fg: "var(--ink)" };
  return (
    <li style={{
      display: "flex", alignItems: "center", gap: 10,
      padding: "10px 14px", borderRadius: 12,
      background: "white", border: "1px solid var(--border-soft)",
      fontSize: 12.5, color: "var(--text-soft)",
    }}>
      <span style={{
        width: 26, height: 26, borderRadius: 8,
        background: palette.bg, color: palette.fg,
        display: "inline-flex", alignItems: "center", justifyContent: "center",
        flexShrink: 0,
      }}><i className={`ti ti-${icon}`} style={{ fontSize: 14 }} /></span>
      {text}
    </li>
  );
}

function KoricoSuggestionCard({ onNavigate }) {
  const items = [
    "Upload current ARC and passport scan",
    "Check eligibility for D-10",
    "Read guide: D-2 → D-10 transition",
    "Book an immigration office appointment",
  ];
  return (
    <SurfaceCard style={{
      background: "linear-gradient(180deg, rgba(212,255,79,0.10) 0%, white 50%)",
      borderColor: "rgba(184,230,60,0.45)",
    }}>
      <CardHead
        eyebrow="Korico's suggestion"
        title="Plan your D-2 → D-10 transition"
        subtitle="Based on your D-2 status, remaining time, and goal of finding a job in Korea, Korico suggests preparing for a D-10 visa within the next 3–4 months."
      />
      <ul style={{
        listStyle: "none", padding: 0, margin: "4px 0 16px",
        display: "flex", flexDirection: "column", gap: 8,
      }}>
        {items.map((it, i) => (
          <li key={it} style={{
            display: "flex", alignItems: "center", gap: 10,
            fontSize: 13.5, color: "var(--ink)",
          }}>
            <span style={{
              width: 22, height: 22, borderRadius: "50%",
              background: "var(--ink)", color: "var(--lime)",
              display: "inline-flex", alignItems: "center", justifyContent: "center",
              flexShrink: 0, fontSize: 10, fontWeight: 700,
            }}>{i + 1}</span>
            {it}
          </li>
        ))}
      </ul>
      <button
        onClick={() => onNavigate?.("visa-plan-d2-d10")}
        style={{
          display: "inline-flex", alignItems: "center", gap: 10,
          padding: "11px 20px", borderRadius: 99,
          background: "var(--ink)", color: "var(--lime)",
          fontFamily: "var(--font-body)", fontWeight: 700, fontSize: 12,
          letterSpacing: "0.16em", textTransform: "uppercase",
          boxShadow: "0 10px 22px rgba(11,27,44,0.20)",
          cursor: "pointer",
        }}
        onMouseEnter={(e) => e.currentTarget.style.transform = "translateY(-1px)"}
        onMouseLeave={(e) => e.currentTarget.style.transform = "translateY(0)"}
      >
        Open step-by-step plan
        <span style={{
          width: 20, height: 20, borderRadius: "50%",
          background: "var(--lime)", color: "var(--ink)",
          display: "inline-flex", alignItems: "center", justifyContent: "center",
        }}><i className="ti ti-arrow-up-right" style={{ fontSize: 11 }} /></span>
      </button>
    </SurfaceCard>
  );
}

function VisaPreferencesCard() {
  const [form, setForm] = useState({
    visa: "D-2",
    country: "VN",
    region: "Seoul",
    goal: "Work long term",
    risk: "Normal",
  });
  const [saved, setSaved] = useState(false);
  const submit = (e) => {
    e.preventDefault();
    setSaved(true);
    setTimeout(() => setSaved(false), 1800);
  };
  return (
    <SurfaceCard>
      <CardHead
        eyebrow="Preferences"
        title="Visa details &amp; preferences"
        subtitle="Korico tailors suggestions to your situation and risk tolerance."
      />
      <form onSubmit={submit} style={{ display: "flex", flexDirection: "column", gap: 14 }}>
        <Field label="Current visa">
          <Select value={form.visa} onChange={(v) => setForm({ ...form, visa: v })}
            options={["D-2", "D-4", "D-10", "E-7", "F-2", "F-6"]} />
        </Field>
        <Field label="Country of citizenship">
          <Select value={form.country} onChange={(v) => setForm({ ...form, country: v })}
            options={["VN", "MN", "ZH", "US", "RU", "TH", "PH", "Other"]} />
        </Field>
        <Field label="City / region in Korea">
          <Select value={form.region} onChange={(v) => setForm({ ...form, region: v })}
            options={["Seoul", "Busan", "Incheon", "Daegu", "Daejeon", "Gwangju", "Other"]} />
        </Field>
        <Field label="Long-term goal">
          <RadioPills
            value={form.goal}
            onChange={(v) => setForm({ ...form, goal: v })}
            options={["Stay 1–2 years", "Work long term", "F-2 / permanent", "Not sure yet"]}
          />
        </Field>
        <Field label="Risk tolerance">
          <RadioPills
            value={form.risk}
            onChange={(v) => setForm({ ...form, risk: v })}
            options={["Play it safe", "Normal", "Okay with complexity"]}
          />
        </Field>

        <div style={{ display: "flex", justifyContent: "space-between", alignItems: "center", marginTop: 4, gap: 10 }}>
          <div style={{ fontSize: 11.5, color: saved ? "var(--success)" : "var(--text-mute)" }}>
            {saved ? "Saved · suggestions refreshed." : "Stays private to your account."}
          </div>
          <button type="submit" style={{
            display: "inline-flex", alignItems: "center", gap: 8,
            padding: "10px 16px", borderRadius: 99,
            background: "var(--lime)", color: "var(--ink)",
            fontFamily: "var(--font-body)", fontWeight: 700, fontSize: 11,
            letterSpacing: "0.16em", textTransform: "uppercase",
          }}>
            Save &amp; refresh
            <span style={{
              width: 18, height: 18, borderRadius: "50%",
              background: "var(--ink)", color: "var(--lime)",
              display: "inline-flex", alignItems: "center", justifyContent: "center",
            }}><i className="ti ti-refresh" style={{ fontSize: 11 }} /></span>
          </button>
        </div>
      </form>
    </SurfaceCard>
  );
}

function RadioPills({ value, onChange, options }) {
  return (
    <div style={{ display: "flex", flexWrap: "wrap", gap: 6 }}>
      {options.map((o) => {
        const on = value === o;
        return (
          <button key={o} type="button" onClick={() => onChange(o)} style={{
            padding: "7px 12px", borderRadius: 99,
            background: on ? "var(--ink)" : "white",
            color: on ? "var(--lime)" : "var(--ink)",
            border: `1px solid ${on ? "var(--ink)" : "var(--border)"}`,
            fontSize: 12, fontWeight: 500,
            transition: "all 0.18s ease",
          }}>{o}</button>
        );
      })}
    </div>
  );
}

function AskShortcutCard({ eyebrow, title, prefill }) {
  const ask = () => {
    window.dispatchEvent(new CustomEvent("korico:ask", { detail: { prefill } }));
  };
  return (
    <SurfaceCard>
      <CardHead eyebrow={eyebrow} title={title} subtitle="Korico opens with this question prefilled." />
      <div style={{
        padding: "14px 16px", borderRadius: 14,
        background: "var(--bg-soft)",
        border: "1px dashed var(--border)",
        fontSize: 13, color: "var(--ink)", lineHeight: 1.55,
        marginBottom: 14,
      }}>
        <i className="ti ti-quote" style={{ fontSize: 16, color: "var(--text-mute)", marginRight: 8, verticalAlign: -2 }} />
        {prefill}
      </div>
      <button onClick={ask} style={{
        display: "inline-flex", alignItems: "center", gap: 10,
        padding: "10px 18px", borderRadius: 99,
        background: "var(--lime)", color: "var(--ink)",
        fontFamily: "var(--font-body)", fontWeight: 700, fontSize: 11,
        letterSpacing: "0.16em", textTransform: "uppercase",
        boxShadow: "0 10px 22px rgba(184,230,60,0.35)",
      }}
        onMouseEnter={(e) => e.currentTarget.style.transform = "translateY(-1px)"}
        onMouseLeave={(e) => e.currentTarget.style.transform = "translateY(0)"}
      >
        Ask in Korico chat
        <span style={{
          width: 18, height: 18, borderRadius: "50%",
          background: "var(--ink)", color: "var(--lime)",
          display: "inline-flex", alignItems: "center", justifyContent: "center",
        }}><i className="ti ti-arrow-up-right" style={{ fontSize: 10 }} /></span>
      </button>
    </SurfaceCard>
  );
}

/* ============================================================
   F-2 CALCULATOR BANNER + PAGE
   ============================================================ */

function F2CalculatorBanner({ onNavigate }) {
  return (
    <button
      onClick={() => onNavigate?.("visa-f2-calc")}
      style={{
        position: "relative",
        display: "grid",
        gridTemplateColumns: "auto 1fr auto",
        gap: 16, alignItems: "center",
        width: "100%", textAlign: "left",
        padding: "18px 22px",
        background: "linear-gradient(120deg, var(--ink) 0%, #11243A 100%)",
        color: "white",
        borderRadius: 20,
        border: "1px solid rgba(184,230,60,0.25)",
        boxShadow: "0 18px 40px rgba(11,27,44,0.18)",
        overflow: "hidden",
        transition: "transform 0.22s ease, box-shadow 0.22s ease",
        cursor: "pointer",
      }}
      onMouseEnter={(e) => {
        e.currentTarget.style.transform = "translateY(-2px)";
        e.currentTarget.style.boxShadow = "0 26px 56px rgba(11,27,44,0.28)";
      }}
      onMouseLeave={(e) => {
        e.currentTarget.style.transform = "translateY(0)";
        e.currentTarget.style.boxShadow = "0 18px 40px rgba(11,27,44,0.18)";
      }}
    >
      {/* decorative lime glow */}
      <span aria-hidden style={{
        position: "absolute", right: -40, top: -40,
        width: 200, height: 200, borderRadius: "50%",
        background: "radial-gradient(circle, rgba(212,255,79,0.30), transparent 70%)",
        pointerEvents: "none",
      }} />

      <div style={{
        width: 48, height: 48, borderRadius: 14,
        background: "var(--lime)", color: "var(--ink)",
        display: "inline-flex", alignItems: "center", justifyContent: "center",
        flexShrink: 0,
      }}>
        <i className="ti ti-calculator" style={{ fontSize: 22 }} />
      </div>

      <div style={{ minWidth: 0, position: "relative" }}>
        <div style={{
          fontSize: 10, fontWeight: 600, color: "var(--lime)",
          letterSpacing: "0.18em", textTransform: "uppercase",
        }}>Long-term residence</div>
        <div style={{
          fontSize: 16, fontWeight: 600, color: "white",
          letterSpacing: "-0.015em", marginTop: 4,
        }}>Are you ready for an F-2 visa?</div>
        <div style={{
          fontSize: 12.5, color: "rgba(255,255,255,0.7)",
          marginTop: 4, lineHeight: 1.45,
        }}>
          Estimate your points across age, education, Korean ability, income, and family — in under 2 minutes.
        </div>
      </div>

      <div style={{
        display: "inline-flex", alignItems: "center", gap: 8,
        padding: "10px 16px", borderRadius: 99,
        background: "var(--lime)", color: "var(--ink)",
        fontSize: 11, fontWeight: 700, letterSpacing: "0.16em", textTransform: "uppercase",
        flexShrink: 0,
      }}>
        Calculate
        <span style={{
          width: 20, height: 20, borderRadius: "50%",
          background: "var(--ink)", color: "var(--lime)",
          display: "inline-flex", alignItems: "center", justifyContent: "center",
        }}><i className="ti ti-arrow-up-right" style={{ fontSize: 11 }} /></span>
      </div>
    </button>
  );
}

/* ---- Scoring table (mock; tweak from official table later) ---- */

const F2_SCORING = {
  version: "2025 reference",
  thresholdPass: 80,   // typical pass mark for F-2-7
  thresholdMax:  130,  // total ceiling shown on the gauge

  age: {
    max: 25,
    options: [
      { v: "18-24", label: "18 – 24",  pts: 23 },
      { v: "25-29", label: "25 – 29",  pts: 25 },
      { v: "30-34", label: "30 – 34",  pts: 20 },
      { v: "35-39", label: "35 – 39",  pts: 17 },
      { v: "40-44", label: "40 – 44",  pts: 12 },
      { v: "45-50", label: "45 – 50",  pts: 8  },
      { v: "51+",   label: "51 and over", pts: 0 },
    ],
  },

  education: {
    max: 25,
    options: [
      { v: "phd",        label: "Doctorate (PhD)",            pts: 25 },
      { v: "ms",         label: "Master's degree",            pts: 20 },
      { v: "bs",         label: "Bachelor's degree",          pts: 15 },
      { v: "associate",  label: "Associate / 2–3 yr college", pts: 10 },
      { v: "specialized", label: "Specialized vocational",    pts: 5  },
      { v: "hs",         label: "High school or less",        pts: 0  },
    ],
  },

  // Combined Korean & social-integration score. We pick the higher of the two.
  korean: {
    max: 20,
    topik: [
      { v: "none", label: "No TOPIK", pts: 0  },
      { v: "1",    label: "TOPIK 1",  pts: 4  },
      { v: "2",    label: "TOPIK 2",  pts: 8  },
      { v: "3",    label: "TOPIK 3",  pts: 12 },
      { v: "4",    label: "TOPIK 4",  pts: 16 },
      { v: "5",    label: "TOPIK 5",  pts: 18 },
      { v: "6",    label: "TOPIK 6",  pts: 20 },
    ],
    kiip: [
      { v: "none",   label: "Not completed",       pts: 0  },
      { v: "basic",  label: "Basic / 1–2단계",      pts: 4  },
      { v: "3",      label: "3단계",                 pts: 8  },
      { v: "4",      label: "4단계",                 pts: 12 },
      { v: "5",      label: "5단계 (final)",         pts: 20 },
    ],
  },

  income: {
    max: 60,
    brackets: [
      { v: "<20",   label: "Less than ₩20M",          pts: 0  },
      { v: "20-30", label: "₩20M – ₩30M",             pts: 10 },
      { v: "30-40", label: "₩30M – ₩40M",             pts: 20 },
      { v: "40-50", label: "₩40M – ₩50M",             pts: 35 },
      { v: "50-70", label: "₩50M – ₩70M",             pts: 45 },
      { v: "70-100", label: "₩70M – ₩100M",           pts: 55 },
      { v: "100+",  label: "₩100M or more",           pts: 60 },
    ],
  },

  bonus: {
    cap: 40, // section is capped
    koreanDegree: [
      { v: "none",      label: "No degree from a Korean institution", pts: 0  },
      { v: "associate", label: "Korean associate / 2-yr college",     pts: 5  },
      { v: "bs",        label: "Korean bachelor's degree",            pts: 10 },
      { v: "ms",        label: "Korean master's degree",              pts: 15 },
      { v: "phd",       label: "Korean doctorate (PhD)",              pts: 20 },
    ],
    family: [
      { v: "none",  label: "None / not applicable",                  pts: 0  },
      { v: "f4",    label: "Family with F-4 / F-2 / F-5 status",     pts: 5  },
      { v: "f6",    label: "Korean spouse or child (F-6 / family)",  pts: 10 },
      { v: "f5",    label: "Korean parent or sibling (F-5)",         pts: 8  },
    ],
    stay: [
      { v: "<3",    label: "Less than 3 years",   pts: 0  },
      { v: "3-4",   label: "3 – 4 years",         pts: 5  },
      { v: "5-7",   label: "5 – 7 years",         pts: 10 },
      { v: "8+",    label: "8 or more years",     pts: 15 },
    ],
  },
};

function pointsFor(table, v) {
  const found = table.find((o) => o.v === v);
  return found ? found.pts : 0;
}

function F2CalculatorPage({ onNavigate }) {
  const [inputs, setInputs] = useState({
    age: "25-29",
    education: "bs",
    topik: "4",
    kiip: "none",
    income: "30-40",
    koreanDegree: "bs",
    family: "none",
    stay: "3-4",
  });

  // Refs for "Adjust" scroll anchors
  const refs = {
    age: useRef(null), education: useRef(null), korean: useRef(null),
    income: useRef(null), bonus: useRef(null),
  };

  const update = (k, v) => setInputs((s) => ({ ...s, [k]: v }));
  const reset  = () => setInputs({
    age: "", education: "", topik: "none", kiip: "none",
    income: "", koreanDegree: "none", family: "none", stay: "<3",
  });

  // Computed scores
  const scores = useMemo(() => {
    const age   = pointsFor(F2_SCORING.age.options,       inputs.age);
    const edu   = pointsFor(F2_SCORING.education.options, inputs.education);
    const topik = pointsFor(F2_SCORING.korean.topik,      inputs.topik);
    const kiip  = pointsFor(F2_SCORING.korean.kiip,       inputs.kiip);
    // Korean: take the higher of TOPIK or KIIP, capped at section max.
    const korean = Math.min(Math.max(topik, kiip), F2_SCORING.korean.max);
    const income = pointsFor(F2_SCORING.income.brackets,  inputs.income);
    const koreanDegree = pointsFor(F2_SCORING.bonus.koreanDegree, inputs.koreanDegree);
    const family = pointsFor(F2_SCORING.bonus.family, inputs.family);
    const stay   = pointsFor(F2_SCORING.bonus.stay,   inputs.stay);
    const bonusRaw = koreanDegree + family + stay;
    const bonus = Math.min(bonusRaw, F2_SCORING.bonus.cap);
    return {
      age, edu, topik, kiip, korean, income,
      koreanDegree, family, stay, bonus, bonusRaw,
      total: age + edu + korean + income + bonus,
    };
  }, [inputs]);

  // Tier
  const total = scores.total;
  const tier = total >= F2_SCORING.thresholdPass
    ? { state: "pass", label: "Possibly eligible", color: "var(--success)", soft: "var(--success-soft)" }
    : total >= F2_SCORING.thresholdPass - 20
    ? { state: "near", label: "Getting closer", color: "var(--warning)", soft: "var(--warning-soft)" }
    : { state: "low",  label: "Low",            color: "var(--danger)",  soft: "var(--danger-soft)" };

  // Animated total
  const [animTotal, setAnimTotal] = useState(total);
  useEffect(() => {
    const startVal = animTotal;
    const delta = total - startVal;
    if (delta === 0) return;
    let raf = 0;
    const start = performance.now();
    const dur = 350;
    const tick = (t) => {
      const p = Math.min(1, (t - start) / dur);
      const e = 1 - Math.pow(1 - p, 3);
      setAnimTotal(Math.round(startVal + delta * e));
      if (p < 1) raf = requestAnimationFrame(tick);
    };
    raf = requestAnimationFrame(tick);
    return () => cancelAnimationFrame(raf);
  }, [total]);

  const scrollTo = (key) => {
    refs[key]?.current?.scrollIntoView({ behavior: "smooth", block: "start" });
  };

  const tips = buildTips(scores, inputs);

  return (
    <div style={{
      maxWidth: 1280,
      animation: "fade-up 0.5s cubic-bezier(0.2,0.7,0.2,1) both",
      animationDelay: "0.05s",
    }}>
      <div style={{ display: "flex", alignItems: "center", justifyContent: "space-between", flexWrap: "wrap", gap: 10 }}>
        <BackBar onBack={() => onNavigate("visa")} label="Visa & status" />
        <div style={{ display: "inline-flex", alignItems: "center", gap: 8 }}>
          <span style={{
            padding: "5px 10px", borderRadius: 99,
            background: "var(--bg-soft)", color: "var(--text-soft)",
            fontSize: 10.5, fontWeight: 600, letterSpacing: "0.08em",
          }}>v {F2_SCORING.version}</span>
          <button onClick={reset} style={{
            padding: "7px 14px", borderRadius: 99,
            background: "white", color: "var(--ink)",
            border: "1px solid var(--border)",
            fontSize: 11, fontWeight: 600, letterSpacing: "0.12em", textTransform: "uppercase",
          }}>
            <i className="ti ti-refresh" style={{ fontSize: 12, marginRight: 6, verticalAlign: -1 }} />
            Reset
          </button>
        </div>
      </div>

      <p style={{
        fontSize: 11.5, color: "var(--text-mute)", lineHeight: 1.55,
        margin: "0 0 18px", fontStyle: "italic", maxWidth: 760,
      }}>
        Korico simplifies the official points table. This calculator is an approximation of the F-2-7 long-term residence system and may not reflect the latest regulations or individual officer decisions. Always confirm with HiKorea or a licensed professional before applying.
      </p>

      <div style={{
        display: "grid", gridTemplateColumns: "1.3fr 1fr", gap: 18,
      }} className="f2-grid">

        {/* LEFT: inputs */}
        <div style={{ display: "flex", flexDirection: "column", gap: 18, minWidth: 0 }}>
          <F2Section
            n={1} title="Age"
            description="Age at the time of applying."
            score={scores.age} max={F2_SCORING.age.max}
            refEl={refs.age}
          >
            <RadioGrid
              options={F2_SCORING.age.options}
              value={inputs.age}
              onChange={(v) => update("age", v)}
              cols={3}
            />
          </F2Section>

          <F2Section
            n={2} title="Education"
            description="Highest completed education. Both Korean and overseas degrees count."
            score={scores.edu} max={F2_SCORING.education.max}
            refEl={refs.education}
          >
            <RadioGrid
              options={F2_SCORING.education.options}
              value={inputs.education}
              onChange={(v) => update("education", v)}
              cols={2}
            />
          </F2Section>

          <F2Section
            n={3} title="Korean & social integration"
            description="Korico counts the higher of your TOPIK score or KIIP (사회통합프로그램) stage."
            score={scores.korean} max={F2_SCORING.korean.max}
            refEl={refs.korean}
          >
            <div style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: 14 }} className="kor-grid">
              <Field label="TOPIK level">
                <SelectF2 value={inputs.topik} onChange={(v) => update("topik", v)} options={F2_SCORING.korean.topik} />
              </Field>
              <Field label="KIIP (사회통합) stage">
                <SelectF2 value={inputs.kiip} onChange={(v) => update("kiip", v)} options={F2_SCORING.korean.kiip} />
              </Field>
            </div>
            <p style={{ fontSize: 11.5, color: "var(--text-mute)", marginTop: 10, lineHeight: 1.5 }}>
              Counting the higher of <strong style={{ color: "var(--ink)" }}>{scores.topik} (TOPIK)</strong> and <strong style={{ color: "var(--ink)" }}>{scores.kiip} (KIIP)</strong> = {scores.korean} points.
            </p>
            <style>{`@media (max-width: 600px) { .kor-grid { grid-template-columns: 1fr !important; }}`}</style>
          </F2Section>

          <F2Section
            n={4} title="Annual income"
            description="Estimated gross annual income in KRW. Includes salary, business income, and other verifiable sources."
            score={scores.income} max={F2_SCORING.income.max}
            refEl={refs.income}
          >
            <RadioGrid
              options={F2_SCORING.income.brackets}
              value={inputs.income}
              onChange={(v) => update("income", v)}
              cols={2}
            />
          </F2Section>

          <F2Section
            n={5} title="Family & stay in Korea"
            description={`Bonus points for ties to Korea — capped at ${F2_SCORING.bonus.cap}.`}
            score={scores.bonus} max={F2_SCORING.bonus.cap}
            refEl={refs.bonus}
            extra={scores.bonusRaw > F2_SCORING.bonus.cap ? `Raw ${scores.bonusRaw} → capped at ${F2_SCORING.bonus.cap}` : null}
          >
            <div style={{ display: "flex", flexDirection: "column", gap: 14 }}>
              <Field label="Degree from a Korean institution">
                <SelectF2 value={inputs.koreanDegree} onChange={(v) => update("koreanDegree", v)} options={F2_SCORING.bonus.koreanDegree} />
              </Field>
              <Field label="Immediate family in Korea">
                <SelectF2 value={inputs.family} onChange={(v) => update("family", v)} options={F2_SCORING.bonus.family} />
              </Field>
              <Field label="Continuous years in Korea">
                <SelectF2 value={inputs.stay} onChange={(v) => update("stay", v)} options={F2_SCORING.bonus.stay} />
              </Field>
            </div>
          </F2Section>
        </div>

        {/* RIGHT: summary */}
        <div style={{ display: "flex", flexDirection: "column", gap: 18, minWidth: 0 }}>
          <F2GaugeCard total={animTotal} max={F2_SCORING.thresholdMax} pass={F2_SCORING.thresholdPass} tier={tier} />

          <SurfaceCard>
            <CardHead eyebrow="Breakdown" title="By category" />
            <ul style={{ listStyle: "none", margin: 0, padding: 0, display: "flex", flexDirection: "column", gap: 8 }}>
              <BreakdownRow label="Age"                value={scores.age}    max={F2_SCORING.age.max}        onAdjust={() => scrollTo("age")} />
              <BreakdownRow label="Education"          value={scores.edu}    max={F2_SCORING.education.max}  onAdjust={() => scrollTo("education")} />
              <BreakdownRow label="Korean & KIIP"      value={scores.korean} max={F2_SCORING.korean.max}     onAdjust={() => scrollTo("korean")} />
              <BreakdownRow label="Income"             value={scores.income} max={F2_SCORING.income.max}     onAdjust={() => scrollTo("income")} />
              <BreakdownRow label="Family / stay"      value={scores.bonus}  max={F2_SCORING.bonus.cap}      onAdjust={() => scrollTo("bonus")} capped={scores.bonusRaw > F2_SCORING.bonus.cap} />
            </ul>
          </SurfaceCard>

          <SurfaceCard style={{
            background: "linear-gradient(180deg, rgba(212,255,79,0.10) 0%, white 50%)",
            borderColor: "rgba(184,230,60,0.45)",
          }}>
            <CardHead eyebrow="Korico suggestions" title="How to improve your score" />
            {tips.length === 0 ? (
              <p style={{ fontSize: 13, color: "var(--text-mute)", lineHeight: 1.55 }}>
                You're scoring well across the board. Keep your records clean and revisit before applying.
              </p>
            ) : (
              <ul style={{ listStyle: "none", margin: 0, padding: 0, display: "flex", flexDirection: "column", gap: 8 }}>
                {tips.map((t, i) => (
                  <li key={i} style={{
                    display: "flex", alignItems: "flex-start", gap: 10,
                    fontSize: 13, color: "var(--ink)", lineHeight: 1.55,
                  }}>
                    <span style={{
                      width: 22, height: 22, borderRadius: "50%",
                      background: "var(--ink)", color: "var(--lime)",
                      display: "inline-flex", alignItems: "center", justifyContent: "center",
                      flexShrink: 0, fontSize: 10, fontWeight: 700, marginTop: 1,
                    }}>{i + 1}</span>
                    {t}
                  </li>
                ))}
              </ul>
            )}
          </SurfaceCard>

          <AskShortcutCard
            eyebrow="Ask Korico"
            title="Talk through your F-2 chances"
            prefill={`I estimated my F-2 score at ${scores.total}/${F2_SCORING.thresholdMax} with age=${inputs.age}, education=${inputs.education}, TOPIK=${inputs.topik}, income=${inputs.income}. What's the most realistic way to improve before applying?`}
          />
        </div>

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

function buildTips(scores, inputs) {
  const tips = [];
  if (scores.korean < 16) {
    tips.push(`Improving TOPIK by one level (currently ${inputs.topik}) or completing the next KIIP stage (currently ${inputs.kiip}) can add 4–8 more points.`);
  }
  if (scores.income < 35) {
    tips.push("Higher verified annual income (next bracket) brings 10–20 more points — wait for a promotion, or document side income properly.");
  }
  if (scores.stay < 10) {
    tips.push("Continuous years in Korea matter — staying past 5 years adds another 5–10 points without anything else changing.");
  }
  if (scores.koreanDegree < 10) {
    tips.push("Earning a degree from a Korean institution adds 5–20 points and unlocks faster D-10 → F-2 paths.");
  }
  if (scores.edu < 15) {
    tips.push("Pursuing a higher degree (Master's or PhD) lifts Education from " + scores.edu + " toward 20–25.");
  }
  return tips.slice(0, 3);
}

/* ---- Section wrapper ---- */

function F2Section({ n, title, description, score, max, refEl, extra, children }) {
  return (
    <section
      ref={refEl}
      style={{
        background: "white",
        borderRadius: 18,
        border: "1px solid var(--border-soft)",
        padding: "20px 22px",
        scrollMarginTop: 16,
      }}>
      <header style={{
        display: "flex", justifyContent: "space-between", alignItems: "flex-start",
        gap: 12, marginBottom: 16,
      }}>
        <div style={{ display: "flex", alignItems: "flex-start", gap: 12, minWidth: 0 }}>
          <div style={{
            width: 30, height: 30, borderRadius: 9,
            background: "var(--ink)", color: "var(--lime)",
            display: "inline-flex", alignItems: "center", justifyContent: "center",
            fontFamily: "var(--font-body)", fontWeight: 700, fontSize: 13,
            flexShrink: 0,
          }}>{n}</div>
          <div style={{ minWidth: 0 }}>
            <h3 style={{
              fontSize: 15, fontWeight: 600, color: "var(--ink)",
              letterSpacing: "-0.015em",
            }}>{title}</h3>
            <p style={{
              fontSize: 12, color: "var(--text-mute)", marginTop: 3, lineHeight: 1.5,
            }}>{description}</p>
          </div>
        </div>
        <div style={{
          padding: "6px 12px", borderRadius: 99,
          background: "var(--lime)", color: "var(--ink)",
          fontFamily: "var(--font-display)", fontSize: 18, fontWeight: 400,
          letterSpacing: "-0.02em", flexShrink: 0,
        }}>
          {score}<span style={{
            fontSize: 11, color: "rgba(11,27,44,0.55)", marginLeft: 4,
            fontFamily: "var(--font-body)", fontWeight: 600,
          }}>/ {max}</span>
        </div>
      </header>
      {children}
      {extra && (
        <div style={{
          marginTop: 10, fontSize: 11, color: "var(--text-mute)", fontStyle: "italic",
        }}>{extra}</div>
      )}
    </section>
  );
}

function RadioGrid({ options, value, onChange, cols }) {
  return (
    <div style={{
      display: "grid", gridTemplateColumns: `repeat(${cols}, 1fr)`, gap: 8,
    }} className="radio-grid">
      {options.map((o) => {
        const on = value === o.v;
        return (
          <button key={o.v} type="button" onClick={() => onChange(o.v)}
            style={{
              display: "flex", alignItems: "center", justifyContent: "space-between",
              gap: 10, padding: "11px 14px",
              borderRadius: 12, textAlign: "left",
              background: on ? "var(--ink)" : "white",
              color: on ? "white" : "var(--ink)",
              border: `1px solid ${on ? "var(--ink)" : "var(--border)"}`,
              transition: "all 0.18s ease",
            }}
            onMouseEnter={(e) => { if (!on) { e.currentTarget.style.borderColor = "var(--ink)"; }}}
            onMouseLeave={(e) => { if (!on) { e.currentTarget.style.borderColor = "var(--border)"; }}}
          >
            <span style={{ fontSize: 12.5, fontWeight: on ? 600 : 500, letterSpacing: "-0.005em" }}>{o.label}</span>
            <span style={{
              fontSize: 11, fontWeight: 700,
              color: on ? "var(--lime)" : "var(--text-mute)",
              flexShrink: 0,
            }}>{o.pts > 0 ? `+${o.pts}` : "0"}</span>
          </button>
        );
      })}
      <style>{`@media (max-width: 720px) { .radio-grid { grid-template-columns: 1fr !important; }}`}</style>
    </div>
  );
}

function SelectF2({ value, onChange, options }) {
  return (
    <div style={{ position: "relative" }}>
      <select value={value} onChange={(e) => onChange(e.target.value)} style={{
        width: "100%", padding: "11px 38px 11px 14px",
        borderRadius: 12, border: "1px solid var(--border)",
        fontFamily: "var(--font-body)",
        fontSize: 13.5, color: "var(--ink)", outline: "none",
        appearance: "none", WebkitAppearance: "none",
        background: "white",
      }}>
        {options.map((o) => (
          <option key={o.v} value={o.v}>{o.label} · {o.pts > 0 ? `+${o.pts}` : "0"}</option>
        ))}
      </select>
      <i className="ti ti-chevron-down" style={{
        position: "absolute", right: 12, top: "50%", transform: "translateY(-50%)",
        fontSize: 16, color: "var(--text-mute)", pointerEvents: "none",
      }} />
    </div>
  );
}

function F2GaugeCard({ total, max, pass, tier }) {
  const pct = Math.max(0, Math.min(100, (total / max) * 100));
  const passPct = (pass / max) * 100;
  return (
    <SurfaceCard>
      <CardHead eyebrow="Your estimated score" title="F-2 points total" />
      <div style={{
        display: "flex", alignItems: "baseline", gap: 8, marginTop: 4,
      }}>
        <div style={{
          fontFamily: "var(--font-display)",
          fontSize: 58, color: "var(--ink)",
          lineHeight: 1, letterSpacing: "-0.03em",
        }}>{total}</div>
        <div style={{ fontSize: 14, color: "var(--text-mute)", fontWeight: 500 }}>
          / {max} points
        </div>
      </div>

      <div style={{
        position: "relative", marginTop: 14,
        height: 12, borderRadius: 99,
        background: "linear-gradient(90deg, var(--danger-soft) 0%, var(--warning-soft) 45%, var(--success-soft) 80%)",
        overflow: "visible",
      }}>
        {/* Filled portion */}
        <div style={{
          position: "absolute", left: 0, top: 0, bottom: 0,
          width: `${pct}%`,
          background: "linear-gradient(90deg, var(--danger) 0%, var(--warning) 45%, var(--success) 80%)",
          borderRadius: 99,
          transition: "width 0.45s cubic-bezier(0.2,0.7,0.2,1)",
        }} />
        {/* Pass threshold marker */}
        <div style={{
          position: "absolute", left: `${passPct}%`, top: -4, bottom: -4,
          width: 2, background: "var(--ink)",
        }} />
        <div style={{
          position: "absolute", left: `calc(${passPct}% - 28px)`, top: -22,
          fontSize: 9.5, fontWeight: 700, color: "var(--ink)",
          letterSpacing: "0.08em", textTransform: "uppercase",
          background: "white", padding: "2px 6px", borderRadius: 4,
          border: "1px solid var(--border)",
          whiteSpace: "nowrap",
        }}>Pass · {pass}</div>
      </div>

      <div style={{
        marginTop: 16, display: "flex", alignItems: "center", justifyContent: "space-between",
        padding: "10px 14px", borderRadius: 12,
        background: tier.soft, color: tier.color,
      }}>
        <span style={{ fontSize: 12, fontWeight: 700, letterSpacing: "0.14em", textTransform: "uppercase" }}>
          {tier.label}
        </span>
        <span style={{ fontSize: 11.5, fontWeight: 500 }}>
          {total >= pass
            ? `+${total - pass} above the typical threshold`
            : `${pass - total} more to reach ${pass}`}
        </span>
      </div>
    </SurfaceCard>
  );
}

function BreakdownRow({ label, value, max, onAdjust, capped }) {
  const pct = Math.min(100, (value / max) * 100);
  return (
    <li style={{
      display: "grid", gridTemplateColumns: "1fr auto", gap: 8,
      padding: "10px 12px", borderRadius: 12,
      background: "white", border: "1px solid var(--border-soft)",
    }}>
      <div style={{ minWidth: 0 }}>
        <div style={{ display: "flex", alignItems: "baseline", gap: 8 }}>
          <span style={{ fontSize: 12.5, fontWeight: 600, color: "var(--ink)" }}>{label}</span>
          <span style={{ fontSize: 11, color: "var(--text-mute)" }}>{value} / {max}</span>
          {capped && <span style={{ fontSize: 9.5, color: "var(--warning)", fontWeight: 600, letterSpacing: "0.06em", textTransform: "uppercase" }}>capped</span>}
        </div>
        <div style={{
          marginTop: 6, height: 5, borderRadius: 99,
          background: "var(--bg-soft)", overflow: "hidden",
        }}>
          <div style={{
            width: `${pct}%`, height: "100%",
            background: "var(--ink)",
            borderRadius: 99,
            transition: "width 0.4s cubic-bezier(0.2,0.7,0.2,1)",
          }} />
        </div>
      </div>
      <button onClick={onAdjust} style={{
        alignSelf: "center",
        fontSize: 11, fontWeight: 600, color: "var(--ink)",
        textDecoration: "underline", textUnderlineOffset: 3,
        textDecorationColor: "var(--border)",
      }}>Adjust</button>
    </li>
  );
}

/* ============================================================
   VISA PLAN — D-2 → D-10 transition (step-by-step workspace)
   ============================================================ */

const D2D10_PLAN = [
  {
    id: "elig",
    icon: "shield-check",
    title: "Confirm you're eligible for D-10",
    summary: "Quick check of the basic requirements so we don't waste a trip to immigration.",
    why: "D-10-1 is for university graduates in Korea looking for work. Most applications fail because of a missing eligibility detail — let's get it right first.",
    tasks: [
      { id: "e1", label: "Graduating within 3 months, or graduated in the last 3 years" },
      { id: "e2", label: "Bachelor's degree or higher (or equivalent overseas qualification)" },
      { id: "e3", label: "No overstay history on previous Korean visas" },
      { id: "e4", label: "₩3,000,000+ in your bank account (or sponsor letter)" },
    ],
    estimated: "~5 minutes",
  },
  {
    id: "docs",
    icon: "folder",
    title: "Gather your documents",
    summary: "Pull everything Korico needs to attach to your application. We'll reuse what's already in My files.",
    why: "Immigration officers process dozens of applications a day. Showing up with a complete folder is half the battle.",
    tasks: [
      { id: "d1", label: "Passport (valid; all pages photocopied)", linkLabel: "Open My files", linkRoute: "files" },
      { id: "d2", label: "ARC scan (front + back)", linkLabel: "ARC page", linkRoute: "arc" },
      { id: "d3", label: "Graduation certificate or expected-graduation letter" },
      { id: "d4", label: "Final transcript (or latest semester)" },
      { id: "d5", label: "Bank statement (last 1 month, ₩3,000,000+)" },
      { id: "d6", label: "Proof of residence (lease / 전입신고 확인서)" },
      { id: "d7", label: "Passport-size photo (3.5×4.5 cm)" },
    ],
    estimated: "30–45 minutes",
  },
  {
    id: "plan",
    icon: "writing-sign",
    title: "Write your job-seeking plan",
    summary: "구직활동 계획서 — the document immigration looks at most carefully.",
    why: "This plan tells immigration why your stay matters. Specifics about industry, role, and timeline beat vague ambitions.",
    tasks: [
      { id: "p1", label: "Pick 1–2 target industries (e.g. AI/ML, biotech)" },
      { id: "p2", label: "List 3–5 specific job titles you're applying to" },
      { id: "p3", label: "Note your TOPIK level + any other Korean ability" },
      { id: "p4", label: "Draft a 3–6 month milestone timeline" },
      { id: "p5", label: "Use Korico's job-plan template", linkLabel: "Open template", linkRoute: "forms" },
    ],
    estimated: "1–2 hours",
  },
  {
    id: "submit",
    icon: "send",
    title: "Book your appointment & submit",
    summary: "Reserve a slot on HiKorea, fill the application, pay the fee, hand everything over.",
    why: "Walk-ins exist but the wait can be 3+ hours. Booking ahead keeps things calm.",
    tasks: [
      { id: "s1", label: "Reserve a slot on HiKorea (또는 walk-in at your immigration office)" },
      { id: "s2", label: "Complete the integrated application (통합신청서)", linkLabel: "Fill with Korico", linkRoute: "form-fill-d2" },
      { id: "s3", label: "Pay the application fee (~₩60,000)" },
      { id: "s4", label: "Bring originals + photocopies of every document" },
    ],
    estimated: "Half-day visit",
  },
  {
    id: "after",
    icon: "calendar-check",
    title: "Wait for the decision & plan your job search",
    summary: "Processing usually takes 2–4 weeks. Use the time to set up interviews.",
    why: "D-10 lets you stay 6 months at a time (extendable up to 2 years). The clock starts when it's issued.",
    tasks: [
      { id: "a1", label: "Track status on HiKorea (or check email)" },
      { id: "a2", label: "Start applying — list which roles + companies", linkLabel: "Talk to Korico", linkRoute: "chat" },
      { id: "a3", label: "Plan the next extension before you hit month 6" },
    ],
    estimated: "2–4 weeks waiting",
  },
];

function VisaPlanD2D10Page({ onNavigate }) {
  // Per-task done state, persisted only for the lifetime of the session
  const [done, setDone] = useState({});
  const [expanded, setExpanded] = useState(D2D10_PLAN[0].id);

  const toggleTask = (id) => setDone((d) => ({ ...d, [id]: !d[id] }));
  const stepStatus = (step) => {
    const ids = step.tasks.map((t) => t.id);
    const completed = ids.filter((id) => done[id]).length;
    if (completed === 0) return { state: "todo", completed };
    if (completed === ids.length) return { state: "done", completed };
    return { state: "active", completed };
  };

  const totalTasks = D2D10_PLAN.reduce((s, st) => s + st.tasks.length, 0);
  const doneTasks  = D2D10_PLAN.reduce((s, st) => s + st.tasks.filter((t) => done[t.id]).length, 0);
  const pct = Math.round((doneTasks / totalTasks) * 100);

  return (
    <div style={{
      maxWidth: 1200,
      animation: "fade-up 0.5s cubic-bezier(0.2,0.7,0.2,1) both",
      animationDelay: "0.05s",
    }}>
      <BackBar onBack={() => onNavigate("visa")} label="Visa & status" />

      {/* Hero / progress */}
      <SurfaceCard style={{
        background: "linear-gradient(180deg, rgba(212,255,79,0.10) 0%, white 60%)",
        borderColor: "rgba(184,230,60,0.45)",
        marginBottom: 18,
      }}>
        <div style={{
          display: "grid", gridTemplateColumns: "1fr auto", gap: 18,
          alignItems: "center",
        }} className="plan-hero">
          <div>
            <div style={{
              fontSize: 10, fontWeight: 600, color: "var(--text-mute)",
              letterSpacing: "0.18em", textTransform: "uppercase",
            }}>Korico plan</div>
            <h2 style={{
              fontSize: 22, fontWeight: 600, color: "var(--ink)",
              letterSpacing: "-0.02em", marginTop: 4,
            }}>D-2 → D-10 transition</h2>
            <p style={{
              fontSize: 13, color: "var(--text-mute)", lineHeight: 1.55,
              marginTop: 6, maxWidth: 560,
            }}>
              Five focused steps to switch from student to job-seeker visa. Tap a step to expand it. Korico saves your progress automatically.
            </p>
          </div>
          <div style={{
            background: "var(--ink)", color: "white",
            borderRadius: 16, padding: "14px 20px",
            minWidth: 180, textAlign: "center",
          }}>
            <div style={{
              fontSize: 10, fontWeight: 600, color: "rgba(255,255,255,0.6)",
              letterSpacing: "0.16em", textTransform: "uppercase",
            }}>Progress</div>
            <div style={{
              fontFamily: "var(--font-display)",
              fontSize: 30, color: "var(--lime)", lineHeight: 1.1, marginTop: 2,
            }}>{pct}%</div>
            <div style={{ fontSize: 11, color: "rgba(255,255,255,0.7)", marginTop: 2 }}>
              {doneTasks} of {totalTasks} tasks
            </div>
          </div>
        </div>

        {/* Progress bar */}
        <div style={{
          marginTop: 18, height: 5, borderRadius: 99,
          background: "var(--bg-soft)", overflow: "hidden",
        }}>
          <div style={{
            width: `${pct}%`, height: "100%",
            background: "linear-gradient(90deg, var(--lime), var(--lime-deep))",
            borderRadius: 99,
            transition: "width 0.5s cubic-bezier(0.2,0.7,0.2,1)",
          }} />
        </div>
      </SurfaceCard>

      <div style={{
        display: "grid", gridTemplateColumns: "1.6fr 1fr", gap: 18,
      }} className="plan-grid">

        {/* Timeline of steps */}
        <div style={{ display: "flex", flexDirection: "column", gap: 12, minWidth: 0 }}>
          {D2D10_PLAN.map((step, i) => {
            const status = stepStatus(step);
            const isOpen = expanded === step.id;
            return (
              <PlanStepCard
                key={step.id}
                step={step}
                index={i}
                status={status}
                isOpen={isOpen}
                onToggle={() => setExpanded(isOpen ? null : step.id)}
                done={done}
                onTaskToggle={toggleTask}
                onNavigate={onNavigate}
                isLast={i === D2D10_PLAN.length - 1}
              />
            );
          })}
        </div>

        {/* Side rail */}
        <div style={{ display: "flex", flexDirection: "column", gap: 18, minWidth: 0 }}>
          <PlanSideStats doneTasks={doneTasks} totalTasks={totalTasks} />
          <PlanQuickActions onNavigate={onNavigate} />
          <AskShortcutCard
            eyebrow="Ask Korico"
            title="Stuck on a step?"
            prefill="I'm planning my D-2 → D-10 transition. Can you walk me through what's most important to prepare next?"
          />
        </div>

        <style>{`
          @media (max-width: 1080px) { .plan-grid { grid-template-columns: 1fr !important; }}
          @media (max-width: 640px)  { .plan-hero { grid-template-columns: 1fr !important; }}
        `}</style>
      </div>
    </div>
  );
}

function PlanStepCard({ step, index, status, isOpen, onToggle, done, onTaskToggle, onNavigate, isLast }) {
  const completed = status.completed;
  const total = step.tasks.length;

  // Status visual tokens
  const tokens = {
    done:   { bg: "var(--success-soft)", fg: "var(--success)", label: "Done" },
    active: { bg: "var(--lime)",         fg: "var(--ink)",     label: "In progress" },
    todo:   { bg: "var(--bg-soft)",      fg: "var(--text-mute)", label: "Not started" },
  }[status.state];

  return (
    <article style={{
      position: "relative",
      background: "white",
      border: "1px solid " + (isOpen ? "rgba(11,27,44,0.16)" : "var(--border-soft)"),
      borderRadius: 18,
      transition: "border-color 0.22s ease, box-shadow 0.22s ease",
      boxShadow: isOpen ? "0 16px 36px rgba(11,27,44,0.06)" : "none",
      overflow: "hidden",
    }}>

      {/* Header row */}
      <button onClick={onToggle} style={{
        display: "grid",
        gridTemplateColumns: "auto 1fr auto",
        gap: 16, alignItems: "center",
        padding: "16px 18px",
        background: "transparent",
        width: "100%", textAlign: "left",
        cursor: "pointer",
      }}>
        <div style={{
          width: 44, height: 44, borderRadius: 12,
          background: status.state === "done" ? "var(--ink)" : "var(--bg-soft)",
          color: status.state === "done" ? "var(--lime)" : "var(--ink)",
          display: "inline-flex", alignItems: "center", justifyContent: "center",
          flexShrink: 0, position: "relative",
        }}>
          {status.state === "done"
            ? <i className="ti ti-check" style={{ fontSize: 20 }} />
            : <i className={`ti ti-${step.icon}`} style={{ fontSize: 20 }} />}
          <span style={{
            position: "absolute", top: -6, right: -6,
            background: "white", color: "var(--ink)",
            border: "1px solid var(--border)",
            borderRadius: 99, padding: "1px 6px",
            fontSize: 9, fontWeight: 700, letterSpacing: "0.06em",
          }}>{index + 1}</span>
        </div>

        <div style={{ minWidth: 0 }}>
          <div style={{
            fontSize: 14.5, fontWeight: 600, color: "var(--ink)",
            letterSpacing: "-0.01em",
          }}>{step.title}</div>
          <div style={{ fontSize: 12, color: "var(--text-mute)", marginTop: 3, lineHeight: 1.5 }}>
            {step.summary}
          </div>
          <div style={{ display: "inline-flex", alignItems: "center", gap: 8, marginTop: 8 }}>
            <span style={{
              padding: "3px 8px", borderRadius: 99,
              background: tokens.bg, color: tokens.fg,
              fontSize: 9.5, fontWeight: 700, letterSpacing: "0.12em", textTransform: "uppercase",
            }}>{tokens.label}</span>
            <span style={{ fontSize: 11, color: "var(--text-mute)" }}>
              {completed}/{total} tasks · {step.estimated}
            </span>
          </div>
        </div>

        <i className={`ti ti-chevron-${isOpen ? "up" : "down"}`}
          style={{ fontSize: 18, color: "var(--text-mute)", flexShrink: 0 }} />
      </button>

      {/* Expanded body */}
      {isOpen && (
        <div style={{
          padding: "0 18px 18px 78px",
          borderTop: "1px solid var(--border-soft)",
          animation: "fade-up 0.3s cubic-bezier(0.2,0.7,0.2,1) both",
        }}>
          {/* Why */}
          <p style={{
            fontSize: 12.5, color: "var(--text-soft)", lineHeight: 1.6,
            margin: "14px 0 14px",
          }}>{step.why}</p>

          {/* Task checklist */}
          <ul style={{
            listStyle: "none", margin: 0, padding: 0,
            display: "flex", flexDirection: "column", gap: 6,
          }}>
            {step.tasks.map((task) => {
              const isDone = !!done[task.id];
              return (
                <li key={task.id} style={{
                  display: "flex", alignItems: "center", gap: 12,
                  padding: "9px 10px", borderRadius: 10,
                  background: isDone ? "var(--bg-soft)" : "transparent",
                  transition: "background 0.18s ease",
                }}>
                  <button
                    onClick={() => onTaskToggle(task.id)}
                    style={{
                      width: 20, height: 20, borderRadius: 6,
                      background: isDone ? "var(--ink)" : "white",
                      border: isDone ? "none" : "1.5px solid var(--border)",
                      color: "var(--lime)",
                      display: "inline-flex", alignItems: "center", justifyContent: "center",
                      flexShrink: 0,
                      transition: "background 0.18s ease, border-color 0.18s ease",
                    }}>
                    {isDone && <i className="ti ti-check" style={{ fontSize: 12, animation: "check-pop 0.3s cubic-bezier(0.2,1.4,0.4,1) both" }} />}
                  </button>
                  <span style={{
                    flex: 1, fontSize: 13, fontWeight: 500,
                    color: isDone ? "var(--text-mute)" : "var(--ink)",
                    textDecoration: isDone ? "line-through" : "none",
                    letterSpacing: "-0.005em",
                  }}>{task.label}</span>
                  {task.linkRoute && (
                    <button
                      onClick={(e) => { e.stopPropagation(); onNavigate?.(task.linkRoute); }}
                      style={{
                        display: "inline-flex", alignItems: "center", gap: 4,
                        padding: "4px 10px", borderRadius: 99,
                        background: "white", color: "var(--ink)",
                        border: "1px solid var(--border)",
                        fontSize: 10.5, fontWeight: 600, letterSpacing: "0.06em",
                        whiteSpace: "nowrap",
                      }}
                      onMouseEnter={(e) => e.currentTarget.style.background = "var(--bg-soft)"}
                      onMouseLeave={(e) => e.currentTarget.style.background = "white"}
                    >
                      {task.linkLabel}
                      <i className="ti ti-arrow-up-right" style={{ fontSize: 11 }} />
                    </button>
                  )}
                </li>
              );
            })}
          </ul>
        </div>
      )}
    </article>
  );
}

function PlanSideStats({ doneTasks, totalTasks }) {
  const remaining = totalTasks - doneTasks;
  return (
    <SurfaceCard>
      <div style={{
        fontSize: 10, fontWeight: 600, color: "var(--text-mute)",
        letterSpacing: "0.18em", textTransform: "uppercase",
      }}>Overview</div>
      <div style={{
        display: "grid", gridTemplateColumns: "1fr 1fr", gap: 12,
        marginTop: 10,
      }}>
        <StatTile label="Tasks left" value={remaining} tone="ink" />
        <StatTile label="Steps" value={D2D10_PLAN.length} tone="lime" />
      </div>
      <div style={{
        marginTop: 14, padding: "10px 14px", borderRadius: 12,
        background: "var(--bg-soft)",
        fontSize: 12, color: "var(--text-soft)", lineHeight: 1.55,
      }}>
        Tip: D-10 applications are usually approved within <strong style={{ color: "var(--ink)" }}>2–4 weeks</strong>. Start at least <strong style={{ color: "var(--ink)" }}>6 weeks</strong> before your D-2 expires.
      </div>
    </SurfaceCard>
  );
}

function StatTile({ label, value, tone }) {
  const palette = tone === "ink"
    ? { bg: "var(--ink)", fg: "var(--lime)" }
    : { bg: "var(--lime)", fg: "var(--ink)" };
  return (
    <div style={{
      padding: "12px 14px", borderRadius: 14,
      background: palette.bg, color: palette.fg,
    }}>
      <div style={{
        fontSize: 9.5, fontWeight: 600, letterSpacing: "0.16em",
        textTransform: "uppercase", opacity: 0.75,
      }}>{label}</div>
      <div style={{
        fontFamily: "var(--font-display)",
        fontSize: 28, fontWeight: 400, letterSpacing: "-0.02em",
        lineHeight: 1.1, marginTop: 2,
      }}>{value}</div>
    </div>
  );
}

function PlanQuickActions({ onNavigate }) {
  const items = [
    { icon: "file-text", label: "Open D-2 → D-10 form",         route: "form-fill-d2" },
    { icon: "folder",    label: "Browse my documents",         route: "files" },
    { icon: "credit-card", label: "ARC details",               route: "arc" },
  ];
  return (
    <SurfaceCard>
      <div style={{
        fontSize: 10, fontWeight: 600, color: "var(--text-mute)",
        letterSpacing: "0.18em", textTransform: "uppercase",
        marginBottom: 10,
      }}>Quick actions</div>
      <div style={{ display: "flex", flexDirection: "column", gap: 6 }}>
        {items.map((it) => (
          <button key={it.label} onClick={() => onNavigate?.(it.route)} style={{
            display: "flex", alignItems: "center", gap: 12,
            padding: "10px 12px", borderRadius: 12,
            background: "white", border: "1px solid var(--border-soft)",
            textAlign: "left", width: "100%",
            transition: "background 0.18s ease, border-color 0.18s ease",
          }}
            onMouseEnter={(e) => { e.currentTarget.style.background = "var(--bg-soft)"; e.currentTarget.style.borderColor = "var(--border)"; }}
            onMouseLeave={(e) => { e.currentTarget.style.background = "white"; e.currentTarget.style.borderColor = "var(--border-soft)"; }}
          >
            <span style={{
              width: 28, height: 28, borderRadius: 8,
              background: "var(--bg-soft)", color: "var(--ink)",
              display: "inline-flex", alignItems: "center", justifyContent: "center",
              flexShrink: 0,
            }}><i className={`ti ti-${it.icon}`} style={{ fontSize: 14 }} /></span>
            <span style={{ flex: 1, fontSize: 12.5, fontWeight: 500, color: "var(--ink)" }}>{it.label}</span>
            <i className="ti ti-arrow-right" style={{ fontSize: 13, color: "var(--text-mute)" }} />
          </button>
        ))}
      </div>
    </SurfaceCard>
  );
}

/* ============================================================
   ARC PAGE
   ============================================================ */

const ARC_DOCS = [
  { name: "ARC front photo",                file: "arc-front.jpg",          date: "2024.03.22", status: "verified" },
  { name: "ARC back photo",                 file: "arc-back.jpg",           date: "2024.03.22", status: "verified" },
  { name: "Proof of address (전입신고 확인서)", file: "address-2024-04.pdf",  date: "2024.04.05", status: "uploaded" },
];

function ArcPage() {
  const [changes, setChanges] = useState({
    address: false,
    school: false,
    other: false,
  });
  const anyChecked = changes.address || changes.school || changes.other;

  return (
    <div style={{
      display: "grid", gridTemplateColumns: "1.5fr 1fr", gap: 22,
      animation: "fade-up 0.5s cubic-bezier(0.2,0.7,0.2,1) both",
      animationDelay: "0.05s",
      maxWidth: 1280,
    }} className="page-grid">
      <div style={{ display: "flex", flexDirection: "column", gap: 22, minWidth: 0 }}>
        <ArcSummaryCard />
        <ArcChangesCard changes={changes} setChanges={setChanges} anyChecked={anyChecked} />
        <ArcRulesCard />
      </div>
      <div style={{ display: "flex", flexDirection: "column", gap: 22, minWidth: 0 }}>
        <ArcDocsCard />
        <AskShortcutCard
          eyebrow="Ask Korico"
          title="ARC question?"
          prefill="I moved to a new apartment 2 months ago but didn't report it yet. What should I do about my ARC?"
        />
      </div>

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

function ArcSummaryCard() {
  return (
    <SurfaceCard>
      <header style={{ display: "flex", alignItems: "flex-start", gap: 14, marginBottom: 18 }}>
        <div style={{
          width: 48, height: 48, borderRadius: 14,
          background: "var(--lime)", color: "var(--ink)",
          display: "inline-flex", alignItems: "center", justifyContent: "center",
          flexShrink: 0,
        }}>
          <i className="ti ti-credit-card" style={{ fontSize: 22 }} />
        </div>
        <div style={{ flex: 1, minWidth: 0 }}>
          <div style={{
            fontSize: 10, fontWeight: 600, color: "var(--text-mute)",
            letterSpacing: "0.18em", textTransform: "uppercase",
          }}>Alien Registration Card</div>
          <h2 style={{
            fontSize: 24, fontWeight: 600, letterSpacing: "-0.02em",
            color: "var(--ink)", marginTop: 4,
          }}>****-1234</h2>
          <div style={{ fontSize: 12.5, color: "var(--text-mute)", marginTop: 4 }}>
            Korico only stores the last 4 digits.
          </div>
        </div>
        <span style={{
          padding: "5px 12px", borderRadius: 99,
          background: "var(--success-soft)", color: "var(--success)",
          fontSize: 10, fontWeight: 700, letterSpacing: "0.14em", textTransform: "uppercase",
        }}>Active</span>
      </header>

      <div style={{
        display: "grid", gridTemplateColumns: "1fr 1fr", gap: 14,
        padding: "16px", borderRadius: 14, background: "var(--bg-soft)",
      }} className="arc-kv">
        <ArcKV label="Issue date" value="2024.03.22" />
        <ArcKV label="Expiry" value="2026.03.15" />
        <ArcKV label="Registered address" value="Seoul · Seodaemun-gu" />
        <ArcKV label="Registered purpose" value="Study (D-2)" />
      </div>

      <div style={{
        marginTop: 14, padding: "10px 14px", borderRadius: 12,
        background: "var(--warning-soft)", color: "var(--warning)",
        display: "inline-flex", alignItems: "center", gap: 10,
        fontSize: 12.5, fontWeight: 500,
      }}>
        <i className="ti ti-alert-triangle" style={{ fontSize: 16 }} />
        Expires in 146 days · plan extension during your visa change.
      </div>

      <style>{`
        @media (max-width: 560px) { .arc-kv { grid-template-columns: 1fr !important; }}
      `}</style>
    </SurfaceCard>
  );
}

function ArcKV({ label, value }) {
  return (
    <div>
      <div style={{
        fontSize: 10, color: "var(--text-mute)", fontWeight: 600,
        letterSpacing: "0.16em", textTransform: "uppercase",
      }}>{label}</div>
      <div style={{
        fontSize: 13.5, color: "var(--ink)", marginTop: 4, fontWeight: 500,
        letterSpacing: "-0.005em",
      }}>{value}</div>
    </div>
  );
}

function ArcChangesCard({ changes, setChanges, anyChecked }) {
  const toggle = (k) => setChanges({ ...changes, [k]: !changes[k] });
  return (
    <SurfaceCard>
      <CardHead
        eyebrow="Updates"
        title="Address & info changes"
        subtitle="By law, you must report most changes within 14 days."
      />
      <div style={{ display: "flex", flexDirection: "column", gap: 8 }}>
        <ToggleRow
          checked={changes.address}
          onToggle={() => toggle("address")}
          icon="map-pin"
          label="My address changed after I moved"
          hint="전입신고 + ARC address update needed."
        />
        <ToggleRow
          checked={changes.school}
          onToggle={() => toggle("school")}
          icon="school"
          label="My school or workplace changed"
          hint="School/workplace change must be reported to immigration."
        />
        <ToggleRow
          checked={changes.other}
          onToggle={() => toggle("other")}
          icon="info-circle"
          label="Other info changed"
          hint="Marital status, passport number, name, etc."
        />
      </div>

      {anyChecked && (
        <div style={{
          marginTop: 16, padding: "14px 16px", borderRadius: 14,
          background: "var(--bg-soft)",
          display: "flex", alignItems: "center", justifyContent: "space-between", gap: 12,
          animation: "fade-up 0.3s cubic-bezier(0.2,0.7,0.2,1) both",
        }}>
          <div style={{ fontSize: 12.5, color: "var(--text-soft)", lineHeight: 1.5 }}>
            We'll add a step-by-step checklist to your today's tasks and remind you 3 days before any deadline.
          </div>
          <div style={{ display: "inline-flex", gap: 8, flexShrink: 0 }}>
            <button style={{
              padding: "9px 14px", borderRadius: 99,
              background: "white", color: "var(--ink)",
              border: "1px solid var(--border)",
              fontSize: 11, fontWeight: 600, letterSpacing: "0.1em", textTransform: "uppercase",
            }}>Open guide</button>
            <button style={{
              padding: "9px 14px", borderRadius: 99,
              background: "var(--ink)", color: "var(--lime)",
              fontSize: 11, fontWeight: 700, letterSpacing: "0.12em", textTransform: "uppercase",
            }}>Create checklist</button>
          </div>
        </div>
      )}
    </SurfaceCard>
  );
}

function ToggleRow({ checked, onToggle, icon, label, hint }) {
  return (
    <button onClick={onToggle} style={{
      display: "flex", alignItems: "center", gap: 12,
      padding: "14px 16px", borderRadius: 14,
      background: checked ? "rgba(212,255,79,0.16)" : "white",
      border: "1px solid " + (checked ? "rgba(184,230,60,0.55)" : "var(--border-soft)"),
      textAlign: "left", width: "100%",
      transition: "background 0.2s ease, border-color 0.2s ease",
    }}>
      <span style={{
        width: 36, height: 36, borderRadius: 10,
        background: checked ? "var(--ink)" : "var(--bg-soft)",
        color: checked ? "var(--lime)" : "var(--ink)",
        display: "inline-flex", alignItems: "center", justifyContent: "center",
        flexShrink: 0, transition: "background 0.2s ease, color 0.2s ease",
      }}>
        <i className={`ti ti-${icon}`} style={{ fontSize: 16 }} />
      </span>
      <div style={{ flex: 1, minWidth: 0 }}>
        <div style={{
          fontSize: 13.5, fontWeight: 600, color: "var(--ink)", letterSpacing: "-0.005em",
        }}>{label}</div>
        <div style={{ fontSize: 11.5, color: "var(--text-mute)", marginTop: 2 }}>{hint}</div>
      </div>
      <span style={{
        width: 38, height: 22, borderRadius: 99,
        background: checked ? "var(--ink)" : "var(--border)",
        position: "relative",
        transition: "background 0.2s ease",
        flexShrink: 0,
      }}>
        <span style={{
          position: "absolute", top: 2, left: checked ? 18 : 2,
          width: 18, height: 18, borderRadius: "50%",
          background: checked ? "var(--lime)" : "white",
          transition: "left 0.2s cubic-bezier(0.2,0.7,0.2,1), background 0.2s ease",
          boxShadow: "0 2px 4px rgba(0,0,0,0.18)",
        }} />
      </span>
    </button>
  );
}

function ArcDocsCard() {
  return (
    <SurfaceCard>
      <CardHead
        eyebrow="Documents"
        title="ARC document center"
        subtitle="Pulled from your file vault — tagged as ARC-related."
        right={
          <button style={{
            padding: "7px 12px", borderRadius: 99,
            background: "var(--ink)", color: "var(--lime)",
            fontSize: 10, fontWeight: 700, letterSpacing: "0.14em", textTransform: "uppercase",
            display: "inline-flex", alignItems: "center", gap: 6,
          }}>
            <i className="ti ti-upload" style={{ fontSize: 12 }} />
            Upload
          </button>
        }
      />
      <div style={{ display: "flex", flexDirection: "column", gap: 8 }}>
        {ARC_DOCS.map((d) => <DocRow key={d.name} d={d} />)}
      </div>
      <button style={{
        marginTop: 12, padding: "9px 14px", borderRadius: 12,
        background: "white", color: "var(--ink)",
        border: "1px dashed var(--border)",
        fontSize: 12, fontWeight: 500,
        display: "inline-flex", alignItems: "center", gap: 8,
      }}
        onMouseEnter={(e) => e.currentTarget.style.background = "var(--bg-soft)"}
        onMouseLeave={(e) => e.currentTarget.style.background = "white"}
      >
        <i className="ti ti-tag" style={{ fontSize: 14 }} />
        Tag a file as ARC document
      </button>
    </SurfaceCard>
  );
}

function ArcRulesCard() {
  const rules = [
    { icon: "calendar-plus",   text: "Register at immigration within 90 days of arrival on a long-term visa." },
    { icon: "map-pin",         text: "Report a new address within 14 days of moving (전입신고)." },
    { icon: "school",          text: "Report a change of school or workplace before the change takes effect." },
    { icon: "report-money",    text: "Late updates can trigger fines from ₩100,000 up to ₩1,000,000 depending on duration and case." },
  ];
  return (
    <SurfaceCard>
      <CardHead
        eyebrow="Important rules"
        title="ARC reminders &amp; penalties"
        subtitle="A quick refresher of the most-missed rules — Korico is not a law firm; confirm with official sources."
      />
      <ul style={{
        listStyle: "none", margin: 0, padding: 0,
        display: "flex", flexDirection: "column", gap: 8,
      }}>
        {rules.map((r) => (
          <li key={r.text} style={{
            display: "flex", alignItems: "center", gap: 10,
            padding: "10px 14px", borderRadius: 12,
            background: "white", border: "1px solid var(--border-soft)",
            fontSize: 12.5, color: "var(--text-soft)", lineHeight: 1.55,
          }}>
            <span style={{
              width: 26, height: 26, borderRadius: 8,
              background: "var(--bg-soft)", color: "var(--ink)",
              display: "inline-flex", alignItems: "center", justifyContent: "center",
              flexShrink: 0,
            }}><i className={`ti ti-${r.icon}`} style={{ fontSize: 14 }} /></span>
            {r.text}
          </li>
        ))}
      </ul>
      <div style={{
        marginTop: 14, fontSize: 11, color: "var(--text-mute)",
        fontStyle: "italic", lineHeight: 1.5,
      }}>
        Korico is not a law firm. Always confirm with HiKorea or a licensed 행정사 / lawyer for your specific case.
      </div>
    </SurfaceCard>
  );
}

/* ============================================================
   TAX & WORK PAGE
   ============================================================ */

const STATUS_OPTIONS = [
  { key: "none",      label: "No work in Korea",          icon: "ban" },
  { key: "parttime",  label: "Part-time student job (알바)", icon: "clock" },
  { key: "fulltime",  label: "Full-time employee",         icon: "briefcase" },
  { key: "freelance", label: "Freelance / multiple jobs",  icon: "shuffle" },
];

const SEED_JOBS = [
  {
    id: "j1",
    type: "Part-time",
    company: "Cafe Onion · Seongsu",
    startDate: "2025.03.04",
    endDate: null,
    payType: "시급",
    payAmount: "₩11,500/h",
    withholding: true,
    hasContract: true,
    notes: "20 hrs/week, weekday mornings.",
  },
  {
    id: "j2",
    type: "Internship",
    company: "Naver Labs",
    startDate: "2025.06.02",
    endDate: "2025.12.31",
    payType: "월급",
    payAmount: "₩1,500,000/mo",
    withholding: true,
    hasContract: false,
    notes: "ML research intern, 20 hrs/week.",
  },
];

const TAX_TASKS = [
  { id: "t1", label: "Check if your employer will do 연말정산 for you", due: "Before January", status: "todo" },
  { id: "t2", label: "Upload latest payslip or income summary",          due: "Anytime",        status: "progress" },
  { id: "t3", label: "Read guide: Taxes for D-2 students with 알바",      due: "When you can",   status: "todo" },
  { id: "t4", label: "Confirm tax residency status",                      due: "Within 30 days", status: "done" },
];

const TAX_GUIDES = [
  { icon: "school",     title: "Taxes for D-2 students with part-time jobs", sub: "What 알바 income means for your visa and taxes." },
  { icon: "building",   title: "Full-time employee taxes & 연말정산",          sub: "How year-end adjustment works for foreign hires." },
  { icon: "shuffle",    title: "Freelancers and multiple jobs",               sub: "When 종합소득세 신고 applies to you." },
];

function TaxPage({ onNavigate, taxState }) {
  const { taxStatus, setTaxStatus, jobs, setEditingJob } = taxState;

  const openAddJob = () => { setEditingJob(null); onNavigate("tax-newjob"); };
  const openJobDetail = (j) => { setEditingJob(j); onNavigate("tax-newjob"); };

  const fullCount = jobs.filter((j) => j.type === "Full-time").length;
  const partCount = jobs.filter((j) => j.type === "Part-time" || j.type === "Internship").length;
  const freeCount = jobs.filter((j) => j.type === "Freelance").length;

  return (
    <div style={{
      display: "grid", gridTemplateColumns: "1.5fr 1fr", gap: 22,
      animation: "fade-up 0.5s cubic-bezier(0.2,0.7,0.2,1) both",
      animationDelay: "0.05s",
      maxWidth: 1280, position: "relative",
    }} className="page-grid">
      <div style={{ display: "flex", flexDirection: "column", gap: 22, minWidth: 0 }}>
        <WorkStatusCard status={taxStatus} setStatus={setTaxStatus} jobs={jobs} fullCount={fullCount} partCount={partCount} freeCount={freeCount} />
        <JobsCard jobs={jobs} onAdd={openAddJob} onOpen={openJobDetail} />
      </div>
      <div style={{ display: "flex", flexDirection: "column", gap: 22, minWidth: 0 }}>
        <TaxOverviewCard status={taxStatus} jobs={jobs} />
        <QuickLinksCard onNavigate={onNavigate} />
        <AskShortcutCard
          eyebrow="Ask Korico"
          title="Tax &amp; work questions"
          prefill="I'm on D-2 and working part-time 20h/week. Will I owe extra tax, and does my employer handle it?"
        />
      </div>

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

function QuickLinksCard({ onNavigate }) {
  const items = [
    { key: "tax-checklist", title: "Work basics checklist", sub: "Confirm written contract, withholding, payslips, and visa registration.", icon: "list-check" },
    { key: "tax-tasks",     title: "Tasks & deadlines",     sub: "Year-end adjustment, payslip uploads, residency checks.",             icon: "calendar-event" },
    { key: "tax-guides",    title: "Tax guides for Korea",  sub: "D-2 알바, full-time 연말정산, freelancer 종합소득세.",                      icon: "book-2" },
  ];
  return (
    <SurfaceCard>
      <CardHead
        eyebrow="More"
        title="Quick links"
        subtitle="Open a focused page for each topic — keeps this overview light."
      />
      <div style={{ display: "flex", flexDirection: "column", gap: 8 }}>
        {items.map((it) => (
          <button key={it.key} onClick={() => onNavigate(it.key)} style={{
            display: "flex", alignItems: "center", gap: 12,
            padding: "12px 14px", borderRadius: 12,
            background: "white", border: "1px solid var(--border-soft)",
            textAlign: "left",
            transition: "background 0.18s ease, border-color 0.18s ease, transform 0.18s ease",
          }}
            onMouseEnter={(e) => { e.currentTarget.style.background = "var(--bg-soft)"; e.currentTarget.style.borderColor = "var(--border)"; e.currentTarget.style.transform = "translateY(-1px)"; }}
            onMouseLeave={(e) => { e.currentTarget.style.background = "white"; e.currentTarget.style.borderColor = "var(--border-soft)"; e.currentTarget.style.transform = "translateY(0)"; }}
          >
            <span style={{
              width: 32, height: 32, borderRadius: 9,
              background: "var(--bg-soft)", color: "var(--ink)",
              display: "inline-flex", alignItems: "center", justifyContent: "center",
              flexShrink: 0,
            }}><i className={`ti ti-${it.icon}`} style={{ fontSize: 16 }} /></span>
            <div style={{ flex: 1, minWidth: 0 }}>
              <div style={{ fontSize: 13, fontWeight: 600, color: "var(--ink)", letterSpacing: "-0.005em" }}>{it.title}</div>
              <div style={{ fontSize: 11, color: "var(--text-mute)", marginTop: 2 }}>{it.sub}</div>
            </div>
            <i className="ti ti-arrow-right" style={{ fontSize: 14, color: "var(--text-mute)" }} />
          </button>
        ))}
      </div>
    </SurfaceCard>
  );
}

/* ---- Add / edit job as a full page ---- */

function NewJobPage({ onNavigate, taxState }) {
  const { jobs, setJobs, editingJob, flash } = taxState;
  const isEdit = !!editingJob;
  const [form, setForm] = useState(editingJob || newJobShape());

  useEffect(() => { setForm(editingJob || newJobShape()); }, [editingJob]);

  const submit = (e) => {
    e?.preventDefault?.();
    if (isEdit) {
      setJobs((arr) => arr.map((x) => x.id === editingJob.id ? { ...x, ...form } : x));
      flash("Job updated.");
    } else {
      const id = "j" + (Date.now() % 100000);
      setJobs((arr) => [...arr, { id, ...form }]);
      flash(form.hasContract ? "Job added." : "Job added. Don't forget to upload your contract.");
    }
    onNavigate("tax");
  };

  return (
    <div style={{
      animation: "fade-up 0.5s cubic-bezier(0.2,0.7,0.2,1) both",
      animationDelay: "0.05s",
      maxWidth: 720,
    }}>
      <BackBar onBack={() => onNavigate("tax")} label="Tax & work" />

      <SurfaceCard>
        <CardHead
          eyebrow={isEdit ? "Edit" : "Add"}
          title={isEdit ? (form.company || "Job details") : "New job"}
          subtitle={isEdit ? "Update the details Korico tracks for this role." : "Save a new role so Korico can track contracts and tax events for you."}
        />

        <form onSubmit={submit} style={{ display: "flex", flexDirection: "column", gap: 16 }}>
          <div style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: 12 }} className="job-form-grid">
            <Field label="Job type">
              <Select value={form.type} onChange={(v) => setForm({ ...form, type: v })}
                options={["Part-time", "Full-time", "Internship", "Freelance"]} />
            </Field>
            <Field label="Company name">
              <input
                value={form.company}
                onChange={(e) => setForm({ ...form, company: e.target.value })}
                placeholder="e.g. Cafe Onion · Seongsu"
                style={inputStyle}
                onFocus={(e) => e.currentTarget.style.borderColor = "var(--ink)"}
                onBlur={(e) => e.currentTarget.style.borderColor = "var(--border)"}
              />
            </Field>
            <Field label="Start date">
              <input type="date" value={form.startDate}
                onChange={(e) => setForm({ ...form, startDate: e.target.value })}
                style={inputStyle}
              />
            </Field>
            <Field label="End date (optional)">
              <input type="date" value={form.endDate || ""}
                onChange={(e) => setForm({ ...form, endDate: e.target.value })}
                style={inputStyle}
              />
            </Field>
            <Field label="Pay type">
              <Select value={form.payType} onChange={(v) => setForm({ ...form, payType: v })}
                options={["시급", "월급", "건별"]} />
            </Field>
            <Field label="Amount">
              <input value={form.payAmount}
                onChange={(e) => setForm({ ...form, payAmount: e.target.value })}
                placeholder="e.g. ₩11,500/h"
                style={inputStyle}
              />
            </Field>
          </div>

          <label style={{
            display: "flex", alignItems: "center", gap: 10,
            padding: "12px 14px", borderRadius: 12,
            background: form.withholding ? "rgba(212,255,79,0.20)" : "var(--bg-soft)",
            border: "1px solid " + (form.withholding ? "rgba(184,230,60,0.5)" : "var(--border-soft)"),
            cursor: "pointer", transition: "all 0.18s ease",
          }}>
            <input type="checkbox" checked={form.withholding}
              onChange={(e) => setForm({ ...form, withholding: e.target.checked })}
              style={{ display: "none" }}
            />
            <span style={{
              width: 22, height: 22, borderRadius: 7,
              background: form.withholding ? "var(--ink)" : "white",
              border: form.withholding ? "none" : "1.5px solid var(--border)",
              display: "inline-flex", alignItems: "center", justifyContent: "center",
              color: "var(--lime)", flexShrink: 0,
            }}>
              {form.withholding && <i className="ti ti-check" style={{ fontSize: 13 }} />}
            </span>
            <span style={{ fontSize: 13, fontWeight: 500, color: "var(--ink)" }}>
              Employer withholds tax
            </span>
          </label>

          <Field label="Contract file (optional)">
            <button type="button"
              onClick={() => setForm({ ...form, hasContract: !form.hasContract })}
              style={{
                width: "100%",
                padding: "20px",
                borderRadius: 12,
                background: form.hasContract ? "rgba(212,255,79,0.16)" : "var(--bg-soft)",
                border: "1px dashed " + (form.hasContract ? "rgba(184,230,60,0.55)" : "var(--border)"),
                color: "var(--ink)",
                display: "flex", alignItems: "center", justifyContent: "center", gap: 10,
                fontSize: 13, fontWeight: 500,
                transition: "all 0.18s ease",
              }}>
              <i className={`ti ti-${form.hasContract ? "file-check" : "upload"}`} style={{ fontSize: 18 }} />
              {form.hasContract ? "contract.pdf · uploaded" : "Drop your contract here or click to upload"}
            </button>
          </Field>

          <Field label="Notes (optional)">
            <textarea value={form.notes || ""}
              onChange={(e) => setForm({ ...form, notes: e.target.value })}
              rows={3}
              placeholder="Anything Korico should remember about this job…"
              style={{ ...inputStyle, resize: "vertical", minHeight: 80 }}
            />
          </Field>

          <div style={{
            display: "flex", justifyContent: "flex-end", gap: 8,
            paddingTop: 8, borderTop: "1px solid var(--border-soft)",
            marginTop: 4,
          }}>
            <button type="button" onClick={() => onNavigate("tax")} style={{
              padding: "11px 18px", borderRadius: 99,
              background: "white", color: "var(--ink)",
              border: "1px solid var(--border)",
              fontSize: 11, fontWeight: 600, letterSpacing: "0.14em", textTransform: "uppercase",
            }}>Cancel</button>
            <button type="submit" style={{
              display: "inline-flex", alignItems: "center", gap: 8,
              padding: "11px 18px", borderRadius: 99,
              background: "var(--lime)", color: "var(--ink)",
              fontSize: 11, fontWeight: 700, letterSpacing: "0.14em", textTransform: "uppercase",
              boxShadow: "0 10px 22px rgba(184,230,60,0.35)",
            }}>
              {isEdit ? "Save changes" : "Save job"}
              <span style={{
                width: 18, height: 18, borderRadius: "50%",
                background: "var(--ink)", color: "var(--lime)",
                display: "inline-flex", alignItems: "center", justifyContent: "center",
              }}><i className="ti ti-check" style={{ fontSize: 11 }} /></span>
            </button>
          </div>
        </form>

        <style>{`
          @media (max-width: 640px) { .job-form-grid { grid-template-columns: 1fr !important; }}
        `}</style>
      </SurfaceCard>
    </div>
  );
}

/* ---- Sub-pages: checklist, tasks, guides ---- */

function WorkChecklistPage({ onNavigate }) {
  return (
    <div style={{ maxWidth: 880, animation: "fade-up 0.5s cubic-bezier(0.2,0.7,0.2,1) both", animationDelay: "0.05s" }}>
      <BackBar onBack={() => onNavigate("tax")} label="Tax & work" />
      <WorkChecklistCard />
    </div>
  );
}

function TaxTasksPage({ onNavigate }) {
  return (
    <div style={{ maxWidth: 880, animation: "fade-up 0.5s cubic-bezier(0.2,0.7,0.2,1) both", animationDelay: "0.05s" }}>
      <BackBar onBack={() => onNavigate("tax")} label="Tax & work" />
      <TaxTasksCard />
    </div>
  );
}

function TaxGuidesPage({ onNavigate }) {
  return (
    <div style={{ maxWidth: 880, animation: "fade-up 0.5s cubic-bezier(0.2,0.7,0.2,1) both", animationDelay: "0.05s" }}>
      <BackBar onBack={() => onNavigate("tax")} label="Tax & work" />
      <TaxGuidesCard />
    </div>
  );
}

function BackBar({ onBack, label }) {
  return (
    <button onClick={onBack} style={{
      display: "inline-flex", alignItems: "center", gap: 8,
      padding: "8px 14px 8px 10px", borderRadius: 99,
      background: "white", border: "1px solid var(--border)",
      color: "var(--ink)",
      fontSize: 11.5, fontWeight: 600, letterSpacing: "0.04em",
      marginBottom: 18,
      transition: "background 0.18s ease, transform 0.18s ease",
    }}
      onMouseEnter={(e) => { e.currentTarget.style.background = "var(--bg-soft)"; e.currentTarget.style.transform = "translateX(-2px)"; }}
      onMouseLeave={(e) => { e.currentTarget.style.background = "white"; e.currentTarget.style.transform = "translateX(0)"; }}
    >
      <i className="ti ti-arrow-left" style={{ fontSize: 14 }} />
      Back to {label}
    </button>
  );
}

function WorkStatusCard({ status, setStatus, jobs, fullCount, partCount, freeCount }) {
  const summary = jobs.length === 0
    ? "Tell us about your work so Korico can suggest the right tax steps."
    : `You reported ${partCount} part-time / internship job${partCount !== 1 ? "s" : ""} and ${fullCount} full-time job${fullCount !== 1 ? "s" : ""}${freeCount ? ` and ${freeCount} freelance contract${freeCount !== 1 ? "s" : ""}` : ""} in Korea.`;

  return (
    <SurfaceCard>
      <CardHead
        eyebrow="Work status"
        title="Current work status"
        subtitle="Pick the option that best describes your situation right now."
      />
      <div style={{ display: "grid", gridTemplateColumns: "repeat(2, 1fr)", gap: 8 }} className="status-grid">
        {STATUS_OPTIONS.map((o) => {
          const on = status === o.key;
          return (
            <button key={o.key} onClick={() => setStatus(o.key)} style={{
              display: "flex", alignItems: "center", gap: 12,
              padding: "13px 14px", borderRadius: 14,
              background: on ? "var(--ink)" : "white",
              color: on ? "var(--lime)" : "var(--ink)",
              border: `1px solid ${on ? "var(--ink)" : "var(--border)"}`,
              textAlign: "left",
              transition: "transform 0.18s cubic-bezier(0.2,1.4,0.4,1), background 0.18s ease, color 0.18s ease",
            }}
              onMouseDown={(e) => e.currentTarget.style.transform = "translateY(1px) scale(0.99)"}
              onMouseUp={(e) => e.currentTarget.style.transform = "translateY(0) scale(1)"}
              onMouseLeave={(e) => e.currentTarget.style.transform = "translateY(0) scale(1)"}
            >
              <span style={{
                width: 32, height: 32, borderRadius: 9,
                background: on ? "var(--lime)" : "var(--bg-soft)",
                color: on ? "var(--ink)" : "var(--ink)",
                display: "inline-flex", alignItems: "center", justifyContent: "center",
                flexShrink: 0,
              }}><i className={`ti ti-${o.icon}`} style={{ fontSize: 16 }} /></span>
              <span style={{ fontSize: 13, fontWeight: 600, letterSpacing: "-0.005em" }}>{o.label}</span>
            </button>
          );
        })}
      </div>
      <p style={{
        marginTop: 14, fontSize: 12.5, color: "var(--text-mute)",
      }}>{summary}</p>

      <style>{`
        @media (max-width: 640px) { .status-grid { grid-template-columns: 1fr !important; }}
      `}</style>
    </SurfaceCard>
  );
}

function JobsCard({ jobs, onAdd, onOpen }) {
  return (
    <SurfaceCard>
      <CardHead
        eyebrow="Jobs"
        title="Jobs & contracts"
        subtitle="Add every paid role — even short-term ones. Korico keeps the paperwork tidy."
        right={
          <a href="#documents" style={{
            fontSize: 11, fontWeight: 600, color: "var(--ink)",
            textDecoration: "none",
            letterSpacing: "0.06em",
            position: "relative",
            display: "inline-flex", alignItems: "center", gap: 6,
          }}>
            View all contracts
            <i className="ti ti-arrow-up-right" style={{ fontSize: 12 }} />
          </a>
        }
      />

      {jobs.length === 0 ? (
        <div style={{
          padding: "28px 22px", borderRadius: 14,
          background: "var(--bg-soft)",
          textAlign: "center",
          fontSize: 13, color: "var(--text-mute)",
        }}>
          No jobs yet. Click Add job to get started.
        </div>
      ) : (
        <div style={{ display: "flex", flexDirection: "column", gap: 10 }}>
          {jobs.map((j) => <JobRow key={j.id} j={j} onClick={() => onOpen(j)} />)}
        </div>
      )}

      <div style={{ display: "flex", justifyContent: "flex-end", marginTop: 14 }}>
        <button onClick={onAdd} style={{
          display: "inline-flex", alignItems: "center", gap: 10,
          padding: "11px 20px", borderRadius: 99,
          background: "var(--lime)", color: "var(--ink)",
          fontFamily: "var(--font-body)", fontWeight: 700, fontSize: 12,
          letterSpacing: "0.16em", textTransform: "uppercase",
          boxShadow: "0 10px 22px rgba(184,230,60,0.35)",
          transition: "transform 0.18s ease, box-shadow 0.18s ease",
        }}
          onMouseEnter={(e) => { e.currentTarget.style.transform = "translateY(-1px)"; e.currentTarget.style.boxShadow = "0 14px 28px rgba(184,230,60,0.5)"; }}
          onMouseLeave={(e) => { e.currentTarget.style.transform = "translateY(0)"; e.currentTarget.style.boxShadow = "0 10px 22px rgba(184,230,60,0.35)"; }}
        >
          <i className="ti ti-plus" style={{ fontSize: 14 }} />
          Add job
        </button>
      </div>
    </SurfaceCard>
  );
}

function JobRow({ j, onClick }) {
  const typePalette = {
    "Part-time":  { bg: "var(--bg-soft)", fg: "var(--ink)" },
    "Full-time":  { bg: "var(--ink)", fg: "var(--lime)" },
    "Internship": { bg: "rgba(46,139,255,0.10)", fg: "var(--sky-1)" },
    "Freelance":  { bg: "var(--warning-soft)", fg: "var(--warning)" },
  }[j.type] || { bg: "var(--bg-soft)", fg: "var(--ink)" };
  const contractPalette = j.hasContract
    ? { bg: "var(--success-soft)", fg: "var(--success)", label: "Contract uploaded" }
    : { bg: "var(--warning-soft)", fg: "var(--warning)", label: "Contract missing" };
  return (
    <button onClick={onClick} style={{
      display: "grid", gridTemplateColumns: "auto 1fr auto", gap: 14,
      alignItems: "center",
      padding: "14px 16px", borderRadius: 14,
      background: "white", border: "1px solid var(--border-soft)",
      textAlign: "left", width: "100%",
      transition: "background 0.18s ease, border-color 0.18s ease, transform 0.18s ease",
    }}
      onMouseEnter={(e) => { e.currentTarget.style.background = "var(--bg-soft)"; e.currentTarget.style.borderColor = "var(--border)"; e.currentTarget.style.transform = "translateY(-1px)"; }}
      onMouseLeave={(e) => { e.currentTarget.style.background = "white"; e.currentTarget.style.borderColor = "var(--border-soft)"; e.currentTarget.style.transform = "translateY(0)"; }}
    >
      <span style={{
        padding: "4px 10px", borderRadius: 99,
        background: typePalette.bg, color: typePalette.fg,
        fontSize: 10, fontWeight: 700, letterSpacing: "0.1em", textTransform: "uppercase",
      }}>{j.type}</span>
      <div style={{ minWidth: 0 }}>
        <div style={{
          fontSize: 13.5, fontWeight: 600, color: "var(--ink)",
          letterSpacing: "-0.005em",
        }}>{j.company}</div>
        <div style={{ fontSize: 11.5, color: "var(--text-mute)", marginTop: 2 }}>
          {j.startDate}{j.endDate ? ` – ${j.endDate}` : " · current"} · {j.payType} {j.payAmount}
        </div>
      </div>
      <span style={{
        padding: "4px 10px", borderRadius: 99,
        background: contractPalette.bg, color: contractPalette.fg,
        fontSize: 10, fontWeight: 700, letterSpacing: "0.1em", textTransform: "uppercase",
        whiteSpace: "nowrap",
      }}>{contractPalette.label}</span>
    </button>
  );
}

function WorkChecklistCard() {
  const [items, setItems] = useState([
    { id: "wc1", label: "I have a written contract for each job", info: "Without a written contract, employers may underpay or skip tax withholding.", done: true },
    { id: "wc2", label: "I know whether my employer withholds tax", info: "If they withhold, you don't need to file separately — most of the time.", done: true },
    { id: "wc3", label: "I registered my workplace for my visa type", info: "D-2 students need permission for off-campus part-time work.", done: false },
    { id: "wc4", label: "I keep payslips or payment records", info: "Save monthly payslips — needed for 연말정산 and visa changes.", done: false },
  ]);
  const toggle = (id) => setItems((arr) => arr.map((x) => x.id === id ? { ...x, done: !x.done } : x));

  return (
    <SurfaceCard>
      <CardHead
        eyebrow="Basics"
        title="Work basics checklist"
        subtitle="Quick check that the fundamentals are covered."
      />
      <div style={{ display: "flex", flexDirection: "column", gap: 6 }}>
        {items.map((it) => (
          <button key={it.id} onClick={() => toggle(it.id)} style={{
            display: "flex", alignItems: "center", gap: 12,
            padding: "11px 14px", borderRadius: 12,
            background: it.done ? "var(--bg-soft)" : "white",
            border: "1px solid " + (it.done ? "var(--border-soft)" : "var(--border)"),
            textAlign: "left", width: "100%",
            transition: "background 0.2s ease, border-color 0.2s ease",
          }}>
            <span style={{
              width: 22, height: 22, borderRadius: 7,
              background: it.done ? "var(--ink)" : "white",
              border: it.done ? "none" : "1.5px solid var(--border)",
              display: "inline-flex", alignItems: "center", justifyContent: "center",
              color: "var(--lime)",
              flexShrink: 0,
              transition: "background 0.2s ease, border-color 0.2s ease",
            }}>
              {it.done && <i className="ti ti-check" style={{ fontSize: 13, animation: "check-pop 0.3s cubic-bezier(0.2,1.4,0.4,1) both" }} />}
            </span>
            <div style={{ flex: 1, minWidth: 0 }}>
              <div style={{
                fontSize: 13, fontWeight: 500,
                color: it.done ? "var(--text-mute)" : "var(--ink)",
                textDecoration: it.done ? "line-through" : "none",
                letterSpacing: "-0.005em",
              }}>{it.label}</div>
              <div style={{ fontSize: 11, color: "var(--text-mute)", marginTop: 2, fontStyle: "italic" }}>
                {it.info}
              </div>
            </div>
          </button>
        ))}
      </div>
    </SurfaceCard>
  );
}

function TaxOverviewCard({ status, jobs }) {
  const monthly = jobs.reduce((sum, j) => {
    const m = j.payAmount?.match(/₩([\d,]+)/);
    if (!m) return sum;
    const n = parseInt(m[1].replace(/,/g, ""), 10);
    if (j.payType === "월급") return sum + n;
    if (j.payType === "시급") return sum + n * 80; // ~20h/wk
    return sum;
  }, 0);
  const yearly = monthly * 12;
  const yearlyStr = "₩" + yearly.toLocaleString("en-US");

  const events = [
    status === "fulltime"  && { icon: "calendar-check", text: "연말정산 — your employer typically handles this in January.", tone: "ink" },
    status === "freelance" && { icon: "report-money", text: "종합소득세 신고 — file by end of May next year.", tone: "warn" },
    (status === "parttime" || status === "fulltime") && { icon: "home", text: "You might claim housing or credit-card deductions.", tone: "ink" },
    jobs.length > 1 && { icon: "alert-circle", text: "Multiple jobs detected — extra filing may apply.", tone: "warn" },
  ].filter(Boolean);

  return (
    <SurfaceCard>
      <CardHead
        eyebrow="Tax"
        title="Tax overview"
        subtitle="General guidance based on what you've shared."
        right={
          <span style={{
            padding: "4px 10px", borderRadius: 99,
            background: "var(--bg-soft)", color: "var(--ink)",
            fontSize: 10, fontWeight: 700, letterSpacing: "0.12em", textTransform: "uppercase",
          }}>Basic guidance</span>
        }
      />

      <div style={{
        padding: "14px 16px", borderRadius: 14,
        background: "var(--bg-soft)",
        marginBottom: 14,
      }}>
        <div style={{
          fontSize: 10, fontWeight: 600, color: "var(--text-mute)",
          letterSpacing: "0.16em", textTransform: "uppercase",
        }}>Estimated yearly income</div>
        <div style={{
          fontSize: 22, fontWeight: 600, color: "var(--ink)",
          letterSpacing: "-0.02em", marginTop: 4,
        }}>{yearly > 0 ? yearlyStr : "Not set"}</div>
        <div style={{ fontSize: 11.5, color: "var(--text-mute)", marginTop: 4 }}>
          Estimate based on your reported jobs · adjust in Files.
        </div>
      </div>

      <ul style={{ listStyle: "none", padding: 0, margin: 0, display: "flex", flexDirection: "column", gap: 8 }}>
        {events.length > 0 ? events.map((e, i) => (
          <li key={i} style={{
            display: "flex", alignItems: "center", gap: 10,
            padding: "10px 12px", borderRadius: 12,
            background: "white", border: "1px solid var(--border-soft)",
            fontSize: 12.5, color: "var(--text-soft)", lineHeight: 1.5,
          }}>
            <span style={{
              width: 26, height: 26, borderRadius: 8,
              background: e.tone === "warn" ? "var(--warning-soft)" : "var(--bg-soft)",
              color: e.tone === "warn" ? "var(--warning)" : "var(--ink)",
              display: "inline-flex", alignItems: "center", justifyContent: "center",
              flexShrink: 0,
            }}><i className={`ti ti-${e.icon}`} style={{ fontSize: 14 }} /></span>
            {e.text}
          </li>
        )) : (
          <li style={{ fontSize: 12.5, color: "var(--text-mute)" }}>Set your work status and add jobs to see tax events.</li>
        )}
      </ul>

      <div style={{
        marginTop: 14, padding: "10px 14px", borderRadius: 12,
        background: "rgba(212,255,79,0.12)",
        border: "1px solid rgba(184,230,60,0.4)",
        display: "flex", alignItems: "center", gap: 8,
        fontSize: 12, color: "var(--ink)", fontWeight: 500,
      }}>
        <i className="ti ti-calendar" style={{ fontSize: 14 }} />
        Next tax season starts in <strong style={{ marginLeft: 4 }}>May 2026</strong>.
      </div>
    </SurfaceCard>
  );
}

function TaxTasksCard() {
  const [tasks, setTasks] = useState(TAX_TASKS);
  const cycle = (id) => setTasks((arr) => arr.map((t) =>
    t.id !== id ? t : { ...t, status: t.status === "todo" ? "progress" : t.status === "progress" ? "done" : "todo" }
  ));
  return (
    <SurfaceCard>
      <CardHead
        eyebrow="Upcoming"
        title="Tasks &amp; deadlines"
        subtitle="Tap a row to cycle through Not started → In progress → Done."
      />
      <div style={{ display: "flex", flexDirection: "column", gap: 8 }}>
        {tasks.map((t) => <TaxTaskRow key={t.id} task={t} onClick={() => cycle(t.id)} />)}
      </div>
    </SurfaceCard>
  );
}

function TaxTaskRow({ task, onClick }) {
  const palette = {
    todo:     { bg: "var(--bg-soft)",      fg: "var(--text-mute)", label: "Not started" },
    progress: { bg: "rgba(212,255,79,0.30)", fg: "var(--ink)",     label: "In progress" },
    done:     { bg: "var(--success-soft)", fg: "var(--success)",  label: "Done" },
  }[task.status];
  return (
    <button onClick={onClick} style={{
      display: "grid", gridTemplateColumns: "1fr auto", gap: 12,
      alignItems: "center",
      padding: "12px 14px", borderRadius: 12,
      background: "white", border: "1px solid var(--border-soft)",
      textAlign: "left", width: "100%",
      transition: "background 0.18s ease, border-color 0.18s ease",
    }}
      onMouseEnter={(e) => { e.currentTarget.style.background = "var(--bg-soft)"; e.currentTarget.style.borderColor = "var(--border)"; }}
      onMouseLeave={(e) => { e.currentTarget.style.background = "white"; e.currentTarget.style.borderColor = "var(--border-soft)"; }}
    >
      <div style={{ minWidth: 0 }}>
        <div style={{
          fontSize: 13, fontWeight: 500, color: task.status === "done" ? "var(--text-mute)" : "var(--ink)",
          textDecoration: task.status === "done" ? "line-through" : "none",
          letterSpacing: "-0.005em",
        }}>{task.label}</div>
        <div style={{ fontSize: 11, color: "var(--text-mute)", marginTop: 2 }}>{task.due}</div>
      </div>
      <span style={{
        padding: "4px 10px", borderRadius: 99,
        background: palette.bg, color: palette.fg,
        fontSize: 10, fontWeight: 700, letterSpacing: "0.1em", textTransform: "uppercase",
      }}>{palette.label}</span>
    </button>
  );
}

function TaxGuidesCard() {
  return (
    <SurfaceCard>
      <CardHead
        eyebrow="Learn"
        title="Tax guides for Korea"
        subtitle="Short, plain-language explainers — pick the one closest to your situation."
      />
      <div style={{ display: "flex", flexDirection: "column", gap: 8 }}>
        {TAX_GUIDES.map((g) => (
          <a key={g.title} href="#guides" style={{
            display: "flex", alignItems: "center", gap: 12,
            padding: "12px 14px", borderRadius: 12,
            background: "white", border: "1px solid var(--border-soft)",
            textDecoration: "none",
            transition: "background 0.18s ease, border-color 0.18s ease",
          }}
            onMouseEnter={(e) => { e.currentTarget.style.background = "var(--bg-soft)"; e.currentTarget.style.borderColor = "var(--border)"; }}
            onMouseLeave={(e) => { e.currentTarget.style.background = "white"; e.currentTarget.style.borderColor = "var(--border-soft)"; }}
          >
            <span style={{
              width: 32, height: 32, borderRadius: 9,
              background: "var(--bg-soft)", color: "var(--ink)",
              display: "inline-flex", alignItems: "center", justifyContent: "center",
              flexShrink: 0,
            }}><i className={`ti ti-${g.icon}`} style={{ fontSize: 16 }} /></span>
            <div style={{ flex: 1, minWidth: 0 }}>
              <div style={{ fontSize: 13, fontWeight: 600, color: "var(--ink)", letterSpacing: "-0.005em" }}>{g.title}</div>
              <div style={{ fontSize: 11, color: "var(--text-mute)", marginTop: 2 }}>{g.sub}</div>
            </div>
            <i className="ti ti-arrow-up-right" style={{ fontSize: 14, color: "var(--text-mute)" }} />
          </a>
        ))}
      </div>
    </SurfaceCard>
  );
}

/* ---- Job drawer (side sheet) ---- */

function JobDrawer({ open, onClose, onSave, initial }) {
  const [form, setForm] = useState(initial || newJobShape());

  useEffect(() => {
    setForm(initial || newJobShape());
  }, [initial, open]);

  useEffect(() => {
    if (!open) return;
    const h = (e) => { if (e.key === "Escape") onClose(); };
    window.addEventListener("keydown", h);
    return () => window.removeEventListener("keydown", h);
  }, [open, onClose]);

  const submit = (e) => {
    e.preventDefault();
    onSave(form);
  };

  return (
    <>
      {/* backdrop */}
      <div
        onClick={onClose}
        style={{
          position: "fixed", inset: 0,
          background: "rgba(11,27,44,0.45)",
          opacity: open ? 1 : 0,
          pointerEvents: open ? "auto" : "none",
          transition: "opacity 0.25s ease",
          zIndex: 70,
        }}
      />
      {/* drawer */}
      <aside
        role="dialog"
        aria-label={initial ? "Edit job" : "Add job"}
        style={{
          position: "fixed",
          top: 0, right: 0, bottom: 0,
          width: "min(460px, 100vw)",
          background: "white",
          boxShadow: "-24px 0 60px rgba(11,27,44,0.18)",
          transform: open ? "translateX(0)" : "translateX(100%)",
          transition: "transform 0.32s cubic-bezier(0.2,0.7,0.2,1)",
          zIndex: 71,
          display: "flex", flexDirection: "column",
        }}
      >
        <header style={{
          padding: "20px 22px", borderBottom: "1px solid var(--border-soft)",
          display: "flex", alignItems: "center", justifyContent: "space-between",
        }}>
          <div>
            <div style={{
              fontSize: 10, fontWeight: 600, color: "var(--text-mute)",
              letterSpacing: "0.18em", textTransform: "uppercase",
            }}>{initial ? "Edit" : "Add"}</div>
            <h2 style={{
              fontSize: 18, fontWeight: 600, color: "var(--ink)",
              letterSpacing: "-0.015em", marginTop: 4,
            }}>{initial ? form.company || "Job details" : "New job"}</h2>
          </div>
          <button onClick={onClose} aria-label="Close" style={{
            width: 36, height: 36, borderRadius: 10,
            background: "var(--bg-soft)", color: "var(--ink)",
            display: "inline-flex", alignItems: "center", justifyContent: "center",
          }}>
            <i className="ti ti-x" style={{ fontSize: 18 }} />
          </button>
        </header>

        <form onSubmit={submit} style={{
          flex: 1, overflowY: "auto",
          padding: "22px",
          display: "flex", flexDirection: "column", gap: 16,
        }}>
          <Field label="Job type">
            <Select value={form.type} onChange={(v) => setForm({ ...form, type: v })}
              options={["Part-time", "Full-time", "Internship", "Freelance"]} />
          </Field>
          <Field label="Company name">
            <input
              value={form.company}
              onChange={(e) => setForm({ ...form, company: e.target.value })}
              placeholder="e.g. Cafe Onion · Seongsu"
              style={{
                width: "100%", padding: "11px 14px",
                borderRadius: 12, border: "1px solid var(--border)",
                fontSize: 14, color: "var(--ink)", outline: "none",
              }}
              onFocus={(e) => e.currentTarget.style.borderColor = "var(--ink)"}
              onBlur={(e) => e.currentTarget.style.borderColor = "var(--border)"}
            />
          </Field>
          <div style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: 12 }}>
            <Field label="Start date">
              <input type="date" value={form.startDate}
                onChange={(e) => setForm({ ...form, startDate: e.target.value })}
                style={inputStyle}
              />
            </Field>
            <Field label="End date (optional)">
              <input type="date" value={form.endDate || ""}
                onChange={(e) => setForm({ ...form, endDate: e.target.value })}
                style={inputStyle}
              />
            </Field>
          </div>
          <div style={{ display: "grid", gridTemplateColumns: "1fr 1.4fr", gap: 12 }}>
            <Field label="Pay type">
              <Select value={form.payType} onChange={(v) => setForm({ ...form, payType: v })}
                options={["시급", "월급", "건별"]} />
            </Field>
            <Field label="Amount">
              <input value={form.payAmount}
                onChange={(e) => setForm({ ...form, payAmount: e.target.value })}
                placeholder="e.g. ₩11,500/h"
                style={inputStyle}
              />
            </Field>
          </div>

          <label style={{
            display: "flex", alignItems: "center", gap: 10,
            padding: "10px 12px", borderRadius: 12,
            background: form.withholding ? "rgba(212,255,79,0.20)" : "var(--bg-soft)",
            border: "1px solid " + (form.withholding ? "rgba(184,230,60,0.5)" : "var(--border-soft)"),
            cursor: "pointer", transition: "all 0.18s ease",
          }}>
            <input type="checkbox" checked={form.withholding}
              onChange={(e) => setForm({ ...form, withholding: e.target.checked })}
              style={{ display: "none" }}
            />
            <span style={{
              width: 22, height: 22, borderRadius: 7,
              background: form.withholding ? "var(--ink)" : "white",
              border: form.withholding ? "none" : "1.5px solid var(--border)",
              display: "inline-flex", alignItems: "center", justifyContent: "center",
              color: "var(--lime)", flexShrink: 0,
            }}>
              {form.withholding && <i className="ti ti-check" style={{ fontSize: 13 }} />}
            </span>
            <span style={{ fontSize: 13, fontWeight: 500, color: "var(--ink)" }}>
              Employer withholds tax
            </span>
          </label>

          <Field label="Contract file (optional)">
            <button type="button"
              onClick={() => setForm({ ...form, hasContract: !form.hasContract })}
              style={{
                width: "100%",
                padding: "16px",
                borderRadius: 12,
                background: form.hasContract ? "rgba(212,255,79,0.16)" : "var(--bg-soft)",
                border: "1px dashed " + (form.hasContract ? "rgba(184,230,60,0.55)" : "var(--border)"),
                color: "var(--ink)",
                display: "flex", alignItems: "center", justifyContent: "center", gap: 10,
                fontSize: 13, fontWeight: 500,
              }}>
              <i className={`ti ti-${form.hasContract ? "file-check" : "upload"}`} style={{ fontSize: 16 }} />
              {form.hasContract ? "contract.pdf · uploaded" : "Drop your contract here or click to upload"}
            </button>
          </Field>

          <Field label="Notes (optional)">
            <textarea value={form.notes || ""}
              onChange={(e) => setForm({ ...form, notes: e.target.value })}
              rows={2}
              placeholder="Anything Korico should remember about this job…"
              style={{ ...inputStyle, resize: "vertical", minHeight: 70 }}
            />
          </Field>
        </form>

        <footer style={{
          padding: "16px 22px", borderTop: "1px solid var(--border-soft)",
          display: "flex", justifyContent: "flex-end", gap: 8,
        }}>
          <button type="button" onClick={onClose} style={{
            padding: "11px 18px", borderRadius: 99,
            background: "white", color: "var(--ink)",
            border: "1px solid var(--border)",
            fontSize: 11, fontWeight: 600, letterSpacing: "0.14em", textTransform: "uppercase",
          }}>Cancel</button>
          <button onClick={submit} style={{
            display: "inline-flex", alignItems: "center", gap: 8,
            padding: "11px 18px", borderRadius: 99,
            background: "var(--lime)", color: "var(--ink)",
            fontSize: 11, fontWeight: 700, letterSpacing: "0.14em", textTransform: "uppercase",
            boxShadow: "0 10px 22px rgba(184,230,60,0.35)",
          }}>
            {initial ? "Save changes" : "Save job"}
            <span style={{
              width: 18, height: 18, borderRadius: "50%",
              background: "var(--ink)", color: "var(--lime)",
              display: "inline-flex", alignItems: "center", justifyContent: "center",
            }}><i className="ti ti-check" style={{ fontSize: 11 }} /></span>
          </button>
        </footer>
      </aside>
    </>
  );
}

const inputStyle = {
  width: "100%", padding: "11px 14px",
  borderRadius: 12, border: "1px solid var(--border)",
  fontSize: 14, color: "var(--ink)", outline: "none",
  fontFamily: "var(--font-body)",
  background: "white",
};

function newJobShape() {
  return {
    type: "Part-time",
    company: "",
    startDate: "",
    endDate: "",
    payType: "시급",
    payAmount: "",
    withholding: true,
    hasContract: false,
    notes: "",
  };
}

function Toast({ text }) {
  return (
    <div style={{
      position: "fixed", bottom: 100, left: "50%", transform: "translateX(-50%)",
      background: "var(--ink)", color: "white",
      padding: "12px 22px", borderRadius: 99,
      fontSize: 13, fontWeight: 500, letterSpacing: "-0.005em",
      boxShadow: "0 18px 40px rgba(11,27,44,0.25)",
      opacity: text ? 1 : 0,
      pointerEvents: "none",
      transition: "opacity 0.25s ease, transform 0.25s ease",
      zIndex: 80,
    }}>{text}</div>
  );
}

/* ============================================================
   HOUSING & MOVING PAGE
   ============================================================ */

const HOUSING_TYPES = [
  { key: "dorm",     label: "Dormitory",         icon: "building-community" },
  { key: "gosiwon",  label: "Gosiwon",           icon: "door" },
  { key: "hasukjip", label: "Hasukjip",          icon: "bed" },
  { key: "wolse",    label: "One-room (월세)",    icon: "home" },
  { key: "jeonse",   label: "Jeonse",            icon: "key" },
  { key: "company",  label: "Company housing",   icon: "building-skyscraper" },
];

const MOVE_HISTORY = [
  { id: "h1", range: "2023.09 – 2024.02", type: "Dormitory · Yonsei",        area: "Seoul · Seodaemun", state: "past" },
  { id: "h2", range: "2024.02 – present",  type: "One-room (월세) · Sinchon",  area: "Seoul · Seodaemun", state: "current" },
];

const HOUSING_DOCS = [
  { name: "임대차 계약서",        file: "rental-contract.pdf",      date: "2024.03.20", tag: "Contract", status: "verified" },
  { name: "전입신고 확인서",      file: "address-2024-04.pdf",      date: "2024.04.05", tag: "Address",  status: "uploaded" },
  { name: "보증금 영수증",        file: "deposit-receipt.png",      date: "2024.03.04", tag: "Receipt",  status: "uploaded" },
];

const HOUSING_GUIDES = [
  { icon: "home",        title: "How jeonse, wolse, and gosiwon work",  sub: "Plain-language breakdown of Korean housing types." },
  { icon: "writing-sign", title: "How to do 전입신고 step by step",       sub: "What to bring to 구청 or 주민센터 and when." },
  { icon: "shield-check", title: "Checking if your contract is safe",    sub: "Clauses to look for before signing 임대차 계약서." },
];

function HousingPage() {
  const [housing, setHousing] = useState({
    type: "wolse",
    address: "서울 서대문구 신촌로 ***",
    moveIn: "2024.03.04",
    monthlyRent: "₩650,000",
    deposit: "₩10,000,000",
    landlord: "부동산",
    jeoninReported: true,
    jeoninDate: "2024.04.05",
  });
  const [history, setHistory] = useState(MOVE_HISTORY);
  const [toast, setToast] = useState("");

  const headerStatus = useMemo(() => statusFor(housing), [housing]);

  const flash = (m) => { setToast(m); setTimeout(() => setToast(""), 3200); };

  const onHousingSave = (next) => {
    setHousing(next);
    flash("Housing info updated. Checklist & ARC suggestions refreshed.");
  };

  const onAddMove = (move) => {
    setHistory((arr) => [...arr, move]);
    flash("Planned move added to your timeline.");
  };

  return (
    <div style={{
      display: "grid", gridTemplateColumns: "1.5fr 1fr", gap: 22,
      animation: "fade-up 0.5s cubic-bezier(0.2,0.7,0.2,1) both",
      animationDelay: "0.05s",
      maxWidth: 1280, position: "relative",
    }} className="page-grid">
      <div style={{ display: "flex", flexDirection: "column", gap: 22, minWidth: 0 }}>
        <HousingStatusBanner headerStatus={headerStatus} />
        <CurrentHousingCard housing={housing} onSave={onHousingSave} />
        <MovingHistoryCard history={history} onAdd={onAddMove} />
        <AddressARCCard />
      </div>
      <div style={{ display: "flex", flexDirection: "column", gap: 22, minWidth: 0 }}>
        <HousingChecklistCard housing={housing} />
        <HousingDocsCard />
        <HousingGuidesCard />
        <AskShortcutCard
          eyebrow="Ask Korico"
          title="Housing questions"
          prefill="I'm moving from gosiwon to one-room next month. What should I do first about 전입신고 and ARC?"
        />
      </div>

      <Toast text={toast} />

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

function statusFor(h) {
  const typeLabel = HOUSING_TYPES.find((t) => t.key === h.type)?.label || "Housing";
  if (h.type === "dorm") return { label: `${typeLabel} · 전입신고 not needed`, tone: "ink" };
  if (h.jeoninReported) return { label: `${typeLabel} · 전입신고 done`, tone: "success" };
  return { label: `${typeLabel} · Address not reported`, tone: "warn" };
}

function HousingStatusBanner({ headerStatus }) {
  const tones = {
    success: { bg: "var(--success-soft)", fg: "var(--success)" },
    warn:    { bg: "var(--warning-soft)", fg: "var(--warning)" },
    ink:     { bg: "var(--ink)",          fg: "var(--lime)"    },
  }[headerStatus.tone];
  return (
    <SurfaceCard style={{
      display: "flex", alignItems: "center", justifyContent: "space-between",
      gap: 16, padding: "16px 20px",
    }}>
      <div style={{ display: "flex", alignItems: "center", gap: 14, minWidth: 0 }}>
        <span style={{
          width: 36, height: 36, borderRadius: 10,
          background: tones.bg, color: tones.fg,
          display: "inline-flex", alignItems: "center", justifyContent: "center",
          flexShrink: 0,
        }}><i className="ti ti-home" style={{ fontSize: 18 }} /></span>
        <div style={{ minWidth: 0 }}>
          <div style={{
            fontSize: 10, fontWeight: 600, color: "var(--text-mute)",
            letterSpacing: "0.18em", textTransform: "uppercase",
          }}>Current status</div>
          <div style={{
            fontSize: 14, fontWeight: 600, color: "var(--ink)", marginTop: 2,
            letterSpacing: "-0.005em",
          }}>{headerStatus.label}</div>
        </div>
      </div>
      <div style={{
        fontSize: 11.5, color: "var(--text-mute)", lineHeight: 1.5,
        maxWidth: 380, textAlign: "right",
      }}>
        Korico explains typical processes — always confirm with your landlord and local 구청 / 동사무소.
      </div>
    </SurfaceCard>
  );
}

function CurrentHousingCard({ housing, onSave }) {
  const [form, setForm] = useState(housing);
  const [editing, setEditing] = useState(false);

  useEffect(() => { setForm(housing); }, [housing]);

  const submit = () => {
    onSave(form);
    setEditing(false);
  };

  return (
    <SurfaceCard>
      <CardHead
        eyebrow="Current housing"
        title="Where you live now"
        subtitle="Korico uses this to tailor 전입신고 and ARC reminders."
        right={
          <button onClick={() => setEditing((v) => !v)} style={{
            padding: "6px 12px", borderRadius: 99,
            background: editing ? "var(--ink)" : "var(--bg-soft)",
            color: editing ? "var(--lime)" : "var(--ink)",
            fontSize: 11, fontWeight: 600, letterSpacing: "0.08em",
            display: "inline-flex", alignItems: "center", gap: 6,
          }}>
            <i className={`ti ti-${editing ? "x" : "pencil"}`} style={{ fontSize: 13 }} />
            {editing ? "Cancel" : "Edit"}
          </button>
        }
      />

      {/* Housing type picker */}
      <div style={{
        display: "grid", gridTemplateColumns: "repeat(3, 1fr)", gap: 8, marginBottom: 16,
      }} className="house-grid">
        {HOUSING_TYPES.map((t) => {
          const on = form.type === t.key;
          return (
            <button
              key={t.key}
              onClick={() => editing && setForm({ ...form, type: t.key })}
              disabled={!editing}
              style={{
                display: "flex", alignItems: "center", gap: 10,
                padding: "10px 12px", borderRadius: 12,
                background: on ? "var(--ink)" : "white",
                color: on ? "var(--lime)" : "var(--ink)",
                border: `1px solid ${on ? "var(--ink)" : "var(--border)"}`,
                cursor: editing ? "pointer" : "default",
                opacity: editing || on ? 1 : 0.85,
                transition: "transform 0.2s cubic-bezier(0.2,1.4,0.4,1), background 0.2s ease, color 0.2s ease",
              }}
              onMouseDown={(e) => editing && (e.currentTarget.style.transform = "scale(0.97)")}
              onMouseUp={(e) => e.currentTarget.style.transform = "scale(1)"}
              onMouseLeave={(e) => e.currentTarget.style.transform = "scale(1)"}
            >
              <span style={{
                width: 28, height: 28, borderRadius: 8,
                background: on ? "var(--lime)" : "var(--bg-soft)",
                color: "var(--ink)",
                display: "inline-flex", alignItems: "center", justifyContent: "center",
                flexShrink: 0,
              }}><i className={`ti ti-${t.icon}`} style={{ fontSize: 14 }} /></span>
              <span style={{ fontSize: 12, fontWeight: 600, letterSpacing: "-0.005em" }}>{t.label}</span>
            </button>
          );
        })}
      </div>

      {/* Detail KV grid */}
      <div style={{
        display: "grid", gridTemplateColumns: "1fr 1fr", gap: 12,
        marginBottom: 14,
      }} className="house-kv">
        <HousingField label="Address" editing={editing}
          value={form.address}
          onChange={(v) => setForm({ ...form, address: v })}
        />
        <HousingField label="Move-in date" editing={editing} type="date"
          value={form.moveIn}
          onChange={(v) => setForm({ ...form, moveIn: v })}
        />
        <HousingField label="Monthly rent" editing={editing}
          value={form.monthlyRent}
          onChange={(v) => setForm({ ...form, monthlyRent: v })}
        />
        <HousingField label="Deposit (보증금)" editing={editing}
          value={form.deposit}
          onChange={(v) => setForm({ ...form, deposit: v })}
        />
        <HousingField label="Landlord type" editing={editing} select
          options={["개인", "부동산", "학교", "회사"]}
          value={form.landlord}
          onChange={(v) => setForm({ ...form, landlord: v })}
        />
        <HousingField label="전입신고" editing={editing} select
          options={["Done", "Not yet"]}
          value={form.jeoninReported ? "Done" : "Not yet"}
          onChange={(v) => setForm({ ...form, jeoninReported: v === "Done" })}
        />
      </div>

      {/* Status line */}
      <div style={{
        padding: "10px 14px", borderRadius: 12,
        background: form.jeoninReported ? "var(--success-soft)" : "var(--warning-soft)",
        color: form.jeoninReported ? "var(--success)" : "var(--warning)",
        fontSize: 12, fontWeight: 500,
        display: "inline-flex", alignItems: "center", gap: 8,
      }}>
        <i className={`ti ti-${form.jeoninReported ? "check" : "alert-triangle"}`} style={{ fontSize: 14 }} />
        {form.jeoninReported
          ? `전입신고 completed on ${form.jeoninDate}`
          : "전입신고 not recorded — file within 14 days of moving."}
      </div>

      {/* Actions */}
      <div style={{
        display: "flex", justifyContent: "space-between", alignItems: "center", gap: 12,
        marginTop: 18, flexWrap: "wrap",
      }}>
        <a href="#move" style={{
          fontSize: 12, color: "var(--ink)", fontWeight: 600,
          textDecoration: "none",
          letterSpacing: "0.06em",
          display: "inline-flex", alignItems: "center", gap: 6,
        }}
          onMouseEnter={(e) => e.currentTarget.style.textDecoration = "underline"}
          onMouseLeave={(e) => e.currentTarget.style.textDecoration = "none"}
        >
          I'm moving soon
          <i className="ti ti-arrow-right" style={{ fontSize: 13 }} />
        </a>
        <button
          disabled={!editing}
          onClick={submit}
          style={{
            display: "inline-flex", alignItems: "center", gap: 10,
            padding: "11px 20px", borderRadius: 99,
            background: editing ? "var(--lime)" : "var(--bg-soft)",
            color: editing ? "var(--ink)" : "var(--text-mute)",
            fontFamily: "var(--font-body)", fontWeight: 700, fontSize: 12,
            letterSpacing: "0.16em", textTransform: "uppercase",
            boxShadow: editing ? "0 10px 22px rgba(184,230,60,0.35)" : "none",
            cursor: editing ? "pointer" : "not-allowed",
            transition: "transform 0.18s ease, box-shadow 0.18s ease",
          }}
          onMouseEnter={(e) => editing && (e.currentTarget.style.transform = "translateY(-1px)")}
          onMouseLeave={(e) => e.currentTarget.style.transform = "translateY(0)"}
        >
          {editing ? "Save changes" : "Add / update home"}
          <span style={{
            width: 20, height: 20, borderRadius: "50%",
            background: editing ? "var(--ink)" : "white",
            color: editing ? "var(--lime)" : "var(--text-mute)",
            display: "inline-flex", alignItems: "center", justifyContent: "center",
          }}><i className="ti ti-check" style={{ fontSize: 11 }} /></span>
        </button>
      </div>

      <style>{`
        @media (max-width: 760px) {
          .house-grid { grid-template-columns: repeat(2, 1fr) !important; }
          .house-kv { grid-template-columns: 1fr !important; }
        }
      `}</style>
    </SurfaceCard>
  );
}

function HousingField({ label, value, onChange, editing, type, select, options }) {
  return (
    <label style={{ display: "flex", flexDirection: "column", gap: 6 }}>
      <span style={{
        fontSize: 10, fontWeight: 600, color: "var(--text-mute)",
        letterSpacing: "0.16em", textTransform: "uppercase",
      }}>{label}</span>
      {!editing ? (
        <div style={{
          fontSize: 13.5, color: "var(--ink)", fontWeight: 500,
          letterSpacing: "-0.005em",
          padding: "8px 0",
        }}>{value || "—"}</div>
      ) : select ? (
        <Select value={value} onChange={onChange} options={options} />
      ) : (
        <input
          type={type || "text"}
          value={value}
          onChange={(e) => onChange(e.target.value)}
          style={{
            padding: "10px 12px", borderRadius: 10,
            border: "1px solid var(--border)",
            fontSize: 13, color: "var(--ink)", outline: "none",
            fontFamily: "var(--font-body)", background: "white",
          }}
          onFocus={(e) => e.currentTarget.style.borderColor = "var(--ink)"}
          onBlur={(e) => e.currentTarget.style.borderColor = "var(--border)"}
        />
      )}
    </label>
  );
}

function MovingHistoryCard({ history, onAdd }) {
  const [adding, setAdding] = useState(false);
  const [draft, setDraft] = useState({ date: "", type: "Unknown", area: "" });

  const submit = (e) => {
    e.preventDefault();
    if (!draft.date) return;
    onAdd({
      id: "h" + Date.now() % 100000,
      range: draft.date + " (planned)",
      type: draft.type + " · " + (draft.area || "—"),
      area: draft.area,
      state: "planned",
    });
    setDraft({ date: "", type: "Unknown", area: "" });
    setAdding(false);
  };

  return (
    <SurfaceCard>
      <CardHead
        eyebrow="Timeline"
        title="Moving history & plans"
        subtitle="Past, current, and planned moves — so Korico can prep address tasks ahead of time."
      />
      <ul style={{ listStyle: "none", margin: 0, padding: 0, display: "flex", flexDirection: "column", gap: 8 }}>
        {history.map((h) => <MoveRow key={h.id} h={h} />)}
      </ul>

      {adding && (
        <form onSubmit={submit} style={{
          marginTop: 14, padding: "14px 16px", borderRadius: 14,
          background: "var(--bg-soft)",
          display: "grid", gridTemplateColumns: "1fr 1fr 1fr auto", gap: 8, alignItems: "end",
          animation: "fade-up 0.3s cubic-bezier(0.2,0.7,0.2,1) both",
        }} className="move-form">
          <HousingField label="Move date" editing type="date"
            value={draft.date} onChange={(v) => setDraft({ ...draft, date: v })} />
          <HousingField label="Housing type" editing select
            options={["Unknown", "Dormitory", "Gosiwon", "Hasukjip", "One-room (월세)", "Jeonse"]}
            value={draft.type} onChange={(v) => setDraft({ ...draft, type: v })} />
          <HousingField label="City / gu" editing
            value={draft.area} onChange={(v) => setDraft({ ...draft, area: v })} />
          <button type="submit" style={{
            padding: "10px 16px", borderRadius: 99,
            background: "var(--ink)", color: "var(--lime)",
            fontSize: 11, fontWeight: 700, letterSpacing: "0.14em", textTransform: "uppercase",
            height: 40,
          }}>Save</button>
          <style>{`
            @media (max-width: 720px) { .move-form { grid-template-columns: 1fr !important; }}
          `}</style>
        </form>
      )}

      <div style={{ display: "flex", justifyContent: "flex-end", marginTop: 14 }}>
        <button onClick={() => setAdding((v) => !v)} style={{
          display: "inline-flex", alignItems: "center", gap: 8,
          padding: "10px 16px", borderRadius: 99,
          background: "white", color: "var(--ink)",
          border: "1px solid var(--ink)",
          fontSize: 11, fontWeight: 700, letterSpacing: "0.14em", textTransform: "uppercase",
          transition: "background 0.18s ease, color 0.18s ease",
        }}
          onMouseEnter={(e) => { e.currentTarget.style.background = "var(--ink)"; e.currentTarget.style.color = "var(--lime)"; }}
          onMouseLeave={(e) => { e.currentTarget.style.background = "white"; e.currentTarget.style.color = "var(--ink)"; }}
        >
          <i className={`ti ti-${adding ? "x" : "plus"}`} style={{ fontSize: 13 }} />
          {adding ? "Close" : "Add planned move"}
        </button>
      </div>
    </SurfaceCard>
  );
}

function MoveRow({ h }) {
  const tones = {
    past:    { bg: "var(--bg-soft)",     fg: "var(--text-mute)", dot: "var(--border)" },
    current: { bg: "rgba(212,255,79,0.18)", fg: "var(--ink)",   dot: "var(--lime)" },
    planned: { bg: "rgba(46,139,255,0.10)", fg: "var(--sky-1)", dot: "var(--sky-2)" },
  }[h.state];
  return (
    <li style={{
      display: "grid", gridTemplateColumns: "auto 1fr auto", gap: 14,
      alignItems: "center",
      padding: "12px 14px", borderRadius: 12,
      background: "white", border: "1px solid var(--border-soft)",
      transition: "border-color 0.18s ease, background 0.18s ease",
    }}
      onMouseEnter={(e) => e.currentTarget.style.borderColor = "var(--border)"}
      onMouseLeave={(e) => e.currentTarget.style.borderColor = "var(--border-soft)"}
    >
      <span style={{
        width: 32, height: 32, borderRadius: 10,
        background: tones.bg, color: tones.fg,
        display: "inline-flex", alignItems: "center", justifyContent: "center",
      }}>
        <span style={{
          width: 8, height: 8, borderRadius: "50%", background: tones.dot,
          animation: h.state === "current" ? "pulse-dot 2s ease-in-out infinite" : "none",
        }} />
      </span>
      <div style={{ minWidth: 0 }}>
        <div style={{ fontSize: 13, fontWeight: 600, color: "var(--ink)", letterSpacing: "-0.005em" }}>{h.type}</div>
        <div style={{ fontSize: 11.5, color: "var(--text-mute)", marginTop: 2 }}>{h.range}{h.area ? ` · ${h.area}` : ""}</div>
      </div>
      <span style={{
        padding: "3px 9px", borderRadius: 99,
        background: tones.bg, color: tones.fg,
        fontSize: 10, fontWeight: 700, letterSpacing: "0.1em", textTransform: "uppercase",
      }}>{h.state}</span>
    </li>
  );
}

function AddressARCCard() {
  const steps = [
    { icon: "truck",        label: "Move to new place" },
    { icon: "writing-sign", label: "전입신고 at 구청 / 주민센터 within 14 days" },
    { icon: "credit-card",  label: "Update ARC info if needed" },
  ];
  return (
    <SurfaceCard>
      <CardHead
        eyebrow="Address & ARC"
        title="How a move connects to your ARC"
        subtitle="When you change address, your ARC and visa need to stay in sync. Here's the quick flow."
      />
      <ol style={{
        listStyle: "none", margin: 0, padding: 0,
        display: "grid", gridTemplateColumns: "repeat(3, 1fr)", gap: 12,
      }} className="arc-steps">
        {steps.map((s, i) => (
          <li key={s.label} style={{
            position: "relative",
            padding: "16px", borderRadius: 14,
            background: "var(--bg-soft)",
            border: "1px solid var(--border-soft)",
            display: "flex", flexDirection: "column", gap: 10,
          }}>
            <span style={{
              width: 30, height: 30, borderRadius: 9,
              background: "var(--ink)", color: "var(--lime)",
              display: "inline-flex", alignItems: "center", justifyContent: "center",
              fontSize: 11, fontWeight: 700, letterSpacing: "0.02em",
            }}>{i + 1}</span>
            <span style={{
              width: 32, height: 32, borderRadius: 9,
              background: "white", color: "var(--ink)",
              display: "inline-flex", alignItems: "center", justifyContent: "center",
            }}><i className={`ti ti-${s.icon}`} style={{ fontSize: 16 }} /></span>
            <div style={{
              fontSize: 12.5, fontWeight: 500, color: "var(--ink)",
              letterSpacing: "-0.005em", lineHeight: 1.45,
            }}>{s.label}</div>
          </li>
        ))}
      </ol>
      <div style={{ marginTop: 14 }}>
        <a href="#arc" style={{
          display: "inline-flex", alignItems: "center", gap: 8,
          padding: "9px 14px", borderRadius: 99,
          background: "white", color: "var(--ink)",
          border: "1px solid var(--border)",
          fontSize: 11, fontWeight: 700, letterSpacing: "0.14em", textTransform: "uppercase",
          textDecoration: "none",
          transition: "background 0.18s ease",
        }}
          onMouseEnter={(e) => e.currentTarget.style.background = "var(--bg-soft)"}
          onMouseLeave={(e) => e.currentTarget.style.background = "white"}
        >
          View ARC page
          <i className="ti ti-arrow-up-right" style={{ fontSize: 12 }} />
        </a>
      </div>
      <style>{`
        @media (max-width: 720px) { .arc-steps { grid-template-columns: 1fr !important; }}
      `}</style>
    </SurfaceCard>
  );
}

function HousingChecklistCard({ housing }) {
  const items = useMemo(() => checklistFor(housing), [housing]);
  const [state, setState] = useState({});
  const toggle = (id) => setState((s) => ({ ...s, [id]: !s[id] }));
  return (
    <SurfaceCard>
      <CardHead
        eyebrow="Checklist"
        title="Housing checklist"
        subtitle="Tailored to your current housing type."
      />
      <ul style={{ listStyle: "none", margin: 0, padding: 0, display: "flex", flexDirection: "column", gap: 6 }}>
        {items.map((it) => {
          const done = state[it.id] ?? it.defaultDone;
          return (
            <li key={it.id}>
              <button onClick={() => toggle(it.id)} style={{
                display: "flex", alignItems: "flex-start", gap: 12,
                padding: "10px 12px", borderRadius: 12,
                background: done ? "var(--bg-soft)" : "white",
                border: "1px solid " + (done ? "var(--border-soft)" : "var(--border)"),
                textAlign: "left", width: "100%",
                transition: "background 0.18s ease, border-color 0.18s ease",
              }}>
                <span style={{
                  width: 20, height: 20, borderRadius: 6,
                  background: done ? "var(--ink)" : "white",
                  border: done ? "none" : "1.5px solid var(--border)",
                  display: "inline-flex", alignItems: "center", justifyContent: "center",
                  color: "var(--lime)", flexShrink: 0, marginTop: 2,
                }}>
                  {done && <i className="ti ti-check" style={{ fontSize: 12, animation: "check-pop 0.3s cubic-bezier(0.2,1.4,0.4,1) both" }} />}
                </span>
                <div style={{ flex: 1, minWidth: 0 }}>
                  <div style={{
                    fontSize: 12.5, fontWeight: 500,
                    color: done ? "var(--text-mute)" : "var(--ink)",
                    textDecoration: done ? "line-through" : "none",
                    letterSpacing: "-0.005em",
                  }}>{it.label}</div>
                  {it.info && (
                    <div style={{ fontSize: 11, color: "var(--text-mute)", marginTop: 2, fontStyle: "italic", lineHeight: 1.5 }}>
                      {it.info}
                    </div>
                  )}
                </div>
              </button>
            </li>
          );
        })}
      </ul>
    </SurfaceCard>
  );
}

function checklistFor(h) {
  if (h.type === "wolse" || h.type === "jeonse") {
    return [
      { id: "c1", label: "Review your 임대차 계약서", info: "Check term, deposit (보증금), exit clauses, and 특약 lines.", defaultDone: true },
      { id: "c2", label: "Confirm deposit and monthly rent", info: "Boost confidence — match the contract numbers against your transfers.", defaultDone: true },
      { id: "c3", label: "Check 전세보증보험 / deposit insurance", info: "Available for many jeonse and some wolse cases via HUG or SGI.", defaultDone: false },
      { id: "c4", label: "Complete 전입신고 within 14 days of moving", info: "Required for ARC address and many tenant protections.", defaultDone: h.jeoninReported },
      { id: "c5", label: "Upload photos of apartment condition", info: "Protects your deposit at move-out.", defaultDone: false },
    ];
  }
  if (h.type === "gosiwon" || h.type === "hasukjip") {
    return [
      { id: "g1", label: "Get a signed receipt or simple contract", info: "Even a one-page agreement helps if disputes happen.", defaultDone: true },
      { id: "g2", label: "Confirm move-in date and monthly fee", info: "Many gosiwon ask for cash — keep records anyway.", defaultDone: true },
      { id: "g3", label: "Ask if 전입신고 is possible at this address", info: "Some gosiwon don't allow it — important for ARC.", defaultDone: false },
      { id: "g4", label: "Save the operator's phone and address", info: "Useful for emergency, building rules, and visa documents.", defaultDone: false },
    ];
  }
  if (h.type === "dorm") {
    return [
      { id: "d1", label: "Save your dormitory check-in confirmation", info: "Treat it like a contract — useful for ARC.", defaultDone: true },
      { id: "d2", label: "Confirm address format for ARC purposes", info: "Use the official building/room format.", defaultDone: true },
      { id: "d3", label: "전입신고 not usually needed for school dorms", info: "Confirm with the international office to be sure.", defaultDone: true },
    ];
  }
  return [
    { id: "x1", label: "Save your housing agreement or company letter", info: "Even company housing needs proof for ARC and immigration.", defaultDone: false },
    { id: "x2", label: "Confirm whether 전입신고 is required", info: "Depends on the building, district, and your contract.", defaultDone: false },
  ];
}

function HousingDocsCard() {
  return (
    <SurfaceCard>
      <CardHead
        eyebrow="Documents"
        title="Housing documents"
        subtitle="Pulled from your file vault and tagged as housing."
        right={
          <a href="#documents" style={{
            fontSize: 11, fontWeight: 600, color: "var(--ink)",
            textDecoration: "none", letterSpacing: "0.06em",
            display: "inline-flex", alignItems: "center", gap: 6,
          }}
            onMouseEnter={(e) => e.currentTarget.style.textDecoration = "underline"}
            onMouseLeave={(e) => e.currentTarget.style.textDecoration = "none"}
          >
            Open all
            <i className="ti ti-arrow-up-right" style={{ fontSize: 12 }} />
          </a>
        }
      />
      <div style={{ display: "flex", flexDirection: "column", gap: 8 }}>
        {HOUSING_DOCS.map((d) => <HousingDocRow key={d.name} d={d} />)}
      </div>
      <div style={{ display: "flex", justifyContent: "flex-end", marginTop: 14 }}>
        <button style={{
          display: "inline-flex", alignItems: "center", gap: 8,
          padding: "10px 16px", borderRadius: 99,
          background: "var(--lime)", color: "var(--ink)",
          fontSize: 11, fontWeight: 700, letterSpacing: "0.14em", textTransform: "uppercase",
          boxShadow: "0 8px 18px rgba(184,230,60,0.32)",
          transition: "transform 0.18s ease",
        }}
          onMouseEnter={(e) => e.currentTarget.style.transform = "translateY(-1px)"}
          onMouseLeave={(e) => e.currentTarget.style.transform = "translateY(0)"}
        >
          <i className="ti ti-upload" style={{ fontSize: 13 }} />
          Upload housing document
        </button>
      </div>
    </SurfaceCard>
  );
}

function HousingDocRow({ d }) {
  const tagPalette = {
    Contract: { bg: "var(--ink)",          fg: "var(--lime)" },
    Address:  { bg: "var(--success-soft)", fg: "var(--success)" },
    Receipt:  { bg: "var(--warning-soft)", fg: "var(--warning)" },
  }[d.tag] || { bg: "var(--bg-soft)", fg: "var(--ink)" };
  return (
    <div style={{
      display: "grid", gridTemplateColumns: "auto 1fr auto auto", gap: 10,
      alignItems: "center",
      padding: "10px 12px", borderRadius: 12,
      background: "white", border: "1px solid var(--border-soft)",
      transition: "background 0.18s ease, border-color 0.18s ease",
    }}
      onMouseEnter={(e) => { e.currentTarget.style.background = "var(--bg-soft)"; e.currentTarget.style.borderColor = "var(--border)"; }}
      onMouseLeave={(e) => { e.currentTarget.style.background = "white"; e.currentTarget.style.borderColor = "var(--border-soft)"; }}
    >
      <span style={{
        width: 32, height: 32, borderRadius: 8,
        background: "var(--bg-soft)", color: "var(--ink)",
        display: "inline-flex", alignItems: "center", justifyContent: "center",
      }}><i className="ti ti-file-text" style={{ fontSize: 16 }} /></span>
      <div style={{ minWidth: 0 }}>
        <div style={{ fontSize: 12.5, fontWeight: 600, color: "var(--ink)", letterSpacing: "-0.005em" }}>{d.name}</div>
        <div style={{ fontSize: 10.5, color: "var(--text-mute)", marginTop: 2 }}>{d.file} · {d.date}</div>
      </div>
      <span style={{
        padding: "3px 8px", borderRadius: 99,
        background: tagPalette.bg, color: tagPalette.fg,
        fontSize: 9.5, fontWeight: 700, letterSpacing: "0.12em", textTransform: "uppercase",
      }}>{d.tag}</span>
      <div style={{ display: "inline-flex", gap: 4 }}>
        <button title="Open" style={iconBtnStyle}>
          <i className="ti ti-external-link" style={{ fontSize: 13 }} />
        </button>
        <button title="Retag" style={iconBtnStyle}>
          <i className="ti ti-tag" style={{ fontSize: 13 }} />
        </button>
      </div>
    </div>
  );
}

const iconBtnStyle = {
  width: 28, height: 28, borderRadius: 8,
  background: "transparent",
  color: "var(--text-mute)",
  display: "inline-flex", alignItems: "center", justifyContent: "center",
  transition: "background 0.18s ease, color 0.18s ease",
};

function HousingGuidesCard() {
  return (
    <SurfaceCard>
      <CardHead
        eyebrow="Learn"
        title="Guides for housing & moving"
        subtitle="Plain-language explainers, tailored to renters in Korea."
      />
      <div style={{ display: "flex", flexDirection: "column", gap: 8 }}>
        {HOUSING_GUIDES.map((g) => (
          <a key={g.title} href="#guides" style={{
            display: "flex", alignItems: "center", gap: 12,
            padding: "10px 12px", borderRadius: 12,
            background: "white", border: "1px solid var(--border-soft)",
            textDecoration: "none",
            transition: "background 0.18s ease, border-color 0.18s ease",
          }}
            onMouseEnter={(e) => { e.currentTarget.style.background = "var(--bg-soft)"; e.currentTarget.style.borderColor = "var(--border)"; }}
            onMouseLeave={(e) => { e.currentTarget.style.background = "white"; e.currentTarget.style.borderColor = "var(--border-soft)"; }}
          >
            <span style={{
              width: 32, height: 32, borderRadius: 9,
              background: "var(--bg-soft)", color: "var(--ink)",
              display: "inline-flex", alignItems: "center", justifyContent: "center",
              flexShrink: 0,
            }}><i className={`ti ti-${g.icon}`} style={{ fontSize: 16 }} /></span>
            <div style={{ flex: 1, minWidth: 0 }}>
              <div style={{ fontSize: 13, fontWeight: 600, color: "var(--ink)", letterSpacing: "-0.005em" }}>{g.title}</div>
              <div style={{ fontSize: 11, color: "var(--text-mute)", marginTop: 2 }}>{g.sub}</div>
            </div>
            <i className="ti ti-arrow-up-right" style={{ fontSize: 14, color: "var(--text-mute)" }} />
          </a>
        ))}
      </div>
    </SurfaceCard>
  );
}

/* ============================================================
   LEGAL & 행정사 DIRECTORY (neutral — no rankings/ratings)
   ============================================================ */

const REGIONS = ["서울", "경기", "부산", "대구", "인천", "광주", "대전", "울산", "기타 지역"];
const TOPIC_OPTS = [
  "Student visas (D-2, D-10)",
  "Work visas (E-7, E-9 등)",
  "Long-term stay (F-2, F-5 등)",
  "Naturalization",
  "Housing & contracts",
  "Tax & work",
  "Everyday admin (ARC, address)",
];
const LANG_OPTS = ["한국어", "English", "中文", "Tiếng Việt", "Монгол", "기타"];
const METHOD_OPTS = ["In-person", "Phone", "Online (video/chat)"];
const COST_OPTS = ["First consultation free", "Paid consultation", "Price not listed"];

const OFFICES = [
  {
    id: "o1",
    name: "Kim & Park 행정사 사무소",
    type: "행정사",
    region: "서울",
    district: "마포구",
    online: true,
    topics: ["Student visas (D-2, D-10)", "Work visas (E-7, E-9 등)", "Everyday admin (ARC, address)"],
    langs: ["한국어", "English"],
    methods: ["In-person", "Online (video/chat)"],
    cost: "Paid consultation",
    phone: "02-XXX-1234",
    email: "hello@kimpark.kr",
    website: "kimpark.kr",
    kakao: true,
    note: "Focus on student and worker visas; weekday evening consultations available.",
  },
  {
    id: "o2",
    name: "Hanul 행정사 그룹",
    type: "행정사",
    region: "서울",
    district: "영등포구",
    online: true,
    topics: ["Long-term stay (F-2, F-5 등)", "Naturalization", "Everyday admin (ARC, address)"],
    langs: ["한국어", "中文", "English"],
    methods: ["In-person", "Phone"],
    cost: "First consultation free",
    phone: "02-XXX-5678",
    email: "info@hanul-arc.kr",
    website: "hanul-arc.kr",
    kakao: false,
    note: "Long-term residence and naturalization specialty. Mandarin-speaking 행정사 on staff.",
  },
  {
    id: "o3",
    name: "Seoul Foreign Help 법무사",
    type: "법무사",
    region: "서울",
    district: "종로구",
    online: false,
    topics: ["Housing & contracts", "Tax & work"],
    langs: ["한국어", "English"],
    methods: ["In-person"],
    cost: "Paid consultation",
    phone: "02-XXX-2222",
    email: "contact@sfh-law.kr",
    website: "",
    kakao: false,
    note: "Drafts and reviews 임대차 계약서 and short employment contracts for foreigners.",
  },
  {
    id: "o4",
    name: "Lee Immigration 행정사",
    type: "행정사",
    region: "경기",
    district: "수원시",
    online: true,
    topics: ["Work visas (E-7, E-9 등)", "Long-term stay (F-2, F-5 등)"],
    langs: ["한국어", "Tiếng Việt"],
    methods: ["Phone", "Online (video/chat)"],
    cost: "Price not listed",
    phone: "031-XXX-7777",
    email: "lee@lee-immi.kr",
    website: "lee-immi.kr",
    kakao: true,
    note: "Online consultations for Vietnamese-speaking workers across Gyeonggi.",
  },
  {
    id: "o5",
    name: "OneStop 행정사",
    type: "행정사",
    region: "부산",
    district: "해운대구",
    online: true,
    topics: ["Student visas (D-2, D-10)", "Everyday admin (ARC, address)"],
    langs: ["한국어", "English", "中文"],
    methods: ["In-person", "Online (video/chat)"],
    cost: "First consultation free",
    phone: "051-XXX-9090",
    email: "hello@onestop-busan.kr",
    website: "",
    kakao: true,
    note: "Busan-based; offers a free 15-minute first consultation for university students.",
  },
  {
    id: "o6",
    name: "GlobalAid 법률 사무소",
    type: "법률 사무소",
    region: "서울",
    district: "강남구",
    online: true,
    topics: ["Work visas (E-7, E-9 등)", "Long-term stay (F-2, F-5 등)", "Naturalization", "Tax & work"],
    langs: ["한국어", "English", "中文", "Монгол"],
    methods: ["In-person", "Phone", "Online (video/chat)"],
    cost: "Paid consultation",
    phone: "02-XXX-3030",
    email: "intl@globalaid.kr",
    website: "globalaid.kr",
    kakao: false,
    note: "Mid-size firm covering complex employment and naturalization cases.",
  },
  {
    id: "o7",
    name: "EveryVisa 행정사",
    type: "행정사",
    region: "대구",
    district: "수성구",
    online: true,
    topics: ["Student visas (D-2, D-10)", "Work visas (E-7, E-9 등)", "Everyday admin (ARC, address)"],
    langs: ["한국어", "English"],
    methods: ["Online (video/chat)", "Phone"],
    cost: "First consultation free",
    phone: "053-XXX-4040",
    email: "team@everyvisa.kr",
    website: "everyvisa.kr",
    kakao: true,
    note: "Online-first; chat consultations on weekdays.",
  },
  {
    id: "o8",
    name: "MN Bridge 행정사",
    type: "행정사",
    region: "서울",
    district: "광진구",
    online: true,
    topics: ["Work visas (E-7, E-9 등)", "Everyday admin (ARC, address)", "Housing & contracts"],
    langs: ["한국어", "Монгол", "English"],
    methods: ["In-person", "Online (video/chat)"],
    cost: "Paid consultation",
    phone: "02-XXX-6060",
    email: "info@mnbridge.kr",
    website: "mnbridge.kr",
    kakao: true,
    note: "Mongolian-speaking 행정사; familiar with E-7 conversions.",
  },
];

const DEFAULT_FILTERS = {
  q: "",
  regions: new Set(),
  online: false,
  topics: new Set(),
  langs: new Set(),
  methods: new Set(),
  costs: new Set(),
};

function LegalPage() {
  const [applied, setApplied] = useState(DEFAULT_FILTERS);
  const [draft, setDraft] = useState(DEFAULT_FILTERS);
  const [saved, setSaved] = useState(new Set());
  const [selectedId, setSelectedId] = useState(null);
  const [visibleCount, setVisibleCount] = useState(5);

  const results = useMemo(() => OFFICES.filter((o) => matchesFilters(o, applied)), [applied]);
  const visible = results.slice(0, visibleCount);
  const selected = OFFICES.find((o) => o.id === selectedId) || null;

  const apply = () => { setApplied(draft); setVisibleCount(5); };
  const reset = () => { setDraft(DEFAULT_FILTERS); setApplied(DEFAULT_FILTERS); };

  const toggleSet = (key, val) => {
    setDraft((d) => {
      const next = new Set(d[key]);
      next.has(val) ? next.delete(val) : next.add(val);
      return { ...d, [key]: next };
    });
  };

  const toggleSave = (id) => {
    setSaved((s) => {
      const n = new Set(s);
      n.has(id) ? n.delete(id) : n.add(id);
      return n;
    });
  };

  // Search box: live filter on q
  useEffect(() => { setApplied((a) => ({ ...a, q: draft.q })); }, [draft.q]);

  return (
    <>
    <div style={{
      animation: "fade-up 0.5s cubic-bezier(0.2,0.7,0.2,1) both",
      animationDelay: "0.05s",
      maxWidth: 1320,
    }}>
      {/* Search + neutrality note */}
      <div style={{
        display: "flex", alignItems: "center", justifyContent: "space-between", gap: 16,
        marginBottom: 16, flexWrap: "wrap",
      }}>
        <p style={{
          fontSize: 11.5, color: "var(--text-mute)", lineHeight: 1.5,
          maxWidth: 720, fontStyle: "italic",
        }}>
          Korico provides this list for information only and does not guarantee results or recommend specific offices. Always check the latest information directly with the 행정사 / 법률 사무소.
        </p>
        <div style={{
          display: "inline-flex", alignItems: "center", gap: 8,
          padding: "8px 14px", borderRadius: 99,
          background: "white", border: "1px solid var(--border)",
          minWidth: 280,
        }}>
          <i className="ti ti-search" style={{ fontSize: 15, color: "var(--text-mute)" }} />
          <input
            value={draft.q}
            onChange={(e) => setDraft({ ...draft, q: e.target.value })}
            placeholder="Search by name, area, or keyword…"
            style={{
              flex: 1, border: "none", outline: "none",
              fontSize: 13, color: "var(--ink)",
              background: "transparent",
            }}
          />
          {draft.q && (
            <button onClick={() => setDraft({ ...draft, q: "" })} aria-label="Clear search" style={{
              color: "var(--text-mute)",
              display: "inline-flex", alignItems: "center", justifyContent: "center",
            }}><i className="ti ti-x" style={{ fontSize: 13 }} /></button>
          )}
        </div>
      </div>

      <div style={{
        display: "grid", gridTemplateColumns: "300px 1fr", gap: 22,
        alignItems: "flex-start",
      }} className="legal-grid">

        {/* FILTERS */}
        <FilterPanel
          draft={draft}
          setDraft={setDraft}
          toggleSet={toggleSet}
          onApply={apply}
          onReset={reset}
        />

        {/* RESULTS */}
        <div style={{ display: "flex", flexDirection: "column", gap: 14, minWidth: 0 }}>
          <div style={{
            display: "flex", alignItems: "center", justifyContent: "space-between", gap: 12,
            padding: "4px 4px 0",
          }}>
            <div style={{ fontSize: 12.5, color: "var(--text-mute)" }}>
              <strong style={{ color: "var(--ink)", fontWeight: 600 }}>{results.length}</strong> office{results.length === 1 ? "" : "s"} match your filters
            </div>
            {saved.size > 0 && (
              <div style={{
                display: "inline-flex", alignItems: "center", gap: 6,
                padding: "5px 10px", borderRadius: 99,
                background: "var(--lime)", color: "var(--ink)",
                fontSize: 10, fontWeight: 700, letterSpacing: "0.12em", textTransform: "uppercase",
              }}>
                <i className="ti ti-bookmark-filled" style={{ fontSize: 12 }} />
                {saved.size} saved
              </div>
            )}
          </div>

          {visible.length === 0 ? (
            <SurfaceCard style={{ padding: "40px 22px", textAlign: "center" }}>
              <div style={{ fontSize: 14, color: "var(--text-mute)" }}>
                No offices match the current filters. Try resetting or broadening your selection.
              </div>
            </SurfaceCard>
          ) : (
            visible.map((o) => (
              <OfficeCard
                key={o.id}
                office={o}
                saved={saved.has(o.id)}
                onSave={() => toggleSave(o.id)}
                onOpen={() => setSelectedId(o.id)}
              />
            ))
          )}

          {visibleCount < results.length && (
            <div style={{ display: "flex", justifyContent: "center", paddingTop: 6 }}>
              <button onClick={() => setVisibleCount((c) => c + 5)} style={{
                padding: "11px 22px", borderRadius: 99,
                background: "white", color: "var(--ink)",
                border: "1px solid var(--ink)",
                fontSize: 11, fontWeight: 700, letterSpacing: "0.16em", textTransform: "uppercase",
                transition: "background 0.18s ease, color 0.18s ease",
              }}
                onMouseEnter={(e) => { e.currentTarget.style.background = "var(--ink)"; e.currentTarget.style.color = "var(--lime)"; }}
                onMouseLeave={(e) => { e.currentTarget.style.background = "white"; e.currentTarget.style.color = "var(--ink)"; }}
              >Load more</button>
            </div>
          )}
        </div>
      </div>

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

    {/* Drawer outside the animated container so position:fixed refers to the viewport */}
    <OfficeDrawer
      office={selected}
      onClose={() => setSelectedId(null)}
      saved={selected && saved.has(selected.id)}
      onSave={() => selected && toggleSave(selected.id)}
    />
    </>
  );
}

function matchesFilters(o, f) {
  if (f.q) {
    const q = f.q.toLowerCase();
    const blob = [o.name, o.region, o.district, ...o.topics, ...o.langs, o.note].join(" ").toLowerCase();
    if (!blob.includes(q)) return false;
  }
  if (f.regions.size > 0 && !f.regions.has(o.region)) return false;
  if (f.online && !o.online) return false;
  if (f.topics.size > 0 && !o.topics.some((t) => f.topics.has(t))) return false;
  if (f.langs.size > 0 && !o.langs.some((l) => f.langs.has(l))) return false;
  if (f.methods.size > 0 && !o.methods.some((m) => f.methods.has(m))) return false;
  if (f.costs.size > 0 && !f.costs.has(o.cost)) return false;
  return true;
}

/* ---- FILTER PANEL ---- */

function FilterPanel({ draft, setDraft, toggleSet, onApply, onReset }) {
  const count = draft.regions.size + draft.topics.size + draft.langs.size + draft.methods.size + draft.costs.size + (draft.online ? 1 : 0);
  return (
    <SurfaceCard style={{ position: "sticky", top: 18, padding: 18, display: "flex", flexDirection: "column", gap: 14 }}>
      <header style={{ display: "flex", alignItems: "center", justifyContent: "space-between" }}>
        <div>
          <div style={{
            fontSize: 10, fontWeight: 600, color: "var(--text-mute)",
            letterSpacing: "0.18em", textTransform: "uppercase",
          }}>Filters</div>
          <div style={{ fontSize: 14, fontWeight: 600, color: "var(--ink)", marginTop: 2 }}>
            Narrow the list
          </div>
        </div>
        {count > 0 && (
          <span style={{
            padding: "3px 9px", borderRadius: 99,
            background: "var(--ink)", color: "var(--lime)",
            fontSize: 10, fontWeight: 700, letterSpacing: "0.1em",
          }}>{count}</span>
        )}
      </header>

      <FilterGroup title="Region / area">
        <CheckList items={REGIONS} selected={draft.regions} onToggle={(v) => toggleSet("regions", v)} />
        <ToggleLine
          on={draft.online}
          onToggle={() => setDraft({ ...draft, online: !draft.online })}
          label="Online / 전국 상담 가능"
        />
      </FilterGroup>

      <FilterGroup title="Main topics">
        <ChipList items={TOPIC_OPTS} selected={draft.topics} onToggle={(v) => toggleSet("topics", v)} />
      </FilterGroup>

      <FilterGroup title="Languages available">
        <CheckList items={LANG_OPTS} selected={draft.langs} onToggle={(v) => toggleSet("langs", v)} compact />
      </FilterGroup>

      <FilterGroup title="Consultation method">
        <CheckList items={METHOD_OPTS} selected={draft.methods} onToggle={(v) => toggleSet("methods", v)} compact />
      </FilterGroup>

      <FilterGroup title="Consultation cost info">
        <CheckList items={COST_OPTS} selected={draft.costs} onToggle={(v) => toggleSet("costs", v)} compact />
      </FilterGroup>

      <div style={{
        display: "flex", gap: 8, paddingTop: 12,
        borderTop: "1px solid var(--border-soft)",
      }}>
        <button onClick={onApply} style={{
          flex: 1, padding: "11px 14px", borderRadius: 99,
          background: "var(--lime)", color: "var(--ink)",
          fontSize: 11, fontWeight: 700, letterSpacing: "0.14em", textTransform: "uppercase",
          boxShadow: "0 8px 18px rgba(184,230,60,0.32)",
        }}
          onMouseEnter={(e) => e.currentTarget.style.transform = "translateY(-1px)"}
          onMouseLeave={(e) => e.currentTarget.style.transform = "translateY(0)"}
        >Apply filters</button>
        <button onClick={onReset} style={{
          padding: "11px 14px", borderRadius: 99,
          background: "white", color: "var(--ink)",
          border: "1px solid var(--border)",
          fontSize: 11, fontWeight: 600, letterSpacing: "0.14em", textTransform: "uppercase",
        }}>Reset</button>
      </div>
    </SurfaceCard>
  );
}

function FilterGroup({ title, children }) {
  const [open, setOpen] = useState(true);
  return (
    <div>
      <button onClick={() => setOpen((o) => !o)} style={{
        display: "flex", alignItems: "center", justifyContent: "space-between",
        width: "100%", padding: "4px 0",
        fontSize: 11, fontWeight: 600, color: "var(--ink)",
        letterSpacing: "0.12em", textTransform: "uppercase",
      }}>
        {title}
        <i className={`ti ti-chevron-${open ? "up" : "down"}`} style={{ fontSize: 14, color: "var(--text-mute)" }} />
      </button>
      {open && <div style={{ marginTop: 8 }}>{children}</div>}
    </div>
  );
}

function CheckList({ items, selected, onToggle, compact }) {
  return (
    <div style={{
      display: "grid",
      gridTemplateColumns: compact ? "1fr" : "1fr 1fr",
      gap: 6,
    }}>
      {items.map((it) => {
        const on = selected.has(it);
        return (
          <label key={it} style={{
            display: "flex", alignItems: "center", gap: 8,
            padding: "5px 0",
            fontSize: 12, color: on ? "var(--ink)" : "var(--text-soft)",
            cursor: "pointer",
          }}>
            <input type="checkbox" checked={on} onChange={() => onToggle(it)} style={{ display: "none" }} />
            <span style={{
              width: 16, height: 16, borderRadius: 5,
              background: on ? "var(--ink)" : "white",
              border: on ? "none" : "1.5px solid var(--border)",
              display: "inline-flex", alignItems: "center", justifyContent: "center",
              color: "var(--lime)",
              flexShrink: 0,
              transition: "background 0.18s ease, border-color 0.18s ease",
            }}>
              {on && <i className="ti ti-check" style={{ fontSize: 10 }} />}
            </span>
            <span style={{ fontWeight: on ? 600 : 500, letterSpacing: "-0.005em" }}>{it}</span>
          </label>
        );
      })}
    </div>
  );
}

function ChipList({ items, selected, onToggle }) {
  return (
    <div style={{ display: "flex", flexWrap: "wrap", gap: 6 }}>
      {items.map((it) => {
        const on = selected.has(it);
        return (
          <button key={it} onClick={() => onToggle(it)} style={{
            padding: "6px 10px", borderRadius: 99,
            background: on ? "var(--ink)" : "white",
            color: on ? "var(--lime)" : "var(--ink)",
            border: `1px solid ${on ? "var(--ink)" : "var(--border)"}`,
            fontSize: 11, fontWeight: 500, letterSpacing: "-0.005em",
            transition: "all 0.18s ease",
            textAlign: "left",
          }}>{it}</button>
        );
      })}
    </div>
  );
}

function ToggleLine({ on, onToggle, label }) {
  return (
    <button onClick={onToggle} style={{
      display: "flex", alignItems: "center", justifyContent: "space-between",
      gap: 10, padding: "8px 4px 4px",
      width: "100%", textAlign: "left",
    }}>
      <span style={{ fontSize: 12, color: "var(--ink)", fontWeight: 500 }}>{label}</span>
      <span style={{
        width: 32, height: 18, borderRadius: 99,
        background: on ? "var(--ink)" : "var(--border)",
        position: "relative",
        transition: "background 0.2s ease",
        flexShrink: 0,
      }}>
        <span style={{
          position: "absolute", top: 2, left: on ? 16 : 2,
          width: 14, height: 14, borderRadius: "50%",
          background: on ? "var(--lime)" : "white",
          transition: "left 0.2s cubic-bezier(0.2,0.7,0.2,1), background 0.2s ease",
          boxShadow: "0 1px 3px rgba(0,0,0,0.18)",
        }} />
      </span>
    </button>
  );
}

/* ---- OFFICE CARD ---- */

function OfficeCard({ office, saved, onSave, onOpen }) {
  return (
    <article style={{
      background: "white",
      border: "1px solid " + (saved ? "rgba(184,230,60,0.6)" : "var(--border-soft)"),
      borderRadius: 18,
      padding: 18,
      display: "flex", flexDirection: "column", gap: 12,
      transition: "border-color 0.22s ease, transform 0.22s ease, box-shadow 0.22s ease",
      cursor: "pointer",
      position: "relative",
    }}
      onClick={onOpen}
      onMouseEnter={(e) => {
        e.currentTarget.style.borderColor = saved ? "rgba(184,230,60,0.8)" : "var(--ink)";
        e.currentTarget.style.transform = "translateY(-2px)";
        e.currentTarget.style.boxShadow = "var(--shadow-md)";
      }}
      onMouseLeave={(e) => {
        e.currentTarget.style.borderColor = saved ? "rgba(184,230,60,0.6)" : "var(--border-soft)";
        e.currentTarget.style.transform = "translateY(0)";
        e.currentTarget.style.boxShadow = "none";
      }}
    >
      {saved && (
        <span style={{
          position: "absolute", top: 14, right: 14,
          padding: "3px 9px", borderRadius: 99,
          background: "var(--lime)", color: "var(--ink)",
          fontSize: 10, fontWeight: 700, letterSpacing: "0.1em", textTransform: "uppercase",
        }}>Saved</span>
      )}

      {/* Top: name + type */}
      <div style={{ display: "flex", alignItems: "flex-start", gap: 10 }}>
        <div style={{
          width: 40, height: 40, borderRadius: 11,
          background: "var(--bg-soft)", color: "var(--ink)",
          display: "inline-flex", alignItems: "center", justifyContent: "center",
          flexShrink: 0,
        }}>
          <i className="ti ti-building-bank" style={{ fontSize: 18 }} />
        </div>
        <div style={{ flex: 1, minWidth: 0, paddingRight: saved ? 70 : 0 }}>
          <div style={{
            fontSize: 15, fontWeight: 600, color: "var(--ink)",
            letterSpacing: "-0.01em",
          }}>{office.name}</div>
          <div style={{ display: "inline-flex", alignItems: "center", gap: 8, marginTop: 4 }}>
            <span style={{
              padding: "2px 8px", borderRadius: 99,
              background: "var(--ink)", color: "var(--lime)",
              fontSize: 9.5, fontWeight: 700, letterSpacing: "0.1em", textTransform: "uppercase",
            }}>{office.type}</span>
            <span style={{ fontSize: 11.5, color: "var(--text-mute)" }}>
              <i className="ti ti-map-pin" style={{ fontSize: 12, verticalAlign: -1, marginRight: 3 }} />
              {office.region} · {office.district}
            </span>
          </div>
        </div>
      </div>

      {/* Topics */}
      <div style={{ display: "flex", flexWrap: "wrap", gap: 6 }}>
        {office.topics.slice(0, 4).map((t) => (
          <span key={t} style={{
            padding: "3px 9px", borderRadius: 99,
            background: "var(--bg-soft)", color: "var(--ink)",
            fontSize: 10.5, fontWeight: 500,
          }}>{t}</span>
        ))}
      </div>

      {/* Langs */}
      <div style={{ display: "flex", flexWrap: "wrap", gap: 6 }}>
        {office.langs.map((l) => (
          <span key={l} style={{
            padding: "3px 9px", borderRadius: 99,
            background: "white", color: "var(--text-soft)",
            border: "1px solid var(--border-soft)",
            fontSize: 10.5, fontWeight: 500,
          }}>{l}</span>
        ))}
      </div>

      {/* Note */}
      <p style={{ fontSize: 12, color: "var(--text-mute)", lineHeight: 1.55, margin: 0 }}>
        {office.note}
      </p>

      {/* Contact row */}
      <div style={{
        display: "flex", alignItems: "center", justifyContent: "space-between", gap: 10,
        paddingTop: 10, borderTop: "1px solid var(--border-soft)",
        flexWrap: "wrap",
      }}>
        <div style={{ display: "inline-flex", flexWrap: "wrap", gap: 14, alignItems: "center" }}>
          {office.phone && (
            <span style={{ fontSize: 11.5, color: "var(--ink)", display: "inline-flex", alignItems: "center", gap: 5 }}>
              <i className="ti ti-phone" style={{ fontSize: 13, color: "var(--text-mute)" }} />
              {office.phone}
            </span>
          )}
          {office.website && (
            <a href={`https://${office.website}`} target="_blank" rel="noreferrer"
              onClick={(e) => e.stopPropagation()}
              style={{ fontSize: 11.5, color: "var(--ink)", display: "inline-flex", alignItems: "center", gap: 5, textDecoration: "none" }}>
              <i className="ti ti-world" style={{ fontSize: 13, color: "var(--text-mute)" }} />
              {office.website}
            </a>
          )}
          {office.kakao && (
            <span style={{
              padding: "2px 8px", borderRadius: 99,
              background: "#FFE812", color: "#3C1E1E",
              fontSize: 9.5, fontWeight: 700, letterSpacing: "0.08em",
            }}>KAKAO</span>
          )}
          {office.email && (
            <span style={{ fontSize: 11.5, color: "var(--text-mute)", display: "inline-flex", alignItems: "center", gap: 5 }}>
              <i className="ti ti-mail" style={{ fontSize: 13 }} />
              email
            </span>
          )}
        </div>
        <button onClick={(e) => { e.stopPropagation(); onSave(); }}
          aria-label={saved ? "Remove from saved" : "Save to my list"}
          style={{
            width: 34, height: 34, borderRadius: 10,
            background: saved ? "var(--lime)" : "white",
            border: "1px solid " + (saved ? "var(--lime)" : "var(--border)"),
            color: "var(--ink)",
            display: "inline-flex", alignItems: "center", justifyContent: "center",
            transition: "all 0.2s cubic-bezier(0.2,1.4,0.4,1)",
          }}
        >
          <i className={`ti ti-${saved ? "bookmark-filled" : "bookmark"}`}
            style={{ fontSize: 15, transition: "transform 0.2s cubic-bezier(0.2,1.4,0.4,1)" }} />
        </button>
      </div>
    </article>
  );
}

/* ---- DETAIL DRAWER ---- */

function OfficeDrawer({ office, onClose, saved, onSave }) {
  const open = !!office;
  const [note, setNote] = useState("");

  useEffect(() => { setNote(""); }, [office?.id]);

  useEffect(() => {
    if (!open) return;
    const h = (e) => { if (e.key === "Escape") onClose(); };
    window.addEventListener("keydown", h);
    return () => window.removeEventListener("keydown", h);
  }, [open, onClose]);

  return (
    <>
      <div onClick={onClose} style={{
        position: "fixed", inset: 0,
        background: "rgba(11,27,44,0.45)",
        opacity: open ? 1 : 0,
        pointerEvents: open ? "auto" : "none",
        transition: "opacity 0.25s ease",
        zIndex: 70,
      }} />
      <aside role="dialog" aria-label="Office details" style={{
        position: "fixed", top: 0, right: 0, bottom: 0,
        width: "min(480px, 100vw)",
        background: "white",
        boxShadow: "-24px 0 60px rgba(11,27,44,0.18)",
        transform: open ? "translateX(0)" : "translateX(100%)",
        transition: "transform 0.32s cubic-bezier(0.2,0.7,0.2,1)",
        zIndex: 71,
        display: "flex", flexDirection: "column",
      }}>
        {office && (
          <>
            <header style={{
              padding: "20px 22px", borderBottom: "1px solid var(--border-soft)",
              display: "flex", alignItems: "flex-start", gap: 12,
            }}>
              <div style={{
                width: 42, height: 42, borderRadius: 12,
                background: "var(--bg-soft)", color: "var(--ink)",
                display: "inline-flex", alignItems: "center", justifyContent: "center",
                flexShrink: 0,
              }}><i className="ti ti-building-bank" style={{ fontSize: 20 }} /></div>
              <div style={{ flex: 1, minWidth: 0 }}>
                <span style={{
                  padding: "2px 8px", borderRadius: 99,
                  background: "var(--ink)", color: "var(--lime)",
                  fontSize: 9.5, fontWeight: 700, letterSpacing: "0.1em", textTransform: "uppercase",
                }}>{office.type}</span>
                <h2 style={{
                  fontSize: 18, fontWeight: 600, color: "var(--ink)",
                  letterSpacing: "-0.015em", marginTop: 6,
                }}>{office.name}</h2>
                <div style={{ fontSize: 12, color: "var(--text-mute)", marginTop: 4 }}>
                  <i className="ti ti-map-pin" style={{ fontSize: 12, verticalAlign: -1, marginRight: 4 }} />
                  {office.region} · {office.district}
                </div>
              </div>
              <button onClick={onClose} aria-label="Close" style={{
                width: 34, height: 34, borderRadius: 10,
                background: "var(--bg-soft)", color: "var(--ink)",
                display: "inline-flex", alignItems: "center", justifyContent: "center",
              }}><i className="ti ti-x" style={{ fontSize: 16 }} /></button>
            </header>

            <div style={{ flex: 1, overflowY: "auto", padding: "18px 22px", display: "flex", flexDirection: "column", gap: 18 }}>
              <DrawerSection title="Topics they say they handle">
                <div style={{ display: "flex", flexWrap: "wrap", gap: 6 }}>
                  {office.topics.map((t) => (
                    <span key={t} style={{
                      padding: "4px 10px", borderRadius: 99,
                      background: "var(--bg-soft)", color: "var(--ink)",
                      fontSize: 11.5, fontWeight: 500,
                    }}>{t}</span>
                  ))}
                </div>
              </DrawerSection>

              <DrawerSection title="Languages">
                <div style={{ display: "flex", flexWrap: "wrap", gap: 6 }}>
                  {office.langs.map((l) => (
                    <span key={l} style={{
                      padding: "4px 10px", borderRadius: 99,
                      background: "white", border: "1px solid var(--border)",
                      color: "var(--ink)", fontSize: 11.5, fontWeight: 500,
                    }}>{l}</span>
                  ))}
                </div>
              </DrawerSection>

              <DrawerSection title="Consultation">
                <div style={{ display: "flex", flexWrap: "wrap", gap: 8 }}>
                  {office.methods.map((m) => (
                    <span key={m} style={{
                      padding: "4px 10px", borderRadius: 99,
                      background: "rgba(212,255,79,0.25)", color: "var(--ink)",
                      fontSize: 11.5, fontWeight: 600,
                    }}>{m}</span>
                  ))}
                  <span style={{
                    padding: "4px 10px", borderRadius: 99,
                    background: "var(--bg-soft)", color: "var(--text-soft)",
                    fontSize: 11.5, fontWeight: 500,
                  }}>{office.cost}</span>
                </div>
              </DrawerSection>

              <DrawerSection title="How to contact">
                <ul style={{ listStyle: "none", margin: 0, padding: 0, display: "flex", flexDirection: "column", gap: 6 }}>
                  {office.phone && (
                    <ContactLine icon="phone" label="Phone" value={office.phone} />
                  )}
                  {office.email && (
                    <ContactLine icon="mail" label="Email" value={office.email} />
                  )}
                  {office.website && (
                    <ContactLine icon="world" label="Website" value={office.website} link={`https://${office.website}`} />
                  )}
                  {office.kakao && (
                    <ContactLine icon="brand-kakao-talk" label="KakaoTalk" value="Channel available" />
                  )}
                </ul>
                <p style={{ fontSize: 11, color: "var(--text-mute)", marginTop: 8, lineHeight: 1.55 }}>
                  Korico provides these contact details for convenience. Confirm the latest contact info on the office's own page before reaching out.
                </p>
              </DrawerSection>

              <DrawerSection title="Your notes">
                <textarea
                  value={note}
                  onChange={(e) => setNote(e.target.value)}
                  rows={3}
                  placeholder="Only visible to you. Add impressions, dates of calls, or follow-ups…"
                  style={{
                    width: "100%", padding: "11px 14px",
                    borderRadius: 12, border: "1px solid var(--border)",
                    fontFamily: "var(--font-body)",
                    fontSize: 13, color: "var(--ink)", outline: "none",
                    resize: "vertical", minHeight: 80,
                    background: "white",
                  }}
                  onFocus={(e) => e.currentTarget.style.borderColor = "var(--ink)"}
                  onBlur={(e) => e.currentTarget.style.borderColor = "var(--border)"}
                />
              </DrawerSection>

              <div style={{
                padding: "12px 14px", borderRadius: 12,
                background: "var(--bg-soft)",
                fontSize: 11, color: "var(--text-mute)", lineHeight: 1.55, fontStyle: "italic",
              }}>
                No rankings, reviews, or success rates are shown here in order to comply with Korean regulations on legal advertising.
              </div>
            </div>

            <footer style={{
              padding: "14px 22px",
              borderTop: "1px solid var(--border-soft)",
              display: "flex", justifyContent: "space-between", gap: 8,
            }}>
              <button onClick={onClose} style={{
                padding: "11px 18px", borderRadius: 99,
                background: "white", color: "var(--ink)",
                border: "1px solid var(--border)",
                fontSize: 11, fontWeight: 600, letterSpacing: "0.14em", textTransform: "uppercase",
              }}>Close</button>
              <button onClick={onSave} style={{
                display: "inline-flex", alignItems: "center", gap: 8,
                padding: "11px 18px", borderRadius: 99,
                background: saved ? "white" : "var(--lime)",
                color: "var(--ink)",
                border: saved ? "1px solid var(--ink)" : "none",
                fontSize: 11, fontWeight: 700, letterSpacing: "0.14em", textTransform: "uppercase",
                boxShadow: saved ? "none" : "0 10px 22px rgba(184,230,60,0.32)",
              }}>
                <i className={`ti ti-bookmark${saved ? "-filled" : ""}`} style={{ fontSize: 13 }} />
                {saved ? "Saved" : "Save to my list"}
              </button>
            </footer>
          </>
        )}
      </aside>
    </>
  );
}

function DrawerSection({ title, children }) {
  return (
    <div>
      <div style={{
        fontSize: 10, fontWeight: 600, color: "var(--text-mute)",
        letterSpacing: "0.18em", textTransform: "uppercase",
        marginBottom: 8,
      }}>{title}</div>
      {children}
    </div>
  );
}

function ContactLine({ icon, label, value, link }) {
  const Content = (
    <div style={{
      display: "flex", alignItems: "center", gap: 10,
      padding: "8px 10px", borderRadius: 10,
      background: "white", border: "1px solid var(--border-soft)",
      textDecoration: "none",
    }}>
      <span style={{
        width: 28, height: 28, borderRadius: 8,
        background: "var(--bg-soft)", color: "var(--ink)",
        display: "inline-flex", alignItems: "center", justifyContent: "center",
        flexShrink: 0,
      }}><i className={`ti ti-${icon}`} style={{ fontSize: 14 }} /></span>
      <div style={{ flex: 1, minWidth: 0 }}>
        <div style={{ fontSize: 10.5, color: "var(--text-mute)", fontWeight: 600, letterSpacing: "0.12em", textTransform: "uppercase" }}>{label}</div>
        <div style={{ fontSize: 13, color: "var(--ink)", fontWeight: 500, marginTop: 1 }}>{value}</div>
      </div>
      {link && <i className="ti ti-arrow-up-right" style={{ fontSize: 14, color: "var(--text-mute)" }} />}
    </div>
  );
  return (
    <li>
      {link ? <a href={link} target="_blank" rel="noreferrer" style={{ textDecoration: "none" }}>{Content}</a> : Content}
    </li>
  );
}

/* ============================================================
   FORMS & TEMPLATES
   ============================================================ */

const FORM_CATEGORIES = [
  { key: "all",     label: "All forms",        icon: "files" },
  { key: "visa",    label: "Visa & status",    icon: "id" },
  { key: "arc",     label: "ARC & residence",  icon: "credit-card" },
  { key: "work",    label: "Work & part-time", icon: "briefcase" },
  { key: "tax",     label: "Tax",              icon: "report-money" },
  { key: "housing", label: "Housing & moving", icon: "home" },
  { key: "school",  label: "School & admission", icon: "school" },
  { key: "other",   label: "Other admin",      icon: "dots" },
];

const VISA_OPTS = ["D-2", "D-10", "E-7", "E-9", "F-2", "F-3", "F-5", "Other"];
const ACTION_OPTS = ["New application", "Extension", "Change of status", "Part-time permission"];
const CHANNEL_OPTS = ["HiKorea online", "In-person at immigration"];
const LANG_OPTS_F = ["Korean", "English", "Bilingual (Kor/Eng)"];
const FORMAT_OPTS = ["Official PDF", "Korico helper template", "Example filled form"];
const COMPLEX_OPTS = ["Quick form", "Medium", "Complex bundle"];

const FORMS = [
  {
    id: "f1",
    title: "D-2 Visa Application / Extension",
    category: "visa", catLabel: "Visa & status · D-2",
    visaTypes: ["D-2"],
    actions: ["New application", "Extension"],
    channel: ["HiKorea online", "In-person at immigration"],
    lang: "Bilingual (Kor/Eng)",
    format: "Official PDF",
    complexity: "Medium",
    estTime: "15–25 min",
    description: "Application and extension form for D-2 student visas, with Korico notes on each field.",
    badges: ["Official HiKorea form", "Kor/Eng"],
    whatFor: "Use this when you're a student arriving in Korea for the first time on a D-2 visa, or when extending your D-2 before your current period expires.",
    docs: [
      "Passport (valid)",
      "Acceptance / enrollment certificate from your university",
      "Tuition payment receipt",
      "Bank statement showing minimum funds",
      "Proof of address in Korea",
    ],
    tips: [
      "Apply for extension at least 4 months before your current D-2 expires.",
      "Photocopy both sides of every required document.",
      "If you're on leave-of-absence, you may not qualify — confirm with your international office.",
    ],
    officialUrl: "https://www.hikorea.go.kr",
  },
  {
    id: "f2",
    title: "D-2 → D-10 Change of Status",
    category: "visa", catLabel: "Visa & status · D-10",
    visaTypes: ["D-2", "D-10"],
    actions: ["Change of status"],
    channel: ["In-person at immigration"],
    lang: "Korean",
    format: "Official PDF",
    complexity: "Complex bundle",
    estTime: "30–45 min",
    description: "Forms needed to change from D-2 student to D-10 job-seeker, including job-seeking plan template and document checklist.",
    badges: ["Official HiKorea form", "Korico helper template"],
    whatFor: "After graduation (or expected graduation within 3 months), students switch to D-10 to legally job-hunt in Korea for up to 2 years.",
    docs: [
      "Passport + ARC",
      "Graduation certificate or expected-graduation letter",
      "Final transcript",
      "Job-seeking plan (구직 활동 계획서) — Korico template included",
      "Proof of residence",
      "Bank statement (₩3,000,000+ recommended)",
    ],
    tips: [
      "The job-seeking plan is the most-rejected document — be specific about industry and target roles.",
      "TOPIK Level 4+ adds points to D-10-1.",
      "Don't let your D-2 expire before applying — apply at least 2 weeks early.",
    ],
    officialUrl: "https://www.hikorea.go.kr",
  },
  {
    id: "f3",
    title: "E-7 Professional Worker Visa",
    category: "visa", catLabel: "Visa & status · E-7",
    visaTypes: ["E-7"],
    actions: ["New application", "Change of status"],
    channel: ["In-person at immigration"],
    lang: "Korean",
    format: "Official PDF",
    complexity: "Complex bundle",
    estTime: "40–60 min",
    description: "Unified application form for professional workers, plus Korico explanation of company documents and proof of qualifications.",
    badges: ["Official HiKorea form", "Korean only"],
    whatFor: "For skilled foreign workers being sponsored by a Korean employer to work in one of the 85 designated E-7 occupation categories.",
    docs: [
      "Passport + ARC",
      "Signed employment contract",
      "Degree certificate or relevant work experience proof",
      "Company business registration",
      "Tax payment certificate of the employer",
      "Korean tax clearance (when extending)",
    ],
    tips: [
      "Employer must meet ratio rules (Korean : foreign employees).",
      "Salary must meet the GNI threshold for your occupation code.",
      "Bring all originals — copies may be requested by the officer.",
    ],
    officialUrl: "https://www.hikorea.go.kr",
  },
  {
    id: "f4",
    title: "F-3 Dependent Visa Application",
    category: "visa", catLabel: "Visa & status · F-3",
    visaTypes: ["F-3"],
    actions: ["New application", "Extension"],
    channel: ["In-person at immigration"],
    lang: "Bilingual (Kor/Eng)",
    format: "Official PDF",
    complexity: "Medium",
    estTime: "20–30 min",
    description: "Application and supporting document list for spouses and children of professional workers.",
    badges: ["Official HiKorea form", "Kor/Eng"],
    whatFor: "For the spouse or unmarried child (under 20) of someone holding D-1 to E-7 visas.",
    docs: [
      "Passport(s)",
      "Marriage certificate or birth certificate (apostilled if foreign)",
      "Sponsor's ARC + work / school certificate",
      "Bank statement of sponsor",
      "Proof of relationship (photos optional)",
    ],
    tips: [
      "Apostille + sworn Korean translation is usually required for foreign certificates.",
      "F-3 holders cannot work in Korea — for that, file a separate work activity permission.",
      "Children turning 20 must transition to a different visa.",
    ],
    officialUrl: "https://www.hikorea.go.kr",
  },
  {
    id: "f5",
    title: "Residency Card (ARC) Application",
    category: "arc", catLabel: "ARC & residence",
    visaTypes: ["D-2", "D-10", "E-7", "F-2", "F-3", "F-5"],
    actions: ["New application"],
    channel: ["In-person at immigration"],
    lang: "Bilingual (Kor/Eng)",
    format: "Official PDF",
    complexity: "Quick form",
    estTime: "10 min",
    description: "Foreign resident registration form for first ARC issuance after arrival.",
    badges: ["Official HiKorea form", "Kor/Eng"],
    whatFor: "All foreigners staying in Korea more than 90 days must register at immigration within 90 days of arrival.",
    docs: [
      "Passport",
      "Visa entry stamp",
      "Proof of address in Korea",
      "Passport-size photo (3.5 × 4.5 cm)",
      "Fee (₩30,000 by stamp or transfer)",
    ],
    tips: [
      "Book your immigration appointment via HiKorea ahead of time — walk-ins are limited.",
      "ARC card mailing takes 2–3 weeks; bring your receipt as temporary proof.",
      "Update your address within 14 days if you move.",
    ],
    officialUrl: "https://www.hikorea.go.kr",
  },
  {
    id: "f6",
    title: "Part-Time Work Permission (외국인 근로활동허가)",
    category: "work", catLabel: "Work & part-time",
    visaTypes: ["D-2", "D-10"],
    actions: ["Part-time permission"],
    channel: ["In-person at immigration"],
    lang: "Korean",
    format: "Official PDF",
    complexity: "Medium",
    estTime: "15 min",
    description: "Form used to request permission for part-time work outside your visa status, plus checklist of required documents.",
    badges: ["Official HiKorea form", "Korean only"],
    whatFor: "Required before you start working part-time on a D-2 or D-10 visa. Skipping this can affect visa renewal.",
    docs: [
      "Passport + ARC",
      "Signed part-time employment contract",
      "Recommendation letter from your school (D-2)",
      "Last semester's transcript (D-2)",
      "TOPIK certificate (if applicable)",
    ],
    tips: [
      "Permitted hours: 20 hrs/week during semesters, unlimited during official breaks.",
      "Different rules apply for degree level (undergrad vs. graduate).",
      "Notify immigration when your job changes — permits aren't transferable.",
    ],
    officialUrl: "https://www.hikorea.go.kr",
  },
  {
    id: "f7",
    title: "Standard Employment Contract (Foreign Workers)",
    category: "work", catLabel: "Work & part-time",
    visaTypes: ["E-7", "E-9", "D-10"],
    actions: ["New application"],
    channel: [],
    lang: "Bilingual (Kor/Eng)",
    format: "Korico helper template",
    complexity: "Quick form",
    estTime: "10–15 min",
    description: "Standard contract template recommended for foreign workers, with bilingual field labels.",
    badges: ["Korico helper template", "Kor/Eng"],
    whatFor: "Use this template if your employer doesn't have a written contract ready, or to compare key clauses against what you've been offered.",
    docs: [
      "Personal info (name, passport, ARC)",
      "Employer info & business registration number",
      "Role, hours, and probation period",
      "Pay structure and payment date",
      "Termination & severance clauses",
    ],
    tips: [
      "Korean labor law requires a written contract — don't accept a verbal-only deal.",
      "Make sure overtime and 4대보험 enrollment are explicit.",
      "Keep one signed original for yourself.",
    ],
  },
  {
    id: "f8",
    title: "Year-End Tax Settlement (연말정산) Helper Packet",
    category: "tax", catLabel: "Tax",
    visaTypes: ["E-7", "D-10", "F-2"],
    actions: [],
    channel: [],
    lang: "Bilingual (Kor/Eng)",
    format: "Korico helper template",
    complexity: "Medium",
    estTime: "30 min",
    description: "Korico helper forms and checklist to prepare information for Korean year-end tax settlement (not an official NTS form).",
    badges: ["Korico helper template", "Kor/Eng"],
    whatFor: "Use in January when your employer asks for documents to run 연말정산 on your behalf, or when you're filing on your own.",
    docs: [
      "Income statement from each employer",
      "Housing rent / 월세 receipts",
      "Credit-card usage summary (홈택스)",
      "Insurance & medical receipts",
      "Donation receipts",
    ],
    tips: [
      "Foreigners may opt for the flat 19% tax rate — check if it benefits you.",
      "Housing deductions need 전입신고 + receipts.",
      "Holding multiple jobs may require separate 종합소득세 in May.",
    ],
  },
  {
    id: "f9",
    title: "Address Change / 전입신고 form",
    category: "housing", catLabel: "Housing & moving",
    visaTypes: ["D-2", "D-10", "E-7", "F-2", "F-3"],
    actions: [],
    channel: ["In-person at immigration"],
    lang: "Korean",
    format: "Official PDF",
    complexity: "Quick form",
    estTime: "10 min",
    description: "Local government form for address change (전입신고), with helper notes on when and where to submit.",
    badges: ["Official form", "Korean only"],
    whatFor: "Use within 14 days of moving to a new address — required for many tenant protections and for keeping your ARC accurate.",
    docs: [
      "Passport + ARC",
      "Rental contract or proof of new residence",
      "Sometimes: landlord ID copy or verbal confirmation",
    ],
    tips: [
      "Submit at the 구청 / 주민센터 of your new district.",
      "Same form can be combined with ARC address update at immigration.",
      "Some gosiwon owners refuse 전입신고 — confirm before signing.",
    ],
    officialUrl: "https://www.gov.kr",
  },
  {
    id: "f11",
    title: "Foreigner Occupation Report (외국인 직업 신고서)",
    category: "work", catLabel: "Work & part-time",
    visaTypes: ["E-7", "E-9", "F-2", "D-10"],
    actions: [],
    channel: ["In-person at immigration"],
    lang: "Bilingual (Kor/Eng)",
    format: "Official PDF",
    complexity: "Quick form",
    estTime: "10–15 min",
    description: "Report your current occupation and classification to immigration. Required when changing jobs or for certain visa renewals.",
    badges: ["Official form", "Kor/Eng"],
    whatFor: "File this when you start a new job, change occupation, or when immigration asks you to declare your current occupation as part of a renewal.",
    docs: [
      "Passport + ARC",
      "Latest employment contract",
      "Pay stub or income proof (if asked)",
    ],
    tips: [
      "Use the occupation code that best matches your contract — be accurate.",
      "Late reports can affect future visa actions.",
      "Keep a signed copy for your own records.",
    ],
    officialUrl: "https://www.hikorea.go.kr/board/BoardApplicationListR.pt",
  },
  {
    id: "f10",
    title: "Proof of Residence template",
    category: "housing", catLabel: "Housing & moving",
    visaTypes: ["D-2", "D-10", "E-7", "F-2"],
    actions: [],
    channel: [],
    lang: "Bilingual (Kor/Eng)",
    format: "Korico helper template",
    complexity: "Quick form",
    estTime: "5 min",
    description: "Korico template listing acceptable residence proofs for immigration and ARC (e.g., lease contract, dorm certificate).",
    badges: ["Korico helper template", "Kor/Eng"],
    whatFor: "Use this checklist when an officer asks for proof of address — it lists the documents most often accepted.",
    docs: [
      "전입신고 확인서",
      "Lease (임대차) contract",
      "Dormitory enrollment certificate",
      "Utility bill in your name",
      "Landlord's confirmation letter",
    ],
    tips: [
      "A single document is usually enough, but bring two if possible.",
      "Originals are preferred over copies.",
      "Names must match your passport exactly.",
    ],
  },
];

const DEFAULT_FORMS_FILTERS = {
  q: "",
  category: "all",
  visaTypes: new Set(),
  actions: new Set(),
  channel: new Set(),
  lang: new Set(),
  format: new Set(),
  complexity: new Set(),
};

function FormsPage({ onNavigate, formsState }) {
  const { savedFormIds, setSavedFormIds, setSelectedFormId } = formsState;
  const [filters, setFilters] = useState(DEFAULT_FORMS_FILTERS);

  const results = useMemo(() => FORMS.filter((f) => matchesForm(f, filters)), [filters]);

  const toggleSet = (key, val) => {
    setFilters((f) => {
      const next = new Set(f[key]);
      next.has(val) ? next.delete(val) : next.add(val);
      return { ...f, [key]: next };
    });
  };

  const toggleSaved = (id) => {
    setSavedFormIds((s) => {
      const n = new Set(s);
      n.has(id) ? n.delete(id) : n.add(id);
      return n;
    });
  };

  const openForm = (id) => {
    setSelectedFormId(id);
    onNavigate("forms-detail");
  };

  const showVisaFilters = filters.category === "visa";
  const activeFilterCount = filters.visaTypes.size + filters.actions.size + filters.channel.size + filters.lang.size + filters.format.size + filters.complexity.size;

  return (
    <div style={{
      animation: "fade-up 0.5s cubic-bezier(0.2,0.7,0.2,1) both",
      animationDelay: "0.05s",
      maxWidth: 1320,
    }}>

      {/* Search */}
      <div style={{
        display: "flex", justifyContent: "flex-end", marginBottom: 14,
      }}>
        <div style={{
          display: "inline-flex", alignItems: "center", gap: 8,
          padding: "8px 14px", borderRadius: 99,
          background: "white", border: "1px solid var(--border)",
          minWidth: 300,
        }}>
          <i className="ti ti-search" style={{ fontSize: 15, color: "var(--text-mute)" }} />
          <input
            value={filters.q}
            onChange={(e) => setFilters({ ...filters, q: e.target.value })}
            placeholder="Search by name, visa type, or keyword…"
            style={{
              flex: 1, border: "none", outline: "none",
              fontSize: 13, color: "var(--ink)",
              background: "transparent",
            }}
          />
          {filters.q && (
            <button onClick={() => setFilters({ ...filters, q: "" })} aria-label="Clear">
              <i className="ti ti-x" style={{ fontSize: 13, color: "var(--text-mute)" }} />
            </button>
          )}
        </div>
      </div>

      {/* Category chips */}
      <div style={{
        display: "flex", flexWrap: "wrap", gap: 6, marginBottom: 12,
      }}>
        {FORM_CATEGORIES.map((c) => {
          const on = filters.category === c.key;
          return (
            <button key={c.key}
              onClick={() => setFilters({ ...filters, category: c.key })}
              style={{
                display: "inline-flex", alignItems: "center", gap: 8,
                padding: "9px 14px", borderRadius: 99,
                background: on ? "var(--ink)" : "white",
                color: on ? "var(--lime)" : "var(--ink)",
                border: `1px solid ${on ? "var(--ink)" : "var(--border)"}`,
                fontSize: 12, fontWeight: 600, letterSpacing: "-0.005em",
                transition: "all 0.18s ease",
              }}>
              <i className={`ti ti-${c.icon}`} style={{ fontSize: 13 }} />
              {c.label}
            </button>
          );
        })}
      </div>

      {/* Visa-specific filters */}
      {showVisaFilters && (
        <SurfaceCard style={{
          padding: 14, marginBottom: 12,
          animation: "fade-up 0.3s cubic-bezier(0.2,0.7,0.2,1) both",
        }}>
          <div style={{ display: "grid", gridTemplateColumns: "1fr 1fr 1fr", gap: 18 }} className="vfilter-grid">
            <FormsFilterGroup label="Visa type">
              <ChipList items={VISA_OPTS} selected={filters.visaTypes} onToggle={(v) => toggleSet("visaTypes", v)} />
            </FormsFilterGroup>
            <FormsFilterGroup label="Action type">
              <ChipList items={ACTION_OPTS} selected={filters.actions} onToggle={(v) => toggleSet("actions", v)} />
            </FormsFilterGroup>
            <FormsFilterGroup label="Application channel">
              <ChipList items={CHANNEL_OPTS} selected={filters.channel} onToggle={(v) => toggleSet("channel", v)} />
            </FormsFilterGroup>
          </div>
          <style>{`
            @media (max-width: 880px) { .vfilter-grid { grid-template-columns: 1fr !important; }}
          `}</style>
        </SurfaceCard>
      )}

      {/* Facet filters */}
      <div style={{
        display: "flex", flexWrap: "wrap", gap: 8, marginBottom: 18,
        padding: "6px 2px",
      }}>
        <FacetDropdown label="Language"   options={LANG_OPTS_F}  selected={filters.lang}        onToggle={(v) => toggleSet("lang", v)} />
        <FacetDropdown label="Format"     options={FORMAT_OPTS}  selected={filters.format}      onToggle={(v) => toggleSet("format", v)} />
        <FacetDropdown label="Complexity" options={COMPLEX_OPTS} selected={filters.complexity} onToggle={(v) => toggleSet("complexity", v)} />

        {(activeFilterCount > 0 || filters.category !== "all" || filters.q) && (
          <button onClick={() => setFilters(DEFAULT_FORMS_FILTERS)} style={{
            marginLeft: "auto",
            padding: "8px 14px", borderRadius: 99,
            background: "transparent", color: "var(--ink)",
            border: "none",
            fontSize: 11.5, fontWeight: 600, letterSpacing: "0.04em",
            textDecoration: "underline",
            textDecorationColor: "var(--border)",
            textUnderlineOffset: 3,
          }}>Clear all</button>
        )}
      </div>

      {/* Count */}
      <div style={{
        fontSize: 12.5, color: "var(--text-mute)", marginBottom: 14,
        paddingLeft: 4,
      }}>
        <strong style={{ color: "var(--ink)", fontWeight: 600 }}>{results.length}</strong> form{results.length === 1 ? "" : "s"} match your filters
      </div>

      {/* Cards grid */}
      {results.length === 0 ? (
        <SurfaceCard style={{ padding: "40px 22px", textAlign: "center" }}>
          <div style={{ fontSize: 14, color: "var(--text-mute)" }}>
            No forms match the current filters. Try a different category or clear the filters.
          </div>
        </SurfaceCard>
      ) : (
        <div style={{
          display: "grid", gridTemplateColumns: "repeat(3, 1fr)", gap: 14,
        }} className="forms-grid">
          {results.map((f, i) => (
            <FormCard key={f.id} form={f}
              saved={savedFormIds.has(f.id)}
              onSave={() => toggleSaved(f.id)}
              onOpen={() => openForm(f.id)}
              delay={i * 50}
            />
          ))}
        </div>
      )}

      <style>{`
        @media (max-width: 1024px) { .forms-grid { grid-template-columns: repeat(2, 1fr) !important; }}
        @media (max-width: 640px)  { .forms-grid { grid-template-columns: 1fr !important; }}
      `}</style>
    </div>
  );
}

function matchesForm(f, filters) {
  if (filters.q) {
    const q = filters.q.toLowerCase();
    const blob = [f.title, f.description, f.catLabel, ...(f.visaTypes || []), ...(f.actions || []), ...(f.badges || [])].join(" ").toLowerCase();
    if (!blob.includes(q)) return false;
  }
  if (filters.category !== "all" && f.category !== filters.category) return false;
  if (filters.visaTypes.size > 0 && !f.visaTypes.some((v) => filters.visaTypes.has(v))) return false;
  if (filters.actions.size > 0 && !(f.actions || []).some((a) => filters.actions.has(a))) return false;
  if (filters.channel.size > 0 && !(f.channel || []).some((c) => filters.channel.has(c))) return false;
  if (filters.lang.size > 0 && !filters.lang.has(f.lang)) return false;
  if (filters.format.size > 0 && !filters.format.has(f.format)) return false;
  if (filters.complexity.size > 0 && !filters.complexity.has(f.complexity)) return false;
  return true;
}

function FormsFilterGroup({ label, children }) {
  return (
    <div>
      <div style={{
        fontSize: 10, fontWeight: 600, color: "var(--text-mute)",
        letterSpacing: "0.18em", textTransform: "uppercase",
        marginBottom: 8,
      }}>{label}</div>
      {children}
    </div>
  );
}

function FacetDropdown({ label, options, selected, onToggle }) {
  const [open, setOpen] = useState(false);
  const ref = useRef(null);

  useEffect(() => {
    if (!open) return;
    const h = (e) => { if (ref.current && !ref.current.contains(e.target)) setOpen(false); };
    document.addEventListener("mousedown", h);
    return () => document.removeEventListener("mousedown", h);
  }, [open]);

  const count = selected.size;
  return (
    <div ref={ref} style={{ position: "relative" }}>
      <button onClick={() => setOpen((v) => !v)} style={{
        display: "inline-flex", alignItems: "center", gap: 8,
        padding: "8px 14px", borderRadius: 99,
        background: count > 0 ? "var(--ink)" : "white",
        color: count > 0 ? "var(--lime)" : "var(--ink)",
        border: `1px solid ${count > 0 ? "var(--ink)" : "var(--border)"}`,
        fontSize: 11.5, fontWeight: 600, letterSpacing: "0.02em",
      }}>
        {label}
        {count > 0 && (
          <span style={{
            background: "var(--lime)", color: "var(--ink)",
            borderRadius: 99, padding: "1px 7px",
            fontSize: 10, fontWeight: 700, letterSpacing: "0.04em",
          }}>{count}</span>
        )}
        <i className={`ti ti-chevron-${open ? "up" : "down"}`} style={{ fontSize: 13, opacity: 0.7 }} />
      </button>
      {open && (
        <div style={{
          position: "absolute", top: "calc(100% + 6px)", left: 0,
          background: "white", border: "1px solid var(--border)",
          borderRadius: 14,
          boxShadow: "0 18px 40px rgba(11,27,44,0.12)",
          padding: 8, minWidth: 200, zIndex: 30,
          animation: "fade-up 0.18s ease-out",
        }}>
          {options.map((o) => {
            const on = selected.has(o);
            return (
              <button key={o} onClick={() => onToggle(o)} style={{
                display: "flex", alignItems: "center", gap: 10,
                width: "100%", padding: "8px 10px", borderRadius: 8,
                background: on ? "var(--bg-soft)" : "transparent",
                textAlign: "left",
                fontSize: 12.5, color: "var(--ink)", fontWeight: on ? 600 : 500,
              }}
                onMouseEnter={(e) => { if (!on) e.currentTarget.style.background = "var(--bg-soft)"; }}
                onMouseLeave={(e) => { if (!on) e.currentTarget.style.background = "transparent"; }}
              >
                <span style={{
                  width: 16, height: 16, borderRadius: 5,
                  background: on ? "var(--ink)" : "white",
                  border: on ? "none" : "1.5px solid var(--border)",
                  display: "inline-flex", alignItems: "center", justifyContent: "center",
                  color: "var(--lime)", flexShrink: 0,
                }}>
                  {on && <i className="ti ti-check" style={{ fontSize: 10 }} />}
                </span>
                <span>{o}</span>
              </button>
            );
          })}
        </div>
      )}
    </div>
  );
}

function FormCard({ form, saved, onSave, onOpen, delay }) {
  return (
    <article
      onClick={onOpen}
      style={{
        background: "white",
        borderRadius: 20,
        border: "1px solid " + (saved ? "rgba(184,230,60,0.6)" : "var(--border-soft)"),
        padding: 18,
        display: "flex", flexDirection: "column", gap: 12,
        transition: "transform 0.22s ease, box-shadow 0.22s ease, border-color 0.22s ease",
        cursor: "pointer",
        animation: "fade-up 0.5s cubic-bezier(0.2,0.7,0.2,1) both",
        animationDelay: `${delay}ms`,
        position: "relative",
      }}
      onMouseEnter={(e) => {
        e.currentTarget.style.transform = "translateY(-3px)";
        e.currentTarget.style.boxShadow = "var(--shadow-md)";
        e.currentTarget.style.borderColor = saved ? "rgba(184,230,60,0.85)" : "var(--ink)";
      }}
      onMouseLeave={(e) => {
        e.currentTarget.style.transform = "translateY(0)";
        e.currentTarget.style.boxShadow = "none";
        e.currentTarget.style.borderColor = saved ? "rgba(184,230,60,0.6)" : "var(--border-soft)";
      }}
    >
      <div style={{ display: "flex", justifyContent: "space-between", alignItems: "flex-start", gap: 10 }}>
        <span style={{
          padding: "3px 9px", borderRadius: 99,
          background: "var(--bg-soft)", color: "var(--ink)",
          fontSize: 9.5, fontWeight: 700, letterSpacing: "0.12em", textTransform: "uppercase",
        }}>{form.catLabel}</span>
        <button onClick={(e) => { e.stopPropagation(); onSave(); }}
          aria-label={saved ? "Remove from saved" : "Save form"}
          style={{
            width: 30, height: 30, borderRadius: 8,
            background: saved ? "var(--lime)" : "transparent",
            border: saved ? "1px solid var(--lime)" : "1px solid var(--border)",
            color: "var(--ink)",
            display: "inline-flex", alignItems: "center", justifyContent: "center",
            transition: "all 0.2s cubic-bezier(0.2,1.4,0.4,1)",
          }}
          onMouseEnter={(e) => { if (!saved) { e.currentTarget.style.borderColor = "var(--ink)"; }}}
          onMouseLeave={(e) => { if (!saved) { e.currentTarget.style.borderColor = "var(--border)"; }}}
        >
          <i className={`ti ti-bookmark${saved ? "-filled" : ""}`} style={{ fontSize: 14 }} />
        </button>
      </div>

      <h3 style={{
        fontSize: 15, fontWeight: 600, color: "var(--ink)",
        letterSpacing: "-0.01em", lineHeight: 1.3,
      }}>{form.title}</h3>

      <p style={{
        fontSize: 12.5, color: "var(--text-mute)", lineHeight: 1.55,
      }}>{form.description}</p>

      <div style={{ display: "flex", flexWrap: "wrap", gap: 6 }}>
        {form.badges.map((b) => {
          const isOfficial = b.toLowerCase().includes("official");
          const isHelper  = b.toLowerCase().includes("helper") || b.toLowerCase().includes("korico");
          const palette = isOfficial
            ? { bg: "var(--ink)", fg: "var(--lime)" }
            : isHelper
              ? { bg: "var(--lime)", fg: "var(--ink)" }
              : { bg: "white", fg: "var(--ink)", border: true };
          return (
            <span key={b} style={{
              padding: "3px 9px", borderRadius: 99,
              background: palette.bg, color: palette.fg,
              fontSize: 10, fontWeight: 600, letterSpacing: "0.04em",
              border: palette.border ? "1px solid var(--border)" : "none",
            }}>{b}</span>
          );
        })}
      </div>

      <div style={{
        display: "flex", alignItems: "center", justifyContent: "space-between",
        gap: 8, marginTop: "auto", paddingTop: 12,
        borderTop: "1px solid var(--border-soft)",
      }}>
        <span style={{ fontSize: 11, color: "var(--text-mute)" }}>
          <i className="ti ti-clock" style={{ fontSize: 12, verticalAlign: -1, marginRight: 4 }} />
          {form.estTime}
        </span>
        <span style={{
          display: "inline-flex", alignItems: "center", gap: 6,
          fontSize: 11, fontWeight: 700, color: "var(--ink)",
          letterSpacing: "0.12em", textTransform: "uppercase",
        }}>
          Open form
          <span style={{
            width: 18, height: 18, borderRadius: "50%",
            background: "var(--ink)", color: "var(--lime)",
            display: "inline-flex", alignItems: "center", justifyContent: "center",
          }}><i className="ti ti-arrow-right" style={{ fontSize: 10 }} /></span>
        </span>
      </div>
    </article>
  );
}

/* ---- FORM DETAIL ---- */

function FormDetailPage({ onNavigate, formsState }) {
  const { selectedFormId, savedFormIds, setSavedFormIds, flash } = formsState;
  const form = FORMS.find((f) => f.id === selectedFormId);
  const saved = form && savedFormIds.has(form.id);

  if (!form) {
    return (
      <div style={{ maxWidth: 800 }}>
        <BackBar onBack={() => onNavigate("forms")} label="Forms & templates" />
        <SurfaceCard><p style={{ fontSize: 14, color: "var(--text-mute)" }}>This form is no longer available.</p></SurfaceCard>
      </div>
    );
  }

  const toggleSave = () => {
    setSavedFormIds((s) => {
      const n = new Set(s);
      n.has(form.id) ? n.delete(form.id) : n.add(form.id);
      return n;
    });
    flash(saved ? "Removed from your forms." : "Saved to my forms.");
  };

  const startChecklist = () => {
    flash("Checklist added to today's tasks.");
  };

  const askAboutForm = () => {
    window.dispatchEvent(new CustomEvent("korico:ask", {
      detail: { prefill: `Can you walk me through "${form.title}" step by step? What do I need to prepare first?` },
    }));
  };

  const catLabel = (FORM_CATEGORIES.find((c) => c.key === form.category) || { label: "Forms" }).label;

  return (
    <div style={{
      animation: "fade-up 0.5s cubic-bezier(0.2,0.7,0.2,1) both",
      animationDelay: "0.05s",
      maxWidth: 1200,
    }}>
      {/* Breadcrumb */}
      <div style={{
        display: "flex", alignItems: "center", gap: 8,
        fontSize: 12, color: "var(--text-mute)", marginBottom: 14, flexWrap: "wrap",
      }}>
        <button onClick={() => onNavigate("forms")} style={{
          color: "var(--text-mute)", fontWeight: 500,
          transition: "color 0.18s ease",
        }}
          onMouseEnter={(e) => e.currentTarget.style.color = "var(--ink)"}
          onMouseLeave={(e) => e.currentTarget.style.color = "var(--text-mute)"}
        >Forms & templates</button>
        <i className="ti ti-chevron-right" style={{ fontSize: 12 }} />
        <span>{catLabel}</span>
        <i className="ti ti-chevron-right" style={{ fontSize: 12 }} />
        <span style={{ color: "var(--ink)", fontWeight: 500 }}>{form.title}</span>
      </div>

      <BackBar onBack={() => onNavigate("forms")} label="Forms & templates" />

      {/* Header card */}
      <SurfaceCard style={{ marginBottom: 18 }}>
        <header style={{ display: "flex", alignItems: "flex-start", gap: 14, marginBottom: 14 }}>
          <div style={{
            width: 44, height: 44, borderRadius: 12,
            background: "var(--ink)", color: "var(--lime)",
            display: "inline-flex", alignItems: "center", justifyContent: "center",
            flexShrink: 0,
          }}><i className="ti ti-file-text" style={{ fontSize: 20 }} /></div>
          <div style={{ flex: 1, minWidth: 0 }}>
            <span style={{
              padding: "3px 9px", borderRadius: 99,
              background: "var(--bg-soft)", color: "var(--ink)",
              fontSize: 9.5, fontWeight: 700, letterSpacing: "0.12em", textTransform: "uppercase",
            }}>{form.catLabel}</span>
            <h1 style={{
              fontSize: 24, fontWeight: 600, color: "var(--ink)",
              letterSpacing: "-0.02em", marginTop: 8,
            }}>{form.title}</h1>
            <p style={{
              fontSize: 13.5, color: "var(--text-mute)", lineHeight: 1.55,
              marginTop: 8, maxWidth: 720,
            }}>{form.description}</p>
          </div>
        </header>

        <div style={{ display: "flex", flexWrap: "wrap", gap: 6 }}>
          {form.visaTypes?.map((v) => (
            <span key={v} style={metaChip()}>{v}</span>
          ))}
          <span style={metaChip()}>{form.lang}</span>
          <span style={metaChip()}>{form.format}</span>
          <span style={metaChip()}>{form.complexity}</span>
          <span style={{ ...metaChip(), background: "var(--lime)", color: "var(--ink)" }}>
            <i className="ti ti-clock" style={{ fontSize: 11, verticalAlign: -1, marginRight: 4 }} />
            {form.estTime}
          </span>
        </div>
      </SurfaceCard>

      {/* Main two-column */}
      <div style={{
        display: "grid", gridTemplateColumns: "1.3fr 1fr", gap: 18, marginBottom: 18,
      }} className="form-detail-grid">
        <div style={{ display: "flex", flexDirection: "column", gap: 18 }}>
          <SurfaceCard>
            <CardHead eyebrow="Context" title="What this form is for" />
            <p style={{ fontSize: 14, color: "var(--text-soft)", lineHeight: 1.65 }}>{form.whatFor}</p>
          </SurfaceCard>

          <SurfaceCard>
            <CardHead eyebrow="Documents" title="What you usually need" subtitle="The exact requirements may vary by district or officer." />
            <ul style={{ listStyle: "none", margin: 0, padding: 0, display: "flex", flexDirection: "column", gap: 6 }}>
              {form.docs.map((d) => (
                <li key={d} style={{
                  display: "flex", alignItems: "center", gap: 10,
                  padding: "10px 12px", borderRadius: 10,
                  background: "white", border: "1px solid var(--border-soft)",
                  fontSize: 13, color: "var(--ink)", letterSpacing: "-0.005em",
                }}>
                  <span style={{
                    width: 22, height: 22, borderRadius: "50%",
                    background: "var(--ink)", color: "var(--lime)",
                    display: "inline-flex", alignItems: "center", justifyContent: "center",
                    flexShrink: 0,
                  }}><i className="ti ti-check" style={{ fontSize: 11 }} /></span>
                  {d}
                </li>
              ))}
            </ul>
          </SurfaceCard>

          <SurfaceCard style={{
            background: "rgba(212,255,79,0.10)",
            border: "1px solid rgba(184,230,60,0.45)",
          }}>
            <CardHead eyebrow="Helper notes" title="Tips Korico saw most often" />
            <ul style={{ listStyle: "none", margin: 0, padding: 0, display: "flex", flexDirection: "column", gap: 8 }}>
              {form.tips.map((t, i) => (
                <li key={t} style={{
                  display: "flex", alignItems: "flex-start", gap: 10,
                  fontSize: 13, color: "var(--ink)", lineHeight: 1.55,
                }}>
                  <span style={{
                    width: 22, height: 22, borderRadius: "50%",
                    background: "var(--ink)", color: "var(--lime)",
                    display: "inline-flex", alignItems: "center", justifyContent: "center",
                    fontSize: 10, fontWeight: 700, flexShrink: 0, marginTop: 1,
                  }}>{i + 1}</span>
                  {t}
                </li>
              ))}
            </ul>
          </SurfaceCard>
        </div>

        <div style={{ display: "flex", flexDirection: "column", gap: 18 }}>
          <SurfaceCard>
            <CardHead eyebrow="Open the form" title={form.format} />
            <div style={{
              width: "100%", aspectRatio: "4 / 3",
              borderRadius: 12, background: "var(--bg-soft)",
              border: "1px dashed var(--border)",
              display: "flex", flexDirection: "column", alignItems: "center", justifyContent: "center",
              gap: 8, color: "var(--text-mute)",
              marginBottom: 14,
            }}>
              <i className="ti ti-file-text" style={{ fontSize: 32, color: "var(--ink)" }} />
              <div style={{ fontSize: 12.5, fontWeight: 500, color: "var(--ink)" }}>{form.title}</div>
              <div style={{ fontSize: 11, color: "var(--text-mute)" }}>Preview</div>
            </div>
            <div style={{ display: "flex", flexDirection: "column", gap: 8 }}>
              {form.officialUrl && (
                <a href={form.officialUrl} target="_blank" rel="noreferrer" style={{
                  display: "inline-flex", alignItems: "center", justifyContent: "center", gap: 10,
                  padding: "12px 18px", borderRadius: 99,
                  background: "var(--ink)", color: "var(--lime)",
                  fontSize: 11, fontWeight: 700, letterSpacing: "0.14em", textTransform: "uppercase",
                  textDecoration: "none",
                  transition: "transform 0.18s ease",
                }}
                  onMouseEnter={(e) => e.currentTarget.style.transform = "translateY(-1px)"}
                  onMouseLeave={(e) => e.currentTarget.style.transform = "translateY(0)"}
                >
                  <i className="ti ti-external-link" style={{ fontSize: 13 }} />
                  Open official form
                </a>
              )}
              <button
                onClick={() => {
                  if (form.id === "f1")       onNavigate("form-fill-d2");
                  else if (form.id === "f11") onNavigate("form-fill-occupation");
                  else flash("Fill with Korico is rolling out form by form. Available now: D-2 Visa Application and Foreigner Occupation Report.");
                }}
                style={{
                  display: "inline-flex", alignItems: "center", justifyContent: "center", gap: 10,
                  padding: "12px 18px", borderRadius: 99,
                  background: "var(--lime)", color: "var(--ink)",
                  fontSize: 11, fontWeight: 700, letterSpacing: "0.14em", textTransform: "uppercase",
                  boxShadow: "0 10px 22px rgba(184,230,60,0.32)",
                  transition: "transform 0.18s ease",
                  cursor: "pointer",
                }}
                onMouseEnter={(e) => e.currentTarget.style.transform = "translateY(-1px)"}
                onMouseLeave={(e) => e.currentTarget.style.transform = "translateY(0)"}
              >
                <i className="ti ti-edit" style={{ fontSize: 13 }} />
                Fill with Korico
              </button>
            </div>
          </SurfaceCard>

          <SurfaceCard>
            <CardHead eyebrow="Actions" title="What's next?" />
            <div style={{ display: "flex", flexDirection: "column", gap: 8 }}>
              <ActionRow icon={saved ? "bookmark-filled" : "bookmark"} label={saved ? "Saved to my forms" : "Save to my forms"} onClick={toggleSave} active={saved} />
              <ActionRow icon="list-check" label="Start checklist" onClick={startChecklist} />
              <ActionRow icon="message-circle" label="Ask about this form" onClick={askAboutForm} />
            </div>
          </SurfaceCard>
        </div>

        <style>{`
          @media (max-width: 1024px) { .form-detail-grid { grid-template-columns: 1fr !important; }}
        `}</style>
      </div>
    </div>
  );
}

function metaChip() {
  return {
    padding: "3px 9px", borderRadius: 99,
    background: "white", color: "var(--ink)",
    border: "1px solid var(--border)",
    fontSize: 10.5, fontWeight: 600, letterSpacing: "0.04em",
  };
}

function ActionRow({ icon, label, onClick, active }) {
  return (
    <button onClick={onClick} style={{
      display: "flex", alignItems: "center", gap: 12,
      padding: "11px 14px", borderRadius: 12,
      background: active ? "rgba(212,255,79,0.16)" : "white",
      border: "1px solid " + (active ? "rgba(184,230,60,0.5)" : "var(--border-soft)"),
      textAlign: "left", width: "100%",
      transition: "background 0.18s ease, border-color 0.18s ease",
    }}
      onMouseEnter={(e) => { if (!active) { e.currentTarget.style.background = "var(--bg-soft)"; e.currentTarget.style.borderColor = "var(--border)"; }}}
      onMouseLeave={(e) => { if (!active) { e.currentTarget.style.background = "white"; e.currentTarget.style.borderColor = "var(--border-soft)"; }}}
    >
      <span style={{
        width: 32, height: 32, borderRadius: 9,
        background: active ? "var(--ink)" : "var(--bg-soft)",
        color: active ? "var(--lime)" : "var(--ink)",
        display: "inline-flex", alignItems: "center", justifyContent: "center",
        flexShrink: 0,
      }}><i className={`ti ti-${icon}`} style={{ fontSize: 15 }} /></span>
      <span style={{ flex: 1, fontSize: 13, fontWeight: 600, color: "var(--ink)" }}>{label}</span>
      <i className="ti ti-arrow-right" style={{ fontSize: 14, color: "var(--text-mute)" }} />
    </button>
  );
}

/* ============================================================
   FULL CHAT PAGE — 3-pane workspace
   ============================================================ */

const CHAT_CONTEXTS = [
  { key: "visa",    label: "Visa & status",     icon: "id" },
  { key: "arc",     label: "ARC",               icon: "credit-card" },
  { key: "tax",     label: "Tax & work",        icon: "report-money" },
  { key: "housing", label: "Housing & moving",  icon: "home" },
  { key: "legal",   label: "Legal & 행정사",      icon: "scale" },
  { key: "forms",   label: "Forms & templates", icon: "file-text" },
];

const STARTER_PROMPTS = {
  visa:    "I'm on D-2 and graduating this semester. What happens to my visa?",
  arc:     "I moved to a new apartment 2 months ago but didn't report it. What should I do about my ARC?",
  tax:     "I'm working part-time 20h/week on D-2. Will I owe extra tax?",
  housing: "I found a one-room in Seoul. Do I need 전입신고?",
  legal:   "Which 행정사 in Seoul handles D-2 → D-10 cases in English?",
  forms:   "Walk me through the D-2 → D-10 change of status form.",
};

const EXAMPLE_PROMPTS = [
  "I'm on D-2 and graduating this semester. What happens to my visa?",
  "I found a one-room in Seoul. Do I need 전입신고?",
  "My company says they do 연말정산. What does that mean for me?",
];

const SEED_CONVERSATIONS = [
  {
    id: "c1",
    title: "D-2 to D-10 options",
    contexts: ["visa"],
    updated: "Today",
    messages: [
      { who: "user", text: "I'm on D-2 and graduating this semester. What happens to my visa?" },
      { who: "bot",  text: "You have a few options. The most common path is to switch to D-10 (job-seeker) so you can stay in Korea up to 2 years while you find work. You'll need:",
        bullets: [
          "Graduation certificate (or expected-graduation letter)",
          "Final transcript",
          "Job-seeking plan — Korico has a template",
          "Bank statement showing ~₩3,000,000+",
        ],
        actions: [
          { icon: "file-text", label: "Open D-2 → D-10 form", route: "forms" },
          { icon: "id",        label: "Open Visa & status",   route: "visa" },
          { icon: "calendar-plus", label: "Add deadline reminder" },
        ],
      },
    ],
  },
  {
    id: "c2",
    title: "전입신고 after moving",
    contexts: ["housing", "arc"],
    updated: "Yesterday",
    messages: [
      { who: "user", text: "I just moved into a wolse in Seodaemun. Do I need 전입신고?" },
      { who: "bot",  text: "Yes — within 14 days of moving. Bring your ARC, passport, and lease to the 주민센터 or 구청. Korico can update your ARC address afterward too." },
    ],
  },
  {
    id: "c3",
    title: "연말정산 for foreigners",
    contexts: ["tax"],
    updated: "3 days ago",
    messages: [
      { who: "user", text: "My company says they do 연말정산. What does that mean?" },
      { who: "bot",  text: "It means your employer handles your year-end tax adjustment in January. You'll mostly just submit receipts (rent, credit cards, donations, insurance). Foreign workers can also opt for the flat 19% rate — Korico can compare both for you." },
    ],
  },
  {
    id: "c4",
    title: "Finding a Vietnamese-speaking 행정사",
    contexts: ["legal"],
    updated: "5 days ago",
    messages: [
      { who: "user", text: "Looking for a 행정사 in Seoul who speaks Vietnamese." },
      { who: "bot",  text: "I found a few options in our directory. Note Korico doesn't rank them — open the Legal page to filter by language and area." },
    ],
  },
  {
    id: "c5",
    title: "Part-time permission for D-2",
    contexts: ["tax", "visa"],
    updated: "Last week",
    messages: [
      { who: "user", text: "Do I need part-time work permission as a D-2 student?" },
      { who: "bot",  text: "Yes. Apply at HiKorea or your local immigration office before you start. You'll need your school's recommendation and the employment contract." },
    ],
  },
];

function ChatPage({ onNavigate, chatState }) {
  const {
    conversations, setConversations,
    activeConvId, setActiveConvId,
    chatContext, setChatContext,
  } = chatState;

  const active = conversations.find((c) => c.id === activeConvId) || null;
  const [text, setText] = useState("");
  const [typing, setTyping] = useState(false);
  const scrollRef = useRef(null);

  useEffect(() => {
    if (scrollRef.current) scrollRef.current.scrollTop = scrollRef.current.scrollHeight;
  }, [active?.messages?.length, typing]);

  const send = (raw) => {
    const value = (raw ?? text).trim();
    if (!value || !active) return;
    setText("");
    setConversations((arr) => arr.map((c) => c.id !== active.id ? c : {
      ...c,
      messages: [...c.messages, { who: "user", text: value }],
      updated: "Just now",
    }));
    setTyping(true);
    setTimeout(() => {
      setTyping(false);
      setConversations((arr) => arr.map((c) => c.id !== active.id ? c : {
        ...c,
        messages: [...c.messages, { who: "bot", text: replyFor(value) }],
      }));
    }, 900);
  };

  const newConversation = (ctxKey = null) => {
    const id = "c" + (Date.now() % 100000);
    const titleSeed = ctxKey ? `${CHAT_CONTEXTS.find((c) => c.key === ctxKey)?.label} chat` : "New conversation";
    setConversations((arr) => [
      { id, title: titleSeed, contexts: ctxKey ? [ctxKey] : [], updated: "Just now", messages: [] },
      ...arr,
    ]);
    setActiveConvId(id);
    setChatContext(ctxKey);
    if (ctxKey && STARTER_PROMPTS[ctxKey]) setText(STARTER_PROMPTS[ctxKey]);
  };

  const pickContext = (key) => {
    if (!active) return newConversation(key);
    setChatContext(key);
    setConversations((arr) => arr.map((c) => c.id !== active.id ? c : {
      ...c,
      contexts: Array.from(new Set([...(c.contexts || []), key])),
    }));
    if (STARTER_PROMPTS[key] && active.messages.length === 0) setText(STARTER_PROMPTS[key]);
  };

  const onKeyDown = (e) => {
    if (e.key === "Enter" && !e.shiftKey) {
      e.preventDefault();
      send();
    }
  };

  const activeContexts = active?.contexts || (chatContext ? [chatContext] : []);

  const [infoOpen, setInfoOpen] = useState(false);

  return (
    <div style={{
      display: "grid",
      gridTemplateColumns: infoOpen ? "260px 1fr 300px" : "260px 1fr",
      gap: 14,
      height: "calc(100vh - 130px)",
      animation: "fade-up 0.5s cubic-bezier(0.2,0.7,0.2,1) both",
      animationDelay: "0.05s",
      transition: "grid-template-columns 0.3s cubic-bezier(0.2,0.7,0.2,1)",
    }} className="chat-grid">

      {/* LEFT: history (contexts live in the composer area now) */}
      <aside className="chat-history-pane" style={{
        background: "transparent",
        padding: "4px 4px 4px 0",
        display: "flex", flexDirection: "column", gap: 10,
        overflow: "hidden",
        minWidth: 0,
      }}>
        <div style={{
          display: "flex", alignItems: "center", justifyContent: "space-between",
          padding: "0 4px",
        }}>
          <div style={{
            fontSize: 11, fontWeight: 600, color: "var(--text-mute)",
            letterSpacing: "0.16em", textTransform: "uppercase",
          }}>History</div>
          <button onClick={() => newConversation()} title="New conversation" style={{
            width: 28, height: 28, borderRadius: 8,
            background: "var(--ink)", color: "var(--lime)",
            display: "inline-flex", alignItems: "center", justifyContent: "center",
          }}><i className="ti ti-plus" style={{ fontSize: 13 }} /></button>
        </div>

        <div style={{
          flex: 1, overflowY: "auto",
          display: "flex", flexDirection: "column", gap: 2,
        }}>
          {conversations.map((c) => (
            <ConvRow key={c.id} conv={c}
              active={c.id === activeConvId}
              onOpen={() => setActiveConvId(c.id)}
              onDelete={() => {
                setConversations((arr) => arr.filter((x) => x.id !== c.id));
                if (c.id === activeConvId) {
                  const next = conversations.find((x) => x.id !== c.id);
                  setActiveConvId(next ? next.id : null);
                }
              }}
            />
          ))}
          {conversations.length === 0 && (
            <div style={{ fontSize: 12, color: "var(--text-mute)", padding: "8px 4px" }}>
              No conversations yet.
            </div>
          )}
        </div>
      </aside>

      {/* CENTER: chat (no card border — sits on canvas) */}
      <section style={{
        background: "white",
        borderRadius: 20,
        display: "flex", flexDirection: "column",
        overflow: "hidden",
        boxShadow: "0 1px 0 var(--border-soft)",
      }}>
        <ChatHeader
          activeContexts={activeContexts}
          onNew={() => newConversation()}
          infoOpen={infoOpen}
          onToggleInfo={() => setInfoOpen((v) => !v)}
        />
        <div ref={scrollRef} style={{
          flex: 1, overflowY: "auto",
          padding: "18px 24px 4px",
          background: "white",
        }}>
          {active && active.messages.length === 0 && (
            <EmptyChatState onPick={(p) => setText(p)} contexts={CHAT_CONTEXTS} onPickContext={pickContext} />
          )}
          {active && active.messages.map((m, i) => (
            <ChatBubble key={i} m={m} onActionRoute={(r) => onNavigate(r)} />
          ))}
          {typing && (
            <div style={{
              alignSelf: "flex-start",
              padding: "10px 14px", borderRadius: "16px 16px 16px 6px",
              background: "var(--bg-soft)",
              display: "inline-flex", gap: 6, alignItems: "center",
              marginBottom: 12,
              width: "fit-content",
            }}>
              <Dot delay={0} /><Dot delay={0.15} /><Dot delay={0.3} />
            </div>
          )}
          {!active && (
            <div style={{
              display: "flex", alignItems: "center", justifyContent: "center",
              height: "100%", textAlign: "center",
              color: "var(--text-mute)", fontSize: 13.5,
            }}>
              Pick a conversation on the left, or start a new one.
            </div>
          )}
        </div>

        <ChatComposer
          text={text} setText={setText}
          onSend={() => send()} onKeyDown={onKeyDown}
          contexts={CHAT_CONTEXTS} activeContexts={activeContexts}
          onPickContext={pickContext}
        />
      </section>

      {/* RIGHT: context side panel — toggled by info icon */}
      {infoOpen && (
        <ContextSidePanel
          onNavigate={onNavigate}
          active={active}
        />
      )}

      <style>{`
        @media (max-width: 1080px) {
          .chat-grid { grid-template-columns: 220px 1fr !important; }
          .chat-side-panel { display: none !important; }
        }
        @media (max-width: 760px) {
          .chat-grid { grid-template-columns: 1fr !important; height: auto !important; }
          .chat-history-pane { display: none !important; }
        }
      `}</style>
    </div>
  );
}

function ConvRow({ conv, active, onOpen, onDelete }) {
  const [hovered, setHovered] = useState(false);
  return (
    <div
      onMouseEnter={() => setHovered(true)}
      onMouseLeave={() => setHovered(false)}
      onClick={onOpen}
      style={{
        position: "relative",
        padding: "8px 10px", borderRadius: 8,
        background: active ? "rgba(11,27,44,0.08)" : (hovered ? "var(--bg-soft)" : "transparent"),
        color: "var(--ink)",
        cursor: "pointer",
        transition: "background 0.18s ease",
      }}>
      <div style={{
        fontSize: 12.5, fontWeight: active ? 600 : 500, letterSpacing: "-0.005em",
        whiteSpace: "nowrap", overflow: "hidden", textOverflow: "ellipsis",
      }}>{conv.title}</div>
      <div style={{
        fontSize: 10.5, color: "var(--text-mute)", marginTop: 2,
      }}>{conv.updated}</div>
      {hovered && (
        <button onClick={(e) => { e.stopPropagation(); onDelete(); }}
          title="Delete"
          style={{
            position: "absolute", top: 6, right: 6,
            width: 22, height: 22, borderRadius: 6,
            background: "white", border: "1px solid var(--border)",
            color: "var(--text-mute)",
            display: "inline-flex", alignItems: "center", justifyContent: "center",
          }}><i className="ti ti-trash" style={{ fontSize: 11 }} /></button>
      )}
    </div>
  );
}

function ChatHeader({ activeContexts, onNew, infoOpen, onToggleInfo }) {
  return (
    <header style={{
      padding: "12px 20px",
      display: "flex", alignItems: "center", justifyContent: "space-between",
      gap: 12, flexWrap: "wrap",
      background: "white",
    }}>
      <div style={{ minWidth: 0, display: "inline-flex", alignItems: "center", gap: 10 }}>
        <h2 style={{
          fontSize: 15, fontWeight: 600, color: "var(--ink)",
          letterSpacing: "-0.015em",
        }}>Korico chat</h2>
        {activeContexts.length > 0 && (
          <span style={{ fontSize: 11, color: "var(--text-mute)" }}>·</span>
        )}
        {activeContexts.slice(0, 2).map((k) => {
          const meta = CHAT_CONTEXTS.find((c) => c.key === k);
          return (
            <span key={k} style={{
              padding: "3px 9px", borderRadius: 99,
              background: "var(--bg-soft)", color: "var(--ink)",
              fontSize: 10.5, fontWeight: 500, letterSpacing: "0.02em",
              display: "inline-flex", alignItems: "center", gap: 5,
            }}>
              <i className={`ti ti-${meta?.icon || "tag"}`} style={{ fontSize: 11 }} />
              {meta?.label || k}
            </span>
          );
        })}
      </div>
      <div style={{ display: "inline-flex", alignItems: "center", gap: 6 }}>
        <button onClick={onToggleInfo}
          title={infoOpen ? "Hide context panel" : "Show context panel"}
          style={{
            width: 32, height: 32, borderRadius: 8,
            background: infoOpen ? "var(--ink)" : "transparent",
            color: infoOpen ? "var(--lime)" : "var(--text-mute)",
            display: "inline-flex", alignItems: "center", justifyContent: "center",
            transition: "background 0.18s ease, color 0.18s ease",
          }}
          onMouseEnter={(e) => { if (!infoOpen) e.currentTarget.style.background = "var(--bg-soft)"; }}
          onMouseLeave={(e) => { if (!infoOpen) e.currentTarget.style.background = "transparent"; }}
        >
          <i className="ti ti-info-circle" style={{ fontSize: 16 }} />
        </button>
        <button onClick={onNew}
          title="New conversation"
          style={{
            width: 32, height: 32, borderRadius: 8,
            background: "transparent", color: "var(--text-mute)",
            display: "inline-flex", alignItems: "center", justifyContent: "center",
            transition: "background 0.18s ease, color 0.18s ease",
          }}
          onMouseEnter={(e) => { e.currentTarget.style.background = "var(--bg-soft)"; e.currentTarget.style.color = "var(--ink)"; }}
          onMouseLeave={(e) => { e.currentTarget.style.background = "transparent"; e.currentTarget.style.color = "var(--text-mute)"; }}
        >
          <i className="ti ti-edit" style={{ fontSize: 15 }} />
        </button>
      </div>
    </header>
  );
}

function EmptyChatState({ onPick, contexts, onPickContext }) {
  return (
    <div style={{
      maxWidth: 520, margin: "20px auto",
      padding: "24px 4px",
      textAlign: "center",
    }}>
      <h3 style={{
        fontFamily: "var(--font-display)",
        fontSize: 24, fontWeight: 400,
        color: "var(--ink)",
        letterSpacing: "-0.015em",
      }}>What can Korico help with today?</h3>

      <div style={{
        display: "flex", flexDirection: "column", gap: 6,
        marginTop: 22, maxWidth: 440, marginLeft: "auto", marginRight: "auto",
      }}>
        {EXAMPLE_PROMPTS.map((p) => (
          <button key={p} onClick={() => onPick(p)} style={{
            padding: "10px 14px", borderRadius: 12,
            background: "var(--bg-soft)", color: "var(--ink)",
            border: "none",
            fontSize: 13, fontWeight: 500, textAlign: "left",
            transition: "background 0.18s ease",
          }}
            onMouseEnter={(e) => { e.currentTarget.style.background = "rgba(11,27,44,0.08)"; }}
            onMouseLeave={(e) => { e.currentTarget.style.background = "var(--bg-soft)"; }}
          >{p}</button>
        ))}
      </div>
    </div>
  );
}

function ChatBubble({ m, onActionRoute }) {
  const isUser = m.who === "user";
  return (
    <div style={{
      display: "flex",
      justifyContent: isUser ? "flex-end" : "flex-start",
      marginBottom: 12,
      animation: "fade-up 0.32s cubic-bezier(0.2,0.7,0.2,1) both",
    }}>
      {!isUser && (
        <div style={{
          width: 28, height: 28, borderRadius: 8,
          background: "var(--ink)", color: "var(--lime)",
          display: "inline-flex", alignItems: "center", justifyContent: "center",
          flexShrink: 0, marginRight: 8, marginTop: 2,
        }}><i className="ti ti-bolt" style={{ fontSize: 14 }} /></div>
      )}
      <div style={{
        maxWidth: "78%",
        padding: "11px 15px",
        borderRadius: isUser ? "16px 16px 6px 16px" : "16px 16px 16px 6px",
        background: isUser ? "var(--ink)" : "white",
        color: isUser ? "white" : "var(--ink)",
        border: isUser ? "none" : "1px solid var(--border-soft)",
        fontSize: 13.5, lineHeight: 1.55,
        boxShadow: isUser ? "none" : "var(--shadow-sm)",
      }}>
        <div>{m.text}</div>
        {m.bullets && (
          <ul style={{
            listStyle: "none", margin: "10px 0 4px", padding: 0,
            display: "flex", flexDirection: "column", gap: 6,
          }}>
            {m.bullets.map((b, i) => (
              <li key={i} style={{
                display: "flex", alignItems: "flex-start", gap: 8, fontSize: 13,
                color: isUser ? "rgba(255,255,255,0.95)" : "var(--text-soft)",
              }}>
                <span style={{
                  width: 5, height: 5, borderRadius: "50%",
                  background: isUser ? "var(--lime)" : "var(--ink)",
                  marginTop: 8, flexShrink: 0,
                }} />
                {b}
              </li>
            ))}
          </ul>
        )}
        {m.actions && (
          <div style={{ display: "flex", flexWrap: "wrap", gap: 6, marginTop: 12 }}>
            {m.actions.map((a, i) => (
              <button key={i}
                onClick={() => a.route && onActionRoute(a.route)}
                style={{
                  display: "inline-flex", alignItems: "center", gap: 6,
                  padding: "6px 10px", borderRadius: 99,
                  background: "var(--lime)", color: "var(--ink)",
                  fontSize: 11, fontWeight: 600, letterSpacing: "-0.005em",
                }}
                onMouseEnter={(e) => e.currentTarget.style.transform = "translateY(-1px)"}
                onMouseLeave={(e) => e.currentTarget.style.transform = "translateY(0)"}
              >
                <i className={`ti ti-${a.icon}`} style={{ fontSize: 12 }} />
                {a.label}
              </button>
            ))}
          </div>
        )}
      </div>
    </div>
  );
}

function ChatComposer({ text, setText, onSend, onKeyDown, contexts, activeContexts, onPickContext }) {
  const [topicOpen, setTopicOpen] = useState(false);
  const popoverRef = useRef(null);
  useEffect(() => {
    if (!topicOpen) return;
    const h = (e) => { if (popoverRef.current && !popoverRef.current.contains(e.target)) setTopicOpen(false); };
    document.addEventListener("mousedown", h);
    return () => document.removeEventListener("mousedown", h);
  }, [topicOpen]);

  return (
    <form onSubmit={(e) => { e.preventDefault(); onSend(); }} style={{
      padding: "10px 20px 14px",
      background: "white",
    }}>
      <div style={{
        display: "flex", alignItems: "flex-end", gap: 8,
        padding: "6px 6px 6px 14px",
        borderRadius: 16,
        background: "var(--bg-soft)",
        transition: "box-shadow 0.2s ease",
      }}>
        <div ref={popoverRef} style={{ position: "relative", alignSelf: "center" }}>
          <button type="button" aria-label="Topics"
            onClick={() => setTopicOpen((v) => !v)}
            title="Pick topics" style={{
            width: 30, height: 30, borderRadius: 8,
            background: topicOpen ? "var(--ink)" : "transparent",
            color: topicOpen ? "var(--lime)" : "var(--text-mute)",
            display: "inline-flex", alignItems: "center", justifyContent: "center",
            transition: "background 0.18s ease, color 0.18s ease",
          }}>
            <i className="ti ti-plus" style={{ fontSize: 16 }} />
          </button>
          {topicOpen && contexts && (
            <div style={{
              position: "absolute", bottom: "calc(100% + 6px)", left: 0,
              background: "white", border: "1px solid var(--border)",
              borderRadius: 12, padding: 6, minWidth: 220,
              boxShadow: "0 18px 40px rgba(11,27,44,0.12)",
              zIndex: 20, animation: "fade-up 0.18s ease-out",
            }}>
              {contexts.map((c) => {
                const on = (activeContexts || []).includes(c.key);
                return (
                  <button key={c.key} type="button"
                    onClick={() => { onPickContext?.(c.key); setTopicOpen(false); }}
                    style={{
                      display: "flex", alignItems: "center", gap: 10,
                      width: "100%", padding: "8px 10px", borderRadius: 8,
                      background: on ? "var(--bg-soft)" : "transparent",
                      textAlign: "left",
                      fontSize: 12.5, color: "var(--ink)", fontWeight: on ? 600 : 500,
                    }}
                    onMouseEnter={(e) => { if (!on) e.currentTarget.style.background = "var(--bg-soft)"; }}
                    onMouseLeave={(e) => { if (!on) e.currentTarget.style.background = "transparent"; }}
                  >
                    <span style={{
                      width: 22, height: 22, borderRadius: 6,
                      background: on ? "var(--ink)" : "transparent",
                      color: on ? "var(--lime)" : "var(--ink)",
                      display: "inline-flex", alignItems: "center", justifyContent: "center",
                      flexShrink: 0,
                    }}><i className={`ti ti-${c.icon}`} style={{ fontSize: 12 }} /></span>
                    {c.label}
                  </button>
                );
              })}
            </div>
          )}
        </div>
        <textarea
          value={text}
          onChange={(e) => setText(e.target.value)}
          onKeyDown={onKeyDown}
          rows={1}
          placeholder="Ask Korico anything…"
          style={{
            flex: 1, border: "none", outline: "none",
            background: "transparent",
            resize: "none",
            fontFamily: "var(--font-body)",
            fontSize: 14, color: "var(--ink)",
            padding: "7px 4px",
            maxHeight: 140,
            lineHeight: 1.5,
          }}
        />
        <button type="submit"
          aria-label="Send"
          style={{
            width: 32, height: 32, borderRadius: "50%",
            background: text.trim() ? "var(--ink)" : "var(--border)",
            color: text.trim() ? "var(--lime)" : "var(--text-mute)",
            display: "inline-flex", alignItems: "center", justifyContent: "center",
            flexShrink: 0, alignSelf: "center",
            transition: "background 0.18s ease, color 0.18s ease",
          }}
        >
          <i className="ti ti-arrow-up" style={{ fontSize: 16 }} />
        </button>
      </div>
    </form>
  );
}

function ContextSidePanel({ onNavigate, active }) {
  const last = active?.messages?.[active.messages.length - 1];
  const suggestions = suggestionsFor(active);
  const related = relatedFor(active);

  return (
    <aside className="chat-side-panel" style={{
      background: "white",
      border: "1px solid var(--border-soft)",
      borderRadius: 20,
      padding: 16,
      display: "flex", flexDirection: "column", gap: 18,
      overflowY: "auto",
    }}>
      <div>
        <SidePanelLabel>My situation</SidePanelLabel>
        <div style={{ display: "flex", flexDirection: "column", gap: 8 }}>
          <SnapshotLine icon="id"          label="Visa"    value="D-2 · valid to 2026.03.15" route="visa"   onNavigate={onNavigate} />
          <SnapshotLine icon="credit-card" label="ARC"     value="Active · ****-1234"        route="arc"    onNavigate={onNavigate} />
          <SnapshotLine icon="home"        label="Housing" value="One-room (월세) · 전입신고 done" route="housing" onNavigate={onNavigate} />
          <SnapshotLine icon="briefcase"   label="Work"    value="Part-time · 2 jobs"        route="tax"    onNavigate={onNavigate} />
        </div>
      </div>

      <div>
        <SidePanelLabel>Suggested actions</SidePanelLabel>
        <div style={{ display: "flex", flexDirection: "column", gap: 6 }}>
          {suggestions.map((s, i) => (
            <button key={i} onClick={() => s.route && onNavigate(s.route)} style={{
              display: "flex", alignItems: "center", gap: 10,
              padding: "9px 12px", borderRadius: 12,
              background: "white", border: "1px solid var(--border-soft)",
              textAlign: "left",
              animation: "fade-up 0.4s cubic-bezier(0.2,0.7,0.2,1) both",
              animationDelay: `${0.1 + i * 0.08}s`,
              transition: "background 0.18s ease, border-color 0.18s ease",
            }}
              onMouseEnter={(e) => { e.currentTarget.style.background = "var(--bg-soft)"; e.currentTarget.style.borderColor = "var(--border)"; }}
              onMouseLeave={(e) => { e.currentTarget.style.background = "white"; e.currentTarget.style.borderColor = "var(--border-soft)"; }}
            >
              <span style={{
                width: 24, height: 24, borderRadius: 7,
                background: "var(--lime)", color: "var(--ink)",
                display: "inline-flex", alignItems: "center", justifyContent: "center",
                flexShrink: 0,
              }}><i className={`ti ti-${s.icon}`} style={{ fontSize: 12 }} /></span>
              <span style={{ fontSize: 12, fontWeight: 500, color: "var(--ink)", lineHeight: 1.45 }}>{s.label}</span>
            </button>
          ))}
        </div>
      </div>

      <div>
        <SidePanelLabel>Related guides &amp; forms</SidePanelLabel>
        <div style={{ display: "flex", flexDirection: "column", gap: 6 }}>
          {related.map((r) => (
            <button key={r.label} onClick={() => onNavigate(r.route)} style={{
              display: "flex", alignItems: "center", gap: 10,
              padding: "9px 12px", borderRadius: 12,
              background: "white", border: "1px solid var(--border-soft)",
              textAlign: "left",
              transition: "background 0.18s ease, border-color 0.18s ease",
            }}
              onMouseEnter={(e) => { e.currentTarget.style.background = "var(--bg-soft)"; e.currentTarget.style.borderColor = "var(--border)"; }}
              onMouseLeave={(e) => { e.currentTarget.style.background = "white"; e.currentTarget.style.borderColor = "var(--border-soft)"; }}
            >
              <span style={{
                width: 24, height: 24, borderRadius: 7,
                background: "var(--bg-soft)", color: "var(--ink)",
                display: "inline-flex", alignItems: "center", justifyContent: "center",
                flexShrink: 0,
              }}><i className={`ti ti-${r.icon}`} style={{ fontSize: 12 }} /></span>
              <div style={{ flex: 1, minWidth: 0 }}>
                <div style={{ fontSize: 11.5, fontWeight: 600, color: "var(--ink)", letterSpacing: "-0.005em" }}>{r.label}</div>
                <div style={{ fontSize: 10.5, color: "var(--text-mute)", marginTop: 1 }}>{r.kind}</div>
              </div>
              <i className="ti ti-arrow-up-right" style={{ fontSize: 12, color: "var(--text-mute)" }} />
            </button>
          ))}
        </div>
      </div>
    </aside>
  );
}

function SidePanelLabel({ children }) {
  return (
    <div style={{
      fontSize: 10, fontWeight: 600, color: "var(--text-mute)",
      letterSpacing: "0.18em", textTransform: "uppercase",
      marginBottom: 10,
    }}>{children}</div>
  );
}

function SnapshotLine({ icon, label, value, route, onNavigate }) {
  return (
    <button onClick={() => onNavigate(route)} style={{
      display: "grid", gridTemplateColumns: "26px 1fr auto", gap: 8,
      alignItems: "center",
      padding: "9px 10px", borderRadius: 10,
      background: "white", border: "1px solid var(--border-soft)",
      textAlign: "left", width: "100%",
      transition: "background 0.18s ease, border-color 0.18s ease",
    }}
      onMouseEnter={(e) => { e.currentTarget.style.background = "var(--bg-soft)"; e.currentTarget.style.borderColor = "var(--border)"; }}
      onMouseLeave={(e) => { e.currentTarget.style.background = "white"; e.currentTarget.style.borderColor = "var(--border-soft)"; }}
    >
      <span style={{
        width: 26, height: 26, borderRadius: 8,
        background: "var(--bg-soft)", color: "var(--ink)",
        display: "inline-flex", alignItems: "center", justifyContent: "center",
      }}><i className={`ti ti-${icon}`} style={{ fontSize: 13 }} /></span>
      <div style={{ minWidth: 0 }}>
        <div style={{ fontSize: 10, color: "var(--text-mute)", fontWeight: 600, letterSpacing: "0.12em", textTransform: "uppercase" }}>{label}</div>
        <div style={{ fontSize: 12.5, color: "var(--ink)", fontWeight: 500, marginTop: 1 }}>{value}</div>
      </div>
      <span style={{
        fontSize: 10, fontWeight: 600, color: "var(--ink)",
        textDecoration: "underline", textUnderlineOffset: 3,
        textDecorationColor: "var(--border)",
      }}>Edit</span>
    </button>
  );
}

function suggestionsFor(conv) {
  if (!conv) return [
    { icon: "id",      label: "Open Visa & status",  route: "visa" },
    { icon: "home",    label: "Open Housing page",   route: "housing" },
    { icon: "file-text", label: "Browse forms",      route: "forms" },
  ];
  const ctxs = conv.contexts || [];
  if (ctxs.includes("visa") || ctxs.includes("forms")) {
    return [
      { icon: "calendar-plus", label: "Add D-10 application deadline" },
      { icon: "list-check",    label: "Create checklist with these 4 steps" },
      { icon: "file-text",     label: "Open D-2 → D-10 form", route: "forms" },
    ];
  }
  if (ctxs.includes("housing") || ctxs.includes("arc")) {
    return [
      { icon: "calendar-plus", label: "Remind me 14 days before move-in" },
      { icon: "credit-card",   label: "Update ARC address", route: "arc" },
      { icon: "home",          label: "Open Housing page",  route: "housing" },
    ];
  }
  if (ctxs.includes("tax")) {
    return [
      { icon: "bookmark",      label: "Save guide: 연말정산 for foreigners" },
      { icon: "briefcase",     label: "Review job records", route: "tax" },
      { icon: "list-check",    label: "Create tax checklist" },
    ];
  }
  return [
    { icon: "list-check",    label: "Create checklist from this conversation" },
    { icon: "calendar-plus", label: "Add deadline reminder" },
    { icon: "bookmark",      label: "Save this conversation" },
  ];
}

function relatedFor(conv) {
  if (!conv) return [
    { label: "How Korico works", kind: "Guide", icon: "book-2", route: "home" },
    { label: "Forms library",    kind: "Section", icon: "file-text", route: "forms" },
  ];
  const ctxs = conv.contexts || [];
  if (ctxs.includes("visa")) return [
    { label: "Guide: D-2 → D-10 change", kind: "Guide", icon: "book-2", route: "visa" },
    { label: "Form: Part-time permission", kind: "Form", icon: "file-text", route: "forms" },
    { label: "Visa page",                  kind: "Section", icon: "id", route: "visa" },
  ];
  if (ctxs.includes("housing") || ctxs.includes("arc")) return [
    { label: "Guide: 전입신고 step by step",  kind: "Guide", icon: "book-2", route: "housing" },
    { label: "Form: Address change",         kind: "Form",  icon: "file-text", route: "forms" },
    { label: "ARC page",                     kind: "Section", icon: "credit-card", route: "arc" },
  ];
  if (ctxs.includes("tax")) return [
    { label: "Guide: 연말정산 for foreigners",  kind: "Guide", icon: "book-2", route: "tax" },
    { label: "Form: Employment contract",     kind: "Form",  icon: "file-text", route: "forms" },
  ];
  if (ctxs.includes("legal")) return [
    { label: "Legal directory", kind: "Section", icon: "scale", route: "legal" },
  ];
  return [
    { label: "Forms library", kind: "Section", icon: "file-text", route: "forms" },
  ];
}

/* ============================================================
   FILL WITH KORICO — D-2 Visa Application / Extension
   ============================================================ */

const LANGS = [
  { code: "ko", label: "한국어" },
  { code: "en", label: "English" },
  { code: "vi", label: "Tiếng Việt" },
];

const D2_STEPS = [
  { key: "personal", labels: { ko: "개인정보", en: "Personal info", vi: "Thông tin cá nhân" } },
  { key: "study",    labels: { ko: "학업 정보", en: "Study info",    vi: "Thông tin học tập" } },
  { key: "contact",  labels: { ko: "연락처·서명", en: "Contact & signature", vi: "Liên hệ & chữ ký" } },
];

// Field schema. Each field belongs to one step.
// `ko` is the official Korean label; `en`/`vi` are Korico's helper labels.
// `placeholder` shown in selected language. Optional `select` makes it a dropdown.
const D2_FIELDS = [
  // type group (visible in every step at the top)
  { key: "applicationType", step: "personal", required: true,
    labels: { ko: "신청/신고 선택", en: "Application type", vi: "Loại đơn" },
    select: [
      { v: "ext",    ko: "체류기간 연장허가",     en: "Extension of period of sojourn", vi: "Gia hạn thời gian lưu trú" },
      { v: "new",    ko: "신규 발급",            en: "New issuance (first-time)",       vi: "Cấp mới (lần đầu)" },
      { v: "change", ko: "체류자격 변경",         en: "Change of status of sojourn",     vi: "Thay đổi tư cách lưu trú" },
    ],
  },

  // personal
  { key: "surname",    step: "personal", required: true,
    labels: { ko: "성", en: "Surname", vi: "Họ" },
    placeholder: { ko: "예: NGUYEN", en: "e.g. NGUYEN", vi: "VD: NGUYEN" } },
  { key: "givenName",  step: "personal", required: true,
    labels: { ko: "이름", en: "Given name(s)", vi: "Tên" },
    placeholder: { ko: "예: MINH ANH", en: "e.g. MINH ANH", vi: "VD: MINH ANH" } },
  { key: "sex",        step: "personal", required: true,
    labels: { ko: "성별", en: "Sex", vi: "Giới tính" },
    select: [
      { v: "M", ko: "남", en: "Male",   vi: "Nam" },
      { v: "F", ko: "여", en: "Female", vi: "Nữ" },
      { v: "X", ko: "기타", en: "Other", vi: "Khác" },
    ],
  },
  { key: "dob",         step: "personal", required: true, type: "date",
    labels: { ko: "생년월일", en: "Date of birth", vi: "Ngày sinh" } },
  { key: "nationality", step: "personal", required: true,
    labels: { ko: "국적", en: "Nationality", vi: "Quốc tịch" },
    placeholder: { ko: "예: 베트남", en: "e.g. Vietnam", vi: "VD: Việt Nam" } },
  { key: "foreignRegNo", step: "personal", required: false,
    labels: { ko: "외국인등록번호", en: "ARC number (if any)", vi: "Số ARC (nếu có)" },
    placeholder: { ko: "예: 020514-6XXXXXX", en: "e.g. 020514-6XXXXXX", vi: "VD: 020514-6XXXXXX" } },
  { key: "passportNo",     step: "personal", required: true,
    labels: { ko: "여권번호", en: "Passport No.", vi: "Số hộ chiếu" },
    placeholder: { ko: "예: N12345678", en: "e.g. N12345678", vi: "VD: N12345678" } },
  { key: "passportIssue",  step: "personal", required: true, type: "date",
    labels: { ko: "여권 발급일자", en: "Passport issue date", vi: "Ngày cấp hộ chiếu" } },
  { key: "passportExpiry", step: "personal", required: true, type: "date",
    labels: { ko: "여권 유효기간", en: "Passport expiry", vi: "Hộ chiếu hết hạn" } },

  // study (D-2 specific helper fields)
  { key: "university", step: "study", required: true,
    labels: { ko: "재학 중인 학교명", en: "University / school name", vi: "Tên trường" },
    placeholder: { ko: "예: 연세대학교", en: "e.g. Yonsei University", vi: "VD: Đại học Yonsei" } },
  { key: "major", step: "study", required: true,
    labels: { ko: "전공 / 학과", en: "Major / department", vi: "Chuyên ngành / khoa" },
    placeholder: { ko: "예: 컴퓨터과학", en: "e.g. Computer Science", vi: "VD: Khoa học máy tính" } },
  { key: "yearOfStudy", step: "study", required: true,
    labels: { ko: "학년", en: "Year of study", vi: "Năm học" },
    select: [
      { v: "1", ko: "1학년", en: "1st year", vi: "Năm 1" },
      { v: "2", ko: "2학년", en: "2nd year", vi: "Năm 2" },
      { v: "3", ko: "3학년", en: "3rd year", vi: "Năm 3" },
      { v: "4", ko: "4학년", en: "4th year", vi: "Năm 4" },
      { v: "g", ko: "대학원", en: "Graduate",  vi: "Sau đại học" },
    ],
  },
  { key: "expectedGraduation", step: "study", required: true, type: "date",
    labels: { ko: "졸업 예정일", en: "Expected graduation", vi: "Dự kiến tốt nghiệp" } },
  { key: "currentVisaExpiry",  step: "study", required: true, type: "date",
    labels: { ko: "현재 비자 만료일", en: "Current visa expiry", vi: "Hạn visa hiện tại" } },
  { key: "extensionReason", step: "study", required: false, type: "textarea",
    labels: { ko: "연장 사유", en: "Reason for extension", vi: "Lý do gia hạn" },
    placeholder: { ko: "예: 동일 학과에서 학업을 계속할 예정입니다.", en: "e.g. I will continue studies in the same program.", vi: "VD: Tôi sẽ tiếp tục học cùng ngành." } },

  // contact
  { key: "cellPhone", step: "contact", required: true,
    labels: { ko: "핸드폰 번호", en: "Cell phone (Korea)", vi: "Điện thoại tại Hàn" },
    placeholder: { ko: "010-XXXX-XXXX", en: "010-XXXX-XXXX", vi: "010-XXXX-XXXX" } },
  { key: "email", step: "contact", required: true,
    labels: { ko: "전자우편", en: "Email", vi: "Email" },
    placeholder: { ko: "name@email.com", en: "name@email.com", vi: "name@email.com" } },
  { key: "addressKr", step: "contact", required: true, type: "textarea",
    labels: { ko: "대한민국 내 주소", en: "Address in Korea", vi: "Địa chỉ tại Hàn" },
    placeholder: { ko: "시 / 구 / 동 포함", en: "Include 시 / 구 / 동", vi: "Bao gồm 시 / 구 / 동" } },
  { key: "addressHome", step: "contact", required: true, type: "textarea",
    labels: { ko: "본국 주소", en: "Address in home country", vi: "Địa chỉ quê nhà" } },
  { key: "phoneHome", step: "contact", required: false,
    labels: { ko: "본국 전화번호", en: "Phone in home country", vi: "Điện thoại quê nhà" } },
  { key: "dateOfApplication", step: "contact", required: true, type: "date",
    labels: { ko: "신청일", en: "Date of application", vi: "Ngày nộp đơn" } },
  { key: "signature", step: "contact", required: true,
    labels: { ko: "서명 또는 인", en: "Signature (typed name)", vi: "Chữ ký (gõ tên)" },
    placeholder: { ko: "이름을 입력해 서명을 대신합니다.", en: "Type your full name as signature.", vi: "Gõ họ tên đầy đủ làm chữ ký." } },
];

const DEFAULT_D2_VALUES = {
  applicationType: "ext",
  surname: "NGUYEN",
  givenName: "MINH ANH",
  sex: "F",
  dob: "2002-05-14",
  nationality: "Vietnam",
  foreignRegNo: "020514-6XXXXXX",
  passportNo: "N12345678",
  passportIssue: "2022-01-10",
  passportExpiry: "2032-01-09",
  university: "Yonsei University",
  major: "Computer Science",
  yearOfStudy: "3",
  expectedGraduation: "2026-02-15",
  currentVisaExpiry: "2026-03-15",
  extensionReason: "",
  cellPhone: "010-1234-5678",
  email: "minh.anh@yonsei.ac.kr",
  addressKr: "서울 서대문구 신촌로 ***",
  addressHome: "Hanoi, Vietnam",
  phoneHome: "",
  dateOfApplication: new Date().toISOString().slice(0, 10),
  signature: "",
};

function FillD2Page({ onNavigate, formsState }) {
  const { flash } = formsState;
  const [lang, setLang] = useState("en");
  const [step, setStep] = useState(0);
  const [values, setValues] = useState(DEFAULT_D2_VALUES);
  const [touched, setTouched] = useState({});
  const [consent, setConsent] = useState(false);
  const [savedFlag, setSavedFlag] = useState("All changes saved");
  const [glow, setGlow] = useState(null);
  const [confirmingClear, setConfirmingClear] = useState(false);
  const [success, setSuccess] = useState(null);
  const fieldRefs = useRef({});

  // Save indicator
  useEffect(() => {
    if (Object.keys(touched).length === 0) return;
    setSavedFlag("Saving…");
    const t = setTimeout(() => setSavedFlag("All changes saved"), 700);
    return () => clearTimeout(t);
  }, [values]);

  const onChange = (key, v) => {
    setValues((prev) => ({ ...prev, [key]: v }));
    setTouched((prev) => ({ ...prev, [key]: true }));
    setGlow(key);
    setTimeout(() => setGlow((g) => (g === key ? null : g)), 600);
  };

  const visibleFields = D2_FIELDS.filter((f) => f.step === D2_STEPS[step].key);
  const requiredKeys = D2_FIELDS.filter((f) => f.required).map((f) => f.key);
  const missing = requiredKeys.filter((k) => !values[k] || String(values[k]).trim() === "");
  const completion = Math.round(((requiredKeys.length - missing.length) / requiredKeys.length) * 100);
  const allRequiredFilled = missing.length === 0;

  const tryGenerate = (draft = false) => {
    if (!draft) {
      if (!allRequiredFilled || !consent) {
        const firstMissing = missing[0];
        if (firstMissing) {
          // jump to step containing missing field
          const f = D2_FIELDS.find((x) => x.key === firstMissing);
          if (f) {
            const idx = D2_STEPS.findIndex((s) => s.key === f.step);
            if (idx >= 0) setStep(idx);
            setTimeout(() => {
              const el = fieldRefs.current[firstMissing];
              el?.scrollIntoView({ behavior: "smooth", block: "center" });
              el?.focus?.();
              setGlow(firstMissing);
              setTimeout(() => setGlow(null), 900);
            }, 50);
          }
          flash("Some required fields are missing. We've scrolled to the first one.");
          return;
        }
        if (!consent) {
          flash("Please confirm the data notice before generating.");
          return;
        }
      }
    }
    // Mock PDF generation. In real impl, call pdf-lib + AcroForm or coord-stamp.
    const ok = Math.random() > 0.04;
    if (!ok) {
      flash("We couldn't finish the PDF right now. Your answers are saved — try again in a few minutes.");
      return;
    }
    setSuccess({
      kind: draft ? "draft" : "final",
      filename: draft ? "D2-application-draft.pdf" : "D2-application.pdf",
    });
  };

  const clearAll = () => {
    setValues(Object.fromEntries(Object.keys(DEFAULT_D2_VALUES).map((k) => [k, ""])));
    setTouched({});
    setConsent(false);
    setConfirmingClear(false);
    flash("All answers cleared.");
  };

  return (
    <div style={{
      display: "flex", flexDirection: "column",
      minHeight: "100vh",
      background: "var(--bg-canvas)",
    }}>
      {/* STICKY HEADER */}
      <header style={{
        position: "sticky", top: 0, zIndex: 30,
        background: "rgba(255,255,255,0.92)",
        backdropFilter: "saturate(180%) blur(12px)",
        WebkitBackdropFilter: "saturate(180%) blur(12px)",
        borderBottom: "1px solid var(--border-soft)",
        padding: "16px clamp(20px, 4vw, 40px)",
      }}>
        <div style={{
          display: "grid", gridTemplateColumns: "1.2fr 1.4fr 1fr", gap: 18,
          alignItems: "center", maxWidth: 1400, margin: "0 auto",
        }} className="fd2-head-grid">

          <div style={{ minWidth: 0 }}>
            <div style={{
              display: "flex", alignItems: "center", gap: 6,
              fontSize: 11, color: "var(--text-mute)", marginBottom: 4, flexWrap: "wrap",
            }}>
              <button onClick={() => onNavigate("forms")} style={{ color: "inherit" }}>Forms &amp; templates</button>
              <i className="ti ti-chevron-right" style={{ fontSize: 11 }} />
              <span>D-2 Visa</span>
              <i className="ti ti-chevron-right" style={{ fontSize: 11 }} />
              <span style={{ color: "var(--ink)", fontWeight: 500 }}>Fill with Korico</span>
            </div>
            <h1 style={{
              fontSize: 18, fontWeight: 600, color: "var(--ink)",
              letterSpacing: "-0.015em",
            }}>D-2 Visa Application / Extension</h1>
            <p style={{ fontSize: 11.5, color: "var(--text-mute)", marginTop: 3, lineHeight: 1.4 }}>
              Answer in your language. Korico maps it to the official Korean application form.
            </p>
          </div>

          <div>
            <div style={{
              display: "flex", alignItems: "center", justifyContent: "space-between",
              fontSize: 10.5, color: "var(--text-mute)",
              fontWeight: 600, letterSpacing: "0.12em", textTransform: "uppercase",
              marginBottom: 6,
            }}>
              <span>Step {step + 1} of {D2_STEPS.length} · {D2_STEPS[step].labels[lang]}</span>
              <span style={{ color: "var(--ink)" }}>{completion}%</span>
            </div>
            <div style={{ display: "flex", gap: 6 }}>
              {D2_STEPS.map((s, i) => {
                const done = i < step;
                const current = i === step;
                return (
                  <button key={s.key} onClick={() => setStep(i)} style={{
                    flex: 1, padding: "8px 8px", borderRadius: 99,
                    background: current ? "var(--ink)" : done ? "rgba(184,230,60,0.45)" : "var(--bg-soft)",
                    color: current ? "var(--lime)" : "var(--ink)",
                    fontSize: 11, fontWeight: 600, letterSpacing: "-0.005em",
                    transition: "background 0.2s ease, color 0.2s ease",
                  }}>{i + 1}. {s.labels[lang]}</button>
                );
              })}
            </div>
            <div style={{
              height: 4, borderRadius: 99, background: "var(--bg-soft)",
              marginTop: 6, overflow: "hidden",
            }}>
              <div style={{
                width: `${completion}%`, height: "100%",
                background: "linear-gradient(90deg, var(--lime), var(--lime-deep))",
                borderRadius: 99,
                transition: "width 0.45s cubic-bezier(0.2,0.7,0.2,1)",
              }} />
            </div>
          </div>

          <div style={{ display: "flex", flexDirection: "column", alignItems: "flex-end", gap: 6 }}>
            <div style={{
              fontSize: 10, fontWeight: 600, color: "var(--text-mute)",
              letterSpacing: "0.12em", textTransform: "uppercase",
            }}>Answer language</div>
            <div style={{
              display: "inline-flex",
              background: "var(--bg-soft)",
              borderRadius: 99, padding: 3,
            }}>
              {LANGS.map((l) => {
                const on = lang === l.code;
                return (
                  <button key={l.code} onClick={() => setLang(l.code)} style={{
                    padding: "6px 12px", borderRadius: 99,
                    background: on ? "var(--ink)" : "transparent",
                    color: on ? "var(--lime)" : "var(--ink)",
                    fontSize: 11.5, fontWeight: 600, letterSpacing: "-0.005em",
                    transition: "all 0.18s ease",
                  }}>{l.label}</button>
                );
              })}
            </div>
          </div>
        </div>

        <style>{`
          @media (max-width: 1024px) {
            .fd2-head-grid { grid-template-columns: 1fr !important; gap: 12px; }
          }
        `}</style>
      </header>

      {/* WORKSPACE */}
      <div style={{
        flex: 1, display: "grid",
        gridTemplateColumns: "1.2fr 1fr", gap: 18,
        maxWidth: 1400, margin: "0 auto",
        padding: "24px clamp(20px, 4vw, 40px) 110px",
        width: "100%",
      }} className="fd2-grid">

        {/* HELPER FORM */}
        <section style={{
          background: "white", border: "1px solid var(--border-soft)",
          borderRadius: 20, padding: "22px 24px",
          animation: "fade-up 0.5s cubic-bezier(0.2,0.7,0.2,1) both",
        }}>
          <header style={{ marginBottom: 14 }}>
            <div style={{
              fontSize: 10, fontWeight: 600, color: "var(--text-mute)",
              letterSpacing: "0.18em", textTransform: "uppercase",
            }}>Korico helper form</div>
            <h2 style={{
              fontSize: 18, fontWeight: 600, color: "var(--ink)",
              letterSpacing: "-0.015em", marginTop: 4,
            }}>{D2_STEPS[step].labels[lang]}</h2>
            <p style={{ fontSize: 12, color: "var(--text-mute)", marginTop: 4 }}>
              Fields marked <strong style={{ color: "var(--ink)" }}>*</strong> are required.
            </p>
          </header>

          <div style={{ display: "flex", flexDirection: "column", gap: 14 }}>
            {visibleFields.map((f) => {
              const isMissing = f.required && (!values[f.key] || String(values[f.key]).trim() === "") && touched[f.key];
              const labelLang = f.labels[lang] || f.labels.en;
              return (
                <label key={f.key} style={{ display: "flex", flexDirection: "column", gap: 5 }}>
                  <span style={{ display: "flex", alignItems: "baseline", gap: 8 }}>
                    <span style={{
                      fontSize: 12.5, fontWeight: 600, color: "var(--ink)",
                      letterSpacing: "-0.005em",
                    }}>
                      {labelLang}{f.required && <span style={{ color: "var(--danger)" }}> *</span>}
                    </span>
                    {lang !== "ko" && (
                      <span style={{ fontSize: 11, color: "var(--text-mute)" }}>
                        {f.labels.ko}
                      </span>
                    )}
                  </span>
                  <D2Input
                    field={f}
                    value={values[f.key]}
                    lang={lang}
                    onChange={(v) => onChange(f.key, v)}
                    inputRef={(el) => (fieldRefs.current[f.key] = el)}
                    invalid={isMissing}
                  />
                  {isMissing && (
                    <span style={{ fontSize: 11, color: "var(--danger)" }}>This field is required.</span>
                  )}
                </label>
              );
            })}
          </div>

          {/* Step navigation */}
          <div style={{
            display: "flex", justifyContent: "space-between",
            marginTop: 24, paddingTop: 16, borderTop: "1px solid var(--border-soft)",
          }}>
            <button onClick={() => setStep((s) => Math.max(0, s - 1))} disabled={step === 0} style={stepBtn(false, step === 0)}>
              <i className="ti ti-arrow-left" style={{ fontSize: 13 }} /> Back
            </button>
            {step < D2_STEPS.length - 1 ? (
              <button onClick={() => setStep((s) => Math.min(D2_STEPS.length - 1, s + 1))} style={stepBtn(true)}>
                Next <i className="ti ti-arrow-right" style={{ fontSize: 13 }} />
              </button>
            ) : (
              <span style={{ fontSize: 11.5, color: "var(--text-mute)" }}>
                You're at the last step — review the preview on the right.
              </span>
            )}
          </div>

          {/* Consent */}
          <div style={{
            marginTop: 28, padding: 18, borderRadius: 14,
            background: "var(--bg-soft)", border: "1px solid var(--border-soft)",
          }}>
            <div style={{
              fontSize: 10, fontWeight: 600, color: "var(--text-mute)",
              letterSpacing: "0.18em", textTransform: "uppercase",
            }}>Data &amp; personal information</div>
            <p style={{
              fontSize: 12.5, color: "var(--text-soft)", lineHeight: 1.6,
              marginTop: 6,
            }}>
              Korico stores your answers only to generate this form and keep your own records. We never share your data with third parties. Always confirm the latest immigration requirements directly with HiKorea or your office.
            </p>
            <label style={{
              display: "flex", alignItems: "center", gap: 10,
              marginTop: 10, cursor: "pointer",
            }}>
              <input type="checkbox" checked={consent} onChange={(e) => setConsent(e.target.checked)} style={{ display: "none" }} />
              <span style={{
                width: 18, height: 18, borderRadius: 5,
                background: consent ? "var(--ink)" : "white",
                border: consent ? "none" : "1.5px solid var(--border)",
                display: "inline-flex", alignItems: "center", justifyContent: "center",
                color: "var(--lime)", flexShrink: 0,
              }}>{consent && <i className="ti ti-check" style={{ fontSize: 12 }} />}</span>
              <span style={{ fontSize: 12.5, color: "var(--ink)", fontWeight: 500 }}>
                I understand that Korico stores this information only to generate my form and my own records. I will check the latest requirements with immigration.
              </span>
            </label>
          </div>
        </section>

        {/* PREVIEW */}
        <section style={{
          background: "white", border: "1px solid var(--border-soft)",
          borderRadius: 20, padding: "22px 24px",
          animation: "fade-up 0.55s cubic-bezier(0.2,0.7,0.2,1) both",
          animationDelay: "0.05s",
          position: "sticky", top: 200, alignSelf: "start",
          maxHeight: "calc(100vh - 240px)",
          display: "flex", flexDirection: "column",
        }}>
          <header style={{
            display: "flex", justifyContent: "space-between", alignItems: "flex-start",
            gap: 10, marginBottom: 14, flexWrap: "wrap",
          }}>
            <div>
              <div style={{
                fontSize: 10, fontWeight: 600, color: "var(--text-mute)",
                letterSpacing: "0.18em", textTransform: "uppercase",
              }}>Official form preview</div>
              <h2 style={{
                fontSize: 16, fontWeight: 600, color: "var(--ink)",
                letterSpacing: "-0.015em", marginTop: 4,
              }}>통합신청서 (신고서)</h2>
              <p style={{ fontSize: 11.5, color: "var(--text-mute)", marginTop: 3, lineHeight: 1.4, maxWidth: 360 }}>
                For review only — you'll get a PDF to print, sign or upload.
              </p>
            </div>
            <a href="https://www.hikorea.go.kr/board/BoardApplicationListR.pt" target="_blank" rel="noreferrer" style={{
              display: "inline-flex", alignItems: "center", gap: 6,
              padding: "7px 12px", borderRadius: 99,
              background: "var(--bg-soft)", color: "var(--ink)",
              border: "1px solid var(--border)",
              fontSize: 10.5, fontWeight: 600, letterSpacing: "0.08em",
              textDecoration: "none",
            }}>
              <i className="ti ti-external-link" style={{ fontSize: 12 }} />
              Original blank form
            </a>
          </header>

          <div style={{
            flex: 1, overflowY: "auto",
            padding: "18px 18px 22px",
            borderRadius: 14,
            background: "linear-gradient(180deg, #FCFCFD 0%, #F4F4F6 100%)",
            border: "1px solid var(--border-soft)",
          }}>
            <OfficialFormPreview values={values} glow={glow} />
          </div>
        </section>

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

      {/* STICKY FOOTER */}
      <footer style={{
        position: "sticky", bottom: 0, zIndex: 25,
        background: "rgba(255,255,255,0.95)",
        backdropFilter: "saturate(180%) blur(12px)",
        WebkitBackdropFilter: "saturate(180%) blur(12px)",
        borderTop: "1px solid var(--border-soft)",
        padding: "12px clamp(20px, 4vw, 40px)",
      }}>
        <div style={{
          maxWidth: 1400, margin: "0 auto",
          display: "flex", justifyContent: "space-between", alignItems: "center",
          gap: 12, flexWrap: "wrap",
        }}>
          <div style={{ display: "flex", alignItems: "center", gap: 14 }}>
            <span style={{
              display: "inline-flex", alignItems: "center", gap: 6,
              fontSize: 12, color: savedFlag === "Saving…" ? "var(--text-mute)" : "var(--success)",
              fontWeight: 500,
            }}>
              <span style={{
                width: 7, height: 7, borderRadius: "50%",
                background: savedFlag === "Saving…" ? "var(--text-mute)" : "var(--success)",
              }} />
              {savedFlag}
            </span>
            {confirmingClear ? (
              <span style={{ fontSize: 12, color: "var(--ink)" }}>
                Sure?
                <button onClick={clearAll} style={ghostBtn("var(--danger)")}>Clear all</button>
                <button onClick={() => setConfirmingClear(false)} style={ghostBtn("var(--text-mute)")}>Cancel</button>
              </span>
            ) : (
              <button onClick={() => setConfirmingClear(true)} style={{
                fontSize: 11.5, color: "var(--text-mute)", fontWeight: 500,
                textDecoration: "underline", textUnderlineOffset: 3,
                textDecorationColor: "var(--border)",
              }}>Clear all answers</button>
            )}
          </div>
          <div style={{ display: "flex", gap: 10, flexWrap: "wrap" }}>
            <button onClick={() => tryGenerate(true)} style={{
              padding: "11px 18px", borderRadius: 99,
              background: "white", color: "var(--ink)",
              border: "1px solid var(--ink)",
              fontSize: 11, fontWeight: 700, letterSpacing: "0.14em", textTransform: "uppercase",
            }}>
              <i className="ti ti-file-download" style={{ fontSize: 13, marginRight: 6, verticalAlign: -1 }} />
              Download draft PDF
            </button>
            <button onClick={() => tryGenerate(false)}
              disabled={!allRequiredFilled || !consent}
              style={{
                display: "inline-flex", alignItems: "center", gap: 8,
                padding: "11px 22px", borderRadius: 99,
                background: !allRequiredFilled || !consent ? "var(--bg-soft)" : "var(--lime)",
                color: !allRequiredFilled || !consent ? "var(--text-mute)" : "var(--ink)",
                fontSize: 11, fontWeight: 700, letterSpacing: "0.14em", textTransform: "uppercase",
                boxShadow: !allRequiredFilled || !consent ? "none" : "0 10px 22px rgba(184,230,60,0.35)",
                cursor: !allRequiredFilled || !consent ? "not-allowed" : "pointer",
                transition: "all 0.18s ease",
              }}>
              Generate final PDF
              <span style={{
                width: 20, height: 20, borderRadius: "50%",
                background: "var(--ink)", color: "var(--lime)",
                display: "inline-flex", alignItems: "center", justifyContent: "center",
              }}><i className="ti ti-arrow-up-right" style={{ fontSize: 11 }} /></span>
            </button>
          </div>
        </div>
      </footer>

      {/* SUCCESS MODAL */}
      {success && (
        <SuccessModal
          success={success}
          onClose={() => setSuccess(null)}
          onShareChat={() => {
            window.dispatchEvent(new CustomEvent("korico:ask", {
              detail: { prefill: "I generated my D-2 form. Could you double-check any field that looks wrong?" },
            }));
            setSuccess(null);
          }}
          onSaveToFiles={() => {
            flash("Saved to My files · D2-application.pdf");
            setSuccess(null);
          }}
        />
      )}
    </div>
  );
}

/* ---- Helper input components ---- */

function D2Input({ field, value, lang, onChange, inputRef, invalid }) {
  const placeholder = field.placeholder?.[lang] || field.placeholder?.en || "";
  const baseStyle = {
    width: "100%",
    padding: "10px 14px",
    borderRadius: 12,
    border: "1px solid " + (invalid ? "var(--danger)" : "var(--border)"),
    fontFamily: "var(--font-body)",
    fontSize: 13.5, color: "var(--ink)", outline: "none",
    background: "white",
    transition: "border-color 0.2s ease, box-shadow 0.2s ease",
  };
  const focus = (e) => {
    e.currentTarget.style.borderColor = "var(--ink)";
    e.currentTarget.style.boxShadow = "0 0 0 3px rgba(212,255,79,0.22)";
  };
  const blur = (e) => {
    e.currentTarget.style.borderColor = invalid ? "var(--danger)" : "var(--border)";
    e.currentTarget.style.boxShadow = "none";
  };

  if (field.select) {
    return (
      <div style={{ position: "relative" }}>
        <select ref={inputRef} value={value || ""} onChange={(e) => onChange(e.target.value)}
          onFocus={focus} onBlur={blur}
          style={{
            ...baseStyle,
            padding: "10px 38px 10px 14px",
            appearance: "none", WebkitAppearance: "none",
          }}>
          <option value="" disabled>Select…</option>
          {field.select.map((o) => (
            <option key={o.v} value={o.v}>
              {o[lang] || o.en} {lang !== "ko" ? ` · ${o.ko}` : ""}
            </option>
          ))}
        </select>
        <i className="ti ti-chevron-down" style={{
          position: "absolute", right: 12, top: "50%", transform: "translateY(-50%)",
          fontSize: 15, color: "var(--text-mute)", pointerEvents: "none",
        }} />
      </div>
    );
  }
  if (field.type === "textarea") {
    return (
      <textarea ref={inputRef} value={value || ""} onChange={(e) => onChange(e.target.value)}
        rows={2} placeholder={placeholder}
        onFocus={focus} onBlur={blur}
        style={{ ...baseStyle, resize: "vertical", minHeight: 60, lineHeight: 1.5 }}
      />
    );
  }
  return (
    <input
      ref={inputRef}
      type={field.type || "text"}
      value={value || ""}
      onChange={(e) => onChange(e.target.value)}
      placeholder={placeholder}
      onFocus={focus} onBlur={blur}
      style={baseStyle}
    />
  );
}

function stepBtn(primary, disabled) {
  return {
    display: "inline-flex", alignItems: "center", gap: 8,
    padding: "9px 16px", borderRadius: 99,
    background: primary ? "var(--ink)" : "white",
    color: primary ? "var(--lime)" : "var(--ink)",
    border: primary ? "none" : "1px solid var(--border)",
    fontSize: 11, fontWeight: 700, letterSpacing: "0.14em", textTransform: "uppercase",
    opacity: disabled ? 0.4 : 1,
    cursor: disabled ? "not-allowed" : "pointer",
  };
}

function ghostBtn(color) {
  return {
    marginLeft: 8,
    fontSize: 11.5, fontWeight: 600, color,
    textDecoration: "underline", textUnderlineOffset: 3, textDecorationColor: "currentColor",
  };
}

/* ---- Official form preview ---- */

function OfficialFormPreview({ values, glow }) {
  const typeLabel = D2_FIELDS[0].select.find((o) => o.v === values.applicationType)?.ko || "—";
  const sexLabel  = D2_FIELDS.find((f) => f.key === "sex")?.select.find((o) => o.v === values.sex)?.ko || "—";
  const yearLabel = D2_FIELDS.find((f) => f.key === "yearOfStudy")?.select.find((o) => o.v === values.yearOfStudy)?.ko || "—";

  return (
    <div style={{
      background: "white",
      borderRadius: 10,
      padding: "20px 22px 22px",
      fontFamily: "'Noto Sans KR', var(--font-body)",
      color: "#1A1A1F",
      boxShadow: "0 1px 0 var(--border-soft)",
    }}>
      <h3 style={{
        textAlign: "center", fontSize: 18, fontWeight: 700, letterSpacing: "-0.01em",
        color: "var(--ink)",
      }}>통합신청서 (신고서)</h3>
      <div style={{
        textAlign: "center", fontSize: 11, color: "var(--text-mute)",
        marginTop: 2, marginBottom: 16,
      }}>Application Form (Report Form)</div>

      <PFieldRow label="신청/신고 선택" glow={glow === "applicationType"} fullValue={typeLabel} />
      <div style={dividerStyle()} />

      <PFieldRow label="성" subEn="Surname" glow={glow === "surname"} value={values.surname} half
                 right={{ label: "이름", subEn: "Given names", glow: glow === "givenName", value: values.givenName }} />
      <PFieldRow label="성별" subEn="Sex" glow={glow === "sex"} value={sexLabel} half
                 right={{ label: "생년월일", subEn: "Date of birth", glow: glow === "dob", value: values.dob }} />
      <PFieldRow label="국적" subEn="Nationality" glow={glow === "nationality"} value={values.nationality} />
      <PFieldRow label="외국인등록번호" subEn="Foreign Registration No." glow={glow === "foreignRegNo"} value={values.foreignRegNo || "—"} />
      <div style={dividerStyle()} />

      <PFieldRow label="여권번호" subEn="Passport No." glow={glow === "passportNo"} value={values.passportNo} />
      <PFieldRow label="여권 발급일자" subEn="Issue date" glow={glow === "passportIssue"} value={values.passportIssue} half
                 right={{ label: "여권 유효기간", subEn: "Expiry", glow: glow === "passportExpiry", value: values.passportExpiry }} />
      <div style={dividerStyle()} />

      <PFieldRow label="재학 중인 학교명" subEn="University" glow={glow === "university"} value={values.university} />
      <PFieldRow label="전공" subEn="Major" glow={glow === "major"} value={values.major} half
                 right={{ label: "학년", subEn: "Year", glow: glow === "yearOfStudy", value: yearLabel }} />
      <PFieldRow label="졸업 예정일" subEn="Expected graduation" glow={glow === "expectedGraduation"} value={values.expectedGraduation} half
                 right={{ label: "현재 비자 만료일", subEn: "Current visa expiry", glow: glow === "currentVisaExpiry", value: values.currentVisaExpiry }} />
      {values.extensionReason && (
        <PFieldRow label="연장 사유" subEn="Reason for extension" glow={glow === "extensionReason"} value={values.extensionReason} />
      )}
      <div style={dividerStyle()} />

      <PFieldRow label="핸드폰 번호" subEn="Cell phone" glow={glow === "cellPhone"} value={values.cellPhone} half
                 right={{ label: "전자우편", subEn: "E-mail", glow: glow === "email", value: values.email }} />
      <PFieldRow label="대한민국 내 주소" subEn="Address in Korea" glow={glow === "addressKr"} value={values.addressKr} />
      <PFieldRow label="본국 주소" subEn="Home country address" glow={glow === "addressHome"} value={values.addressHome} half
                 right={{ label: "본국 전화번호", subEn: "Home phone", glow: glow === "phoneHome", value: values.phoneHome || "—" }} />
      <div style={dividerStyle()} />

      <PFieldRow label="신청일" subEn="Date of application" glow={glow === "dateOfApplication"} value={values.dateOfApplication} half
                 right={{ label: "서명 또는 인", subEn: "Signature", glow: glow === "signature", value: values.signature || "(서명 필요)" }} />
    </div>
  );
}

function dividerStyle() {
  return {
    height: 1, background: "var(--border-soft)",
    margin: "10px 0 6px",
  };
}

function PFieldRow({ label, subEn, glow, value, half, fullValue, right }) {
  if (half && right) {
    return (
      <div style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: 10, marginBottom: 8 }}>
        <PField label={label} subEn={subEn} value={value} glow={glow} />
        <PField label={right.label} subEn={right.subEn} value={right.value} glow={right.glow} />
      </div>
    );
  }
  return <PField label={label} subEn={subEn} value={fullValue ?? value} glow={glow} full />;
}

function PField({ label, subEn, value, glow, full }) {
  return (
    <div style={{
      padding: "8px 12px", borderRadius: 8,
      background: glow ? "rgba(212,255,79,0.45)" : "transparent",
      border: "1px solid " + (glow ? "rgba(184,230,60,0.7)" : "transparent"),
      transition: "background 0.45s ease, border-color 0.45s ease",
      marginBottom: full ? 8 : 0,
    }}>
      <div style={{ display: "flex", alignItems: "baseline", gap: 6 }}>
        <span style={{
          fontSize: 11, fontWeight: 600, color: "var(--ink)", letterSpacing: "-0.005em",
        }}>{label}</span>
        {subEn && (
          <span style={{ fontSize: 9.5, color: "var(--text-mute)" }}>{subEn}</span>
        )}
      </div>
      <div style={{
        marginTop: 4,
        minHeight: 22,
        padding: "5px 10px",
        background: "white",
        border: "1px solid var(--border-soft)",
        borderRadius: 6,
        fontSize: 12.5, color: value && value !== "—" ? "var(--ink)" : "var(--text-mute)",
        fontWeight: value && value !== "—" ? 500 : 400,
        letterSpacing: "-0.005em",
        lineHeight: 1.4,
        whiteSpace: "pre-wrap",
        wordBreak: "break-word",
      }}>{value || "—"}</div>
    </div>
  );
}

/* ---- Success modal ---- */

function SuccessModal({ success, onClose, onShareChat, onSaveToFiles }) {
  const downloadFile = () => {
    if (!success?.url) return;
    const a = document.createElement("a");
    a.href = success.url;
    a.download = success.filename;
    document.body.appendChild(a);
    a.click();
    a.remove();
  };
  const previewFile = () => {
    if (success?.url) window.open(success.url, "_blank", "noopener");
  };
  return (
    <>
      <div onClick={onClose} style={{
        position: "fixed", inset: 0, background: "rgba(11,27,44,0.45)",
        zIndex: 90,
        animation: "fade-in 0.2s ease both",
      }} />
      <div role="dialog" style={{
        position: "fixed", top: "50%", left: "50%",
        transform: "translate(-50%, -50%)",
        background: "white", borderRadius: 22,
        padding: 28, width: "min(440px, 90vw)",
        zIndex: 91,
        boxShadow: "0 30px 80px rgba(11,27,44,0.30)",
        animation: "fade-up 0.3s cubic-bezier(0.2,0.7,0.2,1) both",
      }}>
        <div style={{
          width: 44, height: 44, borderRadius: 12,
          background: "var(--lime)", color: "var(--ink)",
          display: "inline-flex", alignItems: "center", justifyContent: "center",
          marginBottom: 14,
        }}><i className="ti ti-check" style={{ fontSize: 22 }} /></div>
        <h3 style={{
          fontSize: 18, fontWeight: 600, color: "var(--ink)",
          letterSpacing: "-0.015em",
        }}>{success.kind === "draft" ? "Draft PDF ready." : "Your D-2 application is ready."}</h3>
        <p style={{
          fontSize: 13, color: "var(--text-mute)", lineHeight: 1.55, marginTop: 6,
        }}>
          {success.kind === "draft"
            ? "We added a Draft watermark so you can review the layout before generating the final version."
            : "Check the details before printing or uploading. We saved a copy in your files for safe-keeping."}
        </p>
        <div style={{
          marginTop: 18, display: "flex", flexDirection: "column", gap: 8,
        }}>
          <button onClick={downloadFile} style={primaryBtn()}>
            <i className="ti ti-download" style={{ fontSize: 14 }} />
            Download {success.filename}
          </button>
          {success.url && (
            <button onClick={previewFile} style={outlineBtn()}>
              <i className="ti ti-eye" style={{ fontSize: 14 }} />
              Preview in new tab
            </button>
          )}
          <button onClick={onSaveToFiles} style={outlineBtn()}>
            <i className="ti ti-folder-plus" style={{ fontSize: 14 }} />
            Save to My files
          </button>
          <button onClick={onShareChat} style={ghostShareBtn()}>
            <i className="ti ti-message-circle" style={{ fontSize: 14 }} />
            Share with Korico chat for a final check
          </button>
        </div>
        <button onClick={onClose} style={{
          position: "absolute", top: 14, right: 14,
          width: 32, height: 32, borderRadius: 9,
          background: "var(--bg-soft)", color: "var(--ink)",
          display: "inline-flex", alignItems: "center", justifyContent: "center",
        }}><i className="ti ti-x" style={{ fontSize: 16 }} /></button>
      </div>
    </>
  );
}

function primaryBtn() {
  return {
    display: "inline-flex", alignItems: "center", justifyContent: "center", gap: 10,
    padding: "12px 18px", borderRadius: 99,
    background: "var(--lime)", color: "var(--ink)",
    fontSize: 11, fontWeight: 700, letterSpacing: "0.14em", textTransform: "uppercase",
    boxShadow: "0 10px 22px rgba(184,230,60,0.35)",
    cursor: "pointer",
  };
}
function outlineBtn() {
  return {
    display: "inline-flex", alignItems: "center", justifyContent: "center", gap: 10,
    padding: "12px 18px", borderRadius: 99,
    background: "white", color: "var(--ink)",
    border: "1px solid var(--ink)",
    fontSize: 11, fontWeight: 700, letterSpacing: "0.14em", textTransform: "uppercase",
    cursor: "pointer",
  };
}
function ghostShareBtn() {
  return {
    display: "inline-flex", alignItems: "center", justifyContent: "center", gap: 8,
    padding: "10px 16px", borderRadius: 99,
    background: "transparent", color: "var(--text-mute)",
    fontSize: 12, fontWeight: 500, letterSpacing: "-0.005em",
    cursor: "pointer",
  };
}

/* ============================================================
   FILL WITH KORICO — Foreigner Occupation Report (외국인 직업 신고서)
   ============================================================ */

const OCC_STEPS = [
  { key: "identity",   labels: { ko: "신원 정보",   en: "Identity",         vi: "Thông tin cá nhân" } },
  { key: "occupation", labels: { ko: "직업 분류",   en: "Occupation",       vi: "Nghề nghiệp" } },
  { key: "signature",  labels: { ko: "날짜·서명", en: "Date & signature", vi: "Ngày & chữ ký" } },
];

const OCC_FIELDS = [
  // identity
  { key: "surname",    step: "identity", required: true,
    labels: { ko: "성", en: "Surname", vi: "Họ" },
    placeholder: { ko: "예: NGUYEN", en: "e.g. NGUYEN", vi: "VD: NGUYEN" } },
  { key: "givenName",  step: "identity", required: true,
    labels: { ko: "명", en: "Given name(s)", vi: "Tên" },
    placeholder: { ko: "예: MINH ANH", en: "e.g. MINH ANH", vi: "VD: MINH ANH" } },
  { key: "hanjaName",  step: "identity", required: false,
    labels: { ko: "한자성명 (漢字姓名)", en: "Name in Chinese characters (optional)", vi: "Tên Hán tự (nếu có)" } },
  { key: "dob",        step: "identity", required: true, type: "date",
    labels: { ko: "생년월일", en: "Date of birth", vi: "Ngày sinh" } },
  { key: "sex",        step: "identity", required: true,
    labels: { ko: "성별", en: "Sex", vi: "Giới tính" },
    select: [
      { v: "M", ko: "남", en: "Male",   vi: "Nam" },
      { v: "F", ko: "여", en: "Female", vi: "Nữ" },
    ],
  },
  { key: "nationality", step: "identity", required: true,
    labels: { ko: "국적", en: "Nationality / others", vi: "Quốc tịch" },
    placeholder: { ko: "예: 베트남", en: "e.g. Vietnam", vi: "VD: Việt Nam" } },
  { key: "arcNo",       step: "identity", required: false,
    labels: { ko: "외국인등록번호 (있는 경우)", en: "ARC No. (if any)", vi: "Số ARC (nếu có)" },
    placeholder: { ko: "예: 020514-6XXXXXX", en: "e.g. 020514-6XXXXXX", vi: "VD: 020514-6XXXXXX" } },

  // occupation
  { key: "occupationText", step: "occupation", required: true,
    labels: { ko: "현재 직업 (직접 기재)", en: "Current occupation (free text)", vi: "Nghề nghiệp hiện tại" },
    placeholder: { ko: "예: 소프트웨어 엔지니어", en: "e.g. Software engineer", vi: "VD: Kỹ sư phần mềm" } },
  { key: "categoryMain", step: "occupation", required: true,
    labels: { ko: "직업 분류 (대분류)", en: "Occupation category (top level)", vi: "Phân loại nghề (cấp 1)" },
    select: OCC_CAT_TOP(),
  },
  { key: "categorySub", step: "occupation", required: true,
    labels: { ko: "직업 분류 (소분류)", en: "Occupation sub-category", vi: "Phân loại nghề (cấp 2)" },
    dependsOn: "categoryMain",
  },

  // signature
  { key: "dateOfApplication", step: "signature", required: true, type: "date",
    labels: { ko: "신청일", en: "Date of application", vi: "Ngày nộp đơn" } },
  { key: "signature", step: "signature", required: true,
    labels: { ko: "신청인 (서명 또는 인)", en: "Applicant signature (typed name)", vi: "Chữ ký người nộp đơn (gõ tên)" },
    placeholder: { ko: "이름을 입력해 서명을 대신합니다.", en: "Type your full name as signature.", vi: "Gõ họ tên đầy đủ làm chữ ký." } },
  { key: "proxyName", step: "signature", required: false,
    labels: { ko: "대리인 (있는 경우)", en: "Proxy name (if any)", vi: "Người được uỷ quyền (nếu có)" } },
];

function OCC_CAT_TOP() {
  return [
    { v: "0", ko: "0. 무직",                              en: "0. No occupation",                       vi: "0. Không nghề" },
    { v: "1", ko: "1. 관리자",                            en: "1. Managers",                            vi: "1. Quản lý" },
    { v: "2", ko: "2. 전문가 및 관련 종사자",            en: "2. Professionals & related workers",      vi: "2. Chuyên gia" },
    { v: "3", ko: "3. 사무 종사자",                       en: "3. Clerks",                              vi: "3. Văn phòng" },
    { v: "4", ko: "4. 서비스 종사자",                     en: "4. Service workers",                     vi: "4. Dịch vụ" },
    { v: "5", ko: "5. 판매 종사자",                       en: "5. Sales workers",                       vi: "5. Bán hàng" },
    { v: "6", ko: "6. 농림·어업 숙련 종사자",            en: "6. Skilled agriculture, forestry, fishery", vi: "6. Nông-lâm-ngư" },
    { v: "7", ko: "7. 기능원 및 관련 기능 종사자",       en: "7. Craft and related trades",            vi: "7. Thợ kỹ thuật" },
    { v: "8", ko: "8. 장치·기계 조작 및 조립 종사자",   en: "8. Equipment, machine operating",        vi: "8. Vận hành máy móc" },
    { v: "9", ko: "9. 단순노무 종사자",                   en: "9. Elementary workers",                  vi: "9. Lao động phổ thông" },
  ];
}

const OCC_SUBCATS = {
  "0": [{ v: "0-0", ko: "무직", en: "No occupation" }],
  "1": [
    { v: "1-1", ko: "공공 기관 및 기업 고위직", en: "Senior public officials and corporate officials" },
    { v: "1-2", ko: "행정·경영 지원 및 마케팅 관리직", en: "Public, business administration, marketing management" },
    { v: "1-3", ko: "전문 서비스 관리직", en: "Professional services management" },
    { v: "1-4", ko: "건설·전기 및 생산 관련 관리직", en: "Construction, electricity, production-related managers" },
    { v: "1-5", ko: "판매 및 고객 서비스 관리직", en: "Sales and customer service managers" },
  ],
  "2": [
    { v: "2-1", ko: "과학 전문가 및 관련직", en: "Science professionals and related" },
    { v: "2-2", ko: "정보 통신 전문가 및 기술직", en: "Information and communication professionals" },
    { v: "2-3", ko: "공학 전문가 및 기술직", en: "Engineering professionals and technical" },
    { v: "2-4", ko: "보건·사회복지 및 종교 관련직", en: "Health, social welfare and religion related" },
    { v: "2-5", ko: "교육 전문가 및 관련직", en: "Education professionals and related" },
    { v: "2-6", ko: "법률 및 행정 전문직", en: "Legal and administrative professionals" },
    { v: "2-7", ko: "경영·금융 전문가 및 관련직", en: "Business and finance professionals" },
    { v: "2-8", ko: "문화·예술·스포츠 전문가 및 관련직", en: "Culture, arts and sports professionals" },
  ],
  "3": [
    { v: "3-1", ko: "경영 및 회계 관련 사무직", en: "Administration and accounting clerical" },
    { v: "3-2", ko: "금융 사무직", en: "Financial clerical" },
    { v: "3-3", ko: "법률 및 감사 사무직", en: "Legal and inspection clerical" },
    { v: "3-4", ko: "상담·안내·통계 및 기타 사무직", en: "Customer service, info desk, statistical clerical" },
  ],
  "4": [
    { v: "4-1", ko: "경찰·소방 및 보안 관련 서비스직", en: "Police, fire fighting and security service" },
    { v: "4-2", ko: "돌봄·보건 및 개인 생활 서비스직", en: "Caregiving, health and personal service" },
    { v: "4-3", ko: "운송 및 여가 서비스직", en: "Transport and leisure services" },
    { v: "4-4", ko: "조리 및 음식 서비스직", en: "Cooking and food service" },
  ],
  "5": [
    { v: "5-1", ko: "영업직", en: "Sales occupations" },
    { v: "5-2", ko: "매장 판매 및 상품 대여직", en: "Store sales and rental sales" },
    { v: "5-3", ko: "통신 및 방문·노점 판매 관련직", en: "Mobile, door-to-door and street sales" },
  ],
  "6": [
    { v: "6-1", ko: "농·축산 숙련직", en: "Agricultural and livestock skilled" },
    { v: "6-2", ko: "임업 숙련직", en: "Skilled forestry" },
    { v: "6-3", ko: "어업 숙련직", en: "Skilled fishery" },
  ],
  "7": [
    { v: "7-1", ko: "식품가공 관련 기능직", en: "Food processing trades" },
    { v: "7-2", ko: "섬유·의복 및 가죽 관련 기능직", en: "Textile, clothing and leather trades" },
    { v: "7-3", ko: "목재·가구·악기 및 간판 관련 기능직", en: "Wood, furniture, instruments, signs trades" },
    { v: "7-4", ko: "금속 성형 관련 기능직", en: "Metal coremakers and related" },
    { v: "7-5", ko: "운송 및 기계 관련 기능직", en: "Transport and machine trades" },
    { v: "7-6", ko: "전기 및 전자 관련 기능직", en: "Electric and electronic trades" },
    { v: "7-7", ko: "정보 통신 및 방송장비 관련 기능직", en: "ICT and broadcast equipment trades" },
    { v: "7-8", ko: "건설 및 채굴 관련 기능직", en: "Construction and mining trades" },
    { v: "7-9", ko: "기타 기능 관련직", en: "Other technical occupations" },
  ],
  "8": [
    { v: "8-1", ko: "식품가공 관련 기계 조작직", en: "Food processing machine operating" },
    { v: "8-2", ko: "섬유 및 신발 관련 기계 조작직", en: "Textile and shoe machine operating" },
    { v: "8-3", ko: "화학 관련 기계 조작직", en: "Chemical machine operating" },
    { v: "8-4", ko: "금속 및 비금속 관련 기계 조작직", en: "Metal and nonmetal machine operating" },
    { v: "8-5", ko: "기계 제조 및 관련 기계 조작직", en: "Machine production and operating" },
    { v: "8-6", ko: "전기 및 전자 관련 기계 조작직", en: "Electrical and electronic machine operating" },
    { v: "8-7", ko: "운전 및 운송 관련직", en: "Driving and transport related" },
    { v: "8-8", ko: "상하수도 및 재활용 처리 관련 기계 조작직", en: "Water and recycling operating" },
    { v: "8-9", ko: "목재·인쇄 및 기타 기계 조작직", en: "Wood, printing and other machine operating" },
  ],
  "9": [
    { v: "9-1", ko: "건설 및 광업 관련 단순 노무직", en: "Construction and mining elementary" },
    { v: "9-2", ko: "운송 관련 단순 노무직", en: "Transport elementary" },
    { v: "9-3", ko: "제조 관련 단순 노무직", en: "Production elementary" },
    { v: "9-4", ko: "청소 및 경비 관련 단순 노무직", en: "Cleaning and guard elementary" },
    { v: "9-5", ko: "가사·음식 및 판매 관련 단순 노무직", en: "Household, cooking, sales elementary" },
    { v: "9-6", ko: "농림·어업 및 기타 서비스 단순 노무직", en: "Agriculture, fishery, other elementary" },
  ],
};

const DEFAULT_OCC_VALUES = {
  surname: "NGUYEN",
  givenName: "MINH ANH",
  hanjaName: "",
  dob: "2002-05-14",
  sex: "F",
  nationality: "Vietnam",
  arcNo: "020514-6XXXXXX",
  occupationText: "Software engineer (intern)",
  categoryMain: "2",
  categorySub: "2-2",
  dateOfApplication: new Date().toISOString().slice(0, 10),
  signature: "",
  proxyName: "",
};

function FillOccupationPage({ onNavigate, formsState }) {
  const { flash } = formsState;
  const [lang, setLang] = useState("en");
  const [step, setStep] = useState(0);
  const [values, setValues] = useState(DEFAULT_OCC_VALUES);
  const [touched, setTouched] = useState({});
  const [consent, setConsent] = useState(false);
  const [savedFlag, setSavedFlag] = useState("All changes saved");
  const [glow, setGlow] = useState(null);
  const [confirmingClear, setConfirmingClear] = useState(false);
  const [success, setSuccess] = useState(null);
  const fieldRefs = useRef({});

  useEffect(() => {
    if (Object.keys(touched).length === 0) return;
    setSavedFlag("Saving…");
    const t = setTimeout(() => setSavedFlag("All changes saved"), 700);
    return () => clearTimeout(t);
  }, [values]);

  const onChange = (key, v) => {
    setValues((prev) => {
      const next = { ...prev, [key]: v };
      if (key === "categoryMain") next.categorySub = ""; // reset sub when main changes
      return next;
    });
    setTouched((prev) => ({ ...prev, [key]: true }));
    setGlow(key);
    setTimeout(() => setGlow((g) => (g === key ? null : g)), 600);
  };

  // Build field list per step. Inject subcategory options based on categoryMain.
  const renderFields = OCC_FIELDS.filter((f) => f.step === OCC_STEPS[step].key).map((f) => {
    if (f.key === "categorySub") {
      const main = values.categoryMain;
      const opts = (OCC_SUBCATS[main] || []).map((o) => ({
        v: o.v, ko: o.ko, en: o.en, vi: o.en, // English fallback for Vietnamese
      }));
      return { ...f, select: opts.length ? opts : [{ v: "", ko: "—", en: "Pick a top-level category first" }] };
    }
    return f;
  });

  const requiredKeys = OCC_FIELDS.filter((f) => f.required).map((f) => f.key);
  const missing = requiredKeys.filter((k) => !values[k] || String(values[k]).trim() === "");
  const completion = Math.round(((requiredKeys.length - missing.length) / requiredKeys.length) * 100);
  const allRequiredFilled = missing.length === 0;

  const tryGenerate = async (draft = false) => {
    if (!draft) {
      if (!allRequiredFilled || !consent) {
        const first = missing[0];
        if (first) {
          const f = OCC_FIELDS.find((x) => x.key === first);
          if (f) {
            const idx = OCC_STEPS.findIndex((s) => s.key === f.step);
            if (idx >= 0) setStep(idx);
            setTimeout(() => {
              const el = fieldRefs.current[first];
              el?.scrollIntoView({ behavior: "smooth", block: "center" });
              el?.focus?.();
              setGlow(first);
              setTimeout(() => setGlow(null), 900);
            }, 50);
          }
          flash("Some required fields are missing. We've scrolled to the first one.");
          return;
        }
        if (!consent) { flash("Please confirm the data notice before generating."); return; }
      }
    }
    try {
      const blob = await fillOccupationPdf(values, { draft });
      const url  = URL.createObjectURL(blob);
      const filename = draft ? "occupation-report-draft.pdf" : "occupation-report.pdf";
      setSuccess({ kind: draft ? "draft" : "final", filename, url, blob });
    } catch (err) {
      console.error("[occupation pdf]", err);
      flash("PDF generation failed: " + (err?.message || "unknown error") + ". Your answers are saved.");
    }
  };

  const clearAll = () => {
    setValues(Object.fromEntries(Object.keys(DEFAULT_OCC_VALUES).map((k) => [k, ""])));
    setTouched({});
    setConsent(false);
    setConfirmingClear(false);
    flash("All answers cleared.");
  };

  return (
    <div style={{
      display: "flex", flexDirection: "column",
      minHeight: "100vh",
      background: "var(--bg-canvas)",
    }}>
      {/* STICKY HEADER */}
      <header style={{
        position: "sticky", top: 0, zIndex: 30,
        background: "rgba(255,255,255,0.92)",
        backdropFilter: "saturate(180%) blur(12px)",
        WebkitBackdropFilter: "saturate(180%) blur(12px)",
        borderBottom: "1px solid var(--border-soft)",
        padding: "16px clamp(20px, 4vw, 40px)",
      }}>
        <div style={{
          display: "grid", gridTemplateColumns: "1.2fr 1.4fr 1fr", gap: 18,
          alignItems: "center", maxWidth: 1400, margin: "0 auto",
        }} className="fd2-head-grid">
          <div style={{ minWidth: 0 }}>
            <div style={{
              display: "flex", alignItems: "center", gap: 6,
              fontSize: 11, color: "var(--text-mute)", marginBottom: 4, flexWrap: "wrap",
            }}>
              <button onClick={() => onNavigate("forms")} style={{ color: "inherit" }}>Forms &amp; templates</button>
              <i className="ti ti-chevron-right" style={{ fontSize: 11 }} />
              <span>Occupation Report</span>
              <i className="ti ti-chevron-right" style={{ fontSize: 11 }} />
              <span style={{ color: "var(--ink)", fontWeight: 500 }}>Fill with Korico</span>
            </div>
            <h1 style={{
              fontSize: 18, fontWeight: 600, color: "var(--ink)",
              letterSpacing: "-0.015em",
            }}>외국인 직업 신고서 · Foreigner Occupation Report</h1>
            <p style={{ fontSize: 11.5, color: "var(--text-mute)", marginTop: 3, lineHeight: 1.4 }}>
              Answer in your language. Korico maps it to the official Korean report form.
            </p>
          </div>

          <div>
            <div style={{
              display: "flex", alignItems: "center", justifyContent: "space-between",
              fontSize: 10.5, color: "var(--text-mute)",
              fontWeight: 600, letterSpacing: "0.12em", textTransform: "uppercase",
              marginBottom: 6,
            }}>
              <span>Step {step + 1} of {OCC_STEPS.length} · {OCC_STEPS[step].labels[lang]}</span>
              <span style={{ color: "var(--ink)" }}>{completion}%</span>
            </div>
            <div style={{ display: "flex", gap: 6 }}>
              {OCC_STEPS.map((s, i) => {
                const done = i < step;
                const current = i === step;
                return (
                  <button key={s.key} onClick={() => setStep(i)} style={{
                    flex: 1, padding: "8px 8px", borderRadius: 99,
                    background: current ? "var(--ink)" : done ? "rgba(184,230,60,0.45)" : "var(--bg-soft)",
                    color: current ? "var(--lime)" : "var(--ink)",
                    fontSize: 11, fontWeight: 600, letterSpacing: "-0.005em",
                    transition: "background 0.2s ease, color 0.2s ease",
                  }}>{i + 1}. {s.labels[lang]}</button>
                );
              })}
            </div>
            <div style={{
              height: 4, borderRadius: 99, background: "var(--bg-soft)",
              marginTop: 6, overflow: "hidden",
            }}>
              <div style={{
                width: `${completion}%`, height: "100%",
                background: "linear-gradient(90deg, var(--lime), var(--lime-deep))",
                borderRadius: 99,
                transition: "width 0.45s cubic-bezier(0.2,0.7,0.2,1)",
              }} />
            </div>
          </div>

          <div style={{ display: "flex", flexDirection: "column", alignItems: "flex-end", gap: 6 }}>
            <div style={{
              fontSize: 10, fontWeight: 600, color: "var(--text-mute)",
              letterSpacing: "0.12em", textTransform: "uppercase",
            }}>Answer language</div>
            <div style={{
              display: "inline-flex",
              background: "var(--bg-soft)",
              borderRadius: 99, padding: 3,
            }}>
              {LANGS.map((l) => {
                const on = lang === l.code;
                return (
                  <button key={l.code} onClick={() => setLang(l.code)} style={{
                    padding: "6px 12px", borderRadius: 99,
                    background: on ? "var(--ink)" : "transparent",
                    color: on ? "var(--lime)" : "var(--ink)",
                    fontSize: 11.5, fontWeight: 600, letterSpacing: "-0.005em",
                    transition: "all 0.18s ease",
                  }}>{l.label}</button>
                );
              })}
            </div>
          </div>
        </div>
      </header>

      {/* WORKSPACE */}
      <div style={{
        flex: 1, display: "grid",
        gridTemplateColumns: "1.2fr 1fr", gap: 18,
        maxWidth: 1400, margin: "0 auto",
        padding: "24px clamp(20px, 4vw, 40px) 110px",
        width: "100%",
      }} className="fd2-grid">

        {/* HELPER FORM */}
        <section style={{
          background: "white", border: "1px solid var(--border-soft)",
          borderRadius: 20, padding: "22px 24px",
          animation: "fade-up 0.5s cubic-bezier(0.2,0.7,0.2,1) both",
        }}>
          <header style={{ marginBottom: 14 }}>
            <div style={{
              fontSize: 10, fontWeight: 600, color: "var(--text-mute)",
              letterSpacing: "0.18em", textTransform: "uppercase",
            }}>Korico helper form</div>
            <h2 style={{
              fontSize: 18, fontWeight: 600, color: "var(--ink)",
              letterSpacing: "-0.015em", marginTop: 4,
            }}>{OCC_STEPS[step].labels[lang]}</h2>
            <p style={{ fontSize: 12, color: "var(--text-mute)", marginTop: 4 }}>
              Fields marked <strong style={{ color: "var(--ink)" }}>*</strong> are required.
            </p>
          </header>

          <div style={{ display: "flex", flexDirection: "column", gap: 14 }}>
            {renderFields.map((f) => {
              const isMissing = f.required && (!values[f.key] || String(values[f.key]).trim() === "") && touched[f.key];
              const labelLang = f.labels[lang] || f.labels.en;
              return (
                <label key={f.key} style={{ display: "flex", flexDirection: "column", gap: 5 }}>
                  <span style={{ display: "flex", alignItems: "baseline", gap: 8, flexWrap: "wrap" }}>
                    <span style={{
                      fontSize: 12.5, fontWeight: 600, color: "var(--ink)",
                      letterSpacing: "-0.005em",
                    }}>
                      {labelLang}{f.required && <span style={{ color: "var(--danger)" }}> *</span>}
                    </span>
                    {lang !== "ko" && (
                      <span style={{ fontSize: 11, color: "var(--text-mute)" }}>{f.labels.ko}</span>
                    )}
                  </span>
                  <D2Input
                    field={f}
                    value={values[f.key]}
                    lang={lang}
                    onChange={(v) => onChange(f.key, v)}
                    inputRef={(el) => (fieldRefs.current[f.key] = el)}
                    invalid={isMissing}
                  />
                  {isMissing && (
                    <span style={{ fontSize: 11, color: "var(--danger)" }}>This field is required.</span>
                  )}
                </label>
              );
            })}
          </div>

          {/* Step nav */}
          <div style={{
            display: "flex", justifyContent: "space-between",
            marginTop: 24, paddingTop: 16, borderTop: "1px solid var(--border-soft)",
          }}>
            <button onClick={() => setStep((s) => Math.max(0, s - 1))} disabled={step === 0} style={stepBtn(false, step === 0)}>
              <i className="ti ti-arrow-left" style={{ fontSize: 13 }} /> Back
            </button>
            {step < OCC_STEPS.length - 1 ? (
              <button onClick={() => setStep((s) => Math.min(OCC_STEPS.length - 1, s + 1))} style={stepBtn(true)}>
                Next <i className="ti ti-arrow-right" style={{ fontSize: 13 }} />
              </button>
            ) : (
              <span style={{ fontSize: 11.5, color: "var(--text-mute)" }}>
                You're at the last step — review the preview on the right.
              </span>
            )}
          </div>

          {/* Consent */}
          <div style={{
            marginTop: 28, padding: 18, borderRadius: 14,
            background: "var(--bg-soft)", border: "1px solid var(--border-soft)",
          }}>
            <div style={{
              fontSize: 10, fontWeight: 600, color: "var(--text-mute)",
              letterSpacing: "0.18em", textTransform: "uppercase",
            }}>Data &amp; personal information</div>
            <p style={{
              fontSize: 12.5, color: "var(--text-soft)", lineHeight: 1.6,
              marginTop: 6,
            }}>
              Korico stores your answers only to generate this form and keep your own records. Confirm the latest immigration rules at HiKorea before filing.
            </p>
            <label style={{
              display: "flex", alignItems: "center", gap: 10,
              marginTop: 10, cursor: "pointer",
            }}>
              <input type="checkbox" checked={consent} onChange={(e) => setConsent(e.target.checked)} style={{ display: "none" }} />
              <span style={{
                width: 18, height: 18, borderRadius: 5,
                background: consent ? "var(--ink)" : "white",
                border: consent ? "none" : "1.5px solid var(--border)",
                display: "inline-flex", alignItems: "center", justifyContent: "center",
                color: "var(--lime)", flexShrink: 0,
              }}>{consent && <i className="ti ti-check" style={{ fontSize: 12 }} />}</span>
              <span style={{ fontSize: 12.5, color: "var(--ink)", fontWeight: 500 }}>
                I understand that Korico stores this information only to generate my form and my own records. I will check the latest requirements with immigration.
              </span>
            </label>
          </div>
        </section>

        {/* PREVIEW */}
        <section style={{
          background: "white", border: "1px solid var(--border-soft)",
          borderRadius: 20, padding: "22px 24px",
          animation: "fade-up 0.55s cubic-bezier(0.2,0.7,0.2,1) both",
          animationDelay: "0.05s",
          position: "sticky", top: 200, alignSelf: "start",
          maxHeight: "calc(100vh - 240px)",
          display: "flex", flexDirection: "column",
        }}>
          <header style={{
            display: "flex", justifyContent: "space-between", alignItems: "flex-start",
            gap: 10, marginBottom: 14, flexWrap: "wrap",
          }}>
            <div>
              <div style={{
                fontSize: 10, fontWeight: 600, color: "var(--text-mute)",
                letterSpacing: "0.18em", textTransform: "uppercase",
              }}>Official form preview</div>
              <h2 style={{
                fontSize: 16, fontWeight: 600, color: "var(--ink)",
                letterSpacing: "-0.015em", marginTop: 4,
              }}>외국인 직업 신고서</h2>
              <p style={{ fontSize: 11.5, color: "var(--text-mute)", marginTop: 3, lineHeight: 1.4, maxWidth: 360 }}>
                FOREIGNER OCCUPATION REPORT FORM — preview only.
              </p>
            </div>
            <a href="https://www.hikorea.go.kr/board/BoardApplicationListR.pt" target="_blank" rel="noreferrer" style={{
              display: "inline-flex", alignItems: "center", gap: 6,
              padding: "7px 12px", borderRadius: 99,
              background: "var(--bg-soft)", color: "var(--ink)",
              border: "1px solid var(--border)",
              fontSize: 10.5, fontWeight: 600, letterSpacing: "0.08em",
              textDecoration: "none",
            }}>
              <i className="ti ti-external-link" style={{ fontSize: 12 }} />
              Original blank form
            </a>
          </header>

          <div style={{
            flex: 1, overflowY: "auto",
            padding: "18px 18px 22px",
            borderRadius: 14,
            background: "linear-gradient(180deg, #FCFCFD 0%, #F4F4F6 100%)",
            border: "1px solid var(--border-soft)",
          }}>
            <OccupationFormPreview values={values} glow={glow} />
          </div>
        </section>
      </div>

      {/* STICKY FOOTER */}
      <footer style={{
        position: "sticky", bottom: 0, zIndex: 25,
        background: "rgba(255,255,255,0.95)",
        backdropFilter: "saturate(180%) blur(12px)",
        WebkitBackdropFilter: "saturate(180%) blur(12px)",
        borderTop: "1px solid var(--border-soft)",
        padding: "12px clamp(20px, 4vw, 40px)",
      }}>
        <div style={{
          maxWidth: 1400, margin: "0 auto",
          display: "flex", justifyContent: "space-between", alignItems: "center",
          gap: 12, flexWrap: "wrap",
        }}>
          <div style={{ display: "flex", alignItems: "center", gap: 14 }}>
            <span style={{
              display: "inline-flex", alignItems: "center", gap: 6,
              fontSize: 12, color: savedFlag === "Saving…" ? "var(--text-mute)" : "var(--success)",
              fontWeight: 500,
            }}>
              <span style={{
                width: 7, height: 7, borderRadius: "50%",
                background: savedFlag === "Saving…" ? "var(--text-mute)" : "var(--success)",
              }} />
              {savedFlag}
            </span>
            {confirmingClear ? (
              <span style={{ fontSize: 12, color: "var(--ink)" }}>
                Sure?
                <button onClick={clearAll} style={ghostBtn("var(--danger)")}>Clear all</button>
                <button onClick={() => setConfirmingClear(false)} style={ghostBtn("var(--text-mute)")}>Cancel</button>
              </span>
            ) : (
              <button onClick={() => setConfirmingClear(true)} style={{
                fontSize: 11.5, color: "var(--text-mute)", fontWeight: 500,
                textDecoration: "underline", textUnderlineOffset: 3,
                textDecorationColor: "var(--border)",
              }}>Clear all answers</button>
            )}
          </div>
          <div style={{ display: "flex", gap: 10, flexWrap: "wrap" }}>
            <button onClick={() => tryGenerate(true)} style={{
              padding: "11px 18px", borderRadius: 99,
              background: "white", color: "var(--ink)",
              border: "1px solid var(--ink)",
              fontSize: 11, fontWeight: 700, letterSpacing: "0.14em", textTransform: "uppercase",
            }}>
              <i className="ti ti-file-download" style={{ fontSize: 13, marginRight: 6, verticalAlign: -1 }} />
              Download draft PDF
            </button>
            <button onClick={() => tryGenerate(false)}
              disabled={!allRequiredFilled || !consent}
              style={{
                display: "inline-flex", alignItems: "center", gap: 8,
                padding: "11px 22px", borderRadius: 99,
                background: !allRequiredFilled || !consent ? "var(--bg-soft)" : "var(--lime)",
                color: !allRequiredFilled || !consent ? "var(--text-mute)" : "var(--ink)",
                fontSize: 11, fontWeight: 700, letterSpacing: "0.14em", textTransform: "uppercase",
                boxShadow: !allRequiredFilled || !consent ? "none" : "0 10px 22px rgba(184,230,60,0.35)",
                cursor: !allRequiredFilled || !consent ? "not-allowed" : "pointer",
                transition: "all 0.18s ease",
              }}>
              Generate final PDF
              <span style={{
                width: 20, height: 20, borderRadius: "50%",
                background: "var(--ink)", color: "var(--lime)",
                display: "inline-flex", alignItems: "center", justifyContent: "center",
              }}><i className="ti ti-arrow-up-right" style={{ fontSize: 11 }} /></span>
            </button>
          </div>
        </div>
      </footer>

      {/* SUCCESS MODAL */}
      {success && (
        <SuccessModal
          success={success}
          onClose={() => setSuccess(null)}
          onShareChat={() => {
            window.dispatchEvent(new CustomEvent("korico:ask", {
              detail: { prefill: "I generated my Foreigner Occupation Report. Could you double-check the occupation classification?" },
            }));
            setSuccess(null);
          }}
          onSaveToFiles={() => {
            flash("Saved to My files · " + (success.filename || "occupation-report.pdf"));
            setSuccess(null);
          }}
        />
      )}
    </div>
  );
}

/* ---- Real PDF generation (occupation form) ---- */

let _occupationCoords = null;
async function loadOccupationCoords() {
  if (_occupationCoords) return _occupationCoords;
  const res = await fetch("src/forms/occupation.coords.json", { cache: "force-cache" });
  if (!res.ok) throw new Error("coords.json not found (" + res.status + ")");
  _occupationCoords = await res.json();
  return _occupationCoords;
}

let _fontBytes = null;
async function loadKoreanFontBytes(url) {
  if (_fontBytes) return _fontBytes;
  const fullUrl = "src/" + url.split("/").map(encodeURIComponent).join("/");
  const res = await fetch(fullUrl, { cache: "force-cache" });
  if (!res.ok) throw new Error("font not found at " + fullUrl);
  _fontBytes = await res.arrayBuffer();
  return _fontBytes;
}

async function fillOccupationPdf(values, { draft } = {}) {
  if (!window.PDFLib || !window.fontkit) {
    throw new Error("PDF libraries not loaded yet");
  }
  const { PDFDocument, rgb, degrees } = window.PDFLib;

  const coords = await loadOccupationCoords();

  // 1) Source PDF — encode each path segment so Korean filename works
  const pdfUrl = "src/" + coords.pdfPath.split("/").map(encodeURIComponent).join("/");
  const pdfRes = await fetch(pdfUrl, { cache: "force-cache" });
  if (!pdfRes.ok) throw new Error("source PDF not found at " + pdfUrl);
  const pdfBytes = await pdfRes.arrayBuffer();

  // 2) Load + register fontkit
  const pdf = await PDFDocument.load(pdfBytes);
  pdf.registerFontkit(window.fontkit);

  // 3) Embed Korean font. subset:false avoids dropped CJK glyphs with NanumGothic.
  const fontBytes = await loadKoreanFontBytes(coords.fontUrl);
  const font = await pdf.embedFont(fontBytes, { subset: false });

  const pages = pdf.getPages();
  const draw = (text, spec) => {
    if (!text || text === "—") return;
    const page = pages[(spec.page || 1) - 1];
    if (!page) return;
    const size = spec.size || coords.defaults?.size || 10;
    page.drawText(String(text), {
      x: spec.x, y: spec.y, size, font,
      color: rgb(0, 0, 0),
      maxWidth: spec.maxW || undefined,
      lineHeight: size * 1.2,
    });
  };

  // 4) Stamp text fields
  const f = coords.fields;
  draw(values.surname,    f.surname);
  draw(values.givenName,  f.givenName);
  draw(values.hanjaName,  f.hanjaName);
  draw(values.dob,        f.dob);
  draw(values.nationality, f.nationality);
  draw(values.arcNo,      f.arcNo);
  draw(values.occupationText, f.occupationText);
  draw(values.dateOfApplication, f.dateOfApplication);
  draw(values.signature,  f.signature);
  draw(values.proxyName,  f.proxyName);

  // 5) Tick boxes: sex + occupation classification (V mark inside □)
  const check = (spec) => {
    if (!spec) return;
    const page = pages[(spec.page || 1) - 1];
    if (!page) return;
    page.drawText("V", {
      x: spec.x, y: spec.y, size: 11, font,
      color: rgb(0, 0, 0),
    });
  };

  if (values.sex && coords.sexChecks?.[values.sex]) {
    check(coords.sexChecks[values.sex]);
  }
  if (values.categorySub) check(coords.checks[values.categorySub]);
  if (values.categoryMain === "0" && !values.categorySub) check(coords.checks["0-0"]);

  // 6) Draft watermark
  if (draft) {
    const first = pages[0];
    const { width, height } = first.getSize();
    first.drawText("DRAFT", {
      x: width / 2 - 120, y: height / 2 - 40,
      size: 110, font,
      color: rgb(0.85, 0.85, 0.85),
      rotate: degrees(-30),
      opacity: 0.35,
    });
  }

  const out = await pdf.save();
  return new Blob([out], { type: "application/pdf" });
}

/* ---- Occupation form preview ---- */

function OccupationFormPreview({ values, glow }) {
  const top = OCC_CAT_TOP().find((o) => o.v === values.categoryMain);
  const sub = (OCC_SUBCATS[values.categoryMain] || []).find((o) => o.v === values.categorySub);
  const sexLabel = values.sex === "M" ? "남 (Male)" : values.sex === "F" ? "여 (Female)" : "—";

  return (
    <div style={{
      background: "white",
      borderRadius: 10,
      padding: "20px 22px 22px",
      fontFamily: "'Noto Sans KR', var(--font-body)",
      color: "#1A1A1F",
      boxShadow: "0 1px 0 var(--border-soft)",
    }}>
      <h3 style={{
        textAlign: "center", fontSize: 18, fontWeight: 700, letterSpacing: "-0.01em",
        color: "var(--ink)",
      }}>외국인 직업 신고서</h3>
      <div style={{
        textAlign: "center", fontSize: 11, color: "var(--text-mute)",
        marginTop: 2, marginBottom: 16,
      }}>FOREIGNER OCCUPATION REPORT FORM</div>

      <div style={{
        padding: "9px 12px", borderRadius: 8,
        background: "rgba(11,27,44,0.04)",
        fontSize: 11, color: "var(--text-soft)", lineHeight: 1.5, marginBottom: 14,
      }}>
        <strong style={{ color: "var(--ink)" }}>신청서 작성방법</strong> · &lt;직업&gt;은 본인의 현재 직업을 직접 기재하고, 직업분류표에서 해당 항목의 □안에 V표시합니다.
      </div>

      <PFieldRow label="성" subEn="Surname" glow={glow === "surname"} value={values.surname} half
                 right={{ label: "명", subEn: "Given names", glow: glow === "givenName", value: values.givenName }} />
      <PFieldRow label="漢字姓名" subEn="Name in Chinese characters" glow={glow === "hanjaName"} value={values.hanjaName || "—"} />
      <PFieldRow label="생년월일" subEn="Date of birth" glow={glow === "dob"} value={values.dob} half
                 right={{ label: "성별", subEn: "Sex", glow: glow === "sex", value: sexLabel }} />
      <PFieldRow label="국적" subEn="Nationality / others" glow={glow === "nationality"} value={values.nationality} half
                 right={{ label: "외국인등록번호", subEn: "ARC No. (if any)", glow: glow === "arcNo", value: values.arcNo || "—" }} />
      <div style={dividerStyle()} />

      <PFieldRow label="직업 / OCCUPATION" subEn="Free text" glow={glow === "occupationText"} value={values.occupationText} />

      <div style={{
        padding: "10px 12px", borderRadius: 8,
        background: (glow === "categoryMain" || glow === "categorySub") ? "rgba(212,255,79,0.45)" : "var(--bg-soft)",
        border: "1px solid " + ((glow === "categoryMain" || glow === "categorySub") ? "rgba(184,230,60,0.7)" : "transparent"),
        transition: "background 0.45s ease, border-color 0.45s ease",
        marginBottom: 8,
      }}>
        <div style={{ fontSize: 11, fontWeight: 600, color: "var(--ink)" }}>직업분류표</div>
        <div style={{ fontSize: 9.5, color: "var(--text-mute)" }}>Classification list</div>
        <div style={{
          marginTop: 6, padding: "8px 10px",
          background: "white", borderRadius: 6, border: "1px solid var(--border-soft)",
          fontSize: 12, color: top ? "var(--ink)" : "var(--text-mute)",
          fontWeight: top ? 500 : 400,
        }}>
          {top ? `[V] ${top.ko}` : "—"}
        </div>
        <div style={{
          marginTop: 6, padding: "8px 10px",
          background: "white", borderRadius: 6, border: "1px solid var(--border-soft)",
          fontSize: 12, color: sub ? "var(--ink)" : "var(--text-mute)",
          fontWeight: sub ? 500 : 400,
        }}>
          {sub ? `[V] ${sub.ko}` : "—"}
        </div>
      </div>

      <div style={dividerStyle()} />

      <div style={{
        padding: "9px 12px", borderRadius: 8,
        background: "rgba(11,27,44,0.04)",
        fontSize: 10.5, color: "var(--text-soft)", lineHeight: 1.5, marginBottom: 10,
      }}>
        「출입국관리법 시행규칙」 제47조, 제49조의2, 제76조에 따라 위와 같이 신고합니다.
      </div>

      <PFieldRow label="신청일" subEn="Date of application" glow={glow === "dateOfApplication"} value={values.dateOfApplication} half
                 right={{ label: "신청인", subEn: "Applicant (signature/seal)", glow: glow === "signature", value: values.signature || "(서명 필요)" }} />
      {values.proxyName && (
        <PFieldRow label="대리인" subEn="By proxy" glow={glow === "proxyName"} value={values.proxyName} />
      )}
    </div>
  );
}

/* ============================================================
   SHARED PRIMITIVES
   ============================================================ */

function SurfaceCard({ children, style }) {
  return (
    <section style={{
      background: "white",
      border: "1px solid var(--border-soft)",
      borderRadius: "var(--r-card)",
      padding: "clamp(18px, 2.4vh, 26px)",
      boxShadow: "var(--shadow-sm)",
      transition: "transform 0.22s ease, box-shadow 0.22s ease",
      ...style,
    }}
      onMouseEnter={(e) => { e.currentTarget.style.boxShadow = "var(--shadow-md)"; }}
      onMouseLeave={(e) => {
        if (!style?.boxShadow) e.currentTarget.style.boxShadow = "var(--shadow-sm)";
      }}
    >{children}</section>
  );
}

function CardHead({ eyebrow, title, subtitle, right }) {
  return (
    <header style={{ marginBottom: 16, display: "flex", alignItems: "flex-start", justifyContent: "space-between", gap: 16 }}>
      <div style={{ minWidth: 0 }}>
        <div style={{
          fontSize: 10, fontWeight: 600, color: "var(--text-mute)",
          letterSpacing: "0.18em", textTransform: "uppercase",
        }}>{eyebrow}</div>
        <h2 style={{
          fontSize: 18, fontWeight: 600, letterSpacing: "-0.015em",
          color: "var(--ink)", marginTop: 4,
        }}>{title}</h2>
        {subtitle && (
          <p style={{
            fontSize: 12.5, color: "var(--text-mute)", marginTop: 4, lineHeight: 1.5,
          }}>{subtitle}</p>
        )}
      </div>
      {right}
    </header>
  );
}

/* ============================================================
   MOUNT
   ============================================================ */

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