Index: lan-frontend/.env
===================================================================
--- lan-frontend/.env	(revision 2058e5c694bb6097866a5fe6503c519e8f74970f)
+++ lan-frontend/.env	(revision 505f39ae7b51fc1db15123d66bf06aec0dca2f62)
@@ -1,1 +1,2 @@
-VITE_API_BASE=http://192.168.11.232:5555
+VITE_API_BASE=http://localhost:5555
+VITE_GOOGLE_CLIENT_ID=43542590862-pt18e0hb33o41889bu976oshddoemivs.apps.googleusercontent.com
Index: lan-frontend/package-lock.json
===================================================================
--- lan-frontend/package-lock.json	(revision 2058e5c694bb6097866a5fe6503c519e8f74970f)
+++ lan-frontend/package-lock.json	(revision 505f39ae7b51fc1db15123d66bf06aec0dca2f62)
@@ -9,4 +9,5 @@
       "version": "0.0.0",
       "dependencies": {
+        "@react-oauth/google": "^0.13.4",
         "chart.js": "^4.5.1",
         "react": "^19.2.0",
@@ -1014,4 +1015,14 @@
       "integrity": "sha512-M5UknZPHRu3DEDWoipU6sE8PdkZ6Z/S+v4dD+Ke8IaNlpdSQah50lz1KtcFBa2vsdOnwbbnxJwVM4wty6udA5w==",
       "license": "MIT"
+    },
+    "node_modules/@react-oauth/google": {
+      "version": "0.13.4",
+      "resolved": "https://registry.npmjs.org/@react-oauth/google/-/google-0.13.4.tgz",
+      "integrity": "sha512-hGKyNEH+/PK8M0sFEuo3MAEk0txtHpgs94tDQit+s2LXg7b6z53NtzHfqDvoB2X8O6lGB+FRg80hY//X6hfD+w==",
+      "license": "MIT",
+      "peerDependencies": {
+        "react": ">=16.8.0",
+        "react-dom": ">=16.8.0"
+      }
     },
     "node_modules/@reduxjs/toolkit": {
Index: lan-frontend/package.json
===================================================================
--- lan-frontend/package.json	(revision 2058e5c694bb6097866a5fe6503c519e8f74970f)
+++ lan-frontend/package.json	(revision 505f39ae7b51fc1db15123d66bf06aec0dca2f62)
@@ -11,4 +11,5 @@
   },
   "dependencies": {
+    "@react-oauth/google": "^0.13.4",
     "chart.js": "^4.5.1",
     "react": "^19.2.0",
Index: lan-frontend/src/App.jsx
===================================================================
--- lan-frontend/src/App.jsx	(revision 2058e5c694bb6097866a5fe6503c519e8f74970f)
+++ lan-frontend/src/App.jsx	(revision 505f39ae7b51fc1db15123d66bf06aec0dca2f62)
@@ -1,6 +1,6 @@
-import React from "react";
-import {useEffect, useMemo, useState} from "react";
+import React, {useEffect, useMemo, useState} from "react";
 import "./styles/theme.css";
 
+import Login from "./components/Login";
 import TopBar from "./components/TopBar";
 import ComputerCard from "./components/ComputerCard";
@@ -22,13 +22,40 @@
     const [selectedEnv, setSelectedEnv] = useState("default");
 
+    const [me, setMe] = useState(null);
+    const [meLoading, setMeLoading] = useState(true);
+
+    // const [openAI, setOpenAI] = useState(false);
+    // const [scope, setScope] = useState(null);
+
+
+    async function loadMe() {
+        setMeLoading(true);
+        try {
+            const r = await fetch("/api/me", {credentials: "include"});
+            if (r.ok) {
+                const data = await r.json();
+                setMe(data.user);
+            } else {
+                setMe(null);
+            }
+        } catch (e) {
+            console.error("loadMe error", e);
+            setMe(null);
+        } finally {
+            setMeLoading(false);
+        }
+    }
+
     async function refresh() {
         try {
             setLoading(true);
             const [s, c] = await Promise.all([
-                fetch("/api/stats").then((r) => r.json()),
+                fetch("/api/stats", {credentials: "include"}).then((r) => r.json()),
                 fetch("/api/computers", {
+                    credentials: "include",
                     headers: {"X-Env": selectedEnv},
                 }).then((r) => r.json()),
             ]);
+
             setStats(s);
             setComputers(Array.isArray(c) ? c : []);
@@ -41,7 +68,14 @@
     }
 
+    // on mount: check session
     useEffect(() => {
-        refresh();
-    }, [selectedEnv]);
+        loadMe();
+    }, []);
+
+    // when logged in OR env changed, refresh data
+    useEffect(() => {
+        if (me) refresh();
+        // eslint-disable-next-line react-hooks/exhaustive-deps
+    }, [me, selectedEnv]);
 
     const filtered = useMemo(() => {
@@ -51,8 +85,15 @@
             .filter((c) => {
                 if (!q) return true;
-                const hay = [c.name, c.user, c.ip, c.os, c.status].filter(Boolean).join(" ").toLowerCase();
+                const hay = [c.name, c.user, c.ip, c.os, c.status]
+                    .filter(Boolean)
+                    .join(" ")
+                    .toLowerCase();
                 return hay.includes(q);
             });
     }, [computers, query, status]);
+
+    // Gate UI
+    if (meLoading) return <div style={{padding: 20}}>Loading…</div>;
+    if (!me) return <Login onDone={loadMe}/>;
 
     return (
@@ -64,5 +105,8 @@
                 onEnvChange={(env) => setSelectedEnv(env)}
                 selectedEnv={selectedEnv}
+                me={me}
+                onLoggedOut={loadMe}
             />
+
 
             {/* STATS */}
@@ -104,5 +148,9 @@
                         />
 
-                        <select className="select" value={status} onChange={(e) => setStatus(e.target.value)}>
+                        <select
+                            className="select"
+                            value={status}
+                            onChange={(e) => setStatus(e.target.value)}
+                        >
                             <option value="">All status</option>
                             <option value="online">Online</option>
@@ -111,5 +159,7 @@
                         </select>
 
-                        <button className="btn primary" onClick={refresh}>Refresh</button>
+                        <button className="btn primary" onClick={refresh}>
+                            Refresh
+                        </button>
                     </div>
                 </div>
@@ -122,8 +172,12 @@
                     <div style={{display: "flex", gap: 10, alignItems: "center"}}>
                         <span className="pill">{filtered.length} computers</span>
-                        <button className="btn" onClick={() => {
-                            setQuery("");
-                            setStatus("");
-                        }}>Reset
+                        <button
+                            className="btn"
+                            onClick={() => {
+                                setQuery("");
+                                setStatus("");
+                            }}
+                        >
+                            Reset
                         </button>
                     </div>
@@ -142,5 +196,7 @@
                         ))}
                         {filtered.length === 0 && (
-                            <div style={{color: "var(--dim)"}}>No computers match filter.</div>
+                            <div style={{color: "var(--dim)"}}>
+                                No computers match filter.
+                            </div>
                         )}
                     </div>
@@ -160,4 +216,15 @@
 
             {/* AI DRAWER */}
+            {/*<button onClick={() => setOpenAI(true)}>AI</button>*/}
+
+            {/*<AIAssistantDrawer*/}
+            {/*    open={openAI}*/}
+            {/*    onClose={() => setOpenAI(false)}*/}
+            {/*    computers={computers}*/}
+            {/*    scope={scope}*/}
+            {/*    setScope={setScope}*/}
+            {/*    apiBase={import.meta.env.VITE_API_BASE}*/}
+            {/*/>*/}
+
             <AIAssistantDrawer
                 open={aiOpen}
@@ -166,5 +233,8 @@
                 scope={aiScope}
                 setScope={setAiScope}
+                apiBase={import.meta.env.VITE_API_BASE}
             />
+
+
         </div>
     );
Index: lan-frontend/src/components/AIAssistantDrawer.jsx
===================================================================
--- lan-frontend/src/components/AIAssistantDrawer.jsx	(revision 2058e5c694bb6097866a5fe6503c519e8f74970f)
+++ lan-frontend/src/components/AIAssistantDrawer.jsx	(revision 505f39ae7b51fc1db15123d66bf06aec0dca2f62)
@@ -1,83 +1,138 @@
-import React from "react";
+import React, {useEffect, useRef, useState} from "react";
 
-import { useEffect, useRef, useState } from "react";
+export default function AIAssistantDrawer({
+                                              open,
+                                              onClose,
+                                              computers,
+                                              scope,
+                                              setScope,
+                                              apiBase = "", // ако сакаш можеш да пратиш VITE_API_BASE тука
+                                          }) {
+    const [messages, setMessages] = useState([
+        {
+            role: "assistant",
+            text: "Постави прашање за Sysmon, процеси, мрежа. Можеш да избереш компјутер (scope) горе.",
+        },
+    ]);
+    const [input, setInput] = useState("");
+    const [sending, setSending] = useState(false);
+    const bottomRef = useRef(null);
 
-export default function AIAssistantDrawer({ open, onClose, computers, scope, setScope }) {
-  const [messages, setMessages] = useState([
-    { role: "assistant", text: "Постави прашање за Sysmon, процеси, мрежа. Можеш да избереш компјутер (scope) горе." },
-  ]);
-  const [input, setInput] = useState("");
-  const [sending, setSending] = useState(false);
-  const bottomRef = useRef(null);
+    useEffect(() => {
+        if (open) {
+            // затвори со Escape
+            const onKey = (e) => {
+                if (e.key === "Escape") onClose?.();
+            };
+            window.addEventListener("keydown", onKey);
+            return () => window.removeEventListener("keydown", onKey);
+        }
+    }, [open, onClose]);
 
-  useEffect(() => {
-    if (bottomRef.current) bottomRef.current.scrollIntoView({ behavior: "smooth" });
-  }, [messages, open]);
+    useEffect(() => {
+        if (bottomRef.current) bottomRef.current.scrollIntoView({behavior: "smooth"});
+    }, [messages, open]);
 
-  async function send() {
-    const q = input.trim();
-    if (!q || sending) return;
+    async function send() {
+        const q = input.trim();
+        if (!q || sending) return;
 
-    setInput("");
-    setMessages((m) => [...m, { role: "user", text: q }]);
-    setSending(true);
+        setInput("");
+        setMessages((m) => [...m, {role: "user", text: q}]);
+        setSending(true);
 
-    try {
-      const r = await fetch("/api/chat", {
-        method: "POST",
-        headers: { "Content-Type": "application/json" },
-        body: JSON.stringify({ question: q, computer_name: scope || null }),
-      });
-      const data = await r.json();
-      setMessages((m) => [...m, { role: "assistant", text: data.answer || "(no answer)" }]);
-    } catch (e) {
-      setMessages((m) => [...m, { role: "assistant", text: `Грешка: ${String(e.message || e)}` }]);
-    } finally {
-      setSending(false);
+        try {
+            const base = (apiBase || "").replace(/\/$/, ""); // тргни trailing /
+            const url = `${base}/api/chat`;
+
+            const r = await fetch(url, {
+                method: "POST",
+                headers: {"Content-Type": "application/json"},
+                credentials: "include",
+                body: JSON.stringify({question: q, computer_name: scope || null}),
+            });
+
+
+            const data = await r.json().catch(() => ({}));
+            if (!r.ok) {
+                setMessages((m) => [...m, {
+                    role: "assistant",
+                    text: `Error ${r.status}: ${data.error || "Request failed"}`
+                }]);
+            } else {
+                setMessages((m) => [...m, {role: "assistant", text: data.answer || "(no answer)"}]);
+            }
+            setMessages((m) => [
+                ...m,
+                {role: "assistant", text: data.answer || "(no answer)"},
+            ]);
+        } catch (e) {
+            setMessages((m) => [
+                ...m,
+                {role: "assistant", text: `Грешка: ${String(e?.message || e)}`},
+            ]);
+        } finally {
+            setSending(false);
+        }
     }
-  }
 
-  if (!open) return null;
+    if (!open) return null;
 
-  return (
-    <>
-      <div className="drawer-backdrop" onMouseDown={onClose} />
-      <div className="drawer" onMouseDown={(e) => e.stopPropagation()}>
-        <div className="drawer-head">
-          <div>
-            <div className="drawer-title">🤖 AI Assistant</div>
-            <div className="drawer-sub">Uses /api/chat (RAG over your logs)</div>
-          </div>
-          <button className="btn" onClick={onClose}>Close</button>
-        </div>
+    return (
+        <>
+            <div className="aiDrawer-backdrop" onMouseDown={onClose}/>
 
-        <div style={{ padding: "12px 16px", borderBottom: "1px solid var(--border)" }}>
-          <div className="row">
-            <select className="select" value={scope || ""} onChange={(e) => setScope(e.target.value || null)}>
-              <option value="">All computers</option>
-              {(computers || []).map((c) => (
-                <option key={c.name} value={c.name}>{c.name}</option>
-              ))}
-            </select>
-          </div>
-          <div className="small">Tip: “Top процеси по RAM” или “сомнителни sysmon events”</div>
-        </div>
+            <aside
+                className="aiDrawer"
+                role="dialog"
+                aria-modal="true"
+                onMouseDown={(e) => e.stopPropagation()}
+            >
+                <header className="aiDrawer-head">
+                    <div>
+                        <div className="aiDrawer-title">🤖 AI Assistant</div>
+                        <div className="aiDrawer-sub">RAG over your logs</div>
+                    </div>
 
-        <div className="drawer-body">
-          {messages.map((m, i) => (
-            <div key={i} className={`bubble ${m.role === "user" ? "user" : ""}`}>
-              <div style={{ fontSize: 11, color: "var(--dim)", marginBottom: 6 }}>
-                {m.role === "user" ? "You" : "Assistant"}
-              </div>
-              <div style={{ whiteSpace: "pre-wrap" }}>{m.text}</div>
-            </div>
-          ))}
-          <div ref={bottomRef} />
-        </div>
+                    <button className="aiBtn" onClick={onClose} aria-label="Close">
+                        ✕
+                    </button>
+                </header>
 
-        <div className="drawer-foot">
-          <div className="row">
-            <textarea
-              className="textarea"
+                <div className="aiDrawer-toolbar">
+                    <select
+                        className="aiSelect"
+                        value={scope || ""}
+                        onChange={(e) => setScope(e.target.value || null)}
+                    >
+                        <option value="">All computers</option>
+                        {(computers || []).map((c) => (
+                            <option key={c.name} value={c.name}>
+                                {c.name}
+                            </option>
+                        ))}
+                    </select>
+
+                    <div className="aiHint">
+                        Tip: “Top процеси по RAM” / “сомнителни sysmon events”
+                    </div>
+                </div>
+
+                <main className="aiDrawer-body">
+                    {messages.map((m, i) => (
+                        <div
+                            key={i}
+                            className={`aiMsg ${m.role === "user" ? "user" : "assistant"}`}
+                        >
+                            <div className="aiMsg-meta">{m.role === "user" ? "You" : "Assistant"}</div>
+                            <div className="aiMsg-text">{m.text}</div>
+                        </div>
+                    ))}
+                    <div ref={bottomRef}/>
+                </main>
+
+                <footer className="aiDrawer-foot">
+          <textarea
+              className="aiTextarea"
               rows={2}
               value={input}
@@ -85,17 +140,20 @@
               onChange={(e) => setInput(e.target.value)}
               onKeyDown={(e) => {
-                if (e.key === "Enter" && !e.shiftKey) {
-                  e.preventDefault();
-                  send();
-                }
+                  if (e.key === "Enter" && !e.shiftKey) {
+                      e.preventDefault();
+                      send();
+                  }
               }}
-            />
-            <button className="btn primary" onClick={send} disabled={sending || !input.trim()}>
-              {sending ? "Sending…" : "Send"}
-            </button>
-          </div>
-        </div>
-      </div>
-    </>
-  );
+          />
+                    <button
+                        className="aiBtn aiBtnPrimary"
+                        onClick={send}
+                        disabled={sending || !input.trim()}
+                    >
+                        {sending ? "Sending…" : "Send"}
+                    </button>
+                </footer>
+            </aside>
+        </>
+    );
 }
Index: lan-frontend/src/components/ComputerDetailsModal.jsx
===================================================================
--- lan-frontend/src/components/ComputerDetailsModal.jsx	(revision 2058e5c694bb6097866a5fe6503c519e8f74970f)
+++ lan-frontend/src/components/ComputerDetailsModal.jsx	(revision 505f39ae7b51fc1db15123d66bf06aec0dca2f62)
@@ -2,5 +2,5 @@
 
 function severityForEventId(eventId) {
-  const id = parseInt(eventId, 10);
+  const id = Number.parseInt(String(eventId ?? ""), 10);
   const high = new Set([1, 3, 8, 10]);
   const med = new Set([5, 6, 7, 11, 22]);
@@ -10,15 +10,48 @@
 }
 
+function fmtTime(ts) {
+  if (!ts) return "—";
+  try {
+    return new Date(ts).toLocaleTimeString();
+  } catch {
+    return String(ts);
+  }
+}
+
 export default function ComputerDetailsModal({ open, computer, onClose, onAskAI }) {
   const [tab, setTab] = useState("overview");
   const [loading, setLoading] = useState(false);
   const [details, setDetails] = useState(null);
+  const [error, setError] = useState("");
   const [search, setSearch] = useState("");
 
-  // JSON viewer state
+  // JSON viewer
   const [jsonOpen, setJsonOpen] = useState(false);
   const [jsonTitle, setJsonTitle] = useState("");
   const [jsonData, setJsonData] = useState(null);
 
+  // reset when opening / switching pc
+  useEffect(() => {
+    if (!open) return;
+    setTab("overview");
+    setSearch("");
+    setError("");
+    setDetails(null);
+    setJsonOpen(false);
+    setJsonTitle("");
+    setJsonData(null);
+  }, [open, computer?.name]);
+
+  // close on ESC
+  useEffect(() => {
+    if (!open) return;
+    const onKey = (e) => {
+      if (e.key === "Escape") onClose?.();
+    };
+    window.addEventListener("keydown", onKey);
+    return () => window.removeEventListener("keydown", onKey);
+  }, [open, onClose]);
+
+  // load details
   useEffect(() => {
     if (!open || !computer?.name) return;
@@ -26,11 +59,18 @@
 
     async function load() {
+      setLoading(true);
+      setError("");
       try {
-        setLoading(true);
-        const r = await fetch(`/api/computer/${encodeURIComponent(computer.name)}`);
-        const d = await r.json();
+        const r = await fetch(`/api/computer/${encodeURIComponent(computer.name)}`, {
+          credentials: "include",
+        });
+        const d = await r.json().catch(() => ({}));
+        if (!r.ok) throw new Error(d?.error || `HTTP ${r.status}`);
         if (!cancelled) setDetails(d);
       } catch (e) {
-        console.error("details error", e);
+        if (!cancelled) {
+          setError(String(e?.message || e));
+          setDetails(null);
+        }
       } finally {
         if (!cancelled) setLoading(false);
@@ -51,5 +91,5 @@
       const msg = (ev.message || "").toLowerCase();
       const type = (ev.event_type || "").toLowerCase();
-      const id = String(ev.event_id ?? "");
+      const id = String(ev.event_id ?? "").toLowerCase();
       return msg.includes(q) || type.includes(q) || id.includes(q);
     });
@@ -57,7 +97,6 @@
 
   function openJson(ev) {
-    // server ти враќа: { event_id, event_type, message, timestamp, details }
     setJsonTitle(`Sysmon Event ${ev?.event_id ?? ""} • ${ev?.event_type ?? ""}`);
-    setJsonData(ev?.details ?? ev); // ако нема details, покажи цел event
+    setJsonData(ev?.details ?? ev);
     setJsonOpen(true);
   }
@@ -73,30 +112,230 @@
   return (
     <>
-      <div className="backdrop" onMouseDown={onClose}>
-        <div className="modal" onMouseDown={(e) => e.stopPropagation()}>
-          <div className="modal-head">
+      <style>{`
+        .cdm-backdrop{
+          position: fixed; inset: 0; z-index: 60;
+          background: rgba(2,6,23,0.70);
+          backdrop-filter: blur(6px);
+          display:flex; align-items:center; justify-content:center;
+          padding: 18px;
+        }
+        .cdm-modal{
+          width: min(1100px, 96vw);
+          height: min(86vh, 860px);
+          display:flex; flex-direction:column;
+          border-radius: 18px;
+          background: radial-gradient(900px 420px at 20% 0%, rgba(96,165,250,0.18), transparent 60%),
+                      radial-gradient(700px 350px at 80% 10%, rgba(34,211,238,0.10), transparent 55%),
+                      rgba(10,16,32,0.92);
+          border: 1px solid rgba(96,165,250,0.20);
+          box-shadow: 0 30px 80px rgba(0,0,0,0.45);
+          overflow: hidden;
+        }
+        .cdm-head{
+          padding: 14px 16px;
+          border-bottom: 1px solid rgba(96,165,250,0.16);
+          display:flex; align-items:center; justify-content:space-between; gap:12px;
+        }
+        .cdm-title{ font-size: 16px; font-weight: 900; color: rgba(255,255,255,0.95); }
+        .cdm-sub{ margin-top: 2px; font-size: 12px; color: rgba(191,219,254,0.80); }
+        .cdm-right{ display:flex; align-items:center; gap:10px; flex-wrap:wrap; justify-content:flex-end; }
+        .cdm-tabs{
+          display:flex; gap:8px; padding: 6px;
+          background: rgba(15,23,42,0.45);
+          border: 1px solid rgba(96,165,250,0.18);
+          border-radius: 999px;
+        }
+        .cdm-tab{
+          appearance:none; border: 0;
+          padding: 8px 12px;
+          border-radius: 999px;
+          background: transparent;
+          color: rgba(226,232,240,0.88);
+          font-weight: 900;
+          font-size: 12px;
+          cursor:pointer;
+          transition: background .12s ease, transform .12s ease, color .12s ease;
+        }
+        .cdm-tab:hover{ transform: translateY(-1px); background: rgba(30,41,59,0.55); }
+        .cdm-tab.active{
+          background: linear-gradient(135deg, rgba(37,99,235,0.95), rgba(56,189,248,0.65));
+          color: rgba(5,12,24,0.95);
+        }
+        .cdm-btn{
+          appearance:none;
+          border: 1px solid rgba(96,165,250,0.22);
+          background: rgba(15,23,42,0.55);
+          color: rgba(255,255,255,0.92);
+          padding: 9px 12px;
+          border-radius: 12px;
+          font-weight: 900;
+          font-size: 13px;
+          cursor: pointer;
+          transition: transform .12s ease, background .12s ease, border-color .12s ease, opacity .12s ease;
+          box-shadow: 0 8px 20px rgba(0,0,0,0.18);
+        }
+        .cdm-btn:hover{ transform: translateY(-1px); background: rgba(30,41,59,0.65); border-color: rgba(96,165,250,0.38); }
+        .cdm-btn:disabled{ opacity: .6; cursor: not-allowed; transform:none; }
+        .cdm-btn.primary{
+          background: linear-gradient(135deg, rgba(37,99,235,0.95), rgba(56,189,248,0.65));
+          border-color: rgba(147,197,253,0.35);
+          color: rgba(5,12,24,0.95);
+        }
+
+        /* body scroll zone */
+        .cdm-body{
+          flex: 1;
+          display:flex;
+          flex-direction:column;
+          min-height: 0; /* important for scroll */
+        }
+        .cdm-content{
+          flex: 1;
+          min-height: 0;
+          overflow: auto;
+          padding: 14px 16px 18px;
+        }
+
+        .cdm-panel{
+          border-radius: 16px;
+          background: rgba(15,23,42,0.55);
+          border: 1px solid rgba(96,165,250,0.16);
+          overflow: hidden;
+        }
+        .cdm-panel-head{
+          padding: 12px 12px;
+          display:flex; align-items:center; justify-content:space-between; gap:10px;
+          border-bottom: 1px solid rgba(96,165,250,0.14);
+        }
+        .cdm-panel-title{ color: rgba(255,255,255,0.92); font-weight: 900; }
+        .cdm-panel-body{ padding: 12px; }
+
+        /* table area scroll fix */
+        .cdm-table-wrap{
+          border-radius: 14px;
+          border: 1px solid rgba(148,163,184,0.18);
+          background: rgba(2,6,23,0.28);
+          overflow: hidden;
+        }
+        .cdm-table-scroll{
+          max-height: 52vh;
+          overflow: auto;
+        }
+        table{ width: 100%; border-collapse: collapse; }
+        thead th{
+          position: sticky; top: 0;
+          background: rgba(10,16,32,0.95);
+          backdrop-filter: blur(8px);
+          text-align:left;
+          font-size: 12px;
+          color: rgba(191,219,254,0.88);
+          padding: 10px 10px;
+          border-bottom: 1px solid rgba(96,165,250,0.16);
+          z-index: 1;
+        }
+        tbody td{
+          padding: 10px 10px;
+          border-bottom: 1px solid rgba(148,163,184,0.12);
+          color: rgba(226,232,240,0.92);
+          font-size: 13px;
+          vertical-align: top;
+        }
+        tbody tr:hover td{ background: rgba(30,41,59,0.35); }
+
+        .cdm-pill{
+          display:inline-flex; align-items:center; gap:8px;
+          padding: 6px 10px;
+          border-radius: 999px;
+          background: rgba(30,41,59,0.55);
+          border: 1px solid rgba(96,165,250,0.18);
+          color: rgba(255,255,255,0.9);
+          font-weight: 900;
+          font-size: 12px;
+        }
+        .cdm-input{
+          width: min(420px, 45vw);
+          padding: 9px 12px;
+          border-radius: 12px;
+          border: 1px solid rgba(96,165,250,0.18);
+          background: rgba(2,6,23,0.35);
+          color: rgba(255,255,255,0.92);
+          outline: none;
+          font-weight: 800;
+        }
+        .cdm-input::placeholder{ color: rgba(148,163,184,0.75); }
+
+        .cdm-badge{
+          display:inline-flex; align-items:center; justify-content:center;
+          padding: 5px 10px;
+          border-radius: 999px;
+          font-weight: 1000;
+          font-size: 11px;
+          letter-spacing: .3px;
+          border: 1px solid rgba(148,163,184,0.18);
+          background: rgba(15,23,42,0.5);
+          color: rgba(226,232,240,0.95);
+        }
+        .cdm-badge.high{ border-color: rgba(239,68,68,0.35); color: rgba(254,202,202,0.95); }
+        .cdm-badge.medium{ border-color: rgba(251,191,36,0.35); color: rgba(254,243,199,0.95); }
+        .cdm-badge.low{ border-color: rgba(34,197,94,0.25); color: rgba(220,252,231,0.95); }
+
+        /* JSON modal */
+        .cdm-json-modal{
+          width: min(980px, 96vw);
+          height: min(82vh, 860px);
+          display:flex; flex-direction:column;
+          border-radius: 18px;
+          background: rgba(10,16,32,0.94);
+          border: 1px solid rgba(96,165,250,0.20);
+          overflow:hidden;
+        }
+        .cdm-json-body{
+          flex:1; min-height:0; overflow:auto; padding: 14px 16px 18px;
+        }
+        .cdm-pre{
+          margin: 0;
+          padding: 14px;
+          border-radius: 12px;
+          border: 1px solid rgba(148,163,184,0.22);
+          background: rgba(2,6,23,0.35);
+          color: rgba(226,232,240,0.95);
+          font-size: 12px;
+          line-height: 1.5;
+          white-space: pre-wrap;
+          word-break: break-word;
+        }
+      `}</style>
+
+      <div className="cdm-backdrop" onMouseDown={onClose}>
+        <div className="cdm-modal" onMouseDown={(e) => e.stopPropagation()}>
+          <div className="cdm-head">
             <div>
-              <div className="modal-title">{computer.name}</div>
-              <div className="modal-sub">
-                {computer.ip || "—"} • {computer.user || "—"} • {computer.status || "—"}
+              <div className="cdm-title">{computer?.name || "Computer"}</div>
+              <div className="cdm-sub">
+                {computer?.ip || "—"} • {computer?.user || "—"} • {computer?.status || "—"}
               </div>
             </div>
 
-            <div style={{ display: "flex", gap: 10, alignItems: "center" }}>
-              <div className="tabs">
-                <button className={`tab ${tab === "overview" ? "active" : ""}`} onClick={() => setTab("overview")}>
+            <div className="cdm-right">
+              <button className="cdm-btn primary" onClick={() => onAskAI?.(computer?.name)} disabled={!computer?.name}>
+                Ask AI
+              </button>
+
+              <div className="cdm-tabs">
+                <button className={`cdm-tab ${tab === "overview" ? "active" : ""}`} onClick={() => setTab("overview")}>
                   Overview
                 </button>
-                <button className={`tab ${tab === "sysmon" ? "active" : ""}`} onClick={() => setTab("sysmon")}>
+                <button className={`cdm-tab ${tab === "sysmon" ? "active" : ""}`} onClick={() => setTab("sysmon")}>
                   Sysmon
                 </button>
-                <button className={`tab ${tab === "processes" ? "active" : ""}`} onClick={() => setTab("processes")}>
+                <button className={`cdm-tab ${tab === "processes" ? "active" : ""}`} onClick={() => setTab("processes")}>
                   Processes
                 </button>
-                <button className={`tab ${tab === "network" ? "active" : ""}`} onClick={() => setTab("network")}>
+                <button className={`cdm-tab ${tab === "network" ? "active" : ""}`} onClick={() => setTab("network")}>
                   Network
                 </button>
               </div>
-              <button className="btn" onClick={onClose}>
+
+              <button className="cdm-btn" onClick={onClose}>
                 Close
               </button>
@@ -104,276 +343,240 @@
           </div>
 
-          <div style={{ padding: 16 }}>
-            {loading && <div style={{ color: "#94a3b8" }}>Loading…</div>}
-
-            {!loading && details && tab === "overview" && (
-              <div className="panel">
-                <div className="panel-head">
-                  <div className="panel-title">System Overview</div>
-                  <button className="btn primary" onClick={() => onAskAI(computer.name)}>
-                    Ask AI about this PC
-                  </button>
+          <div className="cdm-body">
+            <div className="cdm-content">
+              {loading && <div style={{ color: "rgba(148,163,184,0.95)" }}>Loading…</div>}
+
+              {!loading && error && (
+                <div className="cdm-panel" style={{ borderColor: "rgba(239,68,68,0.35)" }}>
+                  <div className="cdm-panel-head">
+                    <div className="cdm-panel-title">Error</div>
+                  </div>
+                  <div className="cdm-panel-body" style={{ color: "rgba(254,202,202,0.95)" }}>
+                    {error}
+                  </div>
                 </div>
-                <div className="panel-body" style={{ display: "grid", gap: 10 }}>
-                  <div>
-                    <b>User:</b> {details.computer?.user}
-                  </div>
-                  <div>
-                    <b>IP:</b> {details.computer?.ip}
-                  </div>
-                  <div>
-                    <b>OS:</b> {details.computer?.os}
-                  </div>
-                  <div>
-                    <b>First seen:</b> {details.computer?.first_seen}
-                  </div>
-                  <div>
-                    <b>Last seen:</b> {details.computer?.last_seen}
-                  </div>
-                  <div>
-                    <b>Total logs:</b> {details.computer?.total_logs}
+              )}
+
+              {!loading && !error && details && tab === "overview" && (
+                <div className="cdm-panel">
+                  <div className="cdm-panel-head">
+                    <div className="cdm-panel-title">System Overview</div>
+                    <span className="cdm-pill">Env: {details.computer?.env_name || "default"}</span>
+                  </div>
+                  <div className="cdm-panel-body" style={{ display: "grid", gap: 10 }}>
+                    <div><b>User:</b> {details.computer?.user || "—"}</div>
+                    <div><b>IP:</b> {details.computer?.ip || "—"}</div>
+                    <div><b>OS:</b> {details.computer?.os || "—"}</div>
+                    <div><b>First seen:</b> {details.computer?.first_seen || "—"}</div>
+                    <div><b>Last seen:</b> {details.computer?.last_seen || "—"}</div>
+                    <div><b>Total logs:</b> {details.computer?.total_logs ?? "—"}</div>
                   </div>
                 </div>
-              </div>
-            )}
-
-            {!loading && details && tab === "sysmon" && (
-              <div className="panel">
-                <div className="panel-head" style={{ alignItems: "center" }}>
-                  <div className="panel-title">Sysmon Events</div>
-                  <div style={{ display: "flex", gap: 10, alignItems: "center" }}>
-                    <span className="pill">{filteredSysmon.length} events</span>
-                    <input
-                      className="input"
-                      style={{ maxWidth: 380 }}
-                      placeholder="Search by id / type / message…"
-                      value={search}
-                      onChange={(e) => setSearch(e.target.value)}
-                    />
+              )}
+
+              {!loading && !error && details && tab === "sysmon" && (
+                <div className="cdm-panel">
+                  <div className="cdm-panel-head">
+                    <div className="cdm-panel-title">Sysmon Events</div>
+                    <div style={{ display: "flex", gap: 10, alignItems: "center" }}>
+                      <span className="cdm-pill">{filteredSysmon.length} events</span>
+                      <input
+                        className="cdm-input"
+                        placeholder="Search by id / type / message…"
+                        value={search}
+                        onChange={(e) => setSearch(e.target.value)}
+                      />
+                    </div>
+                  </div>
+
+                  <div className="cdm-panel-body">
+                    <div className="cdm-table-wrap">
+                      <div className="cdm-table-scroll">
+                        <table>
+                          <thead>
+                            <tr>
+                              <th style={{ width: 90 }}>Time</th>
+                              <th style={{ width: 70 }}>ID</th>
+                              <th style={{ width: 190 }}>Type</th>
+                              <th style={{ width: 110 }}>Severity</th>
+                              <th>Message</th>
+                              <th style={{ width: 90 }}>View</th>
+                            </tr>
+                          </thead>
+                          <tbody>
+                            {filteredSysmon.slice(0, 400).map((ev, idx) => {
+                              const sev = severityForEventId(ev.event_id);
+                              return (
+                                <tr key={idx}>
+                                  <td>{fmtTime(ev.timestamp)}</td>
+                                  <td><b>{ev.event_id ?? "—"}</b></td>
+                                  <td>{ev.event_type || "—"}</td>
+                                  <td><span className={`cdm-badge ${sev}`}>{sev.toUpperCase()}</span></td>
+                                  <td style={{ fontFamily: "ui-monospace, SFMono-Regular, Menlo, monospace", fontSize: 12 }}>
+                                    {(ev.message || "").slice(0, 220)}
+                                  </td>
+                                  <td>
+                                    <button className="cdm-btn" onClick={() => openJson(ev)}>
+                                      View
+                                    </button>
+                                  </td>
+                                </tr>
+                              );
+                            })}
+
+                            {filteredSysmon.length === 0 && (
+                              <tr>
+                                <td colSpan="6" style={{ color: "rgba(148,163,184,0.95)" }}>
+                                  No sysmon events.
+                                </td>
+                              </tr>
+                            )}
+                          </tbody>
+                        </table>
+                      </div>
+                    </div>
+                    {filteredSysmon.length > 400 && (
+                      <div style={{ marginTop: 10, color: "rgba(148,163,184,0.95)", fontSize: 12 }}>
+                        Showing first 400 (for speed).
+                      </div>
+                    )}
                   </div>
                 </div>
-
-                <div className="panel-body">
-                  <div className="table-wrap">
-                    <table>
-                      <thead>
-                        <tr>
-                          <th style={{ width: 90 }}>Time</th>
-                          <th style={{ width: 70 }}>ID</th>
-                          <th style={{ width: 170 }}>Type</th>
-                          <th style={{ width: 110 }}>Severity</th>
-                          <th>Message</th>
-                          <th style={{ width: 90 }}>View</th>
-                        </tr>
-                      </thead>
-                      <tbody>
-                        {filteredSysmon.slice(0, 200).map((ev, idx) => {
-                          const sev = severityForEventId(ev.event_id);
-                          return (
-                            <tr key={idx}>
-                              <td>{ev.timestamp ? new Date(ev.timestamp).toLocaleTimeString() : "—"}</td>
-                              <td>
-                                <b>{ev.event_id}</b>
-                              </td>
-                              <td>{ev.event_type}</td>
-                              <td>
-                                <span className={`badge ${sev}`}>{sev.toUpperCase()}</span>
-                              </td>
-                              <td
-                                style={{
-                                  fontFamily: "ui-monospace, SFMono-Regular, Menlo, monospace",
-                                  fontSize: 12,
-                                }}
-                              >
-                                {(ev.message || "").slice(0, 140)}
-                              </td>
-                              <td>
-                                <button className="btn" onClick={() => openJson(ev)}>
-                                  View
-                                </button>
-                              </td>
+              )}
+
+              {!loading && !error && details && tab === "processes" && (
+                <div className="cdm-panel">
+                  <div className="cdm-panel-head">
+                    <div className="cdm-panel-title">Recent Processes</div>
+                    <span className="cdm-pill">{(details.recent_processes || []).length} rows</span>
+                  </div>
+
+                  <div className="cdm-panel-body">
+                    <div className="cdm-table-wrap">
+                      <div className="cdm-table-scroll">
+                        <table>
+                          <thead>
+                            <tr>
+                              <th style={{ width: 90 }}>Time</th>
+                              <th style={{ width: 80 }}>PID</th>
+                              <th style={{ width: 200 }}>Name</th>
+                              <th style={{ width: 140 }}>User</th>
+                              <th style={{ width: 90 }}>CPU%</th>
+                              <th style={{ width: 110 }}>RAM MB</th>
+                              <th>Cmdline</th>
                             </tr>
-                          );
-                        })}
-
-                        {filteredSysmon.length === 0 && (
-                          <tr>
-                            <td colSpan="6" style={{ color: "#94a3b8" }}>
-                              No sysmon events.
-                            </td>
-                          </tr>
-                        )}
-                      </tbody>
-                    </table>
-                  </div>
-
-                  {filteredSysmon.length > 200 && (
-                    <div style={{ marginTop: 10, color: "#94a3b8", fontSize: 12 }}>
-                      Showing first 200 (for speed).
+                          </thead>
+                          <tbody>
+                            {(details.recent_processes || []).slice(0, 400).map((p, idx) => (
+                              <tr key={idx}>
+                                <td>{fmtTime(p.timestamp)}</td>
+                                <td><b>{p.pid ?? "—"}</b></td>
+                                <td>{p.name || "—"}</td>
+                                <td>{p.username || "—"}</td>
+                                <td>{p.cpu_percent ?? 0}</td>
+                                <td>{p.memory_mb ?? 0}</td>
+                                <td style={{ fontFamily: "ui-monospace, SFMono-Regular, Menlo, monospace", fontSize: 12 }}>
+                                  {(p.cmdline || "").slice(0, 220)}
+                                </td>
+                              </tr>
+                            ))}
+                            {(details.recent_processes || []).length === 0 && (
+                              <tr>
+                                <td colSpan="7" style={{ color: "rgba(148,163,184,0.95)" }}>
+                                  No process data.
+                                </td>
+                              </tr>
+                            )}
+                          </tbody>
+                        </table>
+                      </div>
                     </div>
-                  )}
+                  </div>
                 </div>
-              </div>
-            )}
-
-            {!loading && details && tab === "processes" && (
-              <div className="panel">
-                <div className="panel-head">
-                  <div className="panel-title">Recent Processes</div>
+              )}
+
+              {!loading && !error && details && tab === "network" && (
+                <div className="cdm-panel">
+                  <div className="cdm-panel-head">
+                    <div className="cdm-panel-title">Network Connections</div>
+                    <span className="cdm-pill">{(details.network_connections || []).length} rows</span>
+                  </div>
+
+                  <div className="cdm-panel-body">
+                    <div className="cdm-table-wrap">
+                      <div className="cdm-table-scroll">
+                        <table>
+                          <thead>
+                            <tr>
+                              <th style={{ width: 90 }}>Time</th>
+                              <th style={{ width: 80 }}>PID</th>
+                              <th style={{ width: 180 }}>Process</th>
+                              <th style={{ width: 220 }}>Local</th>
+                              <th style={{ width: 220 }}>Remote</th>
+                              <th style={{ width: 140 }}>Status</th>
+                            </tr>
+                          </thead>
+                          <tbody>
+                            {(details.network_connections || []).slice(0, 400).map((n, idx) => (
+                              <tr key={idx}>
+                                <td>{fmtTime(n.timestamp)}</td>
+                                <td><b>{n.pid ?? "—"}</b></td>
+                                <td>{n.process_name || "—"}</td>
+                                <td style={{ fontFamily: "ui-monospace, SFMono-Regular, Menlo, monospace", fontSize: 12 }}>
+                                  {n.local_address || "—"}
+                                </td>
+                                <td style={{ fontFamily: "ui-monospace, SFMono-Regular, Menlo, monospace", fontSize: 12 }}>
+                                  {n.remote_address || "—"}
+                                </td>
+                                <td>{n.status || "—"}</td>
+                              </tr>
+                            ))}
+                            {(details.network_connections || []).length === 0 && (
+                              <tr>
+                                <td colSpan="6" style={{ color: "rgba(148,163,184,0.95)" }}>
+                                  No network data.
+                                </td>
+                              </tr>
+                            )}
+                          </tbody>
+                        </table>
+                      </div>
+                    </div>
+                  </div>
                 </div>
-                <div className="panel-body">
-                  <div className="table-wrap">
-                    <table>
-                      <thead>
-                        <tr>
-                          <th>Time</th>
-                          <th>PID</th>
-                          <th>Name</th>
-                          <th>User</th>
-                          <th>CPU%</th>
-                          <th>RAM MB</th>
-                          <th>Cmdline</th>
-                        </tr>
-                      </thead>
-                      <tbody>
-                        {(details.recent_processes || []).slice(0, 150).map((p, idx) => (
-                          <tr key={idx}>
-                            <td>{p.timestamp ? new Date(p.timestamp).toLocaleTimeString() : "—"}</td>
-                            <td>
-                              <b>{p.pid}</b>
-                            </td>
-                            <td>{p.name}</td>
-                            <td>{p.username || "—"}</td>
-                            <td>{p.cpu_percent ?? 0}</td>
-                            <td>{p.memory_mb ?? 0}</td>
-                            <td
-                              style={{
-                                fontFamily: "ui-monospace, SFMono-Regular, Menlo, monospace",
-                                fontSize: 12,
-                              }}
-                            >
-                              {(p.cmdline || "").slice(0, 120)}
-                            </td>
-                          </tr>
-                        ))}
-                        {(details.recent_processes || []).length === 0 && (
-                          <tr>
-                            <td colSpan="7" style={{ color: "#94a3b8" }}>
-                              No process data.
-                            </td>
-                          </tr>
-                        )}
-                      </tbody>
-                    </table>
-                  </div>
-                </div>
-              </div>
-            )}
-
-            {!loading && details && tab === "network" && (
-              <div className="panel">
-                <div className="panel-head">
-                  <div className="panel-title">Network Connections</div>
-                </div>
-                <div className="panel-body">
-                  <div className="table-wrap">
-                    <table>
-                      <thead>
-                        <tr>
-                          <th>Time</th>
-                          <th>PID</th>
-                          <th>Process</th>
-                          <th>Local</th>
-                          <th>Remote</th>
-                          <th>Status</th>
-                        </tr>
-                      </thead>
-                      <tbody>
-                        {(details.network_connections || []).slice(0, 150).map((n, idx) => (
-                          <tr key={idx}>
-                            <td>{n.timestamp ? new Date(n.timestamp).toLocaleTimeString() : "—"}</td>
-                            <td>
-                              <b>{n.pid}</b>
-                            </td>
-                            <td>{n.process_name || "—"}</td>
-                            <td
-                              style={{
-                                fontFamily: "ui-monospace, SFMono-Regular, Menlo, monospace",
-                                fontSize: 12,
-                              }}
-                            >
-                              {n.local_address || "—"}
-                            </td>
-                            <td
-                              style={{
-                                fontFamily: "ui-monospace, SFMono-Regular, Menlo, monospace",
-                                fontSize: 12,
-                              }}
-                            >
-                              {n.remote_address || "—"}
-                            </td>
-                            <td>{n.status || "—"}</td>
-                          </tr>
-                        ))}
-                        {(details.network_connections || []).length === 0 && (
-                          <tr>
-                            <td colSpan="6" style={{ color: "#94a3b8" }}>
-                              No network data.
-                            </td>
-                          </tr>
-                        )}
-                      </tbody>
-                    </table>
-                  </div>
-                </div>
-              </div>
-            )}
-
-            {!loading && !details && <div style={{ color: "#94a3b8" }}>No details.</div>}
+              )}
+
+              {!loading && !error && !details && (
+                <div style={{ color: "rgba(148,163,184,0.95)" }}>No details.</div>
+              )}
+            </div>
           </div>
         </div>
       </div>
 
-      {/* JSON VIEWER MODAL */}
+      {/* JSON VIEWER */}
       {jsonOpen && (
-        <div className="backdrop" onMouseDown={closeJson}>
-          <div className="modal" onMouseDown={(e) => e.stopPropagation()} style={{ width: "min(900px, 96vw)" }}>
-            <div className="modal-head">
+        <div className="cdm-backdrop" onMouseDown={closeJson}>
+          <div className="cdm-json-modal" onMouseDown={(e) => e.stopPropagation()}>
+            <div className="cdm-head">
               <div>
-                <div className="modal-title">View JSON</div>
-                <div className="modal-sub">{jsonTitle}</div>
+                <div className="cdm-title">View JSON</div>
+                <div className="cdm-sub">{jsonTitle}</div>
               </div>
-              <div style={{ display: "flex", gap: 10 }}>
+              <div className="cdm-right">
                 <button
-                  className="btn"
-                  onClick={() => {
-                    const txt = JSON.stringify(jsonData ?? {}, null, 2);
-                    navigator.clipboard.writeText(txt);
-                  }}
+                  className="cdm-btn"
+                  onClick={() => navigator.clipboard.writeText(JSON.stringify(jsonData ?? {}, null, 2))}
                 >
                   Copy
                 </button>
-                <button className="btn" onClick={closeJson}>
+                <button className="cdm-btn" onClick={closeJson}>
                   Close
                 </button>
               </div>
             </div>
-            <div style={{ padding: 16 }}>
-              <pre
-                style={{
-                  margin: 0,
-                  maxHeight: "70vh",
-                  overflow: "auto",
-                  padding: 14,
-                  borderRadius: 12,
-                  border: "1px solid rgba(148,163,184,0.25)",
-                  background: "rgba(2,6,23,0.35)",
-                  color: "rgba(226,232,240,0.95)",
-                  fontSize: 12,
-                  lineHeight: 1.5,
-                }}
-              >
-                {JSON.stringify(jsonData ?? {}, null, 2)}
-              </pre>
+
+            <div className="cdm-json-body">
+              <pre className="cdm-pre">{JSON.stringify(jsonData ?? {}, null, 2)}</pre>
             </div>
           </div>
Index: lan-frontend/src/components/Login.jsx
===================================================================
--- lan-frontend/src/components/Login.jsx	(revision 505f39ae7b51fc1db15123d66bf06aec0dca2f62)
+++ lan-frontend/src/components/Login.jsx	(revision 505f39ae7b51fc1db15123d66bf06aec0dca2f62)
@@ -0,0 +1,29 @@
+import React from "react";
+import { GoogleLogin } from "@react-oauth/google";
+
+export default function Login({ onDone }) {
+  return (
+    <div style={{ display: "grid", placeItems: "center", minHeight: "100vh" }}>
+      <div className="panel" style={{ maxWidth: 460, width: "92%" }}>
+        <div className="panel-head">
+          <div className="panel-title">Sign in to netIntel</div>
+        </div>
+        <div className="panel-body">
+          <GoogleLogin
+            onSuccess={async (cred) => {
+              const r = await fetch("/api/auth/google", {
+                method: "POST",
+                headers: { "Content-Type": "application/json" },
+                credentials: "include",
+                body: JSON.stringify({ credential: cred.credential }),
+              });
+              if (r.ok) onDone?.();
+              else console.error(await r.json());
+            }}
+            onError={() => console.error("Google login failed")}
+          />
+        </div>
+      </div>
+    </div>
+  );
+}
Index: lan-frontend/src/components/TopBar.jsx
===================================================================
--- lan-frontend/src/components/TopBar.jsx	(revision 2058e5c694bb6097866a5fe6503c519e8f74970f)
+++ lan-frontend/src/components/TopBar.jsx	(revision 505f39ae7b51fc1db15123d66bf06aec0dca2f62)
@@ -1,14 +1,19 @@
 import React, { useEffect, useMemo, useState } from "react";
-
-export default function TopBar({ onOpenAI, onRefresh, lastUpdated, onEnvChange }) {
+import logo from "../assets/ChatGPT_Image_Jan_21__2026__01_20_04_PM-removebg-preview (1).png";
+
+export default function TopBar({
+  onOpenAI,
+  onRefresh,
+  lastUpdated,
+  onEnvChange,
+  selectedEnv: selectedEnvProp, // optional (ако сакаш да го контролира App)
+  me,
+  onLoggedOut, // optional callback (App loadMe)
+}) {
   const [open, setOpen] = useState(false);
-
-  // admin auth
-  const [adminKey, setAdminKey] = useState("");
-  const [adminSession, setAdminSession] = useState("");
 
   // env + tokens
   const [envs, setEnvs] = useState(["default"]);
-  const [selectedEnv, setSelectedEnv] = useState("default");
+  const [selectedEnv, setSelectedEnv] = useState(selectedEnvProp || "default");
   const [newEnvName, setNewEnvName] = useState("");
   const [token, setToken] = useState("");
@@ -17,8 +22,16 @@
   const [error, setError] = useState("");
 
-  // helper: fetch env list after login
-  async function loadEnvironments(session) {
+
+  // keep in sync ако App праќа selectedEnv prop
+  useEffect(() => {
+    if (selectedEnvProp && selectedEnvProp !== selectedEnv) {
+      setSelectedEnv(selectedEnvProp);
+    }
+    // eslint-disable-next-line react-hooks/exhaustive-deps
+  }, [selectedEnvProp]);
+
+  async function loadEnvironments() {
     const r = await fetch("/api/admin/environments", {
-      headers: { "X-Admin-Session": session },
+      credentials: "include",
     });
     const data = await r.json();
@@ -28,5 +41,4 @@
     setEnvs(list);
 
-    // ако тековниот не постои, стави првиот од листата
     if (!list.includes(selectedEnv)) {
       setSelectedEnv(list[0]);
@@ -35,46 +47,8 @@
   }
 
-  async function login() {
-    setError("");
-    setToken("");
-
-    if (!adminKey.trim()) {
-      setError("Внеси admin key.");
-      return;
-    }
-
-    setBusy(true);
-    try {
-      const r = await fetch("/api/admin/login", {
-        method: "POST",
-        headers: { "Content-Type": "application/json" },
-        body: JSON.stringify({ admin_key: adminKey.trim() }),
-      });
-      const data = await r.json();
-      if (!r.ok) throw new Error(data?.error || `HTTP ${r.status}`);
-
-      const session = data.session;
-      setAdminSession(session);
-      await loadEnvironments(session);
-    } catch (e) {
-      setError(String(e.message || e));
-    } finally {
-      setBusy(false);
-    }
-  }
-
-  function logout() {
-    setAdminSession("");
-    setAdminKey("");
-    setToken("");
-    setError("");
-    setEnvs(["default"]);
-    setSelectedEnv("default");
-    onEnvChange?.("default");
-  }
-
   async function createEnvironment() {
     setError("");
     setToken("");
+
     if (!newEnvName.trim()) {
       setError("Внеси име за environment.");
@@ -86,8 +60,6 @@
       const r = await fetch("/api/admin/environments", {
         method: "POST",
-        headers: {
-          "Content-Type": "application/json",
-          "X-Admin-Session": adminSession,
-        },
+        headers: { "Content-Type": "application/json" },
+        credentials: "include",
         body: JSON.stringify({ name: newEnvName.trim() }),
       });
@@ -96,6 +68,5 @@
       if (!r.ok) throw new Error(data?.error || `HTTP ${r.status}`);
 
-      // reload list, select new env
-      await loadEnvironments(adminSession);
+      await loadEnvironments();
       setSelectedEnv(newEnvName.trim());
       onEnvChange?.(newEnvName.trim());
@@ -120,8 +91,6 @@
       const r = await fetch("/api/admin/tokens", {
         method: "POST",
-        headers: {
-          "Content-Type": "application/json",
-          "X-Admin-Session": adminSession,
-        },
+        headers: { "Content-Type": "application/json" },
+        credentials: "include",
         body: JSON.stringify({ env: selectedEnv }),
       });
@@ -147,4 +116,15 @@
     setToken("");
     onEnvChange?.(val);
+  }
+
+  async function logout() {
+    try {
+      await fetch("/api/auth/logout", { method: "POST", credentials: "include" });
+    } catch {}
+    onLoggedOut?.();
+    // reset local admin modal state
+    setOpen(false);
+    setToken("");
+    setError("");
   }
 
@@ -161,228 +141,63 @@
     <>
       <style>{`
-        /* ---- TopBar scoped theme ---- */
-        .tb-wrap{
-          position: sticky;
-          top: 0;
-          z-index: 20;
-          backdrop-filter: blur(10px);
+        .tb-wrap{ position: sticky; top: 0; z-index: 20; backdrop-filter: blur(10px);
           background: linear-gradient(180deg, rgba(10,16,32,0.92), rgba(10,16,32,0.75));
-          border-bottom: 1px solid rgba(96,165,250,0.18);
-        }
-        .tb-inner{
-          max-width: 1200px;
-          margin: 0 auto;
-          padding: 14px 18px;
-          display: flex;
-          align-items: center;
-          justify-content: space-between;
-          gap: 14px;
-        }
-
-        .tb-brand{
-          display:flex;
-          align-items:center;
-          gap: 12px;
-          min-width: 260px;
-        }
-        .tb-badge{
-          width: 44px;
-          height: 44px;
-          border-radius: 14px;
-          display:flex;
-          align-items:center;
-          justify-content:center;
-          background:
-            radial-gradient(120px 80px at 30% 20%, rgba(96,165,250,0.55), transparent 60%),
-            linear-gradient(135deg, rgba(30,64,175,0.75), rgba(15,23,42,0.85));
-          border: 1px solid rgba(96,165,250,0.25);
-          box-shadow: 0 10px 25px rgba(0,0,0,0.25);
-        }
-        .tb-title{
-          margin:0;
-          font-size: 16px;
-          font-weight: 900;
-          letter-spacing: 0.4px;
-          color: rgba(255,255,255,0.95);
-          line-height: 1.2;
-        }
-        .tb-sub{
-          margin: 2px 0 0 0;
-          font-size: 12px;
-          color: rgba(191,219,254,0.85);
-        }
-        .tb-sub span{
-          color: rgba(96,165,250,0.95);
-          font-weight: 800;
-        }
-
-        .tb-actions{
-          display:flex;
-          align-items:center;
-          gap: 10px;
-          flex-wrap: wrap;
-          justify-content: flex-end;
-        }
-
-        .tb-pill{
-          display:inline-flex;
-          align-items:center;
-          gap: 8px;
-          padding: 8px 12px;
-          border-radius: 999px;
-          background: rgba(30,41,59,0.65);
-          border: 1px solid rgba(96,165,250,0.22);
-          color: rgba(255,255,255,0.9);
-          font-weight: 800;
-          font-size: 12px;
-          box-shadow: inset 0 1px 0 rgba(255,255,255,0.06);
-        }
-        .tb-pill .dot{
-          width: 8px;
-          height: 8px;
-          border-radius: 999px;
-          background: rgba(96,165,250,0.95);
-          box-shadow: 0 0 0 3px rgba(96,165,250,0.15);
-        }
-
-        .tb-btn{
-          appearance: none;
-          border: 1px solid rgba(96,165,250,0.22);
-          background: rgba(15,23,42,0.55);
-          color: rgba(255,255,255,0.9);
-          padding: 9px 12px;
-          border-radius: 12px;
-          font-weight: 800;
-          font-size: 13px;
-          cursor: pointer;
-          transition: transform .12s ease, background .12s ease, border-color .12s ease, opacity .12s ease;
-          box-shadow: 0 8px 20px rgba(0,0,0,0.18);
-        }
-        .tb-btn:hover{
-          transform: translateY(-1px);
-          background: rgba(30,41,59,0.65);
-          border-color: rgba(96,165,250,0.38);
-        }
-        .tb-btn:disabled{
-          opacity: .6;
-          cursor: not-allowed;
-          transform: none;
-        }
-        .tb-btn.primary{
-          background: linear-gradient(135deg, rgba(37,99,235,0.95), rgba(56,189,248,0.7));
-          border-color: rgba(147,197,253,0.35);
-          color: rgba(5,12,24,0.95);
-        }
-        .tb-btn.primary:hover{
-          background: linear-gradient(135deg, rgba(59,130,246,0.95), rgba(34,211,238,0.75));
-        }
-
-        /* ---- Modal ---- */
-        .tb-backdrop{
-          position: fixed;
-          inset: 0;
-          background: rgba(2,6,23,0.72);
-          backdrop-filter: blur(6px);
-          display:flex;
-          align-items: center;
-          justify-content: center;
-          padding: 20px;
-          z-index: 50;
-        }
-        .tb-modal{
-          width: min(860px, 96vw);
-          border-radius: 18px;
-          background:
-            radial-gradient(900px 420px at 20% 0%, rgba(96,165,250,0.18), transparent 60%),
-            radial-gradient(700px 350px at 80% 10%, rgba(34,211,238,0.10), transparent 55%),
-            rgba(10,16,32,0.92);
-          border: 1px solid rgba(96,165,250,0.22);
-          box-shadow: 0 30px 80px rgba(0,0,0,0.45);
-          overflow: hidden;
-        }
-        .tb-modal-head{
-          padding: 16px 18px;
-          display:flex;
-          align-items: center;
-          justify-content: space-between;
-          gap: 10px;
-          border-bottom: 1px solid rgba(96,165,250,0.18);
-        }
-        .tb-modal-title{
-          color: rgba(255,255,255,0.96);
-          font-weight: 900;
-          letter-spacing: .3px;
-        }
-        .tb-modal-sub{
-          color: rgba(191,219,254,0.8);
-          font-size: 12px;
-          margin-top: 2px;
-        }
-        .tb-grid{
-          padding: 16px;
-          display:grid;
-          gap: 12px;
-        }
-        .tb-card{
-          border-radius: 16px;
-          background: rgba(15,23,42,0.55);
-          border: 1px solid rgba(96,165,250,0.18);
-          padding: 14px;
-        }
-        .tb-card-head{
-          display:flex;
-          align-items:center;
-          justify-content: space-between;
-          margin-bottom: 10px;
-        }
-        .tb-card-title{
-          color: rgba(255,255,255,0.92);
-          font-weight: 900;
-        }
-        .tb-help{
-          color: rgba(148,163,184,0.95);
-          font-size: 12px;
-          margin-top: 8px;
-          line-height: 1.35;
-        }
-        .tb-input, .tb-select{
-          width: 100%;
-          padding: 10px 12px;
-          border-radius: 12px;
-          border: 1px solid rgba(96,165,250,0.18);
-          background: rgba(2,6,23,0.35);
-          color: rgba(255,255,255,0.92);
-          outline: none;
-          font-weight: 700;
-        }
+          border-bottom: 1px solid rgba(96,165,250,0.18); }
+        .tb-inner{ max-width: 1200px; margin: 0 auto; padding: 14px 18px;
+          display: flex; align-items: center; justify-content: space-between; gap: 14px; }
+        .tb-brand{ display:flex; align-items:center; gap: 12px; min-width: 260px; }
+        .tb-badge{ width: 44px; height: 44px; border-radius: 14px; display:flex; align-items:center; justify-content:center;
+          background: radial-gradient(120px 80px at 30% 20%, rgba(96,165,250,0.55), transparent 60%),
+                      linear-gradient(135deg, rgba(30,64,175,0.75), rgba(15,23,42,0.85));
+          border: 1px solid rgba(96,165,250,0.25); box-shadow: 0 10px 25px rgba(0,0,0,0.25); }
+        .tb-title{ margin:0; font-size: 16px; font-weight: 900; letter-spacing: 0.4px; color: rgba(255,255,255,0.95); line-height: 1.2; }
+        .tb-sub{ margin: 2px 0 0 0; font-size: 12px; color: rgba(191,219,254,0.85); }
+        .tb-sub span{ color: rgba(96,165,250,0.95); font-weight: 800; }
+        .tb-actions{ display:flex; align-items:center; gap: 10px; flex-wrap: wrap; justify-content: flex-end; }
+        .tb-pill{ display:inline-flex; align-items:center; gap: 8px; padding: 8px 12px; border-radius: 999px;
+          background: rgba(30,41,59,0.65); border: 1px solid rgba(96,165,250,0.22);
+          color: rgba(255,255,255,0.9); font-weight: 800; font-size: 12px; box-shadow: inset 0 1px 0 rgba(255,255,255,0.06); }
+        .tb-pill .dot{ width: 8px; height: 8px; border-radius: 999px; background: rgba(96,165,250,0.95);
+          box-shadow: 0 0 0 3px rgba(96,165,250,0.15); }
+        .tb-btn{ appearance: none; border: 1px solid rgba(96,165,250,0.22); background: rgba(15,23,42,0.55);
+          color: rgba(255,255,255,0.9); padding: 9px 12px; border-radius: 12px; font-weight: 800;
+          font-size: 13px; cursor: pointer; transition: transform .12s ease, background .12s ease, border-color .12s ease, opacity .12s ease;
+          box-shadow: 0 8px 20px rgba(0,0,0,0.18); }
+        .tb-btn:hover{ transform: translateY(-1px); background: rgba(30,41,59,0.65); border-color: rgba(96,165,250,0.38); }
+        .tb-btn:disabled{ opacity: .6; cursor: not-allowed; transform: none; }
+        .tb-btn.primary{ background: linear-gradient(135deg, rgba(37,99,235,0.95), rgba(56,189,248,0.7));
+          border-color: rgba(147,197,253,0.35); color: rgba(5,12,24,0.95); }
+        .tb-btn.primary:hover{ background: linear-gradient(135deg, rgba(59,130,246,0.95), rgba(34,211,238,0.75)); }
+
+        .tb-backdrop{ position: fixed; inset: 0; background: rgba(2,6,23,0.72); backdrop-filter: blur(6px);
+          display:flex; align-items: center; justify-content: center; padding: 20px; z-index: 50; }
+        .tb-modal{ width: min(860px, 96vw); border-radius: 18px;
+          background: radial-gradient(900px 420px at 20% 0%, rgba(96,165,250,0.18), transparent 60%),
+                      radial-gradient(700px 350px at 80% 10%, rgba(34,211,238,0.10), transparent 55%),
+                      rgba(10,16,32,0.92);
+          border: 1px solid rgba(96,165,250,0.22); box-shadow: 0 30px 80px rgba(0,0,0,0.45); overflow: hidden; }
+        .tb-modal-head{ padding: 16px 18px; display:flex; align-items: center; justify-content: space-between; gap: 10px;
+          border-bottom: 1px solid rgba(96,165,250,0.18); }
+        .tb-modal-title{ color: rgba(255,255,255,0.96); font-weight: 900; letter-spacing: .3px; }
+        .tb-modal-sub{ color: rgba(191,219,254,0.8); font-size: 12px; margin-top: 2px; }
+        .tb-grid{ padding: 16px; display:grid; gap: 12px; }
+        .tb-card{ border-radius: 16px; background: rgba(15,23,42,0.55); border: 1px solid rgba(96,165,250,0.18); padding: 14px; }
+        .tb-card-head{ display:flex; align-items:center; justify-content: space-between; margin-bottom: 10px; gap: 10px; }
+        .tb-card-title{ color: rgba(255,255,255,0.92); font-weight: 900; }
+        .tb-help{ color: rgba(148,163,184,0.95); font-size: 12px; margin-top: 8px; line-height: 1.35; }
+        .tb-input, .tb-select{ width: 100%; padding: 10px 12px; border-radius: 12px;
+          border: 1px solid rgba(96,165,250,0.18); background: rgba(2,6,23,0.35); color: rgba(255,255,255,0.92);
+          outline: none; font-weight: 700; }
         .tb-input::placeholder{ color: rgba(148,163,184,0.75); }
-        .tb-row{
-          display:grid;
-          gap: 10px;
-        }
-        .tb-token{
-          display:flex;
-          align-items:center;
-          justify-content: space-between;
-          gap: 10px;
-          padding: 10px 12px;
-          border-radius: 14px;
-          background: rgba(2,6,23,0.38);
-          border: 1px dashed rgba(147,197,253,0.32);
-          color: rgba(255,255,255,0.92);
-        }
-        .tb-mono{
-          font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
-          font-weight: 800;
-          color: rgba(191,219,254,0.95);
-        }
-        .tb-error{
-          border-color: rgba(239,68,68,0.45) !important;
-          background: rgba(127,29,29,0.15) !important;
-          color: rgba(254,202,202,0.95);
-        }
+        .tb-row{ display:grid; gap: 10px; }
+        .tb-token{ display:flex; align-items:center; justify-content: space-between; gap: 10px; padding: 10px 12px;
+          border-radius: 14px; background: rgba(2,6,23,0.38); border: 1px dashed rgba(147,197,253,0.32);
+          color: rgba(255,255,255,0.92); }
+        .tb-mono{ font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
+          font-weight: 800; color: rgba(191,219,254,0.95); }
+        .tb-error{ border-color: rgba(239,68,68,0.45) !important; background: rgba(127,29,29,0.15) !important;
+          color: rgba(254,202,202,0.95); }
       `}</style>
 
-      {/* TOPBAR */}
       <div className="tb-wrap">
         <div className="tb-inner">
@@ -394,6 +209,23 @@
                 Sysmon Edition • <span>{prettyTime}</span>
               </p>
+              {me?.email && (
+                <p className="tb-sub" style={{ marginTop: 4, opacity: 0.9 }}>
+                  Signed in as <span>{me.email}</span>
+                  {me.role ? ` • ${me.role}` : ""}
+                </p>
+              )}
             </div>
           </div>
+          <div>
+            <img
+                src={logo}
+                alt="NETIntel logo"
+                className="netintel-logo"
+                width={150}
+                style={{marginTop: 10 }}
+            />
+          </div>
+
+
 
           <div className="tb-actions">
@@ -402,12 +234,29 @@
               Env: {selectedEnv}
             </span>
-            <button className="tb-btn" onClick={onRefresh} disabled={busy}>Refresh</button>
-            <button className="tb-btn" onClick={() => setOpen(true)}>Admin</button>
-            <button className="tb-btn primary" onClick={onOpenAI}>AI Assistant</button>
+            <button className="tb-btn" onClick={onRefresh} disabled={busy}>
+              Refresh
+            </button>
+            <button
+              className="tb-btn"
+              onClick={async () => {
+                setOpen(true);
+                setError("");
+                setToken("");
+                try {
+                  await loadEnvironments();
+                } catch (e) {
+                  setError(String(e.message || e));
+                }
+              }}
+            >
+              Admin
+            </button>
+            <button className="tb-btn primary" onClick={onOpenAI}>
+              AI Assistant
+            </button>
           </div>
         </div>
       </div>
 
-      {/* MODAL */}
       {open && (
         <div className="tb-backdrop" onMouseDown={() => setOpen(false)}>
@@ -415,106 +264,92 @@
             <div className="tb-modal-head">
               <div>
-                <div className="tb-modal-title">Admin Panel</div>
-                <div className="tb-modal-sub">Login ➜ Environments ➜ Generate token</div>
-              </div>
-              <button className="tb-btn" onClick={() => setOpen(false)}>Close</button>
+                <div className="tb-modal-title">Tenant Admin</div>
+                <div className="tb-modal-sub">
+                  Environments ➜ Generate token (clients send X-Env-Token to /receive)
+                </div>
+              </div>
+              <div style={{ display: "flex", gap: 10 }}>
+                <button className="tb-btn" onClick={logout}>
+                  Logout
+                </button>
+                <button className="tb-btn" onClick={() => setOpen(false)}>
+                  Close
+                </button>
+              </div>
             </div>
 
             <div className="tb-grid">
-              {/* 1) LOGIN */}
-              {!adminSession ? (
-                <div className="tb-card">
-                  <div className="tb-card-head">
-                    <div className="tb-card-title">Step 1: Admin login</div>
+              <div className="tb-card">
+                <div className="tb-card-head">
+                  <div className="tb-card-title">Choose environment</div>
+                </div>
+                <div className="tb-row">
+                  <select
+                    className="tb-select"
+                    value={selectedEnv}
+                    onChange={(e) => changeEnv(e.target.value)}
+                  >
+                    {envs.map((e) => (
+                      <option key={e} value={e}>
+                        {e}
+                      </option>
+                    ))}
+                  </select>
+                  <div className="tb-help">
+                    Овој env ќе се користи за dashboard филтрирање + token generation.
                   </div>
-
-                  <div className="tb-row">
-                    <input
-                      className="tb-input"
-                      type="password"
-                      value={adminKey}
-                      onChange={(e) => setAdminKey(e.target.value)}
-                      placeholder="Enter admin key"
-                    />
-                    <button className="tb-btn primary" onClick={login} disabled={busy}>
-                      {busy ? "Logging in…" : "Login"}
-                    </button>
-                    <div className="tb-help">
-                      Admin key е само за логирање. После тоа користиме <b>session token</b>.
-                    </div>
-                  </div>
-                </div>
-              ) : (
-                <>
-                  {/* 2) ENV SELECT */}
-                  <div className="tb-card">
-                    <div className="tb-card-head">
-                      <div className="tb-card-title">Step 2: Choose environment</div>
-                      <button className="tb-btn" onClick={logout}>Logout</button>
-                    </div>
-
-                    <div className="tb-row">
-                      <select className="tb-select" value={selectedEnv} onChange={(e) => changeEnv(e.target.value)}>
-                        {envs.map((e) => (
-                          <option key={e} value={e}>{e}</option>
-                        ))}
-                      </select>
+                </div>
+              </div>
+
+              <div className="tb-card">
+                <div className="tb-card-head">
+                  <div className="tb-card-title">Create new environment</div>
+                </div>
+                <div className="tb-row">
+                  <input
+                    className="tb-input"
+                    value={newEnvName}
+                    onChange={(e) => setNewEnvName(e.target.value)}
+                    placeholder="e.g. school-lab / staging"
+                  />
+                  <button className="tb-btn" onClick={createEnvironment} disabled={busy}>
+                    {busy ? "Creating…" : "Create"}
+                  </button>
+                </div>
+              </div>
+
+              <div className="tb-card">
+                <div className="tb-card-head">
+                  <div className="tb-card-title">Generate token (for clients)</div>
+                </div>
+
+                <div className="tb-row">
+                  <button className="tb-btn primary" onClick={generateToken} disabled={busy}>
+                    {busy ? "Generating…" : `Generate token for "${selectedEnv}"`}
+                  </button>
+
+                  {token && (
+                    <>
+                      <div className="tb-token">
+                        <div>
+                          <div style={{ fontWeight: 900, color: "rgba(255,255,255,0.92)" }}>
+                            Token
+                          </div>
+                          <div className="tb-mono">
+                            {token.slice(0, 12)}…{token.slice(-10)}
+                          </div>
+                        </div>
+                        <button className="tb-btn" onClick={copyToken}>
+                          Copy
+                        </button>
+                      </div>
+
                       <div className="tb-help">
-                        Овој env ќе се користи за dashboard филтрирање + token generation.
+                        Клиентот мора да праќа header: <b>X-Env-Token</b> со овој token на <b>/receive</b>.
                       </div>
-                    </div>
-                  </div>
-
-                  {/* 3) CREATE ENV */}
-                  <div className="tb-card">
-                    <div className="tb-card-head">
-                      <div className="tb-card-title">Create new environment</div>
-                    </div>
-
-                    <div className="tb-row">
-                      <input
-                        className="tb-input"
-                        value={newEnvName}
-                        onChange={(e) => setNewEnvName(e.target.value)}
-                        placeholder="e.g. school-lab / staging"
-                      />
-                      <button className="tb-btn" onClick={createEnvironment} disabled={busy}>
-                        {busy ? "Creating…" : "Create"}
-                      </button>
-                    </div>
-                  </div>
-
-                  {/* 4) TOKEN */}
-                  <div className="tb-card">
-                    <div className="tb-card-head">
-                      <div className="tb-card-title">Step 3: Generate token (for clients)</div>
-                    </div>
-
-                    <div className="tb-row">
-                      <button className="tb-btn primary" onClick={generateToken} disabled={busy}>
-                        {busy ? "Generating…" : `Generate token for "${selectedEnv}"`}
-                      </button>
-
-                      {token && (
-                        <>
-                          <div className="tb-token">
-                            <div>
-                              <div style={{ fontWeight: 900, color: "rgba(255,255,255,0.92)" }}>Token</div>
-                              <div className="tb-mono">
-                                {token.slice(0, 12)}…{token.slice(-10)}
-                              </div>
-                            </div>
-                            <button className="tb-btn" onClick={copyToken}>Copy</button>
-                          </div>
-
-                          <div className="tb-help">
-                            Клиентот мора да праќа header: <b>X-Env-Token</b> со овој token на <b>/receive</b>.
-                          </div>
-                        </>
-                      )}
-                    </div>
-                  </div>
-                </>
-              )}
+                    </>
+                  )}
+                </div>
+              </div>
 
               {error && (
Index: lan-frontend/src/index.css
===================================================================
--- lan-frontend/src/index.css	(revision 2058e5c694bb6097866a5fe6503c519e8f74970f)
+++ lan-frontend/src/index.css	(revision 505f39ae7b51fc1db15123d66bf06aec0dca2f62)
@@ -1564,5 +1564,148 @@
 }
 
-@tailwind base;
-@tailwind components;
-@tailwind utilities;
+.aiDrawer-backdrop{
+  position: fixed;
+  inset: 0;
+  background: rgba(0,0,0,.55);
+  backdrop-filter: blur(2px);
+  z-index: 999;
+}
+
+/* десен drawer */
+.aiDrawer{
+  position: fixed;
+  top: 0;
+  right: 0;
+  height: 100vh;
+  width: min(520px, 92vw);
+  background: #0b1220;            /* темна */
+  color: #e7eefc;
+  border-left: 1px solid rgba(255,255,255,.08);
+  z-index: 1000;
+  display: grid;
+  grid-template-rows: auto auto 1fr auto;
+
+  /* slide in */
+  transform: translateX(0);
+  animation: aiSlideIn .18s ease-out;
+}
+
+@keyframes aiSlideIn{
+  from { transform: translateX(24px); opacity: .7; }
+  to   { transform: translateX(0); opacity: 1; }
+}
+
+.aiDrawer-head{
+  padding: 14px 16px;
+  display: flex;
+  align-items: center;
+  justify-content: space-between;
+  border-bottom: 1px solid rgba(255,255,255,.08);
+}
+
+.aiDrawer-title{
+  font-size: 16px;
+  font-weight: 700;
+}
+
+.aiDrawer-sub{
+  font-size: 12px;
+  opacity: .75;
+  margin-top: 2px;
+}
+
+.aiDrawer-toolbar{
+  padding: 12px 16px;
+  border-bottom: 1px solid rgba(255,255,255,.08);
+  display: grid;
+  gap: 8px;
+}
+
+.aiSelect{
+  width: 100%;
+  background: rgba(255,255,255,.06);
+  border: 1px solid rgba(255,255,255,.10);
+  color: #e7eefc;
+  padding: 10px 12px;
+  border-radius: 10px;
+  outline: none;
+}
+
+.aiHint{
+  font-size: 12px;
+  opacity: .75;
+}
+
+.aiDrawer-body{
+  padding: 14px 16px;
+  overflow: auto;
+  display: grid;
+  gap: 10px;
+}
+
+/* chat bubbles */
+.aiMsg{
+  max-width: 92%;
+  border: 1px solid rgba(255,255,255,.08);
+  border-radius: 14px;
+  padding: 10px 12px;
+  background: rgba(255,255,255,.04);
+}
+
+.aiMsg.user{
+  margin-left: auto;
+  background: rgba(88, 167, 255, .12);
+  border-color: rgba(88, 167, 255, .20);
+}
+
+.aiMsg-meta{
+  font-size: 11px;
+  opacity: .7;
+  margin-bottom: 6px;
+}
+
+.aiMsg-text{
+  white-space: pre-wrap;
+  line-height: 1.35;
+  font-size: 14px;
+}
+
+.aiDrawer-foot{
+  padding: 12px 16px;
+  border-top: 1px solid rgba(255,255,255,.08);
+  display: grid;
+  grid-template-columns: 1fr auto;
+  gap: 10px;
+  align-items: end;
+  background: rgba(255,255,255,.02);
+}
+
+.aiTextarea{
+  width: 100%;
+  resize: none;
+  background: rgba(255,255,255,.06);
+  border: 1px solid rgba(255,255,255,.10);
+  color: #e7eefc;
+  padding: 10px 12px;
+  border-radius: 12px;
+  outline: none;
+}
+
+.aiBtn{
+  background: rgba(255,255,255,.06);
+  border: 1px solid rgba(255,255,255,.10);
+  color: #e7eefc;
+  padding: 10px 12px;
+  border-radius: 12px;
+  cursor: pointer;
+}
+
+.aiBtn:disabled{
+  opacity: .5;
+  cursor: not-allowed;
+}
+
+.aiBtnPrimary{
+  background: rgba(88, 167, 255, .22);
+  border-color: rgba(88, 167, 255, .35);
+}
Index: lan-frontend/src/main.jsx
===================================================================
--- lan-frontend/src/main.jsx	(revision 2058e5c694bb6097866a5fe6503c519e8f74970f)
+++ lan-frontend/src/main.jsx	(revision 505f39ae7b51fc1db15123d66bf06aec0dca2f62)
@@ -1,10 +1,13 @@
-import React from 'react';                    // ⬅ додадено
-import ReactDOM from 'react-dom/client';
-import App from './App.jsx';
-import './index.css';
+import React from "react";
+import ReactDOM from "react-dom/client";
+import { GoogleOAuthProvider } from "@react-oauth/google";
+import App from "./App.jsx";
+import "./styles/theme.css";
 
-ReactDOM.createRoot(document.getElementById('root')).render(
+ReactDOM.createRoot(document.getElementById("root")).render(
   <React.StrictMode>
-    <App />
+    <GoogleOAuthProvider clientId={import.meta.env.VITE_GOOGLE_CLIENT_ID}>
+      <App />
+    </GoogleOAuthProvider>
   </React.StrictMode>
 );
Index: lan-frontend/src/styles/theme.css
===================================================================
--- lan-frontend/src/styles/theme.css	(revision 2058e5c694bb6097866a5fe6503c519e8f74970f)
+++ lan-frontend/src/styles/theme.css	(revision 505f39ae7b51fc1db15123d66bf06aec0dca2f62)
@@ -402,2 +402,148 @@
 }
 *::-webkit-scrollbar-track{ background: rgba(2,6,23,0.25); }
+.aiDrawer-backdrop{
+  position: fixed;
+  inset: 0;
+  background: rgba(0,0,0,.55);
+  backdrop-filter: blur(2px);
+  z-index: 999;
+}
+
+/* десен drawer */
+.aiDrawer{
+  position: fixed;
+  top: 0;
+  right: 0;
+  height: 100vh;
+  width: min(520px, 92vw);
+  background: #0b1220;            /* темна */
+  color: #e7eefc;
+  border-left: 1px solid rgba(255,255,255,.08);
+  z-index: 1000;
+  display: grid;
+  grid-template-rows: auto auto 1fr auto;
+
+  /* slide in */
+  transform: translateX(0);
+  animation: aiSlideIn .18s ease-out;
+}
+
+@keyframes aiSlideIn{
+  from { transform: translateX(24px); opacity: .7; }
+  to   { transform: translateX(0); opacity: 1; }
+}
+
+.aiDrawer-head{
+  padding: 14px 16px;
+  display: flex;
+  align-items: center;
+  justify-content: space-between;
+  border-bottom: 1px solid rgba(255,255,255,.08);
+}
+
+.aiDrawer-title{
+  font-size: 16px;
+  font-weight: 700;
+}
+
+.aiDrawer-sub{
+  font-size: 12px;
+  opacity: .75;
+  margin-top: 2px;
+}
+
+.aiDrawer-toolbar{
+  padding: 12px 16px;
+  border-bottom: 1px solid rgba(255,255,255,.08);
+  display: grid;
+  gap: 8px;
+}
+
+.aiSelect{
+  width: 100%;
+  background: rgba(255,255,255,.06);
+  border: 1px solid rgba(255,255,255,.10);
+  color: #e7eefc;
+  padding: 10px 12px;
+  border-radius: 10px;
+  outline: none;
+}
+
+.aiHint{
+  font-size: 12px;
+  opacity: .75;
+}
+
+.aiDrawer-body{
+  padding: 14px 16px;
+  overflow: auto;
+  display: grid;
+  gap: 10px;
+}
+
+/* chat bubbles */
+.aiMsg{
+  max-width: 92%;
+  border: 1px solid rgba(255,255,255,.08);
+  border-radius: 14px;
+  padding: 10px 12px;
+  background: rgba(255,255,255,.04);
+}
+
+.aiMsg.user{
+  margin-left: auto;
+  background: rgba(88, 167, 255, .12);
+  border-color: rgba(88, 167, 255, .20);
+}
+
+.aiMsg-meta{
+  font-size: 11px;
+  opacity: .7;
+  margin-bottom: 6px;
+}
+
+.aiMsg-text{
+  white-space: pre-wrap;
+  line-height: 1.35;
+  font-size: 14px;
+}
+
+.aiDrawer-foot{
+  padding: 12px 16px;
+  border-top: 1px solid rgba(255,255,255,.08);
+  display: grid;
+  grid-template-columns: 1fr auto;
+  gap: 10px;
+  align-items: end;
+  background: rgba(255,255,255,.02);
+}
+
+.aiTextarea{
+  width: 100%;
+  resize: none;
+  background: rgba(255,255,255,.06);
+  border: 1px solid rgba(255,255,255,.10);
+  color: #e7eefc;
+  padding: 10px 12px;
+  border-radius: 12px;
+  outline: none;
+}
+
+.aiBtn{
+  background: rgba(255,255,255,.06);
+  border: 1px solid rgba(255,255,255,.10);
+  color: #e7eefc;
+  padding: 10px 12px;
+  border-radius: 12px;
+  cursor: pointer;
+}
+
+.aiBtn:disabled{
+  opacity: .5;
+  cursor: not-allowed;
+}
+
+.aiBtnPrimary{
+  background: rgba(88, 167, 255, .22);
+  border-color: rgba(88, 167, 255, .35);
+}
Index: lan-frontend/vite.config.js
===================================================================
--- lan-frontend/vite.config.js	(revision 2058e5c694bb6097866a5fe6503c519e8f74970f)
+++ lan-frontend/vite.config.js	(revision 505f39ae7b51fc1db15123d66bf06aec0dca2f62)
@@ -1,11 +1,33 @@
-import { defineConfig } from 'vite'
-import react from '@vitejs/plugin-react'
+// import { defineConfig } from "vite";
+// import react from "@vitejs/plugin-react";
+//
+// export default defineConfig({
+//   plugins: [react()],
+//   server: {
+//     proxy: {
+//       "/api": { target: "http://localhost:5555", changeOrigin: true },
+//       "/receive": { target: "http://localhost:5555", changeOrigin: true },
+//       "/ping": { target: "http://localhost:5555", changeOrigin: true },
+//     },
+//   },
+// });
+import { defineConfig } from "vite";
+import react from "@vitejs/plugin-react";
 
-// https://vite.dev/config/
-export default {
+export default defineConfig({
+  plugins: [react()],
   server: {
     proxy: {
-      "/api": "http://localhost:5555",
+      "/api": {
+        target: "http://localhost:5555",
+        changeOrigin: true,
+        secure: false,
+      },
+      "/receive": {
+        target: "http://localhost:5555",
+        changeOrigin: true,
+        secure: false,
+      },
     },
   },
-};
+});
