2025-12-03 18:42:22 -03:00
|
|
|
|
<!doctype html>
|
|
|
|
|
|
<html lang="en">
|
|
|
|
|
|
<head>
|
|
|
|
|
|
<meta charset="utf-8" />
|
2026-01-03 17:19:17 -03:00
|
|
|
|
<title>Chat - General Bots</title>
|
2025-12-03 18:42:22 -03:00
|
|
|
|
<meta name="viewport" content="width=device-width,initial-scale=1.0" />
|
|
|
|
|
|
<meta
|
|
|
|
|
|
name="description"
|
|
|
|
|
|
content="General Bots - AI-powered workspace"
|
|
|
|
|
|
/>
|
2025-12-15 23:16:09 -03:00
|
|
|
|
<meta name="theme-color" content="#d4f505" />
|
2025-12-03 18:42:22 -03:00
|
|
|
|
|
|
|
|
|
|
<!-- Styles -->
|
|
|
|
|
|
<link rel="stylesheet" href="css/app.css" />
|
|
|
|
|
|
<link rel="stylesheet" href="css/apps-extended.css" />
|
|
|
|
|
|
<link rel="stylesheet" href="css/components.css" />
|
2025-12-15 16:48:36 -03:00
|
|
|
|
<link rel="stylesheet" href="css/base.css" />
|
2025-12-15 23:16:09 -03:00
|
|
|
|
<link rel="stylesheet" href="css/theme-sentient.css" />
|
2025-12-15 16:48:36 -03:00
|
|
|
|
|
|
|
|
|
|
<!-- App-specific CSS -->
|
2025-12-10 22:58:09 -03:00
|
|
|
|
<link rel="stylesheet" href="chat/chat.css" />
|
2025-12-15 16:48:36 -03:00
|
|
|
|
<link rel="stylesheet" href="calendar/calendar.css" />
|
|
|
|
|
|
<link rel="stylesheet" href="drive/drive.css" />
|
|
|
|
|
|
<link rel="stylesheet" href="mail/mail.css" />
|
|
|
|
|
|
<link rel="stylesheet" href="meet/meet.css" />
|
|
|
|
|
|
<link rel="stylesheet" href="paper/paper.css" />
|
|
|
|
|
|
<link rel="stylesheet" href="research/research.css" />
|
2025-12-30 22:42:54 -03:00
|
|
|
|
<link rel="stylesheet" href="tasks/tasks.css?v=20251230" />
|
2025-12-31 23:45:38 -03:00
|
|
|
|
<link rel="stylesheet" href="tasks/taskmd.css?v=20251230" />
|
2025-12-15 16:48:36 -03:00
|
|
|
|
<link rel="stylesheet" href="analytics/analytics.css" />
|
|
|
|
|
|
<link rel="stylesheet" href="monitoring/monitoring.css" />
|
2025-12-03 18:42:22 -03:00
|
|
|
|
|
2025-12-04 12:30:07 -03:00
|
|
|
|
<!-- Local Libraries (no external CDN dependencies) -->
|
|
|
|
|
|
<script src="js/vendor/htmx.min.js"></script>
|
|
|
|
|
|
<script src="js/vendor/htmx-ws.js"></script>
|
|
|
|
|
|
<script src="js/vendor/htmx-json-enc.js"></script>
|
|
|
|
|
|
<script src="js/vendor/marked.min.js"></script>
|
2025-12-15 16:40:04 -03:00
|
|
|
|
|
2025-12-10 22:58:09 -03:00
|
|
|
|
<!-- Enable HTMX to process inline scripts in swapped content -->
|
|
|
|
|
|
<script>
|
|
|
|
|
|
htmx.config.allowEval = true;
|
|
|
|
|
|
htmx.config.includeIndicatorStyles = false;
|
2025-12-31 12:38:54 -03:00
|
|
|
|
htmx.config.timeout = 300000; // 5 minutes for long-running LLM operations
|
2025-12-10 22:58:09 -03:00
|
|
|
|
</script>
|
2025-12-03 18:42:22 -03:00
|
|
|
|
</head>
|
|
|
|
|
|
|
2025-12-15 23:16:09 -03:00
|
|
|
|
<body data-theme="sentient">
|
2025-12-03 18:42:22 -03:00
|
|
|
|
<!-- Loading overlay -->
|
|
|
|
|
|
<div class="loading-overlay" id="loadingOverlay">
|
|
|
|
|
|
<div class="loading-spinner"></div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
<!-- Floating header -->
|
|
|
|
|
|
<header class="float-header" role="banner">
|
2025-12-15 18:48:40 -03:00
|
|
|
|
<!-- Left: Logo + App Tabs -->
|
2025-12-03 18:42:22 -03:00
|
|
|
|
<div class="header-left">
|
|
|
|
|
|
<button
|
|
|
|
|
|
class="logo-wrapper"
|
2025-12-15 18:48:40 -03:00
|
|
|
|
onclick="window.location.href='/#chat'"
|
|
|
|
|
|
title="General Bots"
|
|
|
|
|
|
aria-label="General Bots - Home"
|
2025-12-03 18:42:22 -03:00
|
|
|
|
>
|
2026-01-03 17:19:17 -03:00
|
|
|
|
<svg
|
2025-12-03 18:42:22 -03:00
|
|
|
|
class="logo-icon"
|
2026-01-03 17:19:17 -03:00
|
|
|
|
width="32"
|
|
|
|
|
|
height="20"
|
|
|
|
|
|
viewBox="0 0 140 80"
|
|
|
|
|
|
fill="none"
|
|
|
|
|
|
stroke="currentColor"
|
|
|
|
|
|
stroke-width="2.5"
|
|
|
|
|
|
stroke-linecap="round"
|
|
|
|
|
|
stroke-linejoin="round"
|
|
|
|
|
|
>
|
|
|
|
|
|
<!-- Left antenna -->
|
|
|
|
|
|
<line x1="5" y1="40" x2="25" y2="40" />
|
|
|
|
|
|
<line x1="25" y1="28" x2="25" y2="52" />
|
|
|
|
|
|
<!-- Left gear (outer) -->
|
|
|
|
|
|
<circle cx="50" cy="40" r="16" />
|
|
|
|
|
|
<!-- Left gear (inner) -->
|
|
|
|
|
|
<circle cx="50" cy="40" r="6" />
|
|
|
|
|
|
<!-- Left gear teeth -->
|
|
|
|
|
|
<line x1="50" y1="20" x2="50" y2="26" />
|
|
|
|
|
|
<line x1="50" y1="54" x2="50" y2="60" />
|
|
|
|
|
|
<line x1="30" y1="40" x2="36" y2="40" />
|
|
|
|
|
|
<line x1="64" y1="40" x2="70" y2="40" />
|
|
|
|
|
|
<line x1="38" y1="28" x2="42" y2="32" />
|
|
|
|
|
|
<line x1="58" y1="48" x2="62" y2="52" />
|
|
|
|
|
|
<line x1="38" y1="52" x2="42" y2="48" />
|
|
|
|
|
|
<line x1="58" y1="32" x2="62" y2="28" />
|
|
|
|
|
|
<!-- Right gear (outer) -->
|
|
|
|
|
|
<circle cx="90" cy="40" r="16" />
|
|
|
|
|
|
<!-- Right gear (inner) -->
|
|
|
|
|
|
<circle cx="90" cy="40" r="6" />
|
|
|
|
|
|
<!-- Right gear teeth -->
|
|
|
|
|
|
<line x1="90" y1="20" x2="90" y2="26" />
|
|
|
|
|
|
<line x1="90" y1="54" x2="90" y2="60" />
|
|
|
|
|
|
<line x1="70" y1="40" x2="76" y2="40" />
|
|
|
|
|
|
<line x1="104" y1="40" x2="110" y2="40" />
|
|
|
|
|
|
<line x1="78" y1="28" x2="82" y2="32" />
|
|
|
|
|
|
<line x1="98" y1="48" x2="102" y2="52" />
|
|
|
|
|
|
<line x1="78" y1="52" x2="82" y2="48" />
|
|
|
|
|
|
<line x1="98" y1="32" x2="102" y2="28" />
|
|
|
|
|
|
<!-- Right antenna -->
|
|
|
|
|
|
<line x1="115" y1="40" x2="135" y2="40" />
|
|
|
|
|
|
<line x1="115" y1="28" x2="115" y2="52" />
|
|
|
|
|
|
</svg>
|
2025-12-03 18:42:22 -03:00
|
|
|
|
</button>
|
|
|
|
|
|
|
2025-12-15 18:48:40 -03:00
|
|
|
|
<!-- Main App Tabs -->
|
|
|
|
|
|
<nav class="header-app-tabs">
|
|
|
|
|
|
<a
|
|
|
|
|
|
class="app-tab active"
|
|
|
|
|
|
href="#chat"
|
2026-01-03 17:19:17 -03:00
|
|
|
|
data-section="chat"
|
2025-12-15 18:48:40 -03:00
|
|
|
|
hx-get="/suite/chat/chat.html"
|
|
|
|
|
|
hx-target="#main-content"
|
|
|
|
|
|
hx-push-url="/#chat"
|
|
|
|
|
|
>
|
|
|
|
|
|
<svg
|
|
|
|
|
|
width="18"
|
|
|
|
|
|
height="18"
|
|
|
|
|
|
viewBox="0 0 24 24"
|
|
|
|
|
|
fill="none"
|
|
|
|
|
|
stroke="currentColor"
|
|
|
|
|
|
stroke-width="2"
|
|
|
|
|
|
>
|
|
|
|
|
|
<path
|
|
|
|
|
|
d="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z"
|
|
|
|
|
|
/>
|
|
|
|
|
|
</svg>
|
|
|
|
|
|
<span>Chat</span>
|
|
|
|
|
|
</a>
|
2026-01-03 17:19:17 -03:00
|
|
|
|
<a
|
|
|
|
|
|
class="app-tab"
|
|
|
|
|
|
href="#paper"
|
|
|
|
|
|
data-section="paper"
|
|
|
|
|
|
hx-get="/suite/paper/paper.html"
|
|
|
|
|
|
hx-target="#main-content"
|
|
|
|
|
|
hx-push-url="/#paper"
|
|
|
|
|
|
>
|
|
|
|
|
|
<svg
|
|
|
|
|
|
width="18"
|
|
|
|
|
|
height="18"
|
|
|
|
|
|
viewBox="0 0 24 24"
|
|
|
|
|
|
fill="none"
|
|
|
|
|
|
stroke="currentColor"
|
|
|
|
|
|
stroke-width="2"
|
|
|
|
|
|
>
|
|
|
|
|
|
<path
|
|
|
|
|
|
d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"
|
|
|
|
|
|
/>
|
|
|
|
|
|
<polyline points="14 2 14 8 20 8" />
|
|
|
|
|
|
<line x1="16" y1="13" x2="8" y2="13" />
|
|
|
|
|
|
<line x1="16" y1="17" x2="8" y2="17" />
|
|
|
|
|
|
</svg>
|
|
|
|
|
|
<span>Paper</span>
|
|
|
|
|
|
</a>
|
2025-12-15 18:48:40 -03:00
|
|
|
|
<a
|
|
|
|
|
|
class="app-tab"
|
|
|
|
|
|
href="#mail"
|
2026-01-03 17:19:17 -03:00
|
|
|
|
data-section="mail"
|
2025-12-15 18:48:40 -03:00
|
|
|
|
hx-get="/suite/mail/mail.html"
|
|
|
|
|
|
hx-target="#main-content"
|
|
|
|
|
|
hx-push-url="/#mail"
|
|
|
|
|
|
>
|
|
|
|
|
|
<svg
|
|
|
|
|
|
width="18"
|
|
|
|
|
|
height="18"
|
|
|
|
|
|
viewBox="0 0 24 24"
|
|
|
|
|
|
fill="none"
|
|
|
|
|
|
stroke="currentColor"
|
|
|
|
|
|
stroke-width="2"
|
|
|
|
|
|
>
|
|
|
|
|
|
<path
|
|
|
|
|
|
d="M4 4h16c1.1 0 2 .9 2 2v12c0 1.1-.9 2-2 2H4c-1.1 0-2-.9-2-2V6c0-1.1.9-2 2-2z"
|
|
|
|
|
|
/>
|
|
|
|
|
|
<polyline points="22,6 12,13 2,6" />
|
|
|
|
|
|
</svg>
|
2026-01-03 17:19:17 -03:00
|
|
|
|
<span>Mail</span>
|
2025-12-15 18:48:40 -03:00
|
|
|
|
</a>
|
|
|
|
|
|
<a
|
|
|
|
|
|
class="app-tab"
|
|
|
|
|
|
href="#calendar"
|
2026-01-03 17:19:17 -03:00
|
|
|
|
data-section="calendar"
|
2025-12-15 18:48:40 -03:00
|
|
|
|
hx-get="/suite/calendar/calendar.html"
|
|
|
|
|
|
hx-target="#main-content"
|
|
|
|
|
|
hx-push-url="/#calendar"
|
|
|
|
|
|
>
|
|
|
|
|
|
<svg
|
|
|
|
|
|
width="18"
|
|
|
|
|
|
height="18"
|
|
|
|
|
|
viewBox="0 0 24 24"
|
|
|
|
|
|
fill="none"
|
|
|
|
|
|
stroke="currentColor"
|
|
|
|
|
|
stroke-width="2"
|
|
|
|
|
|
>
|
|
|
|
|
|
<rect
|
|
|
|
|
|
x="3"
|
|
|
|
|
|
y="4"
|
|
|
|
|
|
width="18"
|
|
|
|
|
|
height="18"
|
|
|
|
|
|
rx="2"
|
|
|
|
|
|
ry="2"
|
|
|
|
|
|
/>
|
|
|
|
|
|
<line x1="16" y1="2" x2="16" y2="6" />
|
|
|
|
|
|
<line x1="8" y1="2" x2="8" y2="6" />
|
|
|
|
|
|
<line x1="3" y1="10" x2="21" y2="10" />
|
|
|
|
|
|
</svg>
|
|
|
|
|
|
<span>Calendar</span>
|
|
|
|
|
|
</a>
|
2026-01-03 17:19:17 -03:00
|
|
|
|
<a
|
|
|
|
|
|
class="app-tab"
|
|
|
|
|
|
href="#drive"
|
|
|
|
|
|
data-section="drive"
|
|
|
|
|
|
hx-get="/suite/drive/drive.html"
|
|
|
|
|
|
hx-target="#main-content"
|
|
|
|
|
|
hx-push-url="/#drive"
|
|
|
|
|
|
>
|
|
|
|
|
|
<svg
|
|
|
|
|
|
width="18"
|
|
|
|
|
|
height="18"
|
|
|
|
|
|
viewBox="0 0 24 24"
|
|
|
|
|
|
fill="none"
|
|
|
|
|
|
stroke="currentColor"
|
|
|
|
|
|
stroke-width="2"
|
|
|
|
|
|
>
|
|
|
|
|
|
<path
|
|
|
|
|
|
d="M22 19a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h5l2 3h9a2 2 0 0 1 2 2z"
|
|
|
|
|
|
/>
|
|
|
|
|
|
</svg>
|
|
|
|
|
|
<span>Drive</span>
|
|
|
|
|
|
</a>
|
2025-12-15 18:48:40 -03:00
|
|
|
|
<a
|
|
|
|
|
|
class="app-tab"
|
|
|
|
|
|
href="#tasks"
|
2026-01-03 17:19:17 -03:00
|
|
|
|
data-section="tasks"
|
2025-12-15 18:48:40 -03:00
|
|
|
|
hx-get="/suite/tasks/tasks.html"
|
|
|
|
|
|
hx-target="#main-content"
|
|
|
|
|
|
hx-push-url="/#tasks"
|
|
|
|
|
|
>
|
|
|
|
|
|
<svg
|
|
|
|
|
|
width="18"
|
|
|
|
|
|
height="18"
|
|
|
|
|
|
viewBox="0 0 24 24"
|
|
|
|
|
|
fill="none"
|
|
|
|
|
|
stroke="currentColor"
|
|
|
|
|
|
stroke-width="2"
|
|
|
|
|
|
>
|
|
|
|
|
|
<path d="M9 11l3 3L22 4" />
|
|
|
|
|
|
<path
|
|
|
|
|
|
d="M21 12v7a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h11"
|
|
|
|
|
|
/>
|
|
|
|
|
|
</svg>
|
|
|
|
|
|
<span>Tasks</span>
|
|
|
|
|
|
</a>
|
|
|
|
|
|
</nav>
|
2025-12-03 18:42:22 -03:00
|
|
|
|
|
2026-01-03 17:19:17 -03:00
|
|
|
|
<!-- Apps menu container (button + dropdown) -->
|
|
|
|
|
|
<div class="apps-menu-container" style="position: relative">
|
|
|
|
|
|
<button
|
|
|
|
|
|
class="icon-button apps-button"
|
|
|
|
|
|
id="appsButton"
|
|
|
|
|
|
title="All Applications"
|
|
|
|
|
|
aria-label="Open applications menu"
|
|
|
|
|
|
aria-expanded="false"
|
|
|
|
|
|
aria-haspopup="true"
|
2025-12-03 18:42:22 -03:00
|
|
|
|
>
|
2026-01-03 17:19:17 -03:00
|
|
|
|
<svg
|
|
|
|
|
|
width="20"
|
|
|
|
|
|
height="20"
|
|
|
|
|
|
viewBox="0 0 24 24"
|
|
|
|
|
|
fill="currentColor"
|
|
|
|
|
|
aria-hidden="true"
|
|
|
|
|
|
>
|
|
|
|
|
|
<circle cx="5" cy="5" r="2"></circle>
|
|
|
|
|
|
<circle cx="12" cy="5" r="2"></circle>
|
|
|
|
|
|
<circle cx="19" cy="5" r="2"></circle>
|
|
|
|
|
|
<circle cx="5" cy="12" r="2"></circle>
|
|
|
|
|
|
<circle cx="12" cy="12" r="2"></circle>
|
|
|
|
|
|
<circle cx="19" cy="12" r="2"></circle>
|
|
|
|
|
|
<circle cx="5" cy="19" r="2"></circle>
|
|
|
|
|
|
<circle cx="12" cy="19" r="2"></circle>
|
|
|
|
|
|
<circle cx="19" cy="19" r="2"></circle>
|
|
|
|
|
|
</svg>
|
|
|
|
|
|
</button>
|
|
|
|
|
|
|
|
|
|
|
|
<!-- Apps dropdown menu -->
|
|
|
|
|
|
<nav
|
|
|
|
|
|
class="apps-dropdown"
|
|
|
|
|
|
id="appsDropdown"
|
|
|
|
|
|
role="menu"
|
|
|
|
|
|
aria-label="Applications"
|
|
|
|
|
|
>
|
|
|
|
|
|
<div class="apps-dropdown-title">All Applications</div>
|
|
|
|
|
|
<div class="app-grid" role="group">
|
|
|
|
|
|
<!-- Chat -->
|
|
|
|
|
|
<a
|
|
|
|
|
|
class="app-item active"
|
|
|
|
|
|
href="#chat"
|
|
|
|
|
|
data-section="chat"
|
|
|
|
|
|
role="menuitem"
|
|
|
|
|
|
aria-label="Chat application"
|
|
|
|
|
|
hx-get="/suite/chat/chat.html"
|
|
|
|
|
|
hx-target="#main-content"
|
|
|
|
|
|
hx-push-url="/#chat"
|
|
|
|
|
|
>
|
|
|
|
|
|
<div class="app-icon" aria-hidden="true">
|
|
|
|
|
|
<svg
|
|
|
|
|
|
width="20"
|
|
|
|
|
|
height="20"
|
|
|
|
|
|
viewBox="0 0 24 24"
|
|
|
|
|
|
fill="none"
|
|
|
|
|
|
stroke="currentColor"
|
|
|
|
|
|
stroke-width="2"
|
|
|
|
|
|
>
|
|
|
|
|
|
<path
|
|
|
|
|
|
d="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z"
|
|
|
|
|
|
/>
|
|
|
|
|
|
</svg>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<span>Chat</span>
|
|
|
|
|
|
</a>
|
|
|
|
|
|
|
|
|
|
|
|
<!-- Research -->
|
|
|
|
|
|
<a
|
|
|
|
|
|
class="app-item"
|
|
|
|
|
|
href="#research"
|
|
|
|
|
|
data-section="research"
|
|
|
|
|
|
role="menuitem"
|
|
|
|
|
|
aria-label="Research application"
|
|
|
|
|
|
hx-get="/suite/research/research.html"
|
|
|
|
|
|
hx-target="#main-content"
|
|
|
|
|
|
hx-push-url="/#research"
|
|
|
|
|
|
>
|
|
|
|
|
|
<div class="app-icon" aria-hidden="true">
|
|
|
|
|
|
<svg
|
|
|
|
|
|
width="20"
|
|
|
|
|
|
height="20"
|
|
|
|
|
|
viewBox="0 0 24 24"
|
|
|
|
|
|
fill="none"
|
|
|
|
|
|
stroke="currentColor"
|
|
|
|
|
|
stroke-width="2"
|
|
|
|
|
|
>
|
|
|
|
|
|
<circle cx="11" cy="11" r="8" />
|
|
|
|
|
|
<path d="m21 21-4.35-4.35" />
|
|
|
|
|
|
<path d="M11 8v6M8 11h6" />
|
|
|
|
|
|
</svg>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<span>Research</span>
|
|
|
|
|
|
</a>
|
|
|
|
|
|
|
|
|
|
|
|
<!-- Paper -->
|
|
|
|
|
|
<a
|
|
|
|
|
|
class="app-item"
|
|
|
|
|
|
href="#paper"
|
|
|
|
|
|
data-section="paper"
|
|
|
|
|
|
role="menuitem"
|
|
|
|
|
|
aria-label="Paper - Notes & Writing"
|
|
|
|
|
|
hx-get="/suite/paper/paper.html"
|
|
|
|
|
|
hx-target="#main-content"
|
|
|
|
|
|
hx-push-url="/#paper"
|
|
|
|
|
|
>
|
|
|
|
|
|
<div class="app-icon" aria-hidden="true">
|
|
|
|
|
|
<svg
|
|
|
|
|
|
width="20"
|
|
|
|
|
|
height="20"
|
|
|
|
|
|
viewBox="0 0 24 24"
|
|
|
|
|
|
fill="none"
|
|
|
|
|
|
stroke="currentColor"
|
|
|
|
|
|
stroke-width="2"
|
|
|
|
|
|
>
|
|
|
|
|
|
<path
|
|
|
|
|
|
d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"
|
|
|
|
|
|
/>
|
|
|
|
|
|
<polyline points="14 2 14 8 20 8" />
|
|
|
|
|
|
<line x1="16" y1="13" x2="8" y2="13" />
|
|
|
|
|
|
<line x1="16" y1="17" x2="8" y2="17" />
|
|
|
|
|
|
</svg>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<span>Paper</span>
|
|
|
|
|
|
</a>
|
|
|
|
|
|
|
|
|
|
|
|
<!-- Drive -->
|
|
|
|
|
|
<a
|
|
|
|
|
|
class="app-item"
|
|
|
|
|
|
href="#drive"
|
|
|
|
|
|
data-section="drive"
|
|
|
|
|
|
role="menuitem"
|
|
|
|
|
|
aria-label="Drive application"
|
|
|
|
|
|
hx-get="/suite/drive/drive.html"
|
|
|
|
|
|
hx-target="#main-content"
|
|
|
|
|
|
hx-push-url="/#drive"
|
|
|
|
|
|
>
|
|
|
|
|
|
<div class="app-icon" aria-hidden="true">
|
|
|
|
|
|
<svg
|
|
|
|
|
|
width="20"
|
|
|
|
|
|
height="20"
|
|
|
|
|
|
viewBox="0 0 24 24"
|
|
|
|
|
|
fill="none"
|
|
|
|
|
|
stroke="currentColor"
|
|
|
|
|
|
stroke-width="2"
|
|
|
|
|
|
>
|
|
|
|
|
|
<path
|
|
|
|
|
|
d="M22 19a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h5l2 3h9a2 2 0 0 1 2 2z"
|
|
|
|
|
|
/>
|
|
|
|
|
|
</svg>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<span>Drive</span>
|
|
|
|
|
|
</a>
|
|
|
|
|
|
|
|
|
|
|
|
<!-- Calendar -->
|
|
|
|
|
|
<a
|
|
|
|
|
|
class="app-item"
|
|
|
|
|
|
href="#calendar"
|
|
|
|
|
|
data-section="calendar"
|
|
|
|
|
|
role="menuitem"
|
|
|
|
|
|
aria-label="Calendar application"
|
|
|
|
|
|
hx-get="/suite/calendar/calendar.html"
|
|
|
|
|
|
hx-target="#main-content"
|
|
|
|
|
|
hx-push-url="/#calendar"
|
|
|
|
|
|
>
|
|
|
|
|
|
<div class="app-icon" aria-hidden="true">
|
|
|
|
|
|
<svg
|
|
|
|
|
|
width="20"
|
|
|
|
|
|
height="20"
|
|
|
|
|
|
viewBox="0 0 24 24"
|
|
|
|
|
|
fill="none"
|
|
|
|
|
|
stroke="currentColor"
|
|
|
|
|
|
stroke-width="2"
|
|
|
|
|
|
>
|
|
|
|
|
|
<rect
|
|
|
|
|
|
x="3"
|
|
|
|
|
|
y="4"
|
|
|
|
|
|
width="18"
|
|
|
|
|
|
height="18"
|
|
|
|
|
|
rx="2"
|
|
|
|
|
|
ry="2"
|
|
|
|
|
|
/>
|
|
|
|
|
|
<line x1="16" y1="2" x2="16" y2="6" />
|
|
|
|
|
|
<line x1="8" y1="2" x2="8" y2="6" />
|
|
|
|
|
|
<line x1="3" y1="10" x2="21" y2="10" />
|
|
|
|
|
|
</svg>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<span>Calendar</span>
|
|
|
|
|
|
</a>
|
|
|
|
|
|
|
|
|
|
|
|
<!-- Tasks -->
|
|
|
|
|
|
<a
|
|
|
|
|
|
class="app-item"
|
|
|
|
|
|
href="#tasks"
|
|
|
|
|
|
data-section="tasks"
|
|
|
|
|
|
role="menuitem"
|
|
|
|
|
|
aria-label="Tasks application"
|
|
|
|
|
|
hx-get="/suite/tasks/tasks.html"
|
|
|
|
|
|
hx-target="#main-content"
|
|
|
|
|
|
hx-push-url="/#tasks"
|
|
|
|
|
|
>
|
|
|
|
|
|
<div class="app-icon" aria-hidden="true">
|
|
|
|
|
|
<svg
|
|
|
|
|
|
width="20"
|
|
|
|
|
|
height="20"
|
|
|
|
|
|
viewBox="0 0 24 24"
|
|
|
|
|
|
fill="none"
|
|
|
|
|
|
stroke="currentColor"
|
|
|
|
|
|
stroke-width="2"
|
|
|
|
|
|
>
|
|
|
|
|
|
<path d="M9 11l3 3L22 4" />
|
|
|
|
|
|
<path
|
|
|
|
|
|
d="M21 12v7a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h11"
|
|
|
|
|
|
/>
|
|
|
|
|
|
</svg>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<span>Tasks</span>
|
|
|
|
|
|
</a>
|
|
|
|
|
|
|
|
|
|
|
|
<!-- Mail -->
|
|
|
|
|
|
<a
|
|
|
|
|
|
class="app-item"
|
|
|
|
|
|
href="#mail"
|
|
|
|
|
|
data-section="mail"
|
|
|
|
|
|
role="menuitem"
|
|
|
|
|
|
aria-label="Mail application"
|
|
|
|
|
|
hx-get="/suite/mail/mail.html"
|
|
|
|
|
|
hx-target="#main-content"
|
|
|
|
|
|
hx-push-url="/#mail"
|
|
|
|
|
|
>
|
|
|
|
|
|
<div class="app-icon" aria-hidden="true">
|
|
|
|
|
|
<svg
|
|
|
|
|
|
width="20"
|
|
|
|
|
|
height="20"
|
|
|
|
|
|
viewBox="0 0 24 24"
|
|
|
|
|
|
fill="none"
|
|
|
|
|
|
stroke="currentColor"
|
|
|
|
|
|
stroke-width="2"
|
|
|
|
|
|
>
|
|
|
|
|
|
<path
|
|
|
|
|
|
d="M4 4h16c1.1 0 2 .9 2 2v12c0 1.1-.9 2-2 2H4c-1.1 0-2-.9-2-2V6c0-1.1.9-2 2-2z"
|
|
|
|
|
|
/>
|
|
|
|
|
|
<polyline points="22,6 12,13 2,6" />
|
|
|
|
|
|
</svg>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<span>Mail</span>
|
|
|
|
|
|
</a>
|
|
|
|
|
|
|
|
|
|
|
|
<!-- Meet -->
|
|
|
|
|
|
<a
|
|
|
|
|
|
class="app-item"
|
|
|
|
|
|
href="#meet"
|
|
|
|
|
|
data-section="meet"
|
|
|
|
|
|
role="menuitem"
|
|
|
|
|
|
aria-label="Meet application"
|
|
|
|
|
|
hx-get="/suite/meet/meet.html"
|
|
|
|
|
|
hx-target="#main-content"
|
|
|
|
|
|
hx-push-url="/#meet"
|
|
|
|
|
|
>
|
|
|
|
|
|
<div class="app-icon" aria-hidden="true">
|
|
|
|
|
|
<svg
|
|
|
|
|
|
width="20"
|
|
|
|
|
|
height="20"
|
|
|
|
|
|
viewBox="0 0 24 24"
|
|
|
|
|
|
fill="none"
|
|
|
|
|
|
stroke="currentColor"
|
|
|
|
|
|
stroke-width="2"
|
|
|
|
|
|
>
|
|
|
|
|
|
<polygon
|
|
|
|
|
|
points="23 7 16 12 23 17 23 7"
|
|
|
|
|
|
/>
|
|
|
|
|
|
<rect
|
|
|
|
|
|
x="1"
|
|
|
|
|
|
y="5"
|
|
|
|
|
|
width="15"
|
|
|
|
|
|
height="14"
|
|
|
|
|
|
rx="2"
|
|
|
|
|
|
ry="2"
|
|
|
|
|
|
/>
|
|
|
|
|
|
</svg>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<span>Meet</span>
|
|
|
|
|
|
</a>
|
|
|
|
|
|
|
|
|
|
|
|
<!-- Analytics -->
|
|
|
|
|
|
<a
|
|
|
|
|
|
class="app-item"
|
|
|
|
|
|
href="#analytics"
|
|
|
|
|
|
data-section="analytics"
|
|
|
|
|
|
role="menuitem"
|
|
|
|
|
|
aria-label="Analytics Dashboard"
|
|
|
|
|
|
hx-get="/suite/analytics/analytics.html"
|
|
|
|
|
|
hx-target="#main-content"
|
|
|
|
|
|
hx-push-url="/#analytics"
|
|
|
|
|
|
>
|
|
|
|
|
|
<div class="app-icon" aria-hidden="true">
|
|
|
|
|
|
<svg
|
|
|
|
|
|
width="20"
|
|
|
|
|
|
height="20"
|
|
|
|
|
|
viewBox="0 0 24 24"
|
|
|
|
|
|
fill="none"
|
|
|
|
|
|
stroke="currentColor"
|
|
|
|
|
|
stroke-width="2"
|
|
|
|
|
|
>
|
|
|
|
|
|
<line x1="18" y1="20" x2="18" y2="10" />
|
|
|
|
|
|
<line x1="12" y1="20" x2="12" y2="4" />
|
|
|
|
|
|
<line x1="6" y1="20" x2="6" y2="14" />
|
|
|
|
|
|
</svg>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<span>Analytics</span>
|
|
|
|
|
|
</a>
|
|
|
|
|
|
|
|
|
|
|
|
<!-- Monitoring -->
|
|
|
|
|
|
<a
|
|
|
|
|
|
class="app-item"
|
|
|
|
|
|
href="#monitoring"
|
|
|
|
|
|
data-section="monitoring"
|
|
|
|
|
|
role="menuitem"
|
|
|
|
|
|
aria-label="System Monitoring"
|
|
|
|
|
|
hx-get="/suite/monitoring/monitoring.html"
|
|
|
|
|
|
hx-target="#main-content"
|
|
|
|
|
|
hx-push-url="/#monitoring"
|
|
|
|
|
|
>
|
|
|
|
|
|
<div class="app-icon" aria-hidden="true">
|
|
|
|
|
|
<svg
|
|
|
|
|
|
width="20"
|
|
|
|
|
|
height="20"
|
|
|
|
|
|
viewBox="0 0 24 24"
|
|
|
|
|
|
fill="none"
|
|
|
|
|
|
stroke="currentColor"
|
|
|
|
|
|
stroke-width="2"
|
|
|
|
|
|
>
|
|
|
|
|
|
<circle cx="12" cy="12" r="10" />
|
|
|
|
|
|
<circle cx="12" cy="12" r="6" />
|
|
|
|
|
|
<circle cx="12" cy="12" r="2" />
|
|
|
|
|
|
</svg>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<span>Monitoring</span>
|
|
|
|
|
|
</a>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</nav>
|
|
|
|
|
|
</div>
|
2025-12-15 18:48:40 -03:00
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
<!-- Center: Search -->
|
|
|
|
|
|
<div class="header-center">
|
|
|
|
|
|
<div class="header-search">
|
|
|
|
|
|
<svg
|
|
|
|
|
|
width="16"
|
|
|
|
|
|
height="16"
|
|
|
|
|
|
viewBox="0 0 24 24"
|
|
|
|
|
|
fill="none"
|
|
|
|
|
|
stroke="currentColor"
|
|
|
|
|
|
stroke-width="2"
|
|
|
|
|
|
>
|
|
|
|
|
|
<circle cx="11" cy="11" r="8" />
|
|
|
|
|
|
<path d="m21 21-4.35-4.35" />
|
|
|
|
|
|
</svg>
|
|
|
|
|
|
<input
|
|
|
|
|
|
type="text"
|
|
|
|
|
|
class="search-input"
|
|
|
|
|
|
placeholder="Search..."
|
|
|
|
|
|
id="globalSearch"
|
|
|
|
|
|
/>
|
|
|
|
|
|
<kbd class="search-shortcut">⌘K</kbd>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
<!-- Right: Notifications + User -->
|
|
|
|
|
|
<div class="header-right">
|
2026-01-03 17:19:17 -03:00
|
|
|
|
<!-- Notifications Bell -->
|
|
|
|
|
|
<div class="notifications-menu">
|
|
|
|
|
|
<button
|
|
|
|
|
|
class="icon-button"
|
|
|
|
|
|
id="notificationsBtn"
|
|
|
|
|
|
title="Notifications"
|
|
|
|
|
|
aria-expanded="false"
|
2025-12-15 18:48:40 -03:00
|
|
|
|
>
|
2026-01-03 17:19:17 -03:00
|
|
|
|
<svg
|
|
|
|
|
|
width="20"
|
|
|
|
|
|
height="20"
|
|
|
|
|
|
viewBox="0 0 24 24"
|
|
|
|
|
|
fill="none"
|
|
|
|
|
|
stroke="currentColor"
|
|
|
|
|
|
stroke-width="2"
|
|
|
|
|
|
>
|
|
|
|
|
|
<path
|
|
|
|
|
|
d="M18 8A6 6 0 0 0 6 8c0 7-3 9-3 9h18s-3-2-3-9"
|
|
|
|
|
|
/>
|
|
|
|
|
|
<path d="M13.73 21a2 2 0 0 1-3.46 0" />
|
|
|
|
|
|
</svg>
|
|
|
|
|
|
<span
|
|
|
|
|
|
class="notifications-badge"
|
|
|
|
|
|
id="notificationsBadge"
|
|
|
|
|
|
style="display: none"
|
|
|
|
|
|
>0</span
|
|
|
|
|
|
>
|
|
|
|
|
|
</button>
|
|
|
|
|
|
<div class="notifications-panel" id="notificationsPanel">
|
|
|
|
|
|
<div class="notifications-panel-header">
|
|
|
|
|
|
<span class="notifications-panel-title"
|
|
|
|
|
|
>Notifications</span
|
|
|
|
|
|
>
|
|
|
|
|
|
<button
|
|
|
|
|
|
class="notifications-clear-btn"
|
|
|
|
|
|
id="clearNotificationsBtn"
|
|
|
|
|
|
>
|
|
|
|
|
|
Clear all
|
|
|
|
|
|
</button>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<div class="notifications-list" id="notificationsList">
|
|
|
|
|
|
<div class="notifications-empty">
|
|
|
|
|
|
<span>🔔</span>
|
|
|
|
|
|
<p>No notifications</p>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
2025-12-15 23:16:09 -03:00
|
|
|
|
<button
|
|
|
|
|
|
class="icon-button"
|
|
|
|
|
|
id="settingsBtn"
|
|
|
|
|
|
title="Settings"
|
|
|
|
|
|
aria-expanded="false"
|
|
|
|
|
|
aria-haspopup="true"
|
|
|
|
|
|
>
|
2025-12-15 18:48:40 -03:00
|
|
|
|
<svg
|
|
|
|
|
|
width="20"
|
|
|
|
|
|
height="20"
|
|
|
|
|
|
viewBox="0 0 24 24"
|
|
|
|
|
|
fill="none"
|
|
|
|
|
|
stroke="currentColor"
|
|
|
|
|
|
stroke-width="2"
|
|
|
|
|
|
>
|
|
|
|
|
|
<circle cx="12" cy="12" r="3" />
|
|
|
|
|
|
<path
|
|
|
|
|
|
d="M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 0 1 0 2.83 2 2 0 0 1-2.83 0l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 0 1-2 2 2 2 0 0 1-2-2v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 0 1-2.83 0 2 2 0 0 1 0-2.83l.06-.06a1.65 1.65 0 0 0 .33-1.82 1.65 1.65 0 0 0-1.51-1H3a2 2 0 0 1-2-2 2 2 0 0 1 2-2h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 0 1 0-2.83 2 2 0 0 1 2.83 0l.06.06a1.65 1.65 0 0 0 1.82.33H9a1.65 1.65 0 0 0 1-1.51V3a2 2 0 0 1 2-2 2 2 0 0 1 2 2v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 0 1 2.83 0 2 2 0 0 1 0 2.83l-.06.06a1.65 1.65 0 0 0-.33 1.82V9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 0 1 2 2 2 2 0 0 1-2 2h-.09a1.65 1.65 0 0 0-1.51 1z"
|
|
|
|
|
|
/>
|
|
|
|
|
|
</svg>
|
|
|
|
|
|
</button>
|
2025-12-03 18:42:22 -03:00
|
|
|
|
|
2025-12-15 23:16:09 -03:00
|
|
|
|
<!-- Settings/Theme Panel -->
|
|
|
|
|
|
<div
|
|
|
|
|
|
class="settings-panel"
|
|
|
|
|
|
id="settingsPanel"
|
|
|
|
|
|
role="menu"
|
|
|
|
|
|
aria-label="Settings"
|
|
|
|
|
|
>
|
|
|
|
|
|
<div class="settings-panel-title">Theme</div>
|
|
|
|
|
|
<div class="theme-grid">
|
2025-12-16 09:57:46 -03:00
|
|
|
|
<!-- Core Themes -->
|
2025-12-15 23:16:09 -03:00
|
|
|
|
<button
|
|
|
|
|
|
class="theme-option theme-sentient"
|
|
|
|
|
|
data-theme="sentient"
|
|
|
|
|
|
title="Sentient"
|
|
|
|
|
|
>
|
|
|
|
|
|
<div class="theme-option-inner">
|
|
|
|
|
|
<div class="theme-option-header">
|
|
|
|
|
|
<div class="theme-option-dot"></div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<div class="theme-option-body">
|
|
|
|
|
|
<div class="theme-option-line"></div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
2025-12-16 09:57:46 -03:00
|
|
|
|
<span class="theme-option-name">🤖 Sentient</span>
|
2025-12-15 23:16:09 -03:00
|
|
|
|
</button>
|
|
|
|
|
|
<button
|
|
|
|
|
|
class="theme-option theme-dark"
|
|
|
|
|
|
data-theme="dark"
|
|
|
|
|
|
title="Dark"
|
|
|
|
|
|
>
|
|
|
|
|
|
<div class="theme-option-inner">
|
|
|
|
|
|
<div class="theme-option-header">
|
|
|
|
|
|
<div class="theme-option-dot"></div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<div class="theme-option-body">
|
|
|
|
|
|
<div class="theme-option-line"></div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
2025-12-16 09:57:46 -03:00
|
|
|
|
<span class="theme-option-name">🌑 Dark</span>
|
2025-12-15 23:16:09 -03:00
|
|
|
|
</button>
|
|
|
|
|
|
<button
|
|
|
|
|
|
class="theme-option theme-light"
|
|
|
|
|
|
data-theme="light"
|
|
|
|
|
|
title="Light"
|
|
|
|
|
|
>
|
|
|
|
|
|
<div class="theme-option-inner">
|
|
|
|
|
|
<div class="theme-option-header">
|
|
|
|
|
|
<div class="theme-option-dot"></div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<div class="theme-option-body">
|
|
|
|
|
|
<div class="theme-option-line"></div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
2025-12-16 09:57:46 -03:00
|
|
|
|
<span class="theme-option-name">☀️ Light</span>
|
2025-12-15 23:16:09 -03:00
|
|
|
|
</button>
|
|
|
|
|
|
<button
|
2025-12-16 09:57:46 -03:00
|
|
|
|
class="theme-option theme-blue"
|
|
|
|
|
|
data-theme="blue"
|
|
|
|
|
|
title="Ocean"
|
2025-12-15 23:16:09 -03:00
|
|
|
|
>
|
|
|
|
|
|
<div class="theme-option-inner">
|
|
|
|
|
|
<div class="theme-option-header">
|
|
|
|
|
|
<div class="theme-option-dot"></div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<div class="theme-option-body">
|
|
|
|
|
|
<div class="theme-option-line"></div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
2025-12-16 09:57:46 -03:00
|
|
|
|
<span class="theme-option-name">🌊 Ocean</span>
|
2025-12-15 23:16:09 -03:00
|
|
|
|
</button>
|
|
|
|
|
|
<button
|
|
|
|
|
|
class="theme-option theme-purple"
|
|
|
|
|
|
data-theme="purple"
|
2025-12-16 09:57:46 -03:00
|
|
|
|
title="Violet"
|
2025-12-15 23:16:09 -03:00
|
|
|
|
>
|
|
|
|
|
|
<div class="theme-option-inner">
|
|
|
|
|
|
<div class="theme-option-header">
|
|
|
|
|
|
<div class="theme-option-dot"></div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<div class="theme-option-body">
|
|
|
|
|
|
<div class="theme-option-line"></div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
2025-12-16 09:57:46 -03:00
|
|
|
|
<span class="theme-option-name">💜 Violet</span>
|
2025-12-15 23:16:09 -03:00
|
|
|
|
</button>
|
|
|
|
|
|
<button
|
|
|
|
|
|
class="theme-option theme-green"
|
|
|
|
|
|
data-theme="green"
|
2025-12-16 09:57:46 -03:00
|
|
|
|
title="Forest"
|
|
|
|
|
|
>
|
|
|
|
|
|
<div class="theme-option-inner">
|
|
|
|
|
|
<div class="theme-option-header">
|
|
|
|
|
|
<div class="theme-option-dot"></div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<div class="theme-option-body">
|
|
|
|
|
|
<div class="theme-option-line"></div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<span class="theme-option-name">🌲 Forest</span>
|
|
|
|
|
|
</button>
|
|
|
|
|
|
<button
|
|
|
|
|
|
class="theme-option theme-orange"
|
|
|
|
|
|
data-theme="orange"
|
|
|
|
|
|
title="Sunset"
|
|
|
|
|
|
>
|
|
|
|
|
|
<div class="theme-option-inner">
|
|
|
|
|
|
<div class="theme-option-header">
|
|
|
|
|
|
<div class="theme-option-dot"></div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<div class="theme-option-body">
|
|
|
|
|
|
<div class="theme-option-line"></div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<span class="theme-option-name">🌅 Sunset</span>
|
|
|
|
|
|
</button>
|
|
|
|
|
|
<!-- Retro Themes -->
|
|
|
|
|
|
<button
|
|
|
|
|
|
class="theme-option theme-cyberpunk"
|
|
|
|
|
|
data-theme="cyberpunk"
|
|
|
|
|
|
title="Cyberpunk"
|
|
|
|
|
|
>
|
|
|
|
|
|
<div class="theme-option-inner">
|
|
|
|
|
|
<div class="theme-option-header">
|
|
|
|
|
|
<div class="theme-option-dot"></div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<div class="theme-option-body">
|
|
|
|
|
|
<div class="theme-option-line"></div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<span class="theme-option-name">🌃 Cyberpunk</span>
|
|
|
|
|
|
</button>
|
|
|
|
|
|
<button
|
|
|
|
|
|
class="theme-option theme-retrowave"
|
|
|
|
|
|
data-theme="retrowave"
|
|
|
|
|
|
title="Retrowave"
|
|
|
|
|
|
>
|
|
|
|
|
|
<div class="theme-option-inner">
|
|
|
|
|
|
<div class="theme-option-header">
|
|
|
|
|
|
<div class="theme-option-dot"></div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<div class="theme-option-body">
|
|
|
|
|
|
<div class="theme-option-line"></div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<span class="theme-option-name">🌴 Retrowave</span>
|
|
|
|
|
|
</button>
|
|
|
|
|
|
<button
|
|
|
|
|
|
class="theme-option theme-vapordream"
|
|
|
|
|
|
data-theme="vapordream"
|
|
|
|
|
|
title="Vapor Dream"
|
|
|
|
|
|
>
|
|
|
|
|
|
<div class="theme-option-inner">
|
|
|
|
|
|
<div class="theme-option-header">
|
|
|
|
|
|
<div class="theme-option-dot"></div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<div class="theme-option-body">
|
|
|
|
|
|
<div class="theme-option-line"></div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<span class="theme-option-name"
|
|
|
|
|
|
>💭 Vapor Dream</span
|
|
|
|
|
|
>
|
|
|
|
|
|
</button>
|
|
|
|
|
|
<button
|
|
|
|
|
|
class="theme-option theme-y2kglow"
|
|
|
|
|
|
data-theme="y2kglow"
|
|
|
|
|
|
title="Y2K"
|
|
|
|
|
|
>
|
|
|
|
|
|
<div class="theme-option-inner">
|
|
|
|
|
|
<div class="theme-option-header">
|
|
|
|
|
|
<div class="theme-option-dot"></div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<div class="theme-option-body">
|
|
|
|
|
|
<div class="theme-option-line"></div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<span class="theme-option-name">✨ Y2K</span>
|
|
|
|
|
|
</button>
|
|
|
|
|
|
<button
|
|
|
|
|
|
class="theme-option theme-arcadeflash"
|
|
|
|
|
|
data-theme="arcadeflash"
|
|
|
|
|
|
title="Arcade"
|
|
|
|
|
|
>
|
|
|
|
|
|
<div class="theme-option-inner">
|
|
|
|
|
|
<div class="theme-option-header">
|
|
|
|
|
|
<div class="theme-option-dot"></div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<div class="theme-option-body">
|
|
|
|
|
|
<div class="theme-option-line"></div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<span class="theme-option-name">🕹️ Arcade</span>
|
|
|
|
|
|
</button>
|
|
|
|
|
|
<button
|
|
|
|
|
|
class="theme-option theme-discofever"
|
|
|
|
|
|
data-theme="discofever"
|
|
|
|
|
|
title="Disco"
|
|
|
|
|
|
>
|
|
|
|
|
|
<div class="theme-option-inner">
|
|
|
|
|
|
<div class="theme-option-header">
|
|
|
|
|
|
<div class="theme-option-dot"></div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<div class="theme-option-body">
|
|
|
|
|
|
<div class="theme-option-line"></div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<span class="theme-option-name">🪩 Disco</span>
|
|
|
|
|
|
</button>
|
|
|
|
|
|
<button
|
|
|
|
|
|
class="theme-option theme-grungeera"
|
|
|
|
|
|
data-theme="grungeera"
|
|
|
|
|
|
title="Grunge"
|
|
|
|
|
|
>
|
|
|
|
|
|
<div class="theme-option-inner">
|
|
|
|
|
|
<div class="theme-option-header">
|
|
|
|
|
|
<div class="theme-option-dot"></div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<div class="theme-option-body">
|
|
|
|
|
|
<div class="theme-option-line"></div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<span class="theme-option-name">🎸 Grunge</span>
|
|
|
|
|
|
</button>
|
|
|
|
|
|
<!-- Classic Themes -->
|
|
|
|
|
|
<button
|
|
|
|
|
|
class="theme-option theme-jazzage"
|
|
|
|
|
|
data-theme="jazzage"
|
|
|
|
|
|
title="Jazz Age"
|
|
|
|
|
|
>
|
|
|
|
|
|
<div class="theme-option-inner">
|
|
|
|
|
|
<div class="theme-option-header">
|
|
|
|
|
|
<div class="theme-option-dot"></div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<div class="theme-option-body">
|
|
|
|
|
|
<div class="theme-option-line"></div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<span class="theme-option-name">🎺 Jazz Age</span>
|
|
|
|
|
|
</button>
|
|
|
|
|
|
<button
|
|
|
|
|
|
class="theme-option theme-mellowgold"
|
|
|
|
|
|
data-theme="mellowgold"
|
|
|
|
|
|
title="Mellow Gold"
|
|
|
|
|
|
>
|
|
|
|
|
|
<div class="theme-option-inner">
|
|
|
|
|
|
<div class="theme-option-header">
|
|
|
|
|
|
<div class="theme-option-dot"></div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<div class="theme-option-body">
|
|
|
|
|
|
<div class="theme-option-line"></div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<span class="theme-option-name"
|
|
|
|
|
|
>🌻 Mellow Gold</span
|
|
|
|
|
|
>
|
|
|
|
|
|
</button>
|
|
|
|
|
|
<button
|
|
|
|
|
|
class="theme-option theme-midcenturymod"
|
|
|
|
|
|
data-theme="midcenturymod"
|
|
|
|
|
|
title="Mid Century"
|
|
|
|
|
|
>
|
|
|
|
|
|
<div class="theme-option-inner">
|
|
|
|
|
|
<div class="theme-option-header">
|
|
|
|
|
|
<div class="theme-option-dot"></div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<div class="theme-option-body">
|
|
|
|
|
|
<div class="theme-option-line"></div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<span class="theme-option-name"
|
|
|
|
|
|
>🏠 Mid Century</span
|
|
|
|
|
|
>
|
|
|
|
|
|
</button>
|
|
|
|
|
|
<button
|
|
|
|
|
|
class="theme-option theme-polaroidmemories"
|
|
|
|
|
|
data-theme="polaroidmemories"
|
|
|
|
|
|
title="Polaroid"
|
|
|
|
|
|
>
|
|
|
|
|
|
<div class="theme-option-inner">
|
|
|
|
|
|
<div class="theme-option-header">
|
|
|
|
|
|
<div class="theme-option-dot"></div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<div class="theme-option-body">
|
|
|
|
|
|
<div class="theme-option-line"></div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<span class="theme-option-name">📷 Polaroid</span>
|
|
|
|
|
|
</button>
|
|
|
|
|
|
<button
|
|
|
|
|
|
class="theme-option theme-saturdaycartoons"
|
|
|
|
|
|
data-theme="saturdaycartoons"
|
|
|
|
|
|
title="Cartoons"
|
|
|
|
|
|
>
|
|
|
|
|
|
<div class="theme-option-inner">
|
|
|
|
|
|
<div class="theme-option-header">
|
|
|
|
|
|
<div class="theme-option-dot"></div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<div class="theme-option-body">
|
|
|
|
|
|
<div class="theme-option-line"></div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<span class="theme-option-name">📺 Cartoons</span>
|
|
|
|
|
|
</button>
|
|
|
|
|
|
<button
|
|
|
|
|
|
class="theme-option theme-seasidepostcard"
|
|
|
|
|
|
data-theme="seasidepostcard"
|
|
|
|
|
|
title="Seaside"
|
|
|
|
|
|
>
|
|
|
|
|
|
<div class="theme-option-inner">
|
|
|
|
|
|
<div class="theme-option-header">
|
|
|
|
|
|
<div class="theme-option-dot"></div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<div class="theme-option-body">
|
|
|
|
|
|
<div class="theme-option-line"></div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<span class="theme-option-name">🏖️ Seaside</span>
|
|
|
|
|
|
</button>
|
|
|
|
|
|
<button
|
|
|
|
|
|
class="theme-option theme-typewriter"
|
|
|
|
|
|
data-theme="typewriter"
|
|
|
|
|
|
title="Typewriter"
|
|
|
|
|
|
>
|
|
|
|
|
|
<div class="theme-option-inner">
|
|
|
|
|
|
<div class="theme-option-header">
|
|
|
|
|
|
<div class="theme-option-dot"></div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<div class="theme-option-body">
|
|
|
|
|
|
<div class="theme-option-line"></div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<span class="theme-option-name">⌨️ Typewriter</span>
|
|
|
|
|
|
</button>
|
|
|
|
|
|
<!-- Tech Themes -->
|
|
|
|
|
|
<button
|
|
|
|
|
|
class="theme-option theme-3dbevel"
|
|
|
|
|
|
data-theme="3dbevel"
|
|
|
|
|
|
title="3D Bevel"
|
|
|
|
|
|
>
|
|
|
|
|
|
<div class="theme-option-inner">
|
|
|
|
|
|
<div class="theme-option-header">
|
|
|
|
|
|
<div class="theme-option-dot"></div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<div class="theme-option-body">
|
|
|
|
|
|
<div class="theme-option-line"></div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<span class="theme-option-name">🔲 3D Bevel</span>
|
|
|
|
|
|
</button>
|
|
|
|
|
|
<button
|
|
|
|
|
|
class="theme-option theme-xeroxui"
|
|
|
|
|
|
data-theme="xeroxui"
|
|
|
|
|
|
title="Xerox UI"
|
|
|
|
|
|
>
|
|
|
|
|
|
<div class="theme-option-inner">
|
|
|
|
|
|
<div class="theme-option-header">
|
|
|
|
|
|
<div class="theme-option-dot"></div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<div class="theme-option-body">
|
|
|
|
|
|
<div class="theme-option-line"></div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<span class="theme-option-name">📠 Xerox UI</span>
|
|
|
|
|
|
</button>
|
|
|
|
|
|
<button
|
|
|
|
|
|
class="theme-option theme-xtreegold"
|
|
|
|
|
|
data-theme="xtreegold"
|
|
|
|
|
|
title="XTree Gold"
|
2025-12-15 23:16:09 -03:00
|
|
|
|
>
|
|
|
|
|
|
<div class="theme-option-inner">
|
|
|
|
|
|
<div class="theme-option-header">
|
|
|
|
|
|
<div class="theme-option-dot"></div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<div class="theme-option-body">
|
|
|
|
|
|
<div class="theme-option-line"></div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
2025-12-16 09:57:46 -03:00
|
|
|
|
<span class="theme-option-name">📁 XTree Gold</span>
|
2025-12-15 23:16:09 -03:00
|
|
|
|
</button>
|
|
|
|
|
|
</div>
|
2026-01-03 17:19:17 -03:00
|
|
|
|
<a
|
|
|
|
|
|
class="settings-link"
|
|
|
|
|
|
href="#settings"
|
|
|
|
|
|
hx-get="/suite/settings/index.html"
|
|
|
|
|
|
hx-target="#main-content"
|
|
|
|
|
|
hx-push-url="/#settings"
|
|
|
|
|
|
>
|
|
|
|
|
|
<svg
|
|
|
|
|
|
width="16"
|
|
|
|
|
|
height="16"
|
|
|
|
|
|
viewBox="0 0 24 24"
|
|
|
|
|
|
fill="none"
|
|
|
|
|
|
stroke="currentColor"
|
|
|
|
|
|
stroke-width="2"
|
2025-12-03 18:42:22 -03:00
|
|
|
|
>
|
2026-01-03 17:19:17 -03:00
|
|
|
|
<circle cx="12" cy="12" r="3" />
|
|
|
|
|
|
<path
|
|
|
|
|
|
d="M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 0 1 0 2.83 2 2 0 0 1-2.83 0l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 0 1-2 2 2 2 0 0 1-2-2v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 0 1-2.83 0 2 2 0 0 1 0-2.83l.06-.06a1.65 1.65 0 0 0 .33-1.82 1.65 1.65 0 0 0-1.51-1H3a2 2 0 0 1-2-2 2 2 0 0 1 2-2h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 0 1 0-2.83 2 2 0 0 1 2.83 0l.06.06a1.65 1.65 0 0 0 1.82.33H9a1.65 1.65 0 0 0 1-1.51V3a2 2 0 0 1 2-2 2 2 0 0 1 2 2v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 0 1 2.83 0 2 2 0 0 1 0 2.83l-.06.06a1.65 1.65 0 0 0-.33 1.82V9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 0 1 2 2 2 2 0 0 1-2 2h-.09a1.65 1.65 0 0 0-1.51 1z"
|
|
|
|
|
|
/>
|
|
|
|
|
|
</svg>
|
|
|
|
|
|
<span>Settings</span>
|
|
|
|
|
|
</a>
|
|
|
|
|
|
</div>
|
2025-12-03 18:42:22 -03:00
|
|
|
|
|
|
|
|
|
|
<!-- User avatar -->
|
|
|
|
|
|
<button
|
|
|
|
|
|
class="user-avatar"
|
|
|
|
|
|
id="userAvatar"
|
|
|
|
|
|
title="User Account"
|
|
|
|
|
|
aria-label="User account menu"
|
|
|
|
|
|
>
|
|
|
|
|
|
<span aria-hidden="true">U</span>
|
|
|
|
|
|
</button>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</header>
|
|
|
|
|
|
|
|
|
|
|
|
<!-- Main content area -->
|
2025-12-15 16:40:04 -03:00
|
|
|
|
<main id="main-content" role="main">
|
2025-12-03 18:42:22 -03:00
|
|
|
|
<!-- Sections will be loaded dynamically -->
|
|
|
|
|
|
</main>
|
|
|
|
|
|
|
|
|
|
|
|
<!-- Core scripts -->
|
|
|
|
|
|
<script src="js/theme-manager.js"></script>
|
|
|
|
|
|
<script src="js/htmx-app.js"></script>
|
2026-01-02 12:48:54 -03:00
|
|
|
|
<script src="tasks/tasks.js?v=20260102"></script>
|
2025-12-03 18:42:22 -03:00
|
|
|
|
|
|
|
|
|
|
<!-- Application initialization -->
|
|
|
|
|
|
<script>
|
|
|
|
|
|
// Simple initialization for HTMX app
|
2026-01-03 17:19:17 -03:00
|
|
|
|
// Note: Chat module is self-contained in chat.html
|
2025-12-03 18:42:22 -03:00
|
|
|
|
document.addEventListener("DOMContentLoaded", () => {
|
|
|
|
|
|
console.log("🚀 Initializing General Bots with HTMX...");
|
|
|
|
|
|
|
|
|
|
|
|
// Hide loading overlay
|
|
|
|
|
|
setTimeout(() => {
|
|
|
|
|
|
const loadingOverlay =
|
|
|
|
|
|
document.getElementById("loadingOverlay");
|
|
|
|
|
|
if (loadingOverlay) {
|
|
|
|
|
|
loadingOverlay.classList.add("hidden");
|
|
|
|
|
|
}
|
|
|
|
|
|
}, 500);
|
|
|
|
|
|
|
|
|
|
|
|
// Simple apps menu handling
|
|
|
|
|
|
const appsBtn = document.getElementById("appsButton");
|
|
|
|
|
|
const appsDropdown = document.getElementById("appsDropdown");
|
2025-12-15 23:16:09 -03:00
|
|
|
|
const settingsBtn = document.getElementById("settingsBtn");
|
|
|
|
|
|
const settingsPanel = document.getElementById("settingsPanel");
|
2025-12-03 18:42:22 -03:00
|
|
|
|
|
|
|
|
|
|
if (appsBtn && appsDropdown) {
|
|
|
|
|
|
appsBtn.addEventListener("click", (e) => {
|
|
|
|
|
|
e.stopPropagation();
|
|
|
|
|
|
const isOpen = appsDropdown.classList.toggle("show");
|
|
|
|
|
|
appsBtn.setAttribute("aria-expanded", isOpen);
|
2025-12-15 23:16:09 -03:00
|
|
|
|
// Close settings panel
|
|
|
|
|
|
if (settingsPanel)
|
|
|
|
|
|
settingsPanel.classList.remove("show");
|
2025-12-03 18:42:22 -03:00
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
document.addEventListener("click", (e) => {
|
|
|
|
|
|
if (
|
|
|
|
|
|
!appsDropdown.contains(e.target) &&
|
|
|
|
|
|
!appsBtn.contains(e.target)
|
|
|
|
|
|
) {
|
|
|
|
|
|
appsDropdown.classList.remove("show");
|
|
|
|
|
|
appsBtn.setAttribute("aria-expanded", "false");
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-12-15 23:16:09 -03:00
|
|
|
|
// Settings panel handling
|
|
|
|
|
|
if (settingsBtn && settingsPanel) {
|
|
|
|
|
|
settingsBtn.addEventListener("click", (e) => {
|
|
|
|
|
|
e.stopPropagation();
|
|
|
|
|
|
const isOpen = settingsPanel.classList.toggle("show");
|
|
|
|
|
|
settingsBtn.setAttribute("aria-expanded", isOpen);
|
|
|
|
|
|
// Close apps dropdown
|
|
|
|
|
|
if (appsDropdown) appsDropdown.classList.remove("show");
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
document.addEventListener("click", (e) => {
|
|
|
|
|
|
if (
|
|
|
|
|
|
!settingsPanel.contains(e.target) &&
|
|
|
|
|
|
!settingsBtn.contains(e.target)
|
|
|
|
|
|
) {
|
|
|
|
|
|
settingsPanel.classList.remove("show");
|
|
|
|
|
|
settingsBtn.setAttribute("aria-expanded", "false");
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Theme selection handling
|
|
|
|
|
|
const themeOptions = document.querySelectorAll(".theme-option");
|
|
|
|
|
|
const savedTheme =
|
|
|
|
|
|
localStorage.getItem("gb-theme") || "sentient";
|
|
|
|
|
|
|
|
|
|
|
|
// Apply saved theme
|
|
|
|
|
|
document.body.setAttribute("data-theme", savedTheme);
|
|
|
|
|
|
document
|
|
|
|
|
|
.querySelector(`.theme-option[data-theme="${savedTheme}"]`)
|
|
|
|
|
|
?.classList.add("active");
|
|
|
|
|
|
|
|
|
|
|
|
themeOptions.forEach((option) => {
|
|
|
|
|
|
option.addEventListener("click", () => {
|
|
|
|
|
|
const theme = option.getAttribute("data-theme");
|
|
|
|
|
|
document.body.setAttribute("data-theme", theme);
|
|
|
|
|
|
localStorage.setItem("gb-theme", theme);
|
|
|
|
|
|
themeOptions.forEach((o) =>
|
|
|
|
|
|
o.classList.remove("active"),
|
|
|
|
|
|
);
|
|
|
|
|
|
option.classList.add("active");
|
|
|
|
|
|
|
|
|
|
|
|
// Update theme-color meta tag
|
|
|
|
|
|
const themeColors = {
|
|
|
|
|
|
dark: "#3b82f6",
|
|
|
|
|
|
light: "#3b82f6",
|
|
|
|
|
|
purple: "#a855f7",
|
|
|
|
|
|
green: "#22c55e",
|
|
|
|
|
|
orange: "#f97316",
|
|
|
|
|
|
sentient: "#d4f505",
|
|
|
|
|
|
};
|
|
|
|
|
|
const metaTheme = document.querySelector(
|
|
|
|
|
|
'meta[name="theme-color"]',
|
|
|
|
|
|
);
|
|
|
|
|
|
if (metaTheme) {
|
|
|
|
|
|
metaTheme.setAttribute(
|
|
|
|
|
|
"content",
|
|
|
|
|
|
themeColors[theme] || "#d4f505",
|
|
|
|
|
|
);
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
});
|
|
|
|
|
|
|
2026-01-03 17:19:17 -03:00
|
|
|
|
// List of sections that appear in header tabs
|
|
|
|
|
|
const headerTabSections = [
|
|
|
|
|
|
"chat",
|
|
|
|
|
|
"paper",
|
|
|
|
|
|
"mail",
|
|
|
|
|
|
"calendar",
|
|
|
|
|
|
"drive",
|
|
|
|
|
|
"tasks",
|
|
|
|
|
|
];
|
|
|
|
|
|
|
|
|
|
|
|
// Update active states for navigation (single selection only)
|
|
|
|
|
|
function updateNavigationActive(section) {
|
|
|
|
|
|
// Remove all active states first
|
|
|
|
|
|
document
|
|
|
|
|
|
.querySelectorAll(".app-tab")
|
|
|
|
|
|
.forEach((t) => t.classList.remove("active"));
|
|
|
|
|
|
document
|
|
|
|
|
|
.querySelectorAll(".app-item")
|
|
|
|
|
|
.forEach((i) => i.classList.remove("active"));
|
|
|
|
|
|
appsBtn.classList.remove("active");
|
|
|
|
|
|
|
|
|
|
|
|
// Check if section is in header tabs
|
|
|
|
|
|
const isInHeaderTabs = headerTabSections.includes(section);
|
|
|
|
|
|
|
|
|
|
|
|
// Activate the matching app-tab if in header
|
|
|
|
|
|
if (isInHeaderTabs) {
|
|
|
|
|
|
const headerTab = document.querySelector(
|
|
|
|
|
|
`.app-tab[data-section="${section}"]`,
|
|
|
|
|
|
);
|
|
|
|
|
|
if (headerTab) {
|
|
|
|
|
|
headerTab.classList.add("active");
|
|
|
|
|
|
}
|
|
|
|
|
|
} else {
|
|
|
|
|
|
// Section is NOT in header tabs, activate apps button
|
|
|
|
|
|
appsBtn.classList.add("active");
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Always mark the app-item in dropdown as active
|
|
|
|
|
|
const appItem = document.querySelector(
|
|
|
|
|
|
`.app-item[data-section="${section}"]`,
|
|
|
|
|
|
);
|
|
|
|
|
|
if (appItem) {
|
|
|
|
|
|
appItem.classList.add("active");
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-12-03 18:42:22 -03:00
|
|
|
|
// Handle app item clicks - update active state
|
|
|
|
|
|
document.querySelectorAll(".app-item").forEach((item) => {
|
|
|
|
|
|
item.addEventListener("click", function () {
|
2026-01-03 17:19:17 -03:00
|
|
|
|
const section = this.getAttribute("data-section");
|
|
|
|
|
|
updateNavigationActive(section);
|
2025-12-03 18:42:22 -03:00
|
|
|
|
appsDropdown.classList.remove("show");
|
|
|
|
|
|
appsBtn.setAttribute("aria-expanded", "false");
|
|
|
|
|
|
});
|
|
|
|
|
|
});
|
|
|
|
|
|
|
2026-01-03 17:19:17 -03:00
|
|
|
|
// Handle app tab clicks
|
|
|
|
|
|
document.querySelectorAll(".app-tab").forEach((tab) => {
|
|
|
|
|
|
tab.addEventListener("click", function () {
|
|
|
|
|
|
const section = this.getAttribute("data-section");
|
|
|
|
|
|
updateNavigationActive(section);
|
|
|
|
|
|
});
|
|
|
|
|
|
});
|
|
|
|
|
|
|
2025-12-03 18:42:22 -03:00
|
|
|
|
// Handle hash navigation
|
|
|
|
|
|
function handleHashChange() {
|
|
|
|
|
|
const hash = window.location.hash.slice(1) || "chat";
|
2026-01-03 17:19:17 -03:00
|
|
|
|
updateNavigationActive(hash);
|
|
|
|
|
|
|
|
|
|
|
|
// Trigger HTMX load if not already loaded
|
2025-12-03 18:42:22 -03:00
|
|
|
|
const appItem = document.querySelector(
|
2026-01-03 17:19:17 -03:00
|
|
|
|
`.app-item[data-section="${hash}"]`,
|
2025-12-03 18:42:22 -03:00
|
|
|
|
);
|
|
|
|
|
|
if (appItem) {
|
|
|
|
|
|
const hxGet = appItem.getAttribute("hx-get");
|
|
|
|
|
|
if (hxGet) {
|
|
|
|
|
|
htmx.ajax("GET", hxGet, {
|
|
|
|
|
|
target: "#main-content",
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Load initial content based on hash or default to chat
|
|
|
|
|
|
window.addEventListener("hashchange", handleHashChange);
|
|
|
|
|
|
|
|
|
|
|
|
// Initial load
|
|
|
|
|
|
setTimeout(() => {
|
|
|
|
|
|
handleHashChange();
|
|
|
|
|
|
}, 100);
|
|
|
|
|
|
|
2026-01-03 17:19:17 -03:00
|
|
|
|
// ==========================================================================
|
|
|
|
|
|
// GBAlerts - Global Notification System
|
|
|
|
|
|
// ==========================================================================
|
|
|
|
|
|
window.GBAlerts = (function () {
|
|
|
|
|
|
const notifications = [];
|
|
|
|
|
|
const badge = document.getElementById("notificationsBadge");
|
|
|
|
|
|
const list = document.getElementById("notificationsList");
|
|
|
|
|
|
const btn = document.getElementById("notificationsBtn");
|
|
|
|
|
|
const panel = document.getElementById("notificationsPanel");
|
|
|
|
|
|
const clearBtn = document.getElementById(
|
|
|
|
|
|
"clearNotificationsBtn",
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
function updateBadge() {
|
|
|
|
|
|
if (badge) {
|
|
|
|
|
|
if (notifications.length > 0) {
|
|
|
|
|
|
badge.textContent =
|
|
|
|
|
|
notifications.length > 99
|
|
|
|
|
|
? "99+"
|
|
|
|
|
|
: notifications.length;
|
|
|
|
|
|
badge.style.display = "flex";
|
|
|
|
|
|
} else {
|
|
|
|
|
|
badge.style.display = "none";
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
function renderList() {
|
|
|
|
|
|
if (!list) return;
|
|
|
|
|
|
if (notifications.length === 0) {
|
|
|
|
|
|
list.innerHTML =
|
|
|
|
|
|
'<div class="notifications-empty"><span>🔔</span><p>No notifications</p></div>';
|
|
|
|
|
|
} else {
|
|
|
|
|
|
list.innerHTML = notifications
|
|
|
|
|
|
.map(
|
|
|
|
|
|
(n, i) => `
|
|
|
|
|
|
<div class="notification-item notification-${n.type}" data-index="${i}">
|
|
|
|
|
|
<div class="notification-icon">${n.icon || "📢"}</div>
|
|
|
|
|
|
<div class="notification-content">
|
|
|
|
|
|
<div class="notification-title">${n.title}</div>
|
|
|
|
|
|
<div class="notification-message">${n.message || ""}</div>
|
|
|
|
|
|
<div class="notification-time">${n.time}</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
${n.action ? `<button class="notification-action" onclick="GBAlerts.handleAction(${i})">${n.actionText || "Open"}</button>` : ""}
|
|
|
|
|
|
<button class="notification-dismiss" onclick="GBAlerts.dismiss(${i})">×</button>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
`,
|
|
|
|
|
|
)
|
|
|
|
|
|
.join("");
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
function add(notification) {
|
|
|
|
|
|
notifications.unshift({
|
|
|
|
|
|
...notification,
|
|
|
|
|
|
time: new Date().toLocaleTimeString(),
|
|
|
|
|
|
});
|
|
|
|
|
|
updateBadge();
|
|
|
|
|
|
renderList();
|
|
|
|
|
|
// Auto-open panel when new notification arrives
|
|
|
|
|
|
if (panel) {
|
|
|
|
|
|
panel.classList.add("show");
|
|
|
|
|
|
if (btn) btn.setAttribute("aria-expanded", "true");
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
function dismiss(index) {
|
|
|
|
|
|
notifications.splice(index, 1);
|
|
|
|
|
|
updateBadge();
|
|
|
|
|
|
renderList();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
function clearAll() {
|
|
|
|
|
|
notifications.length = 0;
|
|
|
|
|
|
updateBadge();
|
|
|
|
|
|
renderList();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
function handleAction(index) {
|
|
|
|
|
|
const n = notifications[index];
|
|
|
|
|
|
if (n && n.action) {
|
|
|
|
|
|
if (typeof n.action === "function") {
|
|
|
|
|
|
n.action();
|
|
|
|
|
|
} else if (typeof n.action === "string") {
|
|
|
|
|
|
window.open(n.action, "_blank");
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
dismiss(index);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Toggle panel
|
|
|
|
|
|
if (btn && panel) {
|
|
|
|
|
|
btn.addEventListener("click", (e) => {
|
|
|
|
|
|
e.stopPropagation();
|
|
|
|
|
|
const isOpen = panel.classList.toggle("show");
|
|
|
|
|
|
btn.setAttribute("aria-expanded", isOpen);
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
document.addEventListener("click", (e) => {
|
|
|
|
|
|
if (
|
|
|
|
|
|
!panel.contains(e.target) &&
|
|
|
|
|
|
!btn.contains(e.target)
|
|
|
|
|
|
) {
|
|
|
|
|
|
panel.classList.remove("show");
|
|
|
|
|
|
btn.setAttribute("aria-expanded", "false");
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (clearBtn) {
|
|
|
|
|
|
clearBtn.addEventListener("click", clearAll);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Convenience methods for common notifications
|
|
|
|
|
|
return {
|
|
|
|
|
|
add,
|
|
|
|
|
|
dismiss,
|
|
|
|
|
|
clearAll,
|
|
|
|
|
|
handleAction,
|
|
|
|
|
|
taskCompleted: function (title, url) {
|
|
|
|
|
|
add({
|
|
|
|
|
|
type: "success",
|
|
|
|
|
|
icon: "✅",
|
|
|
|
|
|
title: "Task Completed",
|
|
|
|
|
|
message: title,
|
|
|
|
|
|
action: url,
|
|
|
|
|
|
actionText: "Open App",
|
|
|
|
|
|
});
|
|
|
|
|
|
},
|
|
|
|
|
|
taskFailed: function (title, error) {
|
|
|
|
|
|
add({
|
|
|
|
|
|
type: "error",
|
|
|
|
|
|
icon: "❌",
|
|
|
|
|
|
title: "Task Failed",
|
|
|
|
|
|
message: title + (error ? ": " + error : ""),
|
|
|
|
|
|
});
|
|
|
|
|
|
},
|
|
|
|
|
|
info: function (title, message) {
|
|
|
|
|
|
add({
|
|
|
|
|
|
type: "info",
|
|
|
|
|
|
icon: "ℹ️",
|
|
|
|
|
|
title: title,
|
|
|
|
|
|
message: message,
|
|
|
|
|
|
});
|
|
|
|
|
|
},
|
|
|
|
|
|
warning: function (title, message) {
|
|
|
|
|
|
add({
|
|
|
|
|
|
type: "warning",
|
|
|
|
|
|
icon: "⚠️",
|
|
|
|
|
|
title: title,
|
|
|
|
|
|
message: message,
|
|
|
|
|
|
});
|
|
|
|
|
|
},
|
|
|
|
|
|
connectionStatus: function (status, message) {
|
|
|
|
|
|
add({
|
|
|
|
|
|
type:
|
|
|
|
|
|
status === "connected"
|
|
|
|
|
|
? "success"
|
|
|
|
|
|
: status === "disconnected"
|
|
|
|
|
|
? "error"
|
|
|
|
|
|
: "warning",
|
|
|
|
|
|
icon:
|
|
|
|
|
|
status === "connected"
|
|
|
|
|
|
? "🟢"
|
|
|
|
|
|
: status === "disconnected"
|
|
|
|
|
|
? "🔴"
|
|
|
|
|
|
: "🟡",
|
|
|
|
|
|
title:
|
|
|
|
|
|
"Connection " +
|
|
|
|
|
|
status.charAt(0).toUpperCase() +
|
|
|
|
|
|
status.slice(1),
|
|
|
|
|
|
message: message || "",
|
|
|
|
|
|
});
|
|
|
|
|
|
},
|
|
|
|
|
|
};
|
|
|
|
|
|
})();
|
|
|
|
|
|
|
2025-12-03 18:42:22 -03:00
|
|
|
|
// Keyboard shortcuts
|
|
|
|
|
|
document.addEventListener("keydown", (e) => {
|
|
|
|
|
|
// Alt + number for quick app switching
|
|
|
|
|
|
if (e.altKey && !e.ctrlKey && !e.shiftKey) {
|
|
|
|
|
|
const num = parseInt(e.key);
|
|
|
|
|
|
if (num >= 1 && num <= 9) {
|
|
|
|
|
|
const items =
|
|
|
|
|
|
document.querySelectorAll(".app-item");
|
|
|
|
|
|
if (items[num - 1]) {
|
|
|
|
|
|
items[num - 1].click();
|
|
|
|
|
|
e.preventDefault();
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Alt + A to open apps menu
|
|
|
|
|
|
if (e.altKey && e.key.toLowerCase() === "a") {
|
|
|
|
|
|
appsBtn.click();
|
|
|
|
|
|
e.preventDefault();
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
});
|
|
|
|
|
|
</script>
|
|
|
|
|
|
</body>
|
|
|
|
|
|
</html>
|