/* =========================================================================
 *  CTWCAD — Settings, Trash, Sign-in, Marketing landing
 * =======================================================================*/

/* ---------- SETTINGS ----------------------------------------------- */
function SettingsView({ user }) {
  const [devices, setDevices] = useState(null);
  const [apiKeys, setApiKeys] = useState(null);
  const [usage, setUsage] = useState(null); // { used, limit, fileCount }
  // Notification preference: in-app bell on/off. Local-only, persists in
  // localStorage. NotificationsBell reads the same key on mount/update.
  const [bellOn, setBellOn] = useState(() => localStorage.getItem("ctwcad.notif.bell") !== "0");
  const { theme, mode, setMode } = useTheme();
  useEffect(() => { window.api.listDevices().then(setDevices); }, []);
  useEffect(() => { window.api.listApiKeys().then(setApiKeys); }, []);
  useEffect(() => { window.api.getMyUsage().then(setUsage); }, []);
  const refreshKeys = () => window.api.listApiKeys().then(setApiKeys);
  const toggleBell = () => {
    const next = !bellOn;
    setBellOn(next);
    localStorage.setItem("ctwcad.notif.bell", next ? "1" : "0");
    window.dispatchEvent(new Event("ctwcad:notif-pref-changed"));
  };

  const used = usage?.used || 0;
  const limit = usage?.limit ?? null; // null = unlimited
  const pct = limit ? Math.min(100, (used / limit) * 100)
    : Math.min(100, (used / (5 * 1024 * 1024 * 1024)) * 100); // 5 GB visual scale for unlimited
  const overLimit = limit !== null && used > limit;
  return (
    <div className="ct-page">
      <div className="ct-page-head">
        <div>
          <div className="ct-eyebrow ct-mono">ACCOUNT</div>
          <h1>Settings</h1>
        </div>
      </div>

      <section className="ct-section">
        <h2>Profile</h2>
        <div className="ct-profile">
          <Avatar user={user} size={56}/>
          <div>
            <div className="ct-profile-name">{user?.name}</div>
            <div className="ct-dim ct-mono">{user?.email}</div>
          </div>
          <button className="ct-btn ct-btn-ghost">Edit</button>
        </div>
      </section>

      <section className="ct-section">
        <h2>Appearance</h2>
        <div className="ct-prefs-row">
          <div className="ct-prefs-label">
            <div>Theme</div>
            <div className="ct-dim" style={{fontSize: 12}}>
              Currently <span className="ct-mono">{theme}</span>
              {mode === "auto" ? " (matches your OS)" : ""}.
            </div>
          </div>
          <div className="ct-segmented" role="radiogroup" aria-label="Theme">
            {[
              { id: "light", label: "Light", icon: "sun" },
              { id: "dark",  label: "Dark",  icon: "moon" },
              { id: "auto",  label: "Auto",  icon: "monitor" },
            ].map((opt) => (
              <button
                key={opt.id}
                role="radio"
                aria-checked={mode === opt.id}
                className={"ct-segmented-btn " + (mode === opt.id ? "is-on" : "")}
                onClick={(e) => setMode(opt.id, e)}
              >
                <Icon name={opt.icon} size={13}/>
                <span>{opt.label}</span>
              </button>
            ))}
          </div>
        </div>
      </section>

      <section className="ct-section">
        <h2>Notifications</h2>
        <div className="ct-prefs-row">
          <div className="ct-prefs-label">
            <div>In-app notifications bell</div>
            <div className="ct-dim" style={{fontSize: 12}}>
              Show the bell in the top bar with unread activity counts.
            </div>
          </div>
          <button
            role="switch"
            aria-checked={bellOn}
            className={"ct-switch " + (bellOn ? "is-on" : "")}
            onClick={toggleBell}
            title={bellOn ? "Turn off" : "Turn on"}
          >
            <span className="ct-switch-thumb"/>
          </button>
        </div>
        <div className="ct-prefs-row">
          <div className="ct-prefs-label">
            <div>Keyboard shortcuts</div>
            <div className="ct-dim" style={{fontSize: 12}}>
              Press <kbd>?</kbd> anywhere to see the cheat sheet.
            </div>
          </div>
          <button
            className="ct-btn ct-btn-ghost"
            onClick={() => window.dispatchEvent(new Event("ctwcad:open-shortcuts"))}
          >
            <Icon name="keyboard" size={13}/>View shortcuts
          </button>
        </div>
      </section>

      <section className="ct-section">
        <h2>Storage</h2>
        <div className="ct-storage">
          <div className="ct-storage-bar">
            <div className={"ct-storage-fill" + (overLimit ? " is-over" : "")}
                 style={{ width: pct + "%" }}/>
          </div>
          <div className="ct-storage-meta">
            <span className="ct-mono" style={overLimit ? {color: "var(--ct-danger)"} : undefined}>
              {usage ? fmtBytes(used) : "—"}
            </span>
            <span className="ct-dim ct-mono">
              / {usage ? (limit === null ? "Unlimited" : fmtBytes(limit)) : "—"}
            </span>
            {usage && (
              <span className="ct-dim ct-mono" style={{marginLeft: "auto"}}>
                {usage.fileCount} file{usage.fileCount === 1 ? "" : "s"}
              </span>
            )}
          </div>
          {overLimit && (
            <div className="ct-mono ct-dim" style={{
              marginTop: 8, fontSize: 11.5, color: "var(--ct-danger)",
            }}>
              You're over your limit. Uploads will be blocked until you free space or
              ask the workspace owner to raise the limit.
            </div>
          )}
        </div>
      </section>

      <section className="ct-section">
        <h2>Connected devices</h2>
        <div className="ct-devices">
          {(devices || Array.from({length: 3})).map((d, i) =>
            d ? <DeviceCard key={d.id} device={d} index={i}/>
              : <div key={i} className="ct-device-card ct-skeleton" style={{height: 88}}/>
          )}
        </div>
      </section>

      <section className="ct-section">
        <div style={{display:"flex", alignItems:"center", justifyContent:"space-between", marginBottom: 4}}>
          <h2 style={{margin: 0}}>Connected CTWCAD apps {apiKeys ? `(${apiKeys.length})` : ""}</h2>
          <button
            className="ct-btn ct-btn-ghost is-danger"
            disabled={!apiKeys || apiKeys.length === 0}
            onClick={async () => {
              if (!window.confirm(
                `Sign out of ${apiKeys.length} other device${apiKeys.length === 1 ? "" : "s"}? ` +
                `Each desktop install will lose its sync session and have to sign in again. ` +
                `Other browser tabs will sign out within ~1 minute. This browser stays signed in.`
              )) return;
              try {
                const n = await window.api.revokeAllOtherSessions();
                refreshKeys();
                window.dispatchEvent(new CustomEvent("ctwcad:toast", {
                  detail: { message: `Signed out ${n} device${n === 1 ? "" : "s"}`, icon: "log-out" }
                }));
              } catch (e) {
                window.dispatchEvent(new CustomEvent("ctwcad:toast", {
                  detail: { message: `Couldn't revoke (${e?.code || e?.message || "error"})`, icon: "alert-circle" }
                }));
              }
            }}>
            <Icon name="log-out" size={13}/>Sign out everywhere else
          </button>
        </div>
        <p className="ct-dim" style={{marginTop:0, marginBottom:10}}>
          Each entry is one CTWCAD desktop install authorized to sync as you.
          Revoking signs that install out on its next check.
        </p>
        {apiKeys && apiKeys.length === 0 && (
          <div className="ct-dim ct-mono" style={{padding:14, border:"1px dashed var(--ct-border-soft)", borderRadius:10}}>
            No connected apps yet. Install CTWCAD desktop and choose
            "Connect to CTWCAD Cloud" — it'll open a browser tab here to
            authorize this account.
          </div>
        )}
        {(apiKeys || []).map((k) => (
          <div key={k.id} className="ct-apikey-row">
            <Icon name="monitor" size={18}/>
            <div>
              <div className="ct-apikey-name">{k.deviceName || k.name}</div>
              <div className="ct-apikey-meta">
                {k.os ? `${k.os}` : "—"}
                {k.appVersion ? ` · v${k.appVersion}` : ""}
                {" · added "}{fmtRelative(k.createdAt)}
                {k.lastUsedAt ? ` · last used ${fmtRelative(k.lastUsedAt)}` : " · never used"}
              </div>
            </div>
            <button
              className="ct-btn ct-btn-ghost"
              onClick={async () => {
                try {
                  await window.api.revokeApiKey(k.uid || (user && user.id), k.id);
                  refreshKeys();
                } catch (e) { console.warn("revoke failed", e); }
              }}>
              <Icon name="x" size={13}/>Revoke
            </button>
          </div>
        ))}
      </section>
    </div>
  );
}

function DeviceCard({ device, index = 0 }) {
  const M = window.FramerMotion.motion;
  const osLabel = { windows: "Windows", macos: "macOS", linux: "Linux" }[device.os];
  return (
    <M.div className="ct-device-card"
      initial={{ opacity: 0, y: 8 }} animate={{ opacity: 1, y: 0 }}
      transition={{ delay: index * 0.05, duration: 0.3 }}>
      <div className="ct-device-icon">
        <Icon name={device.os === "macos" ? "laptop" : device.os === "linux" ? "server" : "monitor"} size={20}/>
        <span className={"ct-online-dot " + (device.online ? "is-on" : "")}/>
      </div>
      <div className="ct-device-meta">
        <div className="ct-device-name">{device.name}</div>
        <div className="ct-dim ct-mono">{osLabel} · CTWCAD v{device.appVersion}</div>
      </div>
      <div className="ct-device-time ct-mono ct-dim">
        {device.online ? "Online" : `Last seen ${fmtRelative(device.lastSeenAt)}`}
      </div>
      <button className="ct-btn ct-btn-ghost">Disconnect</button>
    </M.div>
  );
}

/* ---------- MY DIAGNOSTICS ----------------------------------------- *
 * P270: per-user privacy boundary, do not aggregate or admin-bypass.
 * This page reads ONLY /userDiagnostics/<currentUid>/sessions/. Both
 * Firestore rules (docs/firestore.rules) and Storage rules
 * (docs/storage.rules) enforce strict owner-only reads — there is no
 * admin override path on the website. The Firebase project owner can
 * still read everything via the Firebase console (Admin SDK bypasses
 * client rules); that's an inherent property of Firebase, not exposed
 * by this UI. True zero-trust would require client-side encryption
 * with per-user keys — out of scope.
 * ------------------------------------------------------------------- */
function DiagnosticsView({ user }) {
  const [items, setItems] = useState(null);
  const [openRaw, setOpenRaw] = useState({}); // sessionId → bool
  const M = window.FramerMotion.motion;

  useEffect(() => {
    let cancelled = false;
    window.api.listMyDiagnostics()
      .then((rows) => { if (!cancelled) setItems(rows || []); })
      .catch((e) => {
        console.warn("[CTWCAD] listMyDiagnostics failed:", e?.code || e?.message);
        if (!cancelled) setItems([]);
      });
    return () => { cancelled = true; };
  }, []);

  const fmtTime = (ms) => {
    if (!ms) return "—";
    try {
      return new Date(ms).toLocaleString(undefined, {
        month: "short", day: "numeric", year: "numeric",
        hour: "numeric", minute: "2-digit",
      });
    } catch { return String(ms); }
  };

  return (
    <div className="ct-page ct-diag">
      <div className="ct-page-head">
        <div>
          <div className="ct-eyebrow ct-mono">PRIVATE</div>
          <h1>My Diagnostics</h1>
        </div>
      </div>

      <section className="ct-section ct-diag-banner">
        <div className="ct-diag-banner-row">
          <span className="ct-mono ct-dim">Signed in as</span>
          <span className="ct-mono">{user?.email || "—"}</span>
        </div>
        <div className="ct-diag-banner-row">
          <span className="ct-mono ct-dim">Account UID</span>
          <span className="ct-mono ct-diag-uid" title="Use this to verify the data is yours">
            {user?.uid || user?.id || "—"}
          </span>
        </div>
        <div className="ct-diag-note ct-mono ct-dim">
          Only you can read these. Even a website admin can't see this list.
        </div>
      </section>

      <section className="ct-section">
        <h2>Sessions</h2>
        {items === null && (
          <div className="ct-dim ct-mono" style={{ padding: "12px 0" }}>Loading…</div>
        )}
        {items && items.length === 0 && (
          <div className="ct-diag-empty">
            No diagnostic sessions uploaded from desktop yet. Sessions
            upload automatically when you close the CTWCAD desktop app
            while signed in.
          </div>
        )}
        {items && items.length > 0 && (
          <div className="ct-diag-list">
            {items.map((s, i) => {
              const sessionId = s.sessionId || s.id;
              const isOpen = !!openRaw[sessionId];
              return (
                <M.div
                  key={sessionId}
                  className="ct-diag-row"
                  initial={{ opacity: 0, y: 6 }}
                  animate={{ opacity: 1, y: 0 }}
                  transition={{ duration: 0.25, delay: i * 0.02 }}
                >
                  <div className="ct-diag-row-head">
                    <div className="ct-diag-row-title">
                      <span className="ct-mono ct-diag-sid">{sessionId}</span>
                      <span className="ct-dim ct-mono ct-diag-when">{fmtTime(s.createdAtMs)}</span>
                    </div>
                    <div className="ct-diag-row-meta ct-dim ct-mono">
                      <span>
                        {(s.filesIncluded ?? 0)} file{(s.filesIncluded ?? 0) === 1 ? "" : "s"}
                        {" · "}
                        {fmtBytes(s.sizeBytes || 0)}
                      </span>
                      <span>
                        {s.appVersion ? `v${s.appVersion}` : "v—"}
                        {s.device ? ` · ${s.device}` : ""}
                      </span>
                    </div>
                  </div>

                  <div className="ct-diag-row-actions">
                    {s.downloadURL ? (
                      <a
                        className="ct-btn ct-btn-ghost"
                        href={s.downloadURL}
                        target="_blank"
                        rel="noopener"
                        download={`${sessionId}.zip`}
                      >
                        <Icon name="download" size={13}/>
                        <span>Download .zip</span>
                      </a>
                    ) : (
                      <button className="ct-btn ct-btn-ghost" disabled>
                        <Icon name="alert-circle" size={13}/>
                        <span>No download URL</span>
                      </button>
                    )}
                    <button
                      className="ct-btn ct-btn-ghost"
                      onClick={() => setOpenRaw(o => ({ ...o, [sessionId]: !o[sessionId] }))}
                    >
                      <Icon name={isOpen ? "chevron-up" : "chevron-down"} size={13}/>
                      <span>{isOpen ? "Hide raw doc" : "Raw doc"}</span>
                    </button>
                  </div>

                  {isOpen && (
                    <pre className="ct-diag-raw ct-mono">
                      {JSON.stringify(s, null, 2)}
                    </pre>
                  )}
                </M.div>
              );
            })}
          </div>
        )}
      </section>
    </div>
  );
}
/* ---------- TRASH -------------------------------------------------- */
function TrashView({ onOpenFile }) {
  const [items, setItems] = useState(null);
  const [contextMenu, setContextMenu] = useState(null);
  // Replaces window.confirm with a styled ConfirmDialog so the destructive
  // "delete forever" path matches the rest of the app's modal language and
  // is dismissable with Escape / backdrop click.
  const [emptyConfirm, setEmptyConfirm] = useState(false);
  const M = window.FramerMotion.motion;

  const refresh = () => window.api.listTrash().then(setItems);
  useEffect(() => { refresh(); }, []);
  // Trash mutates from the context-menu actions in app.jsx — refresh on
  // each item-action so the row disappears (or reappears on restore).
  useEffect(() => {
    const onChanged = () => refresh();
    window.addEventListener("ctwcad:trash-changed", onChanged);
    return () => window.removeEventListener("ctwcad:trash-changed", onChanged);
  }, []);

  const onRowContext = (e, file) => {
    e.preventDefault();
    setContextMenu({
      kind: "trashed-file",
      file,
      x: Math.min(e.clientX, window.innerWidth - 240),
      y: Math.min(e.clientY, window.innerHeight - 280),
      ox: 0, oy: 0,
    });
  };

  const dispatch = (action, file) => {
    window.dispatchEvent(new CustomEvent("ctwcad:item-action", {
      detail: { action, kind: "trashed-file", file },
    }));
  };

  const requestEmptyTrash = () => {
    if (!items || items.length === 0) return;
    setEmptyConfirm(true);
  };
  const doEmptyTrash = () => {
    setEmptyConfirm(false);
    if (!items || items.length === 0) return;
    const count = items.length;
    Promise.all(items.map(f => window.api.deleteFilePermanently(f.id).catch(() => {})))
      .finally(() => {
        refresh();
        // Surface the result via the global toast bus (handled by app.jsx).
        window.dispatchEvent(new CustomEvent("ctwcad:toast", {
          detail: {
            message: `Deleted ${count} file${count === 1 ? "" : "s"} forever`,
            icon: "trash-2",
          },
        }));
      });
  };

  return (
    <div className="ct-page">
      <div className="ct-page-head">
        <div>
          <div className="ct-eyebrow ct-mono">TRASH</div>
          <h1>Recently deleted</h1>
          <p className="ct-dim">Items are kept here until you delete them forever.</p>
        </div>
        <button className="ct-btn ct-btn-ghost" onClick={requestEmptyTrash} disabled={!items || items.length === 0}>
          <Icon name="trash-2" size={13}/>Empty trash
        </button>
      </div>

      {!items && (
        <div className="ct-trash-list">
          {Array.from({length: 4}).map((_, i) => (
            <div key={i} className="ct-trash-row ct-skeleton" style={{height: 64}}/>
          ))}
        </div>
      )}

      {items && items.length === 0 && (
        <div className="ct-empty">
          <Icon name="trash" size={36}/>
          <div className="ct-empty-title">Nothing in trash</div>
          <div className="ct-dim">Files you move to trash will appear here.</div>
        </div>
      )}

      {items && items.length > 0 && (
        <div className="ct-trash-list">
          {items.map((f, i) => (
            <M.div
              key={f.id}
              className="ct-trash-row"
              initial={{ opacity: 0, y: 4 }}
              animate={{ opacity: 1, y: 0 }}
              transition={{ delay: i * 0.03, duration: 0.22 }}
              onClick={() => onOpenFile?.(f.id)}
              onContextMenu={(e) => onRowContext(e, f)}
            >
              <div className="ct-trash-thumb"><CADThumb file={f} /></div>
              <div className="ct-trash-meta">
                <div className="ct-trash-name">{f.name}</div>
                <div className="ct-mono ct-dim">
                  v{f.versionCount} · {fmtBytes(f.sizeBytes)} · trashed {fmtRelative(f.updatedAt)}
                </div>
              </div>
              <div className="ct-trash-actions">
                <button className="ct-btn ct-btn-ghost" onClick={(e) => { e.stopPropagation(); dispatch("restore", f); }}>
                  <Icon name="undo-2" size={13}/>Restore
                </button>
                <button className="ct-btn ct-btn-ghost is-danger" onClick={(e) => { e.stopPropagation(); dispatch("delete-forever", f); }}>
                  <Icon name="trash-2" size={13}/>Delete
                </button>
              </div>
            </M.div>
          ))}
        </div>
      )}

      <ContextMenu menu={contextMenu} onClose={() => setContextMenu(null)} />

      {/* Styled confirmation dialog replaces the native `window.confirm`
          for "Empty trash" — same component the admin page uses for
          publish / unpublish, so the language is consistent across the
          app. Falls back gracefully if items has somehow gone null
          between mount and click. */}
      <ConfirmDialog
        open={emptyConfirm}
        title={items && items.length > 0
          ? `Permanently delete ${items.length} file${items.length === 1 ? "" : "s"}?`
          : "Empty trash?"}
        body={
          <span>
            <span>
              {items && items.length > 0
                ? `Every file currently in your trash will be removed from CTWCAD Cloud and from any device that synced it. `
                : `Every file in your trash will be removed. `}
            </span>
            <strong style={{ color: "var(--ct-danger)" }}>This cannot be undone.</strong>
          </span>
        }
        confirmLabel={items && items.length > 0
          ? `Delete ${items.length} file${items.length === 1 ? "" : "s"} forever`
          : "Delete forever"}
        danger
        onCancel={() => setEmptyConfirm(false)}
        onConfirm={doEmptyTrash}
      />
    </div>
  );
}

/* ---------- SIGN-IN ------------------------------------------------ */
function SignInView({ onSignIn }) {
  const M = window.FramerMotion.motion;
  const A = window.FramerMotion.AnimatePresence;
  const [pickerOpen, setPickerOpen] = useState(false);
  const [busy, setBusy] = useState(false);
  const [err, setErr] = useState(null);
  const useRealAuth = window.CTWCAD_AUTH && window.CTWCAD_AUTH.provider === "firebase";

  // Pick up redirect-based sign-ins automatically.
  useEffect(() => {
    const onRedirect = (e) => onSignIn(e.detail);
    window.addEventListener("ctwcad:auth-redirect-result", onRedirect);
    return () => window.removeEventListener("ctwcad:auth-redirect-result", onRedirect);
  }, [onSignIn]);

  const handleClick = async () => {
    if (!useRealAuth) { setPickerOpen(true); return; }
    setBusy(true); setErr(null);
    try {
      const acct = await window.CTWCAD_AUTH.signInWithGoogle();
      if (acct) onSignIn(acct);
      // If null, a redirect was kicked off; the page will reload.
    } catch (e) {
      setErr(e?.message || "Sign-in failed");
      setBusy(false);
    }
  };

  return (
    <div className="ct-signin">
      <div className="ct-signin-bg" aria-hidden="true">
        <svg viewBox="0 0 800 800" preserveAspectRatio="xMidYMid slice">
          <defs>
            <pattern id="bg-grid" width="40" height="40" patternUnits="userSpaceOnUse">
              <path d="M 40 0 L 0 0 0 40" fill="none" stroke="currentColor" strokeWidth="0.4" opacity="0.18"/>
            </pattern>
            <radialGradient id="bg-glow" cx="50%" cy="50%" r="50%">
              <stop offset="0%" stopColor="var(--ct-accent)" stopOpacity="0.2"/>
              <stop offset="100%" stopColor="var(--ct-accent)" stopOpacity="0"/>
            </radialGradient>
          </defs>
          <rect width="800" height="800" fill="url(#bg-grid)"/>
          <M.circle cx="400" cy="400" r="280" fill="url(#bg-glow)"
            animate={{ scale: [1, 1.08, 1] }}
            transition={{ duration: 6, repeat: Infinity, ease: "easeInOut" }}
          />
        </svg>
      </div>
      <M.div className="ct-signin-card"
        initial={{ opacity: 0, y: 20, scale: 0.97 }}
        animate={{ opacity: 1, y: 0, scale: 1 }}
        transition={{ type: "spring", stiffness: 240, damping: 28 }}>
        {/* Animated brandmark plays its full draw-in choreography
            on every sign-in render (~3 seconds). On a hard refresh
            it greets the user; if they return after sign-out it plays
            again, which is the right behavior for an auth surface. */}
        <div className="ct-signin-mark">
          <AnimatedBrandmark size={68}/>
        </div>
        <h1>Sign in to CTWCAD</h1>
        <p className="ct-dim">Your CAD files, synced between desktop and cloud.</p>
        <button className="ct-google-btn" onClick={handleClick} disabled={busy}>
          <span className="ct-google-sheen"/>
          <GoogleGlyph/>
          <span>{busy ? "Opening Google…" : "Continue with Google"}</span>
        </button>
        <a
          className="ct-request-access"
          href={"mailto:seth@ctwcad.com"
                + "?subject=" + encodeURIComponent("CTWCAD Cloud — request access")
                + "&body=" + encodeURIComponent(
                    "Hi Seth,\n\nI'd like access to CTWCAD Cloud.\n\n"
                    + "Name:\nCompany / use-case:\nGoogle account (the email I'll sign in with):\n\nThanks!"
                  )}
        >
          <Icon name="mail" size={13}/>
          Email to request access
        </a>
        {/* Install link is intentionally absent here: /install is now
            gated behind sign-in, so any link from this card would just
            bounce back. Signed-in users can reach it from the profile
            menu or by typing /install directly. */}
        {err && <div className="ct-dim" style={{color:"var(--ct-danger)", fontSize:12}}>{err}</div>}
        <div className="ct-signin-foot ct-dim ct-mono">
          {useRealAuth ? "Private beta · invite-only." : "Mock mode — set up firebase-config.js to enable real Google sign-in."}
        </div>
      </M.div>
      <A>
        {pickerOpen && (
          <>
            <M.div className="ct-backdrop"
              initial={{ opacity: 0 }} animate={{ opacity: 1 }} exit={{ opacity: 0 }}
              onClick={() => setPickerOpen(false)} />
            <GoogleAccountPicker
              onCancel={() => setPickerOpen(false)}
              onPick={(acct) => { setPickerOpen(false); onSignIn(acct); }}
            />
          </>
        )}
      </A>
    </div>
  );
}

function GoogleGlyph() {
  return (
    <svg width="16" height="16" viewBox="0 0 18 18" aria-hidden="true">
      <path d="M17.64 9.2c0-.64-.06-1.25-.16-1.84H9v3.48h4.84a4.14 4.14 0 0 1-1.79 2.72v2.26h2.9c1.7-1.56 2.69-3.87 2.69-6.62z" fill="#4285F4"/>
      <path d="M9 18c2.43 0 4.46-.8 5.95-2.18l-2.9-2.26c-.8.54-1.84.86-3.05.86-2.34 0-4.32-1.58-5.03-3.7H.96v2.33A9 9 0 0 0 9 18z" fill="#34A853"/>
      <path d="M3.97 10.72A5.41 5.41 0 0 1 3.68 9c0-.6.1-1.18.29-1.72V4.95H.96A9 9 0 0 0 0 9c0 1.45.35 2.83.96 4.05l3.01-2.33z" fill="#FBBC05"/>
      <path d="M9 3.58c1.32 0 2.5.45 3.44 1.34l2.58-2.58A9 9 0 0 0 9 0 9 9 0 0 0 .96 4.95l3.01 2.33C4.68 5.16 6.66 3.58 9 3.58z" fill="#EA4335"/>
    </svg>
  );
}

/* ---------- MARKETING ---------------------------------------------- */
function MarketingView({ onSignIn }) {
  const M = window.FramerMotion.motion;
  return (
    <div className="ct-marketing">
      <header className="ct-mk-nav">
        <Brandmark size={22}/>
        <nav className="ct-mk-links">
          <a>Product</a><a>Docs</a><a>Changelog</a>
        </nav>
        <div>
          <button className="ct-btn ct-btn-ghost" onClick={onSignIn}>Sign in</button>
          <button className="ct-btn ct-btn-primary" onClick={onSignIn}>Request access</button>
        </div>
      </header>

      <section className="ct-mk-hero">
        <div className="ct-mk-grid-bg" aria-hidden="true"/>
        <M.div className="ct-mk-hero-inner"
          initial={{ opacity: 0, y: 20 }} animate={{ opacity: 1, y: 0 }}
          transition={{ duration: 0.6, ease: [0.22, 1, 0.36, 1] }}>
          <span className="ct-mk-tag ct-mono">▲ CTWCAD CLOUD · BETA</span>
          <h1>Where parametric CAD<br/>meets the cloud.</h1>
          <p>A precision file home for sketches, parts, and assemblies. Sync bidirectionally with the CTWCAD desktop app. Versioned, shareable, fast.</p>
          <div className="ct-mk-cta">
            <button className="ct-btn ct-btn-primary ct-btn-lg" onClick={onSignIn}>Sign in <Icon name="arrow-right" size={14}/></button>
            <button className="ct-btn ct-btn-ghost ct-btn-lg"><Icon name="download" size={14}/>Download desktop</button>
          </div>
        </M.div>
        <M.div className="ct-mk-hero-art"
          initial={{ opacity: 0, y: 30 }} animate={{ opacity: 1, y: 0 }}
          transition={{ delay: 0.2, duration: 0.7, ease: [0.22, 1, 0.36, 1] }}>
          <FauxAppShot/>
        </M.div>
      </section>

      <section className="ct-mk-features">
        {[
          { icon: "git-branch", t: "Every save, versioned", d: "Restore any prior cut. Browse history with diffs and notes." },
          { icon: "share-2",   t: "Share by project",      d: "Granular sharing per folder. Link expiry. Audit log." },
          { icon: "refresh-cw", t: "Bidirectional sync",   d: "Desktop ↔ web. Conflict-free with offline edits." },
          { icon: "shield",    t: "Built for IP",          d: "EU + US regions, encrypted at rest, SSO ready." },
        ].map((f, i) => (
          <M.div key={i} className="ct-mk-feature"
            initial={{ opacity: 0, y: 16 }}
            whileInView={{ opacity: 1, y: 0 }}
            viewport={{ once: true, margin: "-80px" }}
            transition={{ delay: i * 0.06, duration: 0.4 }}>
            <Icon name={f.icon} size={20}/>
            <div className="ct-mk-feature-t">{f.t}</div>
            <div className="ct-dim">{f.d}</div>
          </M.div>
        ))}
      </section>

      <section className="ct-mk-pricing">
        <div className="ct-eyebrow ct-mono">PRIVATE BETA</div>
        <h2>Currently invite-only.</h2>
        <p className="ct-dim" style={{maxWidth:560, margin:"8px auto 24px", textAlign:"center"}}>
          We're working with a small group of teams to harden sync, versioning, and the desktop bridge before opening up.
          Pricing will be announced ahead of general availability.
        </p>
        <div style={{display:"flex", justifyContent:"center"}}>
          <button className="ct-btn ct-btn-primary ct-btn-lg" onClick={onSignIn}>
            Request access <Icon name="arrow-right" size={14}/>
          </button>
        </div>
      </section>

      <footer className="ct-mk-footer">
        <Brandmark size={20}/>
        <span className="ct-dim ct-mono">© 2026 CTWCAD</span>
        <span className="ct-mk-foot-links ct-dim">
          <a>Privacy</a><a>Terms</a><a>Status</a><a>Contact</a>
        </span>
      </footer>
    </div>
  );
}

function FauxAppShot() {
  return (
    <div className="ct-faux">
      <div className="ct-faux-chrome">
        <span className="ct-faux-dot"/><span className="ct-faux-dot"/><span className="ct-faux-dot"/>
        <span className="ct-mono ct-dim">app.ctwcad.dev / chassis-mk-iv / frame</span>
      </div>
      <div className="ct-faux-body">
        <div className="ct-faux-rail">
          <div className="ct-faux-row is-active">Frame</div>
          <div className="ct-faux-row">Drivetrain</div>
          <div className="ct-faux-row">Electronics Bay</div>
          <div className="ct-faux-row">Archive</div>
        </div>
        <div className="ct-faux-grid">
          {[ "step", "ctws", "ctws", "stp", "stl", "pdf" ].map((k, i) => (
            <div key={i} className="ct-faux-card">
              <CADThumb file={{ id: "fx" + i, kind: k, thumbSeed: 7 + i }}/>
            </div>
          ))}
        </div>
      </div>
    </div>
  );
}

/* =========================================================================
 *  INSTALL — public marketing page for the desktop installer
 *  ─────────────────────────────────────────────────────────
 *  Reachable at /install whether or not the user is signed in. The
 *  installer file isn't ready yet, so the CTA shows a "coming soon" toast
 *  and dispatches a real toast event so signed-in users see it in the
 *  toast manager too.
 * =======================================================================*/
function InstallView({ signedIn }) {
  const M = window.FramerMotion.motion;
  const A = window.FramerMotion.AnimatePresence;
  const [showToast, setShowToast] = useState(false);

  // Mouse-tracked parallax on the hero brandmark — adds a subtle 3D
  // feel without being twitchy. The springs smooth it out.
  const mx = window.FramerMotion.useMotionValue(0);
  const my = window.FramerMotion.useMotionValue(0);
  const sx = window.FramerMotion.useSpring(mx, { stiffness: 90, damping: 22 });
  const sy = window.FramerMotion.useSpring(my, { stiffness: 90, damping: 22 });
  const onMove = (e) => {
    mx.set((e.clientX / window.innerWidth - 0.5) * 24);
    my.set((e.clientY / window.innerHeight - 0.5) * 18);
  };

  const goHome = (e) => {
    if (e) e.preventDefault();
    if (typeof window.CTWCAD_NAV === "function") window.CTWCAD_NAV("/");
    else window.location.assign("/");
  };

  const onDownload = () => {
    // Signed-out visitors get routed to sign-in instead of the toast —
    // the actual installer (when it exists) will live behind auth so
    // we can match downloads to allowlist members.
    if (!signedIn) { goHome(); return; }
    setShowToast(true);
    setTimeout(() => setShowToast(false), 4000);
  };

  const features = [
    { icon: "git-branch", title: "Versioned saves",
      desc: "Every save is a version. Restore any cut, anywhere." },
    { icon: "cloud",      title: "Cloud sync",
      desc: "Files round-trip with the website. Open anywhere, edit on your desk." },
    { icon: "boxes",      title: "Real STEP & STL",
      desc: "Native parametric .ctwcad plus AP214 STEP export on every save." },
    { icon: "shield",     title: "Encrypted at rest",
      desc: "DPAPI-protected credentials. Sign in once, revoke any time." },
  ];

  return (
    <div className="ct-install" onMouseMove={onMove}>
      {/* Animated background — two slow-drifting orbs + a faint grid */}
      <div className="ct-install-bg" aria-hidden="true">
        <M.div className="ct-install-orb ct-install-orb-a"
          animate={{ x: [0, 60, -20, 0], y: [0, -30, 20, 0] }}
          transition={{ duration: 18, repeat: Infinity, ease: "easeInOut" }} />
        <M.div className="ct-install-orb ct-install-orb-b"
          animate={{ x: [0, -50, 40, 0], y: [0, 40, -20, 0] }}
          transition={{ duration: 22, repeat: Infinity, ease: "easeInOut" }} />
        <svg className="ct-install-grid" aria-hidden="true">
          <defs>
            <pattern id="install-grid" width="40" height="40" patternUnits="userSpaceOnUse">
              <path d="M 40 0 L 0 0 0 40" fill="none" stroke="currentColor"
                    strokeWidth="0.4" opacity="0.18"/>
            </pattern>
          </defs>
          <rect width="100%" height="100%" fill="url(#install-grid)"/>
        </svg>
      </div>

      {/* Tiny top nav */}
      <header className="ct-install-nav">
        <a href="/" onClick={goHome} className="ct-install-brand">
          <Brandmark size={22} />
        </a>
        <a href="/" onClick={goHome} className="ct-install-back">
          {signedIn ? "Back to app" : "Sign in"} <Icon name="arrow-right" size={12}/>
        </a>
      </header>

      {/* Hero */}
      <section className="ct-install-hero">
        <M.div
          className="ct-install-mark"
          style={{ x: sx, y: sy }}
          initial={{ scale: 0.6, opacity: 0, rotateY: -25 }}
          animate={{ scale: 1, opacity: 1, rotateY: 0 }}
          transition={{ type: "spring", stiffness: 180, damping: 22, delay: 0.05 }}
        >
          <AnimatedBrandmark size={120} />
        </M.div>

        <M.h1
          initial={{ opacity: 0, y: 24 }}
          animate={{ opacity: 1, y: 0 }}
          transition={{ duration: 0.6, delay: 0.25, ease: [0.22, 1, 0.36, 1] }}
        >
          CTWCAD <span className="ct-install-accent">Desktop</span>
        </M.h1>

        <M.p
          className="ct-install-sub"
          initial={{ opacity: 0, y: 18 }}
          animate={{ opacity: 1, y: 0 }}
          transition={{ duration: 0.6, delay: 0.4, ease: [0.22, 1, 0.36, 1] }}
        >
          Parametric CAD for Windows. Sync seamlessly with CTWCAD Cloud — every
          save is versioned, every part is yours.
        </M.p>

        <M.div
          className="ct-install-cta-wrap"
          initial={{ opacity: 0, y: 16 }}
          animate={{ opacity: 1, y: 0 }}
          transition={{ duration: 0.5, delay: 0.55, ease: [0.22, 1, 0.36, 1] }}
        >
          <M.button
            className="ct-install-cta"
            onClick={onDownload}
            whileHover={{ y: -2, scale: 1.02 }}
            whileTap={{ scale: 0.98 }}
            transition={{ type: "spring", stiffness: 380, damping: 22 }}
          >
            <span className="ct-install-cta-sheen" aria-hidden="true"/>
            <Icon name="download" size={16}/>
            <span>Download installer</span>
            <span className="ct-mono ct-install-cta-meta">Windows · v0.9</span>
          </M.button>
          <p className="ct-install-cta-note ct-mono">
            Free · 64-bit Windows 10 / 11
          </p>
        </M.div>
      </section>

      {/* Features — stagger fade-in on scroll */}
      <M.section
        className="ct-install-features"
        initial="hidden"
        whileInView="show"
        viewport={{ once: true, margin: "-80px" }}
        variants={{ show: { transition: { staggerChildren: 0.08 } } }}
      >
        {features.map((f) => (
          <M.div
            key={f.title}
            className="ct-install-feature"
            variants={{
              hidden: { opacity: 0, y: 28 },
              show: { opacity: 1, y: 0,
                      transition: { duration: 0.55, ease: [0.22, 1, 0.36, 1] } },
            }}
            whileHover={{ y: -4, borderColor: "var(--ct-accent)" }}
            transition={{ type: "spring", stiffness: 320, damping: 24 }}
          >
            <Icon name={f.icon} size={20}/>
            <h3>{f.title}</h3>
            <p>{f.desc}</p>
          </M.div>
        ))}
      </M.section>

      {/* Tech chip strip */}
      <M.section
        className="ct-install-strip"
        initial={{ opacity: 0 }}
        whileInView={{ opacity: 1 }}
        viewport={{ once: true, margin: "-60px" }}
        transition={{ duration: 0.7 }}
      >
        <span className="ct-mono ct-dim">Native formats:</span>
        {[".ctwcad", ".step", ".stl", ".iges", ".3mf", ".obj", ".pdf"].map((ext) => (
          <span key={ext} className="ct-install-chip ct-mono">{ext}</span>
        ))}
      </M.section>

      <footer className="ct-install-foot ct-mono ct-dim">
        © 2026 CTWCAD · <a href="/" onClick={goHome}>ctwcad.com</a>
      </footer>

      {/* "Coming soon" toast */}
      <A>
        {showToast && (
          <M.div
            className="ct-install-toast"
            initial={{ y: 32, opacity: 0, scale: 0.95 }}
            animate={{ y: 0, opacity: 1, scale: 1 }}
            exit={{ y: 16, opacity: 0, scale: 0.97 }}
            transition={{ type: "spring", stiffness: 320, damping: 26 }}
          >
            <Icon name="construction" size={14}/>
            <span>Installer coming soon — we're putting the final pass on it.</span>
          </M.div>
        )}
      </A>
    </div>
  );
}

/* =========================================================================
 *  SplashScreen — first-impression brandmark animation
 *  ───────────────────────────────────────────────────
 *  Plays once per browser session: the AnimatedBrandmark draws itself in,
 *  then the overlay fades out and the app behind takes over. Skipped for
 *  the desktop-app connect flow (?connect=1) — those users are mid-task
 *  and shouldn't be made to wait a few extra seconds.
 *
 *  Click anywhere on the splash to skip the rest of the animation.
 * =======================================================================*/
function SplashScreen() {
  const M = window.FramerMotion?.motion;
  const A = window.FramerMotion?.AnimatePresence;
  // Avoid the splash during the connect flow — the desktop is waiting
  // on a fast Firebase-token POST and a 4-second splash is friction.
  const isConnect = typeof window !== "undefined" &&
                    new URLSearchParams(window.location.search).get("connect") === "1";
  const [show, setShow] = useState(() => {
    if (isConnect) return false;
    try { return sessionStorage.getItem("ctwcad.splashShown") !== "1"; }
    catch { return false; }
  });

  useEffect(() => {
    if (!show) return;
    try { sessionStorage.setItem("ctwcad.splashShown", "1"); } catch {}
    // AnimatedBrandmark choreography:
    //   t=0.00  outer square starts (2.0s)
    //   t=1.45  L-stroke starts (1.0s)
    //   t=2.55  dot pops in (0.7s)
    //   →3.25s total. Hold ~250ms, then fade out (0.45s).
    const t = setTimeout(() => setShow(false), 3700);
    return () => clearTimeout(t);
  }, [show]);

  if (!M || !A) return null;

  return (
    <A>
      {show && (
        <M.div
          className="ct-splash"
          initial={{ opacity: 1 }}
          animate={{ opacity: 1 }}
          exit={{ opacity: 0 }}
          transition={{ duration: 0.45, ease: [0.22, 1, 0.36, 1] }}
          onClick={() => setShow(false)}
          role="presentation"
        >
          <div className="ct-splash-mark">
            <AnimatedBrandmark size={140} />
          </div>
          <div className="ct-splash-skip ct-mono ct-dim">click anywhere to skip</div>
        </M.div>
      )}
    </A>
  );
}

/* The brandmark with the L-stroke drawn in and the dot pulsed in.
 * Choreography (longer, premium feel — used on /install and the sign-in card):
 *   t=0.00  outer square starts drawing (2.0s)
 *   t=1.45  L-stroke starts drawing (1.0s)
 *   t=2.55  dot scales in (0.7s with overshoot)
 *   total ≈ 3.25s
 *
 * The outer rounded square uses ROUNDED_RECT_PATH (defined in primitives.jsx)
 * so framer-motion's pathLength animates cleanly without a seam gap.
 */
function AnimatedBrandmark({ size = 120 }) {
  const M = window.FramerMotion.motion;
  return (
    <svg width={size} height={size} viewBox="0 0 32 32" aria-hidden="true">
      <M.path
        d={ROUNDED_RECT_PATH}
        fill="none" stroke="currentColor" strokeWidth="1.5"
        strokeLinecap="round" strokeLinejoin="round"
        initial={{ pathLength: 0, opacity: 0 }}
        animate={{ pathLength: 1, opacity: 1 }}
        transition={{ duration: 2.0, ease: [0.22, 1, 0.36, 1] }}
      />
      <M.path
        d="M 10 22 L 10 10 L 22 10"
        fill="none" stroke="var(--ct-accent)" strokeWidth="1.6"
        strokeLinecap="round" strokeLinejoin="round"
        initial={{ pathLength: 0 }}
        animate={{ pathLength: 1 }}
        transition={{ duration: 1.0, delay: 1.45, ease: [0.22, 1, 0.36, 1] }}
      />
      <M.circle cx="22" cy="22" r="3" fill="var(--ct-accent)"
        initial={{ scale: 0, opacity: 0 }}
        animate={{ scale: [0, 1.5, 1], opacity: 1 }}
        transition={{ duration: 0.7, delay: 2.55, ease: [0.22, 1, 0.36, 1] }}
        style={{ transformOrigin: "22px 22px" }}
      />
    </svg>
  );
}

function Brandmark({ size = 22 }) {
  return (
    <span className="ct-brand">
      <svg width={size} height={size} viewBox="0 0 32 32" aria-hidden="true">
        <rect x="3" y="3" width="26" height="26" rx="6" fill="none" stroke="var(--ct-fg)" strokeWidth="1.5"/>
        <path d="M10 22 L10 10 L22 10" fill="none" stroke="var(--ct-accent)" strokeWidth="1.5"/>
        <circle cx="22" cy="22" r="3" fill="var(--ct-accent)"/>
      </svg>
      <span className="ct-mono ct-brand-word">CTWCAD</span>
    </span>
  );
}

/* =========================================================================
 *  Onboarding tour — first-sign-in walkthrough.
 *  -----------------------------------------------------------------------
 *  Mounted next to SplashScreen at the app root. Reads
 *  /users/{uid}.onboardedAt; if missing, fades in a small popover anchored
 *  to a specific UI element (data-tour="…" attributes elsewhere in the
 *  app). On Skip/Finish we write serverTimestamp() so it never re-shows.
 *
 *  Steps degrade gracefully — if an anchor element isn't on screen
 *  (e.g. mobile layout differs), the popover centers itself.
 * =======================================================================*/
function OnboardingTour({ user }) {
  const M = window.FramerMotion.motion;
  const A = window.FramerMotion.AnimatePresence;
  const [show, setShow] = useState(false);
  const [step, setStep] = useState(0);
  const [anchorRect, setAnchorRect] = useState(null);

  const STEPS = useMemo(() => [
    {
      anchor: null,
      title: "Welcome to CTWCAD Cloud",
      body: "This is your dashboard — pinned projects and recent activity show up here. Let's take 30 seconds to point out the rest.",
    },
    {
      anchor: '[data-tour="nav-files"]',
      title: "Files live in projects",
      body: "Open Files to browse projects and folders. Right-click any project to pin it to your dashboard.",
    },
    {
      anchor: '[data-tour="upload-cta"]',
      title: "Upload anything",
      body: "Drag files anywhere on the page, or click Upload. STEP, STL, 3MF, PDF, DXF — they all preview right in the browser.",
    },
    {
      anchor: '[data-tour="profile-menu"]',
      title: "Sync with desktop & phone",
      body: "Sign in to CTWCAD on your Windows desktop or Android phone with the same Google account — every save syncs here automatically.",
    },
  ], []);

  // Decide whether to show the tour. Skip when the splash screen is
  // running (we don't want two overlays competing for attention) and
  // when we're inside the desktop /install handoff page.
  useEffect(() => {
    if (!user) return;
    if (window.location.pathname.startsWith("/install")) return;
    if (window.location.search.includes("connect=1")) return;
    let cancelled = false;
    (async () => {
      const at = await window.api.getMyOnboardedAt?.().catch(() => null);
      if (cancelled) return;
      if (at) return;
      // Wait a beat so the splash + first paint settle, then show.
      setTimeout(() => { if (!cancelled) setShow(true); }, 1400);
    })();
    return () => { cancelled = true; };
  }, [user?.id, user?.email]);

  // Re-measure the anchor when the step changes or the window resizes.
  useEffect(() => {
    if (!show) return;
    const measure = () => {
      const sel = STEPS[step].anchor;
      if (!sel) { setAnchorRect(null); return; }
      const el = document.querySelector(sel);
      if (!el) { setAnchorRect(null); return; }
      const r = el.getBoundingClientRect();
      setAnchorRect({ top: r.top, left: r.left, width: r.width, height: r.height });
    };
    measure();
    window.addEventListener("resize", measure);
    window.addEventListener("scroll", measure, true);
    return () => {
      window.removeEventListener("resize", measure);
      window.removeEventListener("scroll", measure, true);
    };
  }, [show, step, STEPS]);

  const finish = useCallback(async () => {
    setShow(false);
    try { await window.api.setMyOnboardedAt(); } catch {}
  }, []);

  if (!show) return null;
  const total = STEPS.length;
  const cur = STEPS[step];

  // Position the popover. If we have an anchor rect, place the popover
  // below it (or above, when there's no room below). Otherwise center.
  let popStyle;
  let anchorBox = null;
  if (anchorRect) {
    const POP_W = 320;
    const POP_H_EST = 200;
    const margin = 12;
    const cx = anchorRect.left + anchorRect.width / 2;
    const left = Math.max(12, Math.min(window.innerWidth - POP_W - 12, cx - POP_W / 2));
    let top = anchorRect.top + anchorRect.height + margin;
    if (top + POP_H_EST > window.innerHeight - 12) {
      top = Math.max(12, anchorRect.top - POP_H_EST - margin);
    }
    popStyle = { position: "fixed", top, left, width: POP_W };
    anchorBox = {
      position: "fixed",
      top: anchorRect.top - 4, left: anchorRect.left - 4,
      width: anchorRect.width + 8, height: anchorRect.height + 8,
    };
  } else {
    popStyle = {
      position: "fixed", top: "50%", left: "50%",
      transform: "translate(-50%, -50%)", width: 360,
    };
  }

  return (
    <A>
      <M.div
        className="ct-tour-backdrop"
        initial={{ opacity: 0 }}
        animate={{ opacity: 1 }}
        exit={{ opacity: 0 }}
        transition={{ duration: 0.22, ease: [0.22, 1, 0.36, 1] }}
        onClick={finish}
      />
      {anchorBox && (
        <M.div
          className="ct-tour-spotlight"
          style={anchorBox}
          initial={{ opacity: 0, scale: 0.96 }}
          animate={{ opacity: 1, scale: 1 }}
          exit={{ opacity: 0 }}
          transition={{ type: "spring", stiffness: 320, damping: 28 }}
        />
      )}
      <M.div
        key={step}
        className="ct-tour-pop"
        style={popStyle}
        initial={{ opacity: 0, y: 8, scale: 0.97 }}
        animate={{ opacity: 1, y: 0, scale: 1 }}
        exit={{ opacity: 0, y: 4, scale: 0.98 }}
        transition={{ type: "spring", stiffness: 360, damping: 28 }}
      >
        <div className="ct-tour-step ct-mono ct-dim">
          Step {step + 1} of {total}
        </div>
        <h3 className="ct-tour-title">{cur.title}</h3>
        <p className="ct-tour-body">{cur.body}</p>
        <div className="ct-tour-dots" aria-hidden="true">
          {STEPS.map((_, i) => (
            <span key={i} className={"ct-tour-dot " + (i === step ? "is-on" : "")}/>
          ))}
        </div>
        <div className="ct-tour-actions">
          <button className="ct-btn ct-btn-ghost" onClick={finish}>
            Skip tour
          </button>
          {step < total - 1 ? (
            <button className="ct-btn ct-btn-primary" onClick={() => setStep(step + 1)}>
              Next
              <Icon name="arrow-right" size={13}/>
            </button>
          ) : (
            <button className="ct-btn ct-btn-primary" onClick={finish}>
              <Icon name="check" size={13}/>
              Finish
            </button>
          )}
        </div>
      </M.div>
    </A>
  );
}

Object.assign(window, { SettingsView, TrashView, SignInView, MarketingView, Brandmark, InstallView, AnimatedBrandmark, SplashScreen, OnboardingTour });
