2026-01-24 22:59:20 +00:00
|
|
|
<template>
|
2026-02-17 19:19:54 +00:00
|
|
|
<div class="min-h-screen flex relative dashboard-view" :class="{ 'glass-throw-active': showZoomIn }">
|
2026-03-11 13:11:45 +00:00
|
|
|
<!-- Skip to main content link for keyboard users -->
|
2026-03-11 13:45:59 +00:00
|
|
|
<a href="#main-content" class="skip-to-content">{{ t('common.skipToContent') }}</a>
|
2026-02-17 19:19:54 +00:00
|
|
|
<!-- Background container with 3D perspective - full width to avoid letterboxing -->
|
2026-01-24 22:59:20 +00:00
|
|
|
<div class="bg-perspective-container">
|
2026-03-01 18:07:35 +00:00
|
|
|
<!-- Background - primary layer (visible for all routes, transitions out only for detail pages) -->
|
2026-02-17 19:19:54 +00:00
|
|
|
<div
|
2026-01-24 22:59:20 +00:00
|
|
|
ref="bgDefault"
|
2026-02-17 19:19:54 +00:00
|
|
|
class="bg-layer bg-fullwidth"
|
|
|
|
|
:class="[
|
2026-03-01 18:07:35 +00:00
|
|
|
{ 'bg-transitioning-out': showAltBackground },
|
2026-02-17 19:19:54 +00:00
|
|
|
{ 'zoom-reveal-bg': showZoomIn }
|
|
|
|
|
]"
|
2026-03-01 18:07:35 +00:00
|
|
|
:style="{ backgroundImage: `url(/assets/img/${backgroundImage})` }"
|
2026-02-17 19:19:54 +00:00
|
|
|
/>
|
2026-03-01 18:07:35 +00:00
|
|
|
<!-- Background - detail layer (only visible during app/marketplace detail 3D transition) -->
|
2026-01-24 22:59:20 +00:00
|
|
|
<div
|
|
|
|
|
ref="bgAlt"
|
2026-02-17 19:19:54 +00:00
|
|
|
class="bg-layer bg-fullwidth"
|
2026-03-01 18:07:35 +00:00
|
|
|
:class="{ 'bg-transitioning-in': showAltBackground }"
|
|
|
|
|
style="background-image: url(/assets/img/bg-intro-3.jpg)"
|
2026-01-24 22:59:20 +00:00
|
|
|
/>
|
|
|
|
|
<!-- Glitch overlays - trigger on background change -->
|
|
|
|
|
<div
|
|
|
|
|
class="bg-glitch-layer-1"
|
|
|
|
|
:class="{ 'glitch-active': isGlitching }"
|
2026-03-01 18:07:35 +00:00
|
|
|
:style="{ backgroundImage: `url(/assets/img/${backgroundImage})` }"
|
2026-01-24 22:59:20 +00:00
|
|
|
/>
|
|
|
|
|
<div
|
|
|
|
|
class="bg-glitch-layer-2"
|
|
|
|
|
:class="{ 'glitch-active': isGlitching }"
|
2026-03-01 18:07:35 +00:00
|
|
|
:style="{ backgroundImage: `url(/assets/img/${backgroundImage})` }"
|
2026-01-24 22:59:20 +00:00
|
|
|
/>
|
|
|
|
|
<div
|
|
|
|
|
class="bg-glitch-scan"
|
|
|
|
|
:class="{ 'glitch-active': isGlitching }"
|
|
|
|
|
/>
|
feat: AIUI chat mode integration with iframe, context broker, overnight loop
- Chat mode: AIUI loads in sandboxed iframe at /dashboard/chat with transparent bg
- Mode switcher: Easy + Pro tabs only, Chat is a launcher button
- Keyboard shortcuts: Cmd+1 (Easy), Cmd+2 (Pro), Cmd+3 (Chat), Cmd+M (cycle)
- Directional transitions: chat slides from/to left, dashboard from/to right
- Context broker: postMessage protocol for quarantined AIUI communication
- AI permissions store: user-controlled toggles for data access categories
- Settings UI: AI Data Access section with per-category toggles
- AIUI container manifest and nginx proxy config for /aiui/
- Deploy script builds AIUI with /aiui/ base path
- Overnight loop infrastructure (loop.sh, prepare.sh, plan.md, prompt.md)
- Security hooks for autonomous overnight runs
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-04 12:06:20 +00:00
|
|
|
<!-- Glitch overlays removed — only intro glitch plays (via isGlitching) -->
|
2026-01-24 22:59:20 +00:00
|
|
|
</div>
|
|
|
|
|
|
2026-02-17 19:19:54 +00:00
|
|
|
<!-- Oomph accent - brief impact flash when dashboard loads -->
|
|
|
|
|
<div
|
|
|
|
|
v-if="showZoomIn"
|
|
|
|
|
class="fixed inset-0 pointer-events-none z-[100] oomph-flash"
|
|
|
|
|
aria-hidden="true"
|
|
|
|
|
/>
|
|
|
|
|
<!-- Reveal flashes and glitch overlay - enthralling entrance -->
|
|
|
|
|
<div
|
|
|
|
|
v-if="showZoomIn"
|
|
|
|
|
class="fixed inset-0 pointer-events-none z-[99] reveal-flash-glitch"
|
|
|
|
|
aria-hidden="true"
|
|
|
|
|
/>
|
|
|
|
|
|
2026-03-14 17:12:41 +00:00
|
|
|
<!-- Background overlay - uniform 0.2 opacity -->
|
|
|
|
|
<div
|
|
|
|
|
class="fixed inset-0 pointer-events-none bg-black/20"
|
2026-01-24 22:59:20 +00:00
|
|
|
style="z-index: -5;"
|
|
|
|
|
/>
|
|
|
|
|
|
2026-02-17 19:19:54 +00:00
|
|
|
<!-- Sidebar - Desktop Only, animates in at end with separate parts -->
|
|
|
|
|
<aside
|
feat: AIUI chat mode integration with iframe, context broker, overnight loop
- Chat mode: AIUI loads in sandboxed iframe at /dashboard/chat with transparent bg
- Mode switcher: Easy + Pro tabs only, Chat is a launcher button
- Keyboard shortcuts: Cmd+1 (Easy), Cmd+2 (Pro), Cmd+3 (Chat), Cmd+M (cycle)
- Directional transitions: chat slides from/to left, dashboard from/to right
- Context broker: postMessage protocol for quarantined AIUI communication
- AI permissions store: user-controlled toggles for data access categories
- Settings UI: AI Data Access section with per-category toggles
- AIUI container manifest and nginx proxy config for /aiui/
- Deploy script builds AIUI with /aiui/ base path
- Overnight loop infrastructure (loop.sh, prepare.sh, plan.md, prompt.md)
- Security hooks for autonomous overnight runs
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-04 12:06:20 +00:00
|
|
|
v-show="!chatFullscreen"
|
2026-02-17 19:19:54 +00:00
|
|
|
data-controller-zone="sidebar"
|
2026-02-17 19:42:59 +00:00
|
|
|
class="hidden md:flex w-[256px] flex-shrink-0 relative flex-col z-10"
|
2026-02-17 19:19:54 +00:00
|
|
|
:class="{ 'sidebar-animate': showZoomIn }"
|
|
|
|
|
>
|
|
|
|
|
<div class="sidebar-shell">
|
2026-03-04 05:23:42 +00:00
|
|
|
<div class="sidebar-inner flex flex-col min-h-full">
|
|
|
|
|
<div class="sidebar-logo flex items-center gap-3 mb-8 p-6 pb-0 shrink-0">
|
2026-02-17 19:19:54 +00:00
|
|
|
<AnimatedLogo />
|
|
|
|
|
<div class="min-w-0 flex-1">
|
|
|
|
|
<h2 class="text-lg font-semibold text-white truncate">{{ serverName }}</h2>
|
|
|
|
|
<p class="text-xs text-white/60">v{{ version }}</p>
|
|
|
|
|
</div>
|
2026-01-24 22:59:20 +00:00
|
|
|
</div>
|
|
|
|
|
|
2026-03-11 13:45:59 +00:00
|
|
|
<nav class="sidebar-nav flex-1 min-h-0 space-y-2 p-6 pt-4" :aria-label="t('dashboard.mainNav')">
|
2026-02-17 19:19:54 +00:00
|
|
|
<RouterLink
|
|
|
|
|
v-for="(item, idx) in desktopNavItems"
|
|
|
|
|
:key="item.path"
|
|
|
|
|
:to="item.path"
|
|
|
|
|
class="sidebar-nav-item flex items-center gap-3 px-4 py-3 rounded-lg text-white/80 hover:bg-white/10 hover:text-white transition-colors"
|
feat: add Discover page — cypherpunk app store with sovereignty messaging
- New Discover.vue with hero banner, featured sovereignty stack apps,
principle cards, manifesto footer, and full app grid
- Featured apps (Bitcoin Knots, LND, BTCPay, Vaultwarden) with
expanded privacy/sovereignty descriptions
- Discover is first tab in categories bar on App Store pages
- Smart back navigation: detail pages return to Discover when navigated from there
- Category clicks from Discover navigate to Marketplace with category pre-selected
- Cypherpunk aesthetic: terminal tags, scanline overlays, gradient accents,
animated Bitcoin orange headings
- Global CSS classes: discover-hero, discover-terminal-tag, discover-featured-card,
discover-principle-card, discover-manifesto
- Route added: /dashboard/discover
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-19 15:14:12 +00:00
|
|
|
:class="{ 'nav-tab-active': item.isCombined && (route.path.includes('/apps') || route.path.includes('/marketplace') || route.path.includes('/discover') || route.path.includes('/app-session') || (item.path === '/dashboard/apps' && !!appLauncher.panelAppId)) }"
|
2026-03-14 04:14:04 +00:00
|
|
|
:exact-active-class="item.isCombined ? undefined : 'nav-tab-active'"
|
2026-03-16 12:58:35 +00:00
|
|
|
@click="appLauncher.closePanel()"
|
2026-02-17 19:19:54 +00:00
|
|
|
:style="{ '--nav-stagger': idx }"
|
|
|
|
|
>
|
security+feat: v1.3.0 — pentest remediation, container reliability, UI overhaul
Security (33 pentest findings addressed):
- CRITICAL: backend binds 127.0.0.1, path traversal in tor.rs/dwn fixed
- HIGH: federation requires signatures, XSS login redirect, RBAC viewer restricted
- HIGH: tar slip prevention, S3 SSRF validation, backup ID validation
- MEDIUM: remember-me random secret, TOTP session rotation, password re-auth
- LOW: CSP unsafe-inline removed, CORS dev-only, onion/webhook validation
Container reliability:
- Memory limits on all 37 containers (OOM prevention)
- Exited vs stopped state distinction with health-aware status badges
- Crash recovery coordination (no more restart cascade)
- User-stopped tracking survives reboots
- Tiered boot recovery (databases → core → services → apps)
UI:
- Wallet TransactionsModal, health-aware app status badges
- Restart button on containers, exited/crashed red state
- Mesh view overhaul, glass button updates, BaseModal/ToggleSwitch
- Apps sticky header removed, dev faucet, mutable mock wallet
Infrastructure:
- LND REST port 8080 exposed over Tor (LND Connect fix)
- Nginx cookie_session fix, deploy script Tor config updated
- Dev environment: podman auto-start, boot mode simulation
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-19 12:44:31 +00:00
|
|
|
<svg v-if="item.icon === 'web5'" class="w-5 h-5" aria-hidden="true" fill="currentColor" viewBox="0 0 1631 1624">
|
|
|
|
|
<path fill-rule="evenodd" clip-rule="evenodd" d="M914.932 359.228H916.229V715.252H1630.47V1088.98H1451.41V1267.98H1274.33V1445H1093.31V1624H715.534V1264.77H714.237V908.748H0V535.02H179.051V356.025H356.135V178.996H537.154V0H914.932V359.228ZM916.229 1425.33H1073.64V1248.31H1254.66V1071.28H1431.74V913.918H916.229V1425.33ZM556.83 375.695H375.811V552.723H198.727V710.082H714.237V198.666H556.83V375.695Z" />
|
|
|
|
|
</svg>
|
|
|
|
|
<svg v-else class="w-5 h-5" aria-hidden="true" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
feat: AIUI chat mode integration with iframe, context broker, overnight loop
- Chat mode: AIUI loads in sandboxed iframe at /dashboard/chat with transparent bg
- Mode switcher: Easy + Pro tabs only, Chat is a launcher button
- Keyboard shortcuts: Cmd+1 (Easy), Cmd+2 (Pro), Cmd+3 (Chat), Cmd+M (cycle)
- Directional transitions: chat slides from/to left, dashboard from/to right
- Context broker: postMessage protocol for quarantined AIUI communication
- AI permissions store: user-controlled toggles for data access categories
- Settings UI: AI Data Access section with per-category toggles
- AIUI container manifest and nginx proxy config for /aiui/
- Deploy script builds AIUI with /aiui/ base path
- Overnight loop infrastructure (loop.sh, prepare.sh, plan.md, prompt.md)
- Security hooks for autonomous overnight runs
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-04 12:06:20 +00:00
|
|
|
<path
|
|
|
|
|
v-for="(path, index) in getIconPath(item.icon)"
|
2026-02-17 19:19:54 +00:00
|
|
|
:key="index"
|
feat: AIUI chat mode integration with iframe, context broker, overnight loop
- Chat mode: AIUI loads in sandboxed iframe at /dashboard/chat with transparent bg
- Mode switcher: Easy + Pro tabs only, Chat is a launcher button
- Keyboard shortcuts: Cmd+1 (Easy), Cmd+2 (Pro), Cmd+3 (Chat), Cmd+M (cycle)
- Directional transitions: chat slides from/to left, dashboard from/to right
- Context broker: postMessage protocol for quarantined AIUI communication
- AI permissions store: user-controlled toggles for data access categories
- Settings UI: AI Data Access section with per-category toggles
- AIUI container manifest and nginx proxy config for /aiui/
- Deploy script builds AIUI with /aiui/ base path
- Overnight loop infrastructure (loop.sh, prepare.sh, plan.md, prompt.md)
- Security hooks for autonomous overnight runs
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-04 12:06:20 +00:00
|
|
|
stroke-linecap="round"
|
|
|
|
|
stroke-linejoin="round"
|
|
|
|
|
stroke-width="2"
|
|
|
|
|
:d="path"
|
2026-02-17 19:19:54 +00:00
|
|
|
/>
|
|
|
|
|
</svg>
|
|
|
|
|
<span>{{ item.label }}</span>
|
2026-03-09 07:43:12 +00:00
|
|
|
<span
|
|
|
|
|
v-if="item.path === '/dashboard/web5' && web5Badge.pendingRequestCount > 0"
|
|
|
|
|
class="ml-auto w-5 h-5 flex items-center justify-center rounded-full bg-orange-500 text-white text-[10px] font-bold"
|
|
|
|
|
>{{ web5Badge.pendingRequestCount }}</span>
|
2026-03-17 00:03:08 +00:00
|
|
|
<span
|
|
|
|
|
v-if="item.path === '/dashboard/mesh' && meshStore.totalUnread > 0"
|
|
|
|
|
class="ml-auto w-5 h-5 flex items-center justify-center rounded-full bg-orange-500 text-white text-[10px] font-bold"
|
|
|
|
|
>{{ meshStore.totalUnread }}</span>
|
2026-02-17 19:19:54 +00:00
|
|
|
</RouterLink>
|
|
|
|
|
|
feat: AIUI chat mode integration with iframe, context broker, overnight loop
- Chat mode: AIUI loads in sandboxed iframe at /dashboard/chat with transparent bg
- Mode switcher: Easy + Pro tabs only, Chat is a launcher button
- Keyboard shortcuts: Cmd+1 (Easy), Cmd+2 (Pro), Cmd+3 (Chat), Cmd+M (cycle)
- Directional transitions: chat slides from/to left, dashboard from/to right
- Context broker: postMessage protocol for quarantined AIUI communication
- AI permissions store: user-controlled toggles for data access categories
- Settings UI: AI Data Access section with per-category toggles
- AIUI container manifest and nginx proxy config for /aiui/
- Deploy script builds AIUI with /aiui/ base path
- Overnight loop infrastructure (loop.sh, prepare.sh, plan.md, prompt.md)
- Security hooks for autonomous overnight runs
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-04 12:06:20 +00:00
|
|
|
<!-- Chat launcher button -->
|
|
|
|
|
<button
|
|
|
|
|
@click="router.push('/dashboard/chat')"
|
|
|
|
|
class="chat-launcher-btn w-full flex items-center gap-3 px-4 py-3 rounded-lg transition-all duration-300"
|
|
|
|
|
>
|
2026-03-11 13:04:31 +00:00
|
|
|
<svg class="w-5 h-5" aria-hidden="true" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
feat: AIUI chat mode integration with iframe, context broker, overnight loop
- Chat mode: AIUI loads in sandboxed iframe at /dashboard/chat with transparent bg
- Mode switcher: Easy + Pro tabs only, Chat is a launcher button
- Keyboard shortcuts: Cmd+1 (Easy), Cmd+2 (Pro), Cmd+3 (Chat), Cmd+M (cycle)
- Directional transitions: chat slides from/to left, dashboard from/to right
- Context broker: postMessage protocol for quarantined AIUI communication
- AI permissions store: user-controlled toggles for data access categories
- Settings UI: AI Data Access section with per-category toggles
- AIUI container manifest and nginx proxy config for /aiui/
- Deploy script builds AIUI with /aiui/ base path
- Overnight loop infrastructure (loop.sh, prepare.sh, plan.md, prompt.md)
- Security hooks for autonomous overnight runs
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-04 12:06:20 +00:00
|
|
|
<path v-for="(path, index) in getIconPath('chat')" :key="index" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" :d="path" />
|
|
|
|
|
</svg>
|
2026-03-12 00:19:30 +00:00
|
|
|
<span>AIUI</span>
|
feat: AIUI chat mode integration with iframe, context broker, overnight loop
- Chat mode: AIUI loads in sandboxed iframe at /dashboard/chat with transparent bg
- Mode switcher: Easy + Pro tabs only, Chat is a launcher button
- Keyboard shortcuts: Cmd+1 (Easy), Cmd+2 (Pro), Cmd+3 (Chat), Cmd+M (cycle)
- Directional transitions: chat slides from/to left, dashboard from/to right
- Context broker: postMessage protocol for quarantined AIUI communication
- AI permissions store: user-controlled toggles for data access categories
- Settings UI: AI Data Access section with per-category toggles
- AIUI container manifest and nginx proxy config for /aiui/
- Deploy script builds AIUI with /aiui/ base path
- Overnight loop infrastructure (loop.sh, prepare.sh, plan.md, prompt.md)
- Security hooks for autonomous overnight runs
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-04 12:06:20 +00:00
|
|
|
</button>
|
2026-02-17 15:03:34 +00:00
|
|
|
|
feat: AIUI chat mode integration with iframe, context broker, overnight loop
- Chat mode: AIUI loads in sandboxed iframe at /dashboard/chat with transparent bg
- Mode switcher: Easy + Pro tabs only, Chat is a launcher button
- Keyboard shortcuts: Cmd+1 (Easy), Cmd+2 (Pro), Cmd+3 (Chat), Cmd+M (cycle)
- Directional transitions: chat slides from/to left, dashboard from/to right
- Context broker: postMessage protocol for quarantined AIUI communication
- AI permissions store: user-controlled toggles for data access categories
- Settings UI: AI Data Access section with per-category toggles
- AIUI container manifest and nginx proxy config for /aiui/
- Deploy script builds AIUI with /aiui/ base path
- Overnight loop infrastructure (loop.sh, prepare.sh, plan.md, prompt.md)
- Security hooks for autonomous overnight runs
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-04 12:06:20 +00:00
|
|
|
<!-- Logout - styled as nav item, below Settings -->
|
2026-02-17 19:19:54 +00:00
|
|
|
<button
|
|
|
|
|
@click="handleLogout"
|
|
|
|
|
class="sidebar-logout-btn w-full flex items-center gap-3 px-4 py-3 rounded-lg text-white/80 hover:bg-white/10 hover:text-white transition-colors"
|
|
|
|
|
>
|
2026-03-11 13:04:31 +00:00
|
|
|
<svg class="w-5 h-5" aria-hidden="true" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
2026-02-17 19:19:54 +00:00
|
|
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M17 16l4-4m0 0l-4-4m4 4H7m6 4v1a3 3 0 01-3 3H6a3 3 0 01-3-3V7a3 3 0 013-3h4a3 3 0 013 3v1" />
|
|
|
|
|
</svg>
|
|
|
|
|
<span>Logout</span>
|
|
|
|
|
</button>
|
feat: AIUI chat mode integration with iframe, context broker, overnight loop
- Chat mode: AIUI loads in sandboxed iframe at /dashboard/chat with transparent bg
- Mode switcher: Easy + Pro tabs only, Chat is a launcher button
- Keyboard shortcuts: Cmd+1 (Easy), Cmd+2 (Pro), Cmd+3 (Chat), Cmd+M (cycle)
- Directional transitions: chat slides from/to left, dashboard from/to right
- Context broker: postMessage protocol for quarantined AIUI communication
- AI permissions store: user-controlled toggles for data access categories
- Settings UI: AI Data Access section with per-category toggles
- AIUI container manifest and nginx proxy config for /aiui/
- Deploy script builds AIUI with /aiui/ base path
- Overnight loop infrastructure (loop.sh, prepare.sh, plan.md, prompt.md)
- Security hooks for autonomous overnight runs
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-04 12:06:20 +00:00
|
|
|
</nav>
|
|
|
|
|
|
|
|
|
|
<div class="sidebar-controller px-6 pb-2 shrink-0">
|
|
|
|
|
<ControllerIndicator />
|
2026-02-17 19:19:54 +00:00
|
|
|
</div>
|
2026-03-04 05:23:42 +00:00
|
|
|
|
feat: AIUI chat mode integration with iframe, context broker, overnight loop
- Chat mode: AIUI loads in sandboxed iframe at /dashboard/chat with transparent bg
- Mode switcher: Easy + Pro tabs only, Chat is a launcher button
- Keyboard shortcuts: Cmd+1 (Easy), Cmd+2 (Pro), Cmd+3 (Chat), Cmd+M (cycle)
- Directional transitions: chat slides from/to left, dashboard from/to right
- Context broker: postMessage protocol for quarantined AIUI communication
- AI permissions store: user-controlled toggles for data access categories
- Settings UI: AI Data Access section with per-category toggles
- AIUI container manifest and nginx proxy config for /aiui/
- Deploy script builds AIUI with /aiui/ base path
- Overnight loop infrastructure (loop.sh, prepare.sh, plan.md, prompt.md)
- Security hooks for autonomous overnight runs
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-04 12:06:20 +00:00
|
|
|
<!-- Online status -->
|
|
|
|
|
<div class="px-6 pb-2 shrink-0">
|
|
|
|
|
<div class="rounded-lg bg-white/5 border border-white/10 px-4 py-2.5">
|
|
|
|
|
<OnlineStatusPill />
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<!-- Mode switcher -->
|
2026-03-04 05:23:42 +00:00
|
|
|
<div class="px-6 pb-6 shrink-0">
|
feat: AIUI chat mode integration with iframe, context broker, overnight loop
- Chat mode: AIUI loads in sandboxed iframe at /dashboard/chat with transparent bg
- Mode switcher: Easy + Pro tabs only, Chat is a launcher button
- Keyboard shortcuts: Cmd+1 (Easy), Cmd+2 (Pro), Cmd+3 (Chat), Cmd+M (cycle)
- Directional transitions: chat slides from/to left, dashboard from/to right
- Context broker: postMessage protocol for quarantined AIUI communication
- AI permissions store: user-controlled toggles for data access categories
- Settings UI: AI Data Access section with per-category toggles
- AIUI container manifest and nginx proxy config for /aiui/
- Deploy script builds AIUI with /aiui/ base path
- Overnight loop infrastructure (loop.sh, prepare.sh, plan.md, prompt.md)
- Security hooks for autonomous overnight runs
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-04 12:06:20 +00:00
|
|
|
<ModeSwitcher />
|
2026-03-04 05:23:42 +00:00
|
|
|
</div>
|
2026-02-17 19:19:54 +00:00
|
|
|
</div>
|
2026-01-24 22:59:20 +00:00
|
|
|
</div>
|
|
|
|
|
</aside>
|
|
|
|
|
|
2026-02-17 19:19:54 +00:00
|
|
|
<!-- Main Content (Xbox: Right goes here from sidebar) -->
|
|
|
|
|
<main
|
2026-03-11 13:11:45 +00:00
|
|
|
id="main-content"
|
2026-02-17 19:19:54 +00:00
|
|
|
data-controller-zone="main"
|
2026-03-14 17:12:41 +00:00
|
|
|
class="flex-1 overflow-hidden relative pb-0 glass-piece z-10"
|
2026-02-17 19:19:54 +00:00
|
|
|
:class="{ 'glass-throw-main': showZoomIn }"
|
|
|
|
|
>
|
2026-02-18 11:29:05 +00:00
|
|
|
<div data-controller-main-entry class="absolute top-4 right-4 md:top-6 md:right-8 z-20">
|
2026-03-04 05:23:42 +00:00
|
|
|
<!-- Controller zone entry point - no switcher -->
|
2026-02-18 10:26:33 +00:00
|
|
|
</div>
|
|
|
|
|
|
2026-01-24 22:59:20 +00:00
|
|
|
<!-- Connection Status Banner -->
|
|
|
|
|
<div v-if="isOffline && !store.isReconnecting && store.isAuthenticated" class="path-option-card mx-6 mt-6 px-6 py-3 border-l-4 border-yellow-500">
|
|
|
|
|
<div class="flex items-center gap-2 text-yellow-200">
|
|
|
|
|
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
|
|
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z" />
|
|
|
|
|
</svg>
|
|
|
|
|
<span class="font-medium">
|
|
|
|
|
{{ isRestarting ? 'Server is restarting...' : isShuttingDown ? 'Server is shutting down...' : 'Connection lost' }}
|
|
|
|
|
</span>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<!-- Reconnecting Banner -->
|
|
|
|
|
<div v-if="store.isReconnecting && store.isAuthenticated" class="path-option-card mx-6 mt-6 px-6 py-3 border-l-4 border-blue-500">
|
|
|
|
|
<div class="flex items-center gap-2 text-blue-200">
|
|
|
|
|
<svg class="w-5 h-5 animate-spin" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
|
|
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 4v5h.582m15.356 2A8.001 8.001 0 004.582 9m0 0H9m11 11v-5h-.581m0 0a8.003 8.003 0 01-15.357-2m15.357 2H15" />
|
|
|
|
|
</svg>
|
|
|
|
|
<span class="font-medium">Reconnecting...</span>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
|
2026-02-17 19:19:54 +00:00
|
|
|
<!-- Persistent Mobile Tabs for Apps/Marketplace - glass piece 3 -->
|
2026-01-24 22:59:20 +00:00
|
|
|
<div
|
|
|
|
|
v-if="showAppsTabs"
|
2026-02-17 19:19:54 +00:00
|
|
|
class="md:hidden fixed top-0 left-0 right-0 z-40 px-4 pt-4 pb-2 glass-piece"
|
|
|
|
|
:class="{ 'glass-throw-mobile-tabs': showZoomIn }"
|
2026-01-24 22:59:20 +00:00
|
|
|
style="background: rgba(0, 0, 0, 0.25); backdrop-filter: blur(18px); -webkit-backdrop-filter: blur(18px); transform: translateZ(0);"
|
|
|
|
|
>
|
feat: v1.2.0-alpha — E2E encrypted mesh relay, steganography, relay status polling
Phase 5 mesh networking:
- E2E encrypted TX relay (X25519 + ChaCha20-Poly1305) — non-Archy nodes
relay encrypted blobs transparently via Meshcore native routing
- Steganographic encoding modes (WeatherStation, SensorNetwork) — traffic
looks like sensor data on the wire, 0xAA marker, configurable per-node
- Pre-flight Bitcoin Core health check on relay node — specific error codes
(bitcoin_unreachable, bitcoin_syncing, tx_rejected) instead of generic fails
- mesh.relay-status RPC endpoint — frontend polls for relay result every 3s
- On-Chain / Lightning tabs in Off-Grid Bitcoin panel
- Archy Peers vs Mesh Broadcast relay mode selector
- Mesh view fills viewport (no page scroll), internal panel scrolling
- Version bump to 1.2.0-alpha
Also includes: deploy hardening, container fixes, IndeedHub updates,
boot screen, dashboard improvements, MASTER_PLAN task tracking
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-17 23:56:37 +00:00
|
|
|
<div class="mode-switcher mode-switcher-full">
|
2026-01-24 22:59:20 +00:00
|
|
|
<RouterLink
|
|
|
|
|
to="/dashboard/apps"
|
feat: v1.2.0-alpha — E2E encrypted mesh relay, steganography, relay status polling
Phase 5 mesh networking:
- E2E encrypted TX relay (X25519 + ChaCha20-Poly1305) — non-Archy nodes
relay encrypted blobs transparently via Meshcore native routing
- Steganographic encoding modes (WeatherStation, SensorNetwork) — traffic
looks like sensor data on the wire, 0xAA marker, configurable per-node
- Pre-flight Bitcoin Core health check on relay node — specific error codes
(bitcoin_unreachable, bitcoin_syncing, tx_rejected) instead of generic fails
- mesh.relay-status RPC endpoint — frontend polls for relay result every 3s
- On-Chain / Lightning tabs in Off-Grid Bitcoin panel
- Archy Peers vs Mesh Broadcast relay mode selector
- Mesh view fills viewport (no page scroll), internal panel scrolling
- Version bump to 1.2.0-alpha
Also includes: deploy hardening, container fixes, IndeedHub updates,
boot screen, dashboard improvements, MASTER_PLAN task tracking
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-17 23:56:37 +00:00
|
|
|
class="mode-switcher-btn"
|
|
|
|
|
:class="{ 'mode-switcher-btn-active': (route.path === '/dashboard/apps' || route.path.startsWith('/dashboard/apps/')) && route.query.tab !== 'services' }"
|
|
|
|
|
>My Apps</RouterLink>
|
2026-01-24 22:59:20 +00:00
|
|
|
<RouterLink
|
|
|
|
|
to="/dashboard/marketplace"
|
feat: v1.2.0-alpha — E2E encrypted mesh relay, steganography, relay status polling
Phase 5 mesh networking:
- E2E encrypted TX relay (X25519 + ChaCha20-Poly1305) — non-Archy nodes
relay encrypted blobs transparently via Meshcore native routing
- Steganographic encoding modes (WeatherStation, SensorNetwork) — traffic
looks like sensor data on the wire, 0xAA marker, configurable per-node
- Pre-flight Bitcoin Core health check on relay node — specific error codes
(bitcoin_unreachable, bitcoin_syncing, tx_rejected) instead of generic fails
- mesh.relay-status RPC endpoint — frontend polls for relay result every 3s
- On-Chain / Lightning tabs in Off-Grid Bitcoin panel
- Archy Peers vs Mesh Broadcast relay mode selector
- Mesh view fills viewport (no page scroll), internal panel scrolling
- Version bump to 1.2.0-alpha
Also includes: deploy hardening, container fixes, IndeedHub updates,
boot screen, dashboard improvements, MASTER_PLAN task tracking
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-17 23:56:37 +00:00
|
|
|
class="mode-switcher-btn"
|
feat: add Discover page — cypherpunk app store with sovereignty messaging
- New Discover.vue with hero banner, featured sovereignty stack apps,
principle cards, manifesto footer, and full app grid
- Featured apps (Bitcoin Knots, LND, BTCPay, Vaultwarden) with
expanded privacy/sovereignty descriptions
- Discover is first tab in categories bar on App Store pages
- Smart back navigation: detail pages return to Discover when navigated from there
- Category clicks from Discover navigate to Marketplace with category pre-selected
- Cypherpunk aesthetic: terminal tags, scanline overlays, gradient accents,
animated Bitcoin orange headings
- Global CSS classes: discover-hero, discover-terminal-tag, discover-featured-card,
discover-principle-card, discover-manifesto
- Route added: /dashboard/discover
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-19 15:14:12 +00:00
|
|
|
:class="{ 'mode-switcher-btn-active': route.path === '/dashboard/marketplace' || route.path.startsWith('/dashboard/marketplace/') || route.path === '/dashboard/discover' }"
|
feat: v1.2.0-alpha — E2E encrypted mesh relay, steganography, relay status polling
Phase 5 mesh networking:
- E2E encrypted TX relay (X25519 + ChaCha20-Poly1305) — non-Archy nodes
relay encrypted blobs transparently via Meshcore native routing
- Steganographic encoding modes (WeatherStation, SensorNetwork) — traffic
looks like sensor data on the wire, 0xAA marker, configurable per-node
- Pre-flight Bitcoin Core health check on relay node — specific error codes
(bitcoin_unreachable, bitcoin_syncing, tx_rejected) instead of generic fails
- mesh.relay-status RPC endpoint — frontend polls for relay result every 3s
- On-Chain / Lightning tabs in Off-Grid Bitcoin panel
- Archy Peers vs Mesh Broadcast relay mode selector
- Mesh view fills viewport (no page scroll), internal panel scrolling
- Version bump to 1.2.0-alpha
Also includes: deploy hardening, container fixes, IndeedHub updates,
boot screen, dashboard improvements, MASTER_PLAN task tracking
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-17 23:56:37 +00:00
|
|
|
>App Store</RouterLink>
|
|
|
|
|
<RouterLink
|
|
|
|
|
to="/dashboard/apps?tab=services"
|
|
|
|
|
class="mode-switcher-btn"
|
|
|
|
|
:class="{ 'mode-switcher-btn-active': route.query.tab === 'services' }"
|
|
|
|
|
>Services</RouterLink>
|
2026-01-24 22:59:20 +00:00
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
|
2026-02-17 19:19:54 +00:00
|
|
|
<!-- Persistent Mobile Tabs for Network/Cloud - glass piece 4 -->
|
2026-01-24 22:59:20 +00:00
|
|
|
<div
|
|
|
|
|
v-if="showNetworkTabs"
|
2026-02-17 19:19:54 +00:00
|
|
|
class="md:hidden fixed top-0 left-0 right-0 z-40 px-4 pt-4 pb-2 glass-piece"
|
|
|
|
|
:class="{ 'glass-throw-mobile-tabs-2': showZoomIn }"
|
2026-01-24 22:59:20 +00:00
|
|
|
style="background: rgba(0, 0, 0, 0.25); backdrop-filter: blur(18px); -webkit-backdrop-filter: blur(18px); transform: translateZ(0);"
|
|
|
|
|
:style="{ top: showAppsTabs ? '80px' : '0' }"
|
|
|
|
|
>
|
feat: v1.2.0-alpha — E2E encrypted mesh relay, steganography, relay status polling
Phase 5 mesh networking:
- E2E encrypted TX relay (X25519 + ChaCha20-Poly1305) — non-Archy nodes
relay encrypted blobs transparently via Meshcore native routing
- Steganographic encoding modes (WeatherStation, SensorNetwork) — traffic
looks like sensor data on the wire, 0xAA marker, configurable per-node
- Pre-flight Bitcoin Core health check on relay node — specific error codes
(bitcoin_unreachable, bitcoin_syncing, tx_rejected) instead of generic fails
- mesh.relay-status RPC endpoint — frontend polls for relay result every 3s
- On-Chain / Lightning tabs in Off-Grid Bitcoin panel
- Archy Peers vs Mesh Broadcast relay mode selector
- Mesh view fills viewport (no page scroll), internal panel scrolling
- Version bump to 1.2.0-alpha
Also includes: deploy hardening, container fixes, IndeedHub updates,
boot screen, dashboard improvements, MASTER_PLAN task tracking
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-17 23:56:37 +00:00
|
|
|
<div class="mode-switcher mode-switcher-full">
|
|
|
|
|
<RouterLink
|
|
|
|
|
to="/dashboard/web5"
|
|
|
|
|
class="mode-switcher-btn"
|
|
|
|
|
:class="{ 'mode-switcher-btn-active': route.path === '/dashboard/web5' || route.path.startsWith('/dashboard/web5/') }"
|
|
|
|
|
>Web5</RouterLink>
|
2026-01-24 22:59:20 +00:00
|
|
|
<RouterLink
|
|
|
|
|
to="/dashboard/cloud"
|
feat: v1.2.0-alpha — E2E encrypted mesh relay, steganography, relay status polling
Phase 5 mesh networking:
- E2E encrypted TX relay (X25519 + ChaCha20-Poly1305) — non-Archy nodes
relay encrypted blobs transparently via Meshcore native routing
- Steganographic encoding modes (WeatherStation, SensorNetwork) — traffic
looks like sensor data on the wire, 0xAA marker, configurable per-node
- Pre-flight Bitcoin Core health check on relay node — specific error codes
(bitcoin_unreachable, bitcoin_syncing, tx_rejected) instead of generic fails
- mesh.relay-status RPC endpoint — frontend polls for relay result every 3s
- On-Chain / Lightning tabs in Off-Grid Bitcoin panel
- Archy Peers vs Mesh Broadcast relay mode selector
- Mesh view fills viewport (no page scroll), internal panel scrolling
- Version bump to 1.2.0-alpha
Also includes: deploy hardening, container fixes, IndeedHub updates,
boot screen, dashboard improvements, MASTER_PLAN task tracking
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-17 23:56:37 +00:00
|
|
|
class="mode-switcher-btn"
|
|
|
|
|
:class="{ 'mode-switcher-btn-active': route.path === '/dashboard/cloud' || route.path.startsWith('/dashboard/cloud/') }"
|
|
|
|
|
>Cloud</RouterLink>
|
2026-01-24 22:59:20 +00:00
|
|
|
<RouterLink
|
|
|
|
|
to="/dashboard/server"
|
feat: v1.2.0-alpha — E2E encrypted mesh relay, steganography, relay status polling
Phase 5 mesh networking:
- E2E encrypted TX relay (X25519 + ChaCha20-Poly1305) — non-Archy nodes
relay encrypted blobs transparently via Meshcore native routing
- Steganographic encoding modes (WeatherStation, SensorNetwork) — traffic
looks like sensor data on the wire, 0xAA marker, configurable per-node
- Pre-flight Bitcoin Core health check on relay node — specific error codes
(bitcoin_unreachable, bitcoin_syncing, tx_rejected) instead of generic fails
- mesh.relay-status RPC endpoint — frontend polls for relay result every 3s
- On-Chain / Lightning tabs in Off-Grid Bitcoin panel
- Archy Peers vs Mesh Broadcast relay mode selector
- Mesh view fills viewport (no page scroll), internal panel scrolling
- Version bump to 1.2.0-alpha
Also includes: deploy hardening, container fixes, IndeedHub updates,
boot screen, dashboard improvements, MASTER_PLAN task tracking
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-17 23:56:37 +00:00
|
|
|
class="mode-switcher-btn"
|
|
|
|
|
:class="{ 'mode-switcher-btn-active': route.path === '/dashboard/server' || route.path.startsWith('/dashboard/server/') }"
|
|
|
|
|
>Network</RouterLink>
|
|
|
|
|
<RouterLink
|
|
|
|
|
to="/dashboard/mesh"
|
|
|
|
|
class="mode-switcher-btn"
|
|
|
|
|
:class="{ 'mode-switcher-btn-active': route.path === '/dashboard/mesh' || route.path.startsWith('/dashboard/mesh/') }"
|
|
|
|
|
>Mesh</RouterLink>
|
2026-01-24 22:59:20 +00:00
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
|
2026-03-05 10:14:10 +00:00
|
|
|
<div class="perspective-container-wrapper glass-piece" :class="{ 'glass-throw-content': showZoomIn && !isHomeRoute }">
|
2026-01-24 22:59:20 +00:00
|
|
|
<div class="perspective-container">
|
|
|
|
|
<RouterView v-slot="{ Component, route }">
|
|
|
|
|
<Transition :name="getTransitionName(route)">
|
|
|
|
|
<div :key="route.path" class="view-wrapper">
|
|
|
|
|
<div
|
feat: v1.2.0-alpha — E2E encrypted mesh relay, steganography, relay status polling
Phase 5 mesh networking:
- E2E encrypted TX relay (X25519 + ChaCha20-Poly1305) — non-Archy nodes
relay encrypted blobs transparently via Meshcore native routing
- Steganographic encoding modes (WeatherStation, SensorNetwork) — traffic
looks like sensor data on the wire, 0xAA marker, configurable per-node
- Pre-flight Bitcoin Core health check on relay node — specific error codes
(bitcoin_unreachable, bitcoin_syncing, tx_rejected) instead of generic fails
- mesh.relay-status RPC endpoint — frontend polls for relay result every 3s
- On-Chain / Lightning tabs in Off-Grid Bitcoin panel
- Archy Peers vs Mesh Broadcast relay mode selector
- Mesh view fills viewport (no page scroll), internal panel scrolling
- Version bump to 1.2.0-alpha
Also includes: deploy hardening, container fixes, IndeedHub updates,
boot screen, dashboard improvements, MASTER_PLAN task tracking
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-17 23:56:37 +00:00
|
|
|
v-if="route.path === '/dashboard/chat' || route.path === '/dashboard/mesh'"
|
security+feat: v1.3.0 — pentest remediation, container reliability, UI overhaul
Security (33 pentest findings addressed):
- CRITICAL: backend binds 127.0.0.1, path traversal in tor.rs/dwn fixed
- HIGH: federation requires signatures, XSS login redirect, RBAC viewer restricted
- HIGH: tar slip prevention, S3 SSRF validation, backup ID validation
- MEDIUM: remember-me random secret, TOTP session rotation, password re-auth
- LOW: CSP unsafe-inline removed, CORS dev-only, onion/webhook validation
Container reliability:
- Memory limits on all 37 containers (OOM prevention)
- Exited vs stopped state distinction with health-aware status badges
- Crash recovery coordination (no more restart cascade)
- User-stopped tracking survives reboots
- Tiered boot recovery (databases → core → services → apps)
UI:
- Wallet TransactionsModal, health-aware app status badges
- Restart button on containers, exited/crashed red state
- Mesh view overhaul, glass button updates, BaseModal/ToggleSwitch
- Apps sticky header removed, dev faucet, mutable mock wallet
Infrastructure:
- LND REST port 8080 exposed over Tor (LND Connect fix)
- Nginx cookie_session fix, deploy script Tor config updated
- Dev environment: podman auto-start, boot mode simulation
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-19 12:44:31 +00:00
|
|
|
:class="['h-full', mobileTabPaddingTop ? 'overflow-y-auto' : '']"
|
|
|
|
|
:style="mobileTabPaddingTop ? { paddingTop: (mobileTabPaddingTop + 16) + 'px' } : undefined"
|
feat: AIUI chat mode integration with iframe, context broker, overnight loop
- Chat mode: AIUI loads in sandboxed iframe at /dashboard/chat with transparent bg
- Mode switcher: Easy + Pro tabs only, Chat is a launcher button
- Keyboard shortcuts: Cmd+1 (Easy), Cmd+2 (Pro), Cmd+3 (Chat), Cmd+M (cycle)
- Directional transitions: chat slides from/to left, dashboard from/to right
- Context broker: postMessage protocol for quarantined AIUI communication
- AI permissions store: user-controlled toggles for data access categories
- Settings UI: AI Data Access section with per-category toggles
- AIUI container manifest and nginx proxy config for /aiui/
- Deploy script builds AIUI with /aiui/ base path
- Overnight loop infrastructure (loop.sh, prepare.sh, plan.md, prompt.md)
- Security hooks for autonomous overnight runs
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-04 12:06:20 +00:00
|
|
|
>
|
|
|
|
|
<component :is="Component" />
|
|
|
|
|
</div>
|
|
|
|
|
<div
|
|
|
|
|
v-else
|
2026-01-24 22:59:20 +00:00
|
|
|
:class="[
|
2026-03-14 17:12:41 +00:00
|
|
|
'absolute inset-0 px-4 pt-4 md:pt-8 md:px-8 overflow-y-auto',
|
feat: AIUI chat mode integration with iframe, context broker, overnight loop
- Chat mode: AIUI loads in sandboxed iframe at /dashboard/chat with transparent bg
- Mode switcher: Easy + Pro tabs only, Chat is a launcher button
- Keyboard shortcuts: Cmd+1 (Easy), Cmd+2 (Pro), Cmd+3 (Chat), Cmd+M (cycle)
- Directional transitions: chat slides from/to left, dashboard from/to right
- Context broker: postMessage protocol for quarantined AIUI communication
- AI permissions store: user-controlled toggles for data access categories
- Settings UI: AI Data Access section with per-category toggles
- AIUI container manifest and nginx proxy config for /aiui/
- Deploy script builds AIUI with /aiui/ base path
- Overnight loop infrastructure (loop.sh, prepare.sh, plan.md, prompt.md)
- Security hooks for autonomous overnight runs
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-04 12:06:20 +00:00
|
|
|
needsMobileBackButtonSpace
|
2026-03-14 17:12:41 +00:00
|
|
|
? 'mobile-scroll-pad-back'
|
|
|
|
|
: 'mobile-scroll-pad'
|
2026-01-24 22:59:20 +00:00
|
|
|
]"
|
2026-03-05 10:14:10 +00:00
|
|
|
:style="mobileTabPaddingTop ? { paddingTop: (mobileTabPaddingTop + 16) + 'px' } : undefined"
|
2026-01-24 22:59:20 +00:00
|
|
|
>
|
2026-03-14 17:12:41 +00:00
|
|
|
<component :is="Component" class="view-container flex-none" />
|
|
|
|
|
<!-- Bottom spacer — scroll clearance on all pages -->
|
|
|
|
|
<div class="shrink-0 h-6 md:h-12" aria-hidden="true"></div>
|
2026-01-24 22:59:20 +00:00
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</Transition>
|
|
|
|
|
</RouterView>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
2026-03-16 12:58:35 +00:00
|
|
|
|
|
|
|
|
<!-- Panel mode app session — renders alongside current page content -->
|
|
|
|
|
<Transition name="panel-slide">
|
|
|
|
|
<div v-if="appLauncher.panelAppId" class="app-panel-container">
|
|
|
|
|
<AppSession :app-id-prop="appLauncher.panelAppId" @close="appLauncher.closePanel()" />
|
|
|
|
|
</div>
|
|
|
|
|
</Transition>
|
2026-01-24 22:59:20 +00:00
|
|
|
</main>
|
|
|
|
|
|
2026-02-17 19:19:54 +00:00
|
|
|
<!-- Mobile Bottom Tab Bar - glass piece 5 -->
|
2026-01-24 22:59:20 +00:00
|
|
|
<nav
|
|
|
|
|
ref="mobileTabBar"
|
|
|
|
|
data-mobile-tab-bar
|
2026-03-11 13:45:59 +00:00
|
|
|
:aria-label="t('dashboard.mobileNav')"
|
2026-02-17 19:19:54 +00:00
|
|
|
class="md:hidden fixed bottom-0 left-0 right-0 border-t border-glass-border shadow-glass z-50 glass-piece"
|
|
|
|
|
:class="{ 'glass-throw-tabbar': showZoomIn }"
|
2026-03-05 08:24:56 +00:00
|
|
|
style="background: rgba(0, 0, 0, 0.25); backdrop-filter: blur(18px); -webkit-backdrop-filter: blur(18px); padding-bottom: env(safe-area-inset-bottom, 0px);"
|
2026-01-24 22:59:20 +00:00
|
|
|
>
|
|
|
|
|
<div class="flex justify-around items-center px-2 py-3 relative">
|
|
|
|
|
<RouterLink
|
|
|
|
|
v-for="item in mobileNavItems"
|
|
|
|
|
:key="item.path"
|
|
|
|
|
:to="item.path"
|
2026-03-16 12:58:35 +00:00
|
|
|
@click="appLauncher.closePanel()"
|
2026-03-09 07:43:12 +00:00
|
|
|
class="flex flex-col items-center justify-center w-full py-1.5 rounded-lg text-white/70 transition-all duration-300 relative z-10 gap-0.5"
|
2026-01-24 22:59:20 +00:00
|
|
|
:class="{
|
feat: AIUI chat mode integration with iframe, context broker, overnight loop
- Chat mode: AIUI loads in sandboxed iframe at /dashboard/chat with transparent bg
- Mode switcher: Easy + Pro tabs only, Chat is a launcher button
- Keyboard shortcuts: Cmd+1 (Easy), Cmd+2 (Pro), Cmd+3 (Chat), Cmd+M (cycle)
- Directional transitions: chat slides from/to left, dashboard from/to right
- Context broker: postMessage protocol for quarantined AIUI communication
- AI permissions store: user-controlled toggles for data access categories
- Settings UI: AI Data Access section with per-category toggles
- AIUI container manifest and nginx proxy config for /aiui/
- Deploy script builds AIUI with /aiui/ base path
- Overnight loop infrastructure (loop.sh, prepare.sh, plan.md, prompt.md)
- Security hooks for autonomous overnight runs
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-04 12:06:20 +00:00
|
|
|
'nav-tab-active': item.isCombined
|
2026-01-24 22:59:20 +00:00
|
|
|
? (item.path === '/dashboard/apps'
|
2026-03-16 12:58:35 +00:00
|
|
|
? (route.path.includes('/apps') || route.path.includes('/marketplace') || route.path.includes('/app-session'))
|
2026-01-24 22:59:20 +00:00
|
|
|
: (route.path.includes('/cloud') || route.path.includes('/server')))
|
|
|
|
|
: undefined
|
|
|
|
|
}"
|
|
|
|
|
:exact-active-class="item.isCombined ? undefined : 'nav-tab-active'"
|
|
|
|
|
>
|
security+feat: v1.3.0 — pentest remediation, container reliability, UI overhaul
Security (33 pentest findings addressed):
- CRITICAL: backend binds 127.0.0.1, path traversal in tor.rs/dwn fixed
- HIGH: federation requires signatures, XSS login redirect, RBAC viewer restricted
- HIGH: tar slip prevention, S3 SSRF validation, backup ID validation
- MEDIUM: remember-me random secret, TOTP session rotation, password re-auth
- LOW: CSP unsafe-inline removed, CORS dev-only, onion/webhook validation
Container reliability:
- Memory limits on all 37 containers (OOM prevention)
- Exited vs stopped state distinction with health-aware status badges
- Crash recovery coordination (no more restart cascade)
- User-stopped tracking survives reboots
- Tiered boot recovery (databases → core → services → apps)
UI:
- Wallet TransactionsModal, health-aware app status badges
- Restart button on containers, exited/crashed red state
- Mesh view overhaul, glass button updates, BaseModal/ToggleSwitch
- Apps sticky header removed, dev faucet, mutable mock wallet
Infrastructure:
- LND REST port 8080 exposed over Tor (LND Connect fix)
- Nginx cookie_session fix, deploy script Tor config updated
- Dev environment: podman auto-start, boot mode simulation
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-19 12:44:31 +00:00
|
|
|
<svg v-if="item.icon === 'web5'" class="w-6 h-6 transition-all duration-300" aria-hidden="true" fill="currentColor" viewBox="0 0 1631 1624">
|
|
|
|
|
<path fill-rule="evenodd" clip-rule="evenodd" d="M914.932 359.228H916.229V715.252H1630.47V1088.98H1451.41V1267.98H1274.33V1445H1093.31V1624H715.534V1264.77H714.237V908.748H0V535.02H179.051V356.025H356.135V178.996H537.154V0H914.932V359.228ZM916.229 1425.33H1073.64V1248.31H1254.66V1071.28H1431.74V913.918H916.229V1425.33ZM556.83 375.695H375.811V552.723H198.727V710.082H714.237V198.666H556.83V375.695Z" />
|
|
|
|
|
</svg>
|
|
|
|
|
<svg v-else class="w-6 h-6 transition-all duration-300" aria-hidden="true" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
feat: AIUI chat mode integration with iframe, context broker, overnight loop
- Chat mode: AIUI loads in sandboxed iframe at /dashboard/chat with transparent bg
- Mode switcher: Easy + Pro tabs only, Chat is a launcher button
- Keyboard shortcuts: Cmd+1 (Easy), Cmd+2 (Pro), Cmd+3 (Chat), Cmd+M (cycle)
- Directional transitions: chat slides from/to left, dashboard from/to right
- Context broker: postMessage protocol for quarantined AIUI communication
- AI permissions store: user-controlled toggles for data access categories
- Settings UI: AI Data Access section with per-category toggles
- AIUI container manifest and nginx proxy config for /aiui/
- Deploy script builds AIUI with /aiui/ base path
- Overnight loop infrastructure (loop.sh, prepare.sh, plan.md, prompt.md)
- Security hooks for autonomous overnight runs
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-04 12:06:20 +00:00
|
|
|
<path
|
|
|
|
|
v-for="(path, index) in getIconPath(item.icon)"
|
2026-01-24 22:59:20 +00:00
|
|
|
:key="index"
|
feat: AIUI chat mode integration with iframe, context broker, overnight loop
- Chat mode: AIUI loads in sandboxed iframe at /dashboard/chat with transparent bg
- Mode switcher: Easy + Pro tabs only, Chat is a launcher button
- Keyboard shortcuts: Cmd+1 (Easy), Cmd+2 (Pro), Cmd+3 (Chat), Cmd+M (cycle)
- Directional transitions: chat slides from/to left, dashboard from/to right
- Context broker: postMessage protocol for quarantined AIUI communication
- AI permissions store: user-controlled toggles for data access categories
- Settings UI: AI Data Access section with per-category toggles
- AIUI container manifest and nginx proxy config for /aiui/
- Deploy script builds AIUI with /aiui/ base path
- Overnight loop infrastructure (loop.sh, prepare.sh, plan.md, prompt.md)
- Security hooks for autonomous overnight runs
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-04 12:06:20 +00:00
|
|
|
stroke-linecap="round"
|
|
|
|
|
stroke-linejoin="round"
|
|
|
|
|
stroke-width="2"
|
|
|
|
|
:d="path"
|
2026-01-24 22:59:20 +00:00
|
|
|
/>
|
|
|
|
|
</svg>
|
2026-03-09 07:43:12 +00:00
|
|
|
<span class="text-[10px] leading-tight">{{ item.label }}</span>
|
2026-01-24 22:59:20 +00:00
|
|
|
</RouterLink>
|
feat: AIUI chat mode integration with iframe, context broker, overnight loop
- Chat mode: AIUI loads in sandboxed iframe at /dashboard/chat with transparent bg
- Mode switcher: Easy + Pro tabs only, Chat is a launcher button
- Keyboard shortcuts: Cmd+1 (Easy), Cmd+2 (Pro), Cmd+3 (Chat), Cmd+M (cycle)
- Directional transitions: chat slides from/to left, dashboard from/to right
- Context broker: postMessage protocol for quarantined AIUI communication
- AI permissions store: user-controlled toggles for data access categories
- Settings UI: AI Data Access section with per-category toggles
- AIUI container manifest and nginx proxy config for /aiui/
- Deploy script builds AIUI with /aiui/ base path
- Overnight loop infrastructure (loop.sh, prepare.sh, plan.md, prompt.md)
- Security hooks for autonomous overnight runs
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-04 12:06:20 +00:00
|
|
|
<!-- Chat launcher -->
|
|
|
|
|
<button
|
|
|
|
|
@click="router.push('/dashboard/chat')"
|
2026-03-09 07:43:12 +00:00
|
|
|
class="chat-launcher-btn-mobile flex flex-col items-center justify-center w-full py-1.5 rounded-lg transition-all duration-300 relative z-10 gap-0.5"
|
feat: AIUI chat mode integration with iframe, context broker, overnight loop
- Chat mode: AIUI loads in sandboxed iframe at /dashboard/chat with transparent bg
- Mode switcher: Easy + Pro tabs only, Chat is a launcher button
- Keyboard shortcuts: Cmd+1 (Easy), Cmd+2 (Pro), Cmd+3 (Chat), Cmd+M (cycle)
- Directional transitions: chat slides from/to left, dashboard from/to right
- Context broker: postMessage protocol for quarantined AIUI communication
- AI permissions store: user-controlled toggles for data access categories
- Settings UI: AI Data Access section with per-category toggles
- AIUI container manifest and nginx proxy config for /aiui/
- Deploy script builds AIUI with /aiui/ base path
- Overnight loop infrastructure (loop.sh, prepare.sh, plan.md, prompt.md)
- Security hooks for autonomous overnight runs
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-04 12:06:20 +00:00
|
|
|
>
|
2026-03-09 07:43:12 +00:00
|
|
|
<svg class="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
feat: AIUI chat mode integration with iframe, context broker, overnight loop
- Chat mode: AIUI loads in sandboxed iframe at /dashboard/chat with transparent bg
- Mode switcher: Easy + Pro tabs only, Chat is a launcher button
- Keyboard shortcuts: Cmd+1 (Easy), Cmd+2 (Pro), Cmd+3 (Chat), Cmd+M (cycle)
- Directional transitions: chat slides from/to left, dashboard from/to right
- Context broker: postMessage protocol for quarantined AIUI communication
- AI permissions store: user-controlled toggles for data access categories
- Settings UI: AI Data Access section with per-category toggles
- AIUI container manifest and nginx proxy config for /aiui/
- Deploy script builds AIUI with /aiui/ base path
- Overnight loop infrastructure (loop.sh, prepare.sh, plan.md, prompt.md)
- Security hooks for autonomous overnight runs
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-04 12:06:20 +00:00
|
|
|
<path v-for="(path, index) in getIconPath('chat')" :key="index" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" :d="path" />
|
|
|
|
|
</svg>
|
2026-03-12 00:19:30 +00:00
|
|
|
<span class="text-[10px] leading-tight">AIUI</span>
|
feat: AIUI chat mode integration with iframe, context broker, overnight loop
- Chat mode: AIUI loads in sandboxed iframe at /dashboard/chat with transparent bg
- Mode switcher: Easy + Pro tabs only, Chat is a launcher button
- Keyboard shortcuts: Cmd+1 (Easy), Cmd+2 (Pro), Cmd+3 (Chat), Cmd+M (cycle)
- Directional transitions: chat slides from/to left, dashboard from/to right
- Context broker: postMessage protocol for quarantined AIUI communication
- AI permissions store: user-controlled toggles for data access categories
- Settings UI: AI Data Access section with per-category toggles
- AIUI container manifest and nginx proxy config for /aiui/
- Deploy script builds AIUI with /aiui/ base path
- Overnight loop infrastructure (loop.sh, prepare.sh, plan.md, prompt.md)
- Security hooks for autonomous overnight runs
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-04 12:06:20 +00:00
|
|
|
</button>
|
2026-01-24 22:59:20 +00:00
|
|
|
</div>
|
|
|
|
|
</nav>
|
2026-03-11 13:04:31 +00:00
|
|
|
|
|
|
|
|
<!-- Health Notifications Toast -->
|
|
|
|
|
<div
|
|
|
|
|
v-if="healthNotifications.length > 0"
|
|
|
|
|
class="fixed top-4 right-4 z-[200] flex flex-col gap-2 max-w-sm"
|
|
|
|
|
>
|
|
|
|
|
<div
|
|
|
|
|
v-for="notif in healthNotifications"
|
|
|
|
|
:key="notif.id"
|
|
|
|
|
class="p-3 rounded-xl border backdrop-blur-lg shadow-lg"
|
|
|
|
|
:class="notif.level === 'error'
|
|
|
|
|
? 'bg-red-500/15 border-red-500/30'
|
|
|
|
|
: notif.level === 'warning'
|
|
|
|
|
? 'bg-yellow-500/15 border-yellow-500/30'
|
|
|
|
|
: 'bg-blue-500/15 border-blue-500/30'"
|
|
|
|
|
>
|
|
|
|
|
<div class="flex items-start gap-2">
|
|
|
|
|
<svg xmlns="http://www.w3.org/2000/svg" class="h-4 w-4 mt-0.5 shrink-0" :class="notif.level === 'error' ? 'text-red-400' : notif.level === 'warning' ? 'text-yellow-400' : 'text-blue-400'" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
|
|
|
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-2.5L13.732 4.5c-.77-.833-2.694-.833-3.464 0L3.34 16.5c-.77.833.192 2.5 1.732 2.5z" />
|
|
|
|
|
</svg>
|
|
|
|
|
<div class="flex-1 min-w-0">
|
|
|
|
|
<p class="text-sm font-medium text-white">{{ notif.title }}</p>
|
|
|
|
|
<p class="text-xs text-white/60 mt-0.5">{{ notif.message }}</p>
|
|
|
|
|
</div>
|
|
|
|
|
<button
|
|
|
|
|
class="text-white/40 hover:text-white/80 transition-colors shrink-0"
|
|
|
|
|
@click="dismissNotification(notif.id)"
|
|
|
|
|
>
|
|
|
|
|
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
|
|
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12" />
|
|
|
|
|
</svg>
|
|
|
|
|
</button>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
2026-01-24 22:59:20 +00:00
|
|
|
</div>
|
|
|
|
|
</template>
|
|
|
|
|
|
|
|
|
|
<script setup lang="ts">
|
|
|
|
|
import { computed, ref, watch, onMounted, onBeforeUnmount, nextTick } from 'vue'
|
2026-03-11 13:04:31 +00:00
|
|
|
import { RouterLink, RouterView, useRouter, useRoute, type RouteLocationNormalizedLoaded } from 'vue-router'
|
2026-03-11 13:45:59 +00:00
|
|
|
import { useI18n } from 'vue-i18n'
|
2026-01-24 22:59:20 +00:00
|
|
|
import { useAppStore } from '../stores/app'
|
2026-03-16 12:58:35 +00:00
|
|
|
import { useAppLauncherStore } from '../stores/appLauncher'
|
|
|
|
|
import AppSession from '@/views/AppSession.vue'
|
2026-03-11 13:45:59 +00:00
|
|
|
|
|
|
|
|
const { t } = useI18n()
|
2026-02-17 19:19:54 +00:00
|
|
|
import { useLoginTransitionStore } from '../stores/loginTransition'
|
2026-02-17 15:03:34 +00:00
|
|
|
import AnimatedLogo from '@/components/AnimatedLogo.vue'
|
2026-03-04 05:23:42 +00:00
|
|
|
import OnlineStatusPill from '@/components/OnlineStatusPill.vue'
|
2026-02-17 15:03:34 +00:00
|
|
|
import ControllerIndicator from '@/components/ControllerIndicator.vue'
|
2026-03-04 07:09:31 +00:00
|
|
|
import ModeSwitcher from '@/components/ModeSwitcher.vue'
|
|
|
|
|
import { useUIModeStore } from '@/stores/uiMode'
|
2026-02-17 19:19:54 +00:00
|
|
|
import { playDashboardLoadOomph } from '@/composables/useLoginSounds'
|
2026-03-09 07:43:12 +00:00
|
|
|
import { useWeb5BadgeStore } from '@/stores/web5Badge'
|
2026-03-17 00:03:08 +00:00
|
|
|
import { useMeshStore } from '@/stores/mesh'
|
2026-01-24 22:59:20 +00:00
|
|
|
|
2026-03-04 07:09:31 +00:00
|
|
|
const uiMode = useUIModeStore()
|
|
|
|
|
|
feat: AIUI chat mode integration with iframe, context broker, overnight loop
- Chat mode: AIUI loads in sandboxed iframe at /dashboard/chat with transparent bg
- Mode switcher: Easy + Pro tabs only, Chat is a launcher button
- Keyboard shortcuts: Cmd+1 (Easy), Cmd+2 (Pro), Cmd+3 (Chat), Cmd+M (cycle)
- Directional transitions: chat slides from/to left, dashboard from/to right
- Context broker: postMessage protocol for quarantined AIUI communication
- AI permissions store: user-controlled toggles for data access categories
- Settings UI: AI Data Access section with per-category toggles
- AIUI container manifest and nginx proxy config for /aiui/
- Deploy script builds AIUI with /aiui/ base path
- Overnight loop infrastructure (loop.sh, prepare.sh, plan.md, prompt.md)
- Security hooks for autonomous overnight runs
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-04 12:06:20 +00:00
|
|
|
// Chat fullscreen: hide sidebar + mobile nav when on /dashboard/chat (any mode)
|
|
|
|
|
const chatFullscreen = computed(() => route.path === '/dashboard/chat')
|
|
|
|
|
|
|
|
|
|
|
2026-01-24 22:59:20 +00:00
|
|
|
const router = useRouter()
|
|
|
|
|
const route = useRoute()
|
|
|
|
|
const store = useAppStore()
|
2026-03-16 12:58:35 +00:00
|
|
|
const appLauncher = useAppLauncherStore()
|
2026-02-17 19:19:54 +00:00
|
|
|
const loginTransition = useLoginTransitionStore()
|
2026-03-09 07:43:12 +00:00
|
|
|
const web5Badge = useWeb5BadgeStore()
|
2026-03-17 00:03:08 +00:00
|
|
|
const meshStore = useMeshStore()
|
2026-02-17 19:19:54 +00:00
|
|
|
|
|
|
|
|
const showZoomIn = ref(false)
|
2026-03-01 18:07:35 +00:00
|
|
|
const pendingTimers: ReturnType<typeof setTimeout>[] = []
|
|
|
|
|
|
|
|
|
|
function scheduledTimeout(fn: () => void, ms: number) {
|
|
|
|
|
const id = setTimeout(fn, ms)
|
|
|
|
|
pendingTimers.push(id)
|
|
|
|
|
return id
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function isDetailRoute(path: string) {
|
|
|
|
|
return (path.includes('/apps/') && !path.endsWith('/apps')) ||
|
|
|
|
|
(path.includes('/marketplace/') && !path.endsWith('/marketplace'))
|
|
|
|
|
}
|
2026-01-24 22:59:20 +00:00
|
|
|
|
|
|
|
|
const showAltBackground = ref(false)
|
2026-02-17 19:19:54 +00:00
|
|
|
const isHomeRoute = computed(() => route.path === '/dashboard' || route.path === '/dashboard/')
|
2026-01-24 22:59:20 +00:00
|
|
|
const isGlitching = ref(false)
|
|
|
|
|
|
2026-03-01 18:07:35 +00:00
|
|
|
const ROUTE_BACKGROUNDS: Record<string, string> = {
|
|
|
|
|
'/dashboard': 'bg-home.jpg',
|
|
|
|
|
'/dashboard/': 'bg-home.jpg',
|
|
|
|
|
'/dashboard/apps': 'bg-myapps.jpg',
|
|
|
|
|
'/dashboard/marketplace': 'bg-appstore.jpg',
|
|
|
|
|
'/dashboard/cloud': 'bg-cloud.jpg',
|
2026-03-17 00:03:08 +00:00
|
|
|
'/dashboard/mesh': 'bg-mesh.jpg',
|
2026-03-01 18:07:35 +00:00
|
|
|
'/dashboard/server': 'bg-network.jpg',
|
|
|
|
|
'/dashboard/web5': 'bg-web5.jpg',
|
|
|
|
|
'/dashboard/settings': 'bg-settings.jpg',
|
feat: AIUI chat mode integration with iframe, context broker, overnight loop
- Chat mode: AIUI loads in sandboxed iframe at /dashboard/chat with transparent bg
- Mode switcher: Easy + Pro tabs only, Chat is a launcher button
- Keyboard shortcuts: Cmd+1 (Easy), Cmd+2 (Pro), Cmd+3 (Chat), Cmd+M (cycle)
- Directional transitions: chat slides from/to left, dashboard from/to right
- Context broker: postMessage protocol for quarantined AIUI communication
- AI permissions store: user-controlled toggles for data access categories
- Settings UI: AI Data Access section with per-category toggles
- AIUI container manifest and nginx proxy config for /aiui/
- Deploy script builds AIUI with /aiui/ base path
- Overnight loop infrastructure (loop.sh, prepare.sh, plan.md, prompt.md)
- Security hooks for autonomous overnight runs
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-04 12:06:20 +00:00
|
|
|
'/dashboard/chat': 'bg-home.jpg',
|
2026-03-01 18:07:35 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const backgroundImage = computed(() => {
|
|
|
|
|
if (isDetailRoute(route.path)) return 'bg-intro.jpg'
|
|
|
|
|
return ROUTE_BACKGROUNDS[route.path] || 'bg-home.jpg'
|
2026-01-24 22:59:20 +00:00
|
|
|
})
|
|
|
|
|
|
2026-03-01 18:07:35 +00:00
|
|
|
const isDarkRoute = computed(() => {
|
|
|
|
|
const p = route.path
|
|
|
|
|
return p.includes('/dashboard/web5') ||
|
|
|
|
|
p.includes('/dashboard/server') ||
|
|
|
|
|
p.includes('/dashboard/settings') ||
|
|
|
|
|
(p.includes('/dashboard/apps') && !isDetailRoute(p)) ||
|
|
|
|
|
p.includes('/dashboard/marketplace') ||
|
|
|
|
|
p.includes('/dashboard/cloud')
|
2026-01-24 22:59:20 +00:00
|
|
|
})
|
|
|
|
|
|
2026-03-01 18:07:35 +00:00
|
|
|
const showDarkOverlay = ref(isDarkRoute.value)
|
|
|
|
|
let overlayTimer: ReturnType<typeof setTimeout> | null = null
|
|
|
|
|
|
|
|
|
|
watch(isDarkRoute, (dark) => {
|
|
|
|
|
if (overlayTimer) { clearTimeout(overlayTimer); overlayTimer = null }
|
|
|
|
|
if (dark) {
|
|
|
|
|
showDarkOverlay.value = true
|
|
|
|
|
} else {
|
|
|
|
|
overlayTimer = scheduledTimeout(() => { showDarkOverlay.value = false }, 450)
|
|
|
|
|
}
|
2026-01-24 22:59:20 +00:00
|
|
|
})
|
2026-03-01 18:07:35 +00:00
|
|
|
|
2026-01-24 22:59:20 +00:00
|
|
|
const mobileTabBar = ref<HTMLElement | null>(null)
|
|
|
|
|
const appsTabRef = ref<HTMLElement | null>(null)
|
|
|
|
|
const marketplaceTabRef = ref<HTMLElement | null>(null)
|
|
|
|
|
const appsTabIndicatorLeft = ref(0)
|
|
|
|
|
const appsTabIndicatorWidth = ref(0)
|
|
|
|
|
|
|
|
|
|
const serverTabRef = ref<HTMLElement | null>(null)
|
|
|
|
|
const cloudTabRef = ref<HTMLElement | null>(null)
|
|
|
|
|
const networkTabIndicatorLeft = ref(0)
|
|
|
|
|
const networkTabIndicatorWidth = ref(0)
|
|
|
|
|
|
|
|
|
|
watch(() => route.path, (newPath) => {
|
|
|
|
|
const isAppDetails = isDetailRoute(newPath)
|
|
|
|
|
const wasAppDetails = showAltBackground.value
|
2026-03-01 18:07:35 +00:00
|
|
|
|
2026-01-24 22:59:20 +00:00
|
|
|
showAltBackground.value = isAppDetails
|
2026-03-01 18:07:35 +00:00
|
|
|
|
2026-01-24 22:59:20 +00:00
|
|
|
if (isAppDetails && !wasAppDetails) {
|
2026-03-01 18:07:35 +00:00
|
|
|
scheduledTimeout(() => {
|
2026-01-24 22:59:20 +00:00
|
|
|
isGlitching.value = true
|
2026-03-01 18:07:35 +00:00
|
|
|
scheduledTimeout(() => { isGlitching.value = false }, 375)
|
|
|
|
|
}, 500)
|
2026-01-24 22:59:20 +00:00
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
const needsMobileBackButtonSpace = computed(() => isDetailRoute(route.path))
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Show persistent tabs for Apps/Marketplace on mobile
|
|
|
|
|
const showAppsTabs = computed(() => {
|
|
|
|
|
if (typeof window === 'undefined') return false
|
|
|
|
|
if (window.innerWidth >= 768) return false
|
feat: add Discover page — cypherpunk app store with sovereignty messaging
- New Discover.vue with hero banner, featured sovereignty stack apps,
principle cards, manifesto footer, and full app grid
- Featured apps (Bitcoin Knots, LND, BTCPay, Vaultwarden) with
expanded privacy/sovereignty descriptions
- Discover is first tab in categories bar on App Store pages
- Smart back navigation: detail pages return to Discover when navigated from there
- Category clicks from Discover navigate to Marketplace with category pre-selected
- Cypherpunk aesthetic: terminal tags, scanline overlays, gradient accents,
animated Bitcoin orange headings
- Global CSS classes: discover-hero, discover-terminal-tag, discover-featured-card,
discover-principle-card, discover-manifesto
- Route added: /dashboard/discover
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-19 15:14:12 +00:00
|
|
|
return route.path.includes('/apps') || route.path.includes('/marketplace') || route.path.includes('/discover')
|
2026-01-24 22:59:20 +00:00
|
|
|
})
|
|
|
|
|
|
|
|
|
|
// Show persistent tabs for Network/Cloud on mobile
|
|
|
|
|
const showNetworkTabs = computed(() => {
|
|
|
|
|
if (typeof window === 'undefined') return false
|
|
|
|
|
if (window.innerWidth >= 768) return false
|
2026-03-05 10:14:10 +00:00
|
|
|
if (route.name === 'cloud-folder') return false
|
feat: v1.2.0-alpha — E2E encrypted mesh relay, steganography, relay status polling
Phase 5 mesh networking:
- E2E encrypted TX relay (X25519 + ChaCha20-Poly1305) — non-Archy nodes
relay encrypted blobs transparently via Meshcore native routing
- Steganographic encoding modes (WeatherStation, SensorNetwork) — traffic
looks like sensor data on the wire, 0xAA marker, configurable per-node
- Pre-flight Bitcoin Core health check on relay node — specific error codes
(bitcoin_unreachable, bitcoin_syncing, tx_rejected) instead of generic fails
- mesh.relay-status RPC endpoint — frontend polls for relay result every 3s
- On-Chain / Lightning tabs in Off-Grid Bitcoin panel
- Archy Peers vs Mesh Broadcast relay mode selector
- Mesh view fills viewport (no page scroll), internal panel scrolling
- Version bump to 1.2.0-alpha
Also includes: deploy hardening, container fixes, IndeedHub updates,
boot screen, dashboard improvements, MASTER_PLAN task tracking
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-17 23:56:37 +00:00
|
|
|
return route.path.includes('/server') || route.path.includes('/cloud') || route.path.includes('/web5') || route.path.includes('/mesh')
|
2026-01-24 22:59:20 +00:00
|
|
|
})
|
|
|
|
|
|
2026-03-05 10:14:10 +00:00
|
|
|
// Top padding for content div to clear fixed mobile tab overlays
|
|
|
|
|
const mobileTabPaddingTop = computed(() => {
|
|
|
|
|
if (typeof window === 'undefined' || window.innerWidth >= 768) return 0
|
|
|
|
|
if (showAppsTabs.value && showNetworkTabs.value) return 160
|
|
|
|
|
if (showAppsTabs.value || showNetworkTabs.value) return 80
|
|
|
|
|
return 0
|
|
|
|
|
})
|
|
|
|
|
|
2026-01-24 22:59:20 +00:00
|
|
|
function updateTabBarHeight() {
|
|
|
|
|
if (typeof window === 'undefined') return
|
|
|
|
|
if (mobileTabBar.value) {
|
|
|
|
|
const height = mobileTabBar.value.offsetHeight
|
|
|
|
|
document.documentElement.style.setProperty('--mobile-tab-bar-height', `${height}px`)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function updateAppsTabIndicator() {
|
|
|
|
|
if (typeof window === 'undefined' || window.innerWidth >= 768) return
|
|
|
|
|
|
|
|
|
|
const isAppsActive = route.path === '/dashboard/apps' || route.path.startsWith('/dashboard/apps/')
|
|
|
|
|
const activeTab = isAppsActive ? appsTabRef.value : marketplaceTabRef.value
|
|
|
|
|
|
|
|
|
|
if (!activeTab) return
|
|
|
|
|
|
|
|
|
|
const container = activeTab.parentElement
|
|
|
|
|
if (!container) return
|
|
|
|
|
|
|
|
|
|
const containerRect = container.getBoundingClientRect()
|
|
|
|
|
const tabRect = activeTab.getBoundingClientRect()
|
|
|
|
|
|
|
|
|
|
appsTabIndicatorLeft.value = tabRect.left - containerRect.left
|
|
|
|
|
appsTabIndicatorWidth.value = tabRect.width
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function updateNetworkTabIndicator() {
|
|
|
|
|
if (typeof window === 'undefined' || window.innerWidth >= 768) return
|
|
|
|
|
|
|
|
|
|
const isCloudActive = route.path === '/dashboard/cloud' || route.path.startsWith('/dashboard/cloud/')
|
|
|
|
|
const activeTab = isCloudActive ? cloudTabRef.value : serverTabRef.value
|
|
|
|
|
|
|
|
|
|
if (!activeTab) return
|
|
|
|
|
|
|
|
|
|
const container = activeTab.parentElement
|
|
|
|
|
if (!container) return
|
|
|
|
|
|
|
|
|
|
const containerRect = container.getBoundingClientRect()
|
|
|
|
|
const tabRect = activeTab.getBoundingClientRect()
|
|
|
|
|
|
|
|
|
|
networkTabIndicatorLeft.value = tabRect.left - containerRect.left
|
|
|
|
|
networkTabIndicatorWidth.value = tabRect.width
|
|
|
|
|
}
|
|
|
|
|
|
2026-03-01 18:07:35 +00:00
|
|
|
function onResize() {
|
|
|
|
|
updateTabBarHeight()
|
|
|
|
|
updateAppsTabIndicator()
|
|
|
|
|
updateNetworkTabIndicator()
|
|
|
|
|
}
|
|
|
|
|
|
2026-01-24 22:59:20 +00:00
|
|
|
onMounted(() => {
|
2026-02-17 19:19:54 +00:00
|
|
|
document.body.classList.add('dashboard-active')
|
|
|
|
|
if (loginTransition.justLoggedIn) {
|
|
|
|
|
playDashboardLoadOomph()
|
|
|
|
|
showZoomIn.value = true
|
|
|
|
|
loginTransition.setPendingWelcomeTyping(true)
|
|
|
|
|
loginTransition.setJustLoggedIn(false)
|
|
|
|
|
const triggerRevealGlitch = () => {
|
|
|
|
|
isGlitching.value = true
|
2026-03-01 18:07:35 +00:00
|
|
|
scheduledTimeout(() => { isGlitching.value = false }, 380)
|
2026-02-17 19:19:54 +00:00
|
|
|
}
|
2026-03-01 18:07:35 +00:00
|
|
|
scheduledTimeout(triggerRevealGlitch, 500)
|
|
|
|
|
scheduledTimeout(triggerRevealGlitch, 1200)
|
|
|
|
|
scheduledTimeout(triggerRevealGlitch, 2000)
|
|
|
|
|
scheduledTimeout(() => { showZoomIn.value = false }, 8000)
|
|
|
|
|
scheduledTimeout(() => {
|
2026-02-17 19:19:54 +00:00
|
|
|
loginTransition.setStartWelcomeTyping(true)
|
|
|
|
|
loginTransition.setPendingWelcomeTyping(false)
|
|
|
|
|
}, 4000)
|
|
|
|
|
}
|
|
|
|
|
|
2026-03-01 18:07:35 +00:00
|
|
|
onResize()
|
|
|
|
|
window.addEventListener('resize', onResize)
|
2026-03-11 13:04:31 +00:00
|
|
|
window.addEventListener('keydown', handleKioskShortcuts)
|
2026-03-09 07:43:12 +00:00
|
|
|
web5Badge.refresh()
|
2026-01-24 22:59:20 +00:00
|
|
|
})
|
|
|
|
|
|
|
|
|
|
onBeforeUnmount(() => {
|
2026-02-17 19:19:54 +00:00
|
|
|
document.body.classList.remove('dashboard-active')
|
2026-03-01 18:07:35 +00:00
|
|
|
window.removeEventListener('resize', onResize)
|
2026-03-11 13:04:31 +00:00
|
|
|
window.removeEventListener('keydown', handleKioskShortcuts)
|
2026-03-01 18:07:35 +00:00
|
|
|
for (const id of pendingTimers) clearTimeout(id)
|
|
|
|
|
pendingTimers.length = 0
|
|
|
|
|
if (overlayTimer) { clearTimeout(overlayTimer); overlayTimer = null }
|
2026-01-24 22:59:20 +00:00
|
|
|
})
|
|
|
|
|
|
2026-03-11 13:04:31 +00:00
|
|
|
// Kiosk keyboard shortcuts (active when kiosk=true in localStorage or query param)
|
|
|
|
|
function isKioskMode(): boolean {
|
|
|
|
|
try {
|
|
|
|
|
return localStorage.getItem('kiosk') === 'true' || new URLSearchParams(window.location.search).has('kiosk')
|
|
|
|
|
} catch { return false }
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function handleKioskShortcuts(e: KeyboardEvent) {
|
|
|
|
|
if (!isKioskMode()) return
|
|
|
|
|
if (e.ctrlKey && e.shiftKey) {
|
|
|
|
|
if (e.key === 'R' || e.key === 'r') {
|
|
|
|
|
e.preventDefault()
|
|
|
|
|
router.push('/recovery')
|
|
|
|
|
} else if (e.key === 'H' || e.key === 'h') {
|
|
|
|
|
e.preventDefault()
|
|
|
|
|
router.push('/dashboard')
|
|
|
|
|
} else if (e.key === 'Q' || e.key === 'q') {
|
|
|
|
|
e.preventDefault()
|
|
|
|
|
if (confirm('Reboot the server?')) {
|
|
|
|
|
fetch('/rpc/', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ method: 'system.reboot' }) }).catch(() => {})
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2026-01-24 22:59:20 +00:00
|
|
|
// Watch route changes to update indicator position
|
|
|
|
|
watch(() => route.path, () => {
|
|
|
|
|
nextTick(() => {
|
|
|
|
|
updateAppsTabIndicator()
|
|
|
|
|
updateNetworkTabIndicator()
|
|
|
|
|
})
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
const serverName = computed(() => store.serverName)
|
|
|
|
|
const version = computed(() => store.serverInfo?.version || '0.0.0')
|
|
|
|
|
const isOffline = computed(() => store.isOffline)
|
|
|
|
|
const isRestarting = computed(() => store.isRestarting)
|
|
|
|
|
const isShuttingDown = computed(() => store.isShuttingDown)
|
|
|
|
|
|
2026-03-04 07:09:31 +00:00
|
|
|
// Navigation items — reactive based on UI mode
|
|
|
|
|
interface NavItem {
|
|
|
|
|
path: string
|
|
|
|
|
label: string
|
|
|
|
|
icon: string
|
|
|
|
|
isCombined?: boolean
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const gamerDesktopNav: NavItem[] = [
|
|
|
|
|
{ path: '/dashboard', label: 'Home', icon: 'home' },
|
2026-03-14 04:14:04 +00:00
|
|
|
{ path: '/dashboard/apps', label: 'Apps', icon: 'apps', isCombined: true },
|
2026-03-04 07:09:31 +00:00
|
|
|
{ path: '/dashboard/cloud', label: 'Cloud', icon: 'cloud' },
|
2026-03-17 00:03:08 +00:00
|
|
|
{ path: '/dashboard/mesh', label: 'Mesh', icon: 'mesh' },
|
2026-03-04 07:09:31 +00:00
|
|
|
{ path: '/dashboard/server', label: 'Network', icon: 'server' },
|
|
|
|
|
{ path: '/dashboard/web5', label: 'Web5', icon: 'web5' },
|
|
|
|
|
{ path: '/dashboard/settings', label: 'Settings', icon: 'settings' },
|
2026-01-24 22:59:20 +00:00
|
|
|
]
|
|
|
|
|
|
2026-03-04 07:09:31 +00:00
|
|
|
const easyDesktopNav: NavItem[] = [
|
|
|
|
|
{ path: '/dashboard', label: 'Home', icon: 'home' },
|
feat: AIUI chat mode integration with iframe, context broker, overnight loop
- Chat mode: AIUI loads in sandboxed iframe at /dashboard/chat with transparent bg
- Mode switcher: Easy + Pro tabs only, Chat is a launcher button
- Keyboard shortcuts: Cmd+1 (Easy), Cmd+2 (Pro), Cmd+3 (Chat), Cmd+M (cycle)
- Directional transitions: chat slides from/to left, dashboard from/to right
- Context broker: postMessage protocol for quarantined AIUI communication
- AI permissions store: user-controlled toggles for data access categories
- Settings UI: AI Data Access section with per-category toggles
- AIUI container manifest and nginx proxy config for /aiui/
- Deploy script builds AIUI with /aiui/ base path
- Overnight loop infrastructure (loop.sh, prepare.sh, plan.md, prompt.md)
- Security hooks for autonomous overnight runs
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-04 12:06:20 +00:00
|
|
|
{ path: '/dashboard/apps', label: 'My Apps', icon: 'apps' },
|
feat: cloud native file browser, settings Claude auth, deploy hardening
- Add native Cloud file browser with FileBrowser API integration
- Add cloud store, filebrowser-client, useAudioPlayer, useFileType composables
- Add Cloud components: FileGrid, FileCard, FileCardGrid, CloudToolbar
- Add Claude authentication section to Settings with OAuth status check
- Harden deploy script to preserve /aiui/ and claude-login.html
- Add nginx proxies for btcpay, homeassistant, filebrowser (HTTPS block)
- Add app configs for filebrowser, searxng, penpot in package.rs
- Update goal progress tracking with app aliases
- Improve mobile back button composable with ResizeObserver
- Update various views with cloud integration and UI refinements
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-04 23:05:01 +00:00
|
|
|
{ path: '/dashboard/cloud', label: 'Cloud', icon: 'cloud' },
|
2026-03-04 07:09:31 +00:00
|
|
|
{ path: '/dashboard/settings', label: 'Settings', icon: 'settings' },
|
2026-01-24 22:59:20 +00:00
|
|
|
]
|
|
|
|
|
|
2026-03-04 07:09:31 +00:00
|
|
|
const chatDesktopNav: NavItem[] = [
|
|
|
|
|
{ path: '/dashboard', label: 'Home', icon: 'home' },
|
|
|
|
|
{ path: '/dashboard/apps', label: 'My Apps', icon: 'apps' },
|
|
|
|
|
{ path: '/dashboard/settings', label: 'Settings', icon: 'settings' },
|
|
|
|
|
]
|
|
|
|
|
|
|
|
|
|
const desktopNavItems = computed(() => {
|
|
|
|
|
if (uiMode.isEasy) return easyDesktopNav
|
|
|
|
|
if (uiMode.isChat) return chatDesktopNav
|
|
|
|
|
return gamerDesktopNav
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
const gamerMobileNav: NavItem[] = [
|
|
|
|
|
{ path: '/dashboard', label: 'Home', icon: 'home' },
|
|
|
|
|
{ path: '/dashboard/apps', label: 'Apps', icon: 'apps', isCombined: true },
|
feat: v1.2.0-alpha — E2E encrypted mesh relay, steganography, relay status polling
Phase 5 mesh networking:
- E2E encrypted TX relay (X25519 + ChaCha20-Poly1305) — non-Archy nodes
relay encrypted blobs transparently via Meshcore native routing
- Steganographic encoding modes (WeatherStation, SensorNetwork) — traffic
looks like sensor data on the wire, 0xAA marker, configurable per-node
- Pre-flight Bitcoin Core health check on relay node — specific error codes
(bitcoin_unreachable, bitcoin_syncing, tx_rejected) instead of generic fails
- mesh.relay-status RPC endpoint — frontend polls for relay result every 3s
- On-Chain / Lightning tabs in Off-Grid Bitcoin panel
- Archy Peers vs Mesh Broadcast relay mode selector
- Mesh view fills viewport (no page scroll), internal panel scrolling
- Version bump to 1.2.0-alpha
Also includes: deploy hardening, container fixes, IndeedHub updates,
boot screen, dashboard improvements, MASTER_PLAN task tracking
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-17 23:56:37 +00:00
|
|
|
{ path: '/dashboard/web5', label: 'Web5', icon: 'web5', isCombined: true },
|
2026-03-04 07:09:31 +00:00
|
|
|
{ path: '/dashboard/settings', label: 'Settings', icon: 'settings' },
|
|
|
|
|
]
|
|
|
|
|
|
|
|
|
|
const easyMobileNav: NavItem[] = [
|
|
|
|
|
{ path: '/dashboard', label: 'Home', icon: 'home' },
|
feat: AIUI chat mode integration with iframe, context broker, overnight loop
- Chat mode: AIUI loads in sandboxed iframe at /dashboard/chat with transparent bg
- Mode switcher: Easy + Pro tabs only, Chat is a launcher button
- Keyboard shortcuts: Cmd+1 (Easy), Cmd+2 (Pro), Cmd+3 (Chat), Cmd+M (cycle)
- Directional transitions: chat slides from/to left, dashboard from/to right
- Context broker: postMessage protocol for quarantined AIUI communication
- AI permissions store: user-controlled toggles for data access categories
- Settings UI: AI Data Access section with per-category toggles
- AIUI container manifest and nginx proxy config for /aiui/
- Deploy script builds AIUI with /aiui/ base path
- Overnight loop infrastructure (loop.sh, prepare.sh, plan.md, prompt.md)
- Security hooks for autonomous overnight runs
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-04 12:06:20 +00:00
|
|
|
{ path: '/dashboard/apps', label: 'Apps', icon: 'apps' },
|
feat: cloud native file browser, settings Claude auth, deploy hardening
- Add native Cloud file browser with FileBrowser API integration
- Add cloud store, filebrowser-client, useAudioPlayer, useFileType composables
- Add Cloud components: FileGrid, FileCard, FileCardGrid, CloudToolbar
- Add Claude authentication section to Settings with OAuth status check
- Harden deploy script to preserve /aiui/ and claude-login.html
- Add nginx proxies for btcpay, homeassistant, filebrowser (HTTPS block)
- Add app configs for filebrowser, searxng, penpot in package.rs
- Update goal progress tracking with app aliases
- Improve mobile back button composable with ResizeObserver
- Update various views with cloud integration and UI refinements
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-04 23:05:01 +00:00
|
|
|
{ path: '/dashboard/cloud', label: 'Cloud', icon: 'cloud' },
|
2026-03-04 07:09:31 +00:00
|
|
|
{ path: '/dashboard/settings', label: 'Settings', icon: 'settings' },
|
|
|
|
|
]
|
|
|
|
|
|
|
|
|
|
const chatMobileNav: NavItem[] = [
|
|
|
|
|
{ path: '/dashboard', label: 'Home', icon: 'home' },
|
|
|
|
|
{ path: '/dashboard/apps', label: 'Apps', icon: 'apps' },
|
|
|
|
|
{ path: '/dashboard/settings', label: 'Settings', icon: 'settings' },
|
|
|
|
|
]
|
|
|
|
|
|
|
|
|
|
const mobileNavItems = computed(() => {
|
|
|
|
|
if (uiMode.isEasy) return easyMobileNav
|
|
|
|
|
if (uiMode.isChat) return chatMobileNav
|
|
|
|
|
return gamerMobileNav
|
|
|
|
|
})
|
|
|
|
|
|
2026-01-24 22:59:20 +00:00
|
|
|
function getIconPath(iconName: string): string[] {
|
|
|
|
|
const icons: Record<string, string[]> = {
|
|
|
|
|
home: ['M3 12l2-2m0 0l7-7 7 7M5 10v10a1 1 0 001 1h3m10-11l2 2m-2-2v10a1 1 0 01-1 1h-3m-6 0a1 1 0 001-1v-4a1 1 0 011-1h2a1 1 0 011 1v4a1 1 0 001 1m-6 0h6'],
|
|
|
|
|
apps: ['M4 6a2 2 0 012-2h2a2 2 0 012 2v2a2 2 0 01-2 2H6a2 2 0 01-2-2V6zM14 6a2 2 0 012-2h2a2 2 0 012 2v2a2 2 0 01-2 2h-2a2 2 0 01-2-2V6zM4 16a2 2 0 012-2h2a2 2 0 012 2v2a2 2 0 01-2 2H6a2 2 0 01-2-2v-2zM14 16a2 2 0 012-2h2a2 2 0 012 2v2a2 2 0 01-2 2h-2a2 2 0 01-2-2v-2z'],
|
|
|
|
|
marketplace: ['M16 11V7a4 4 0 00-8 0v4M5 9h14l1 12H4L5 9z'],
|
|
|
|
|
cloud: ['M3 15a4 4 0 004 4h9a5 5 0 10-.1-9.999 5.002 5.002 0 10-9.78 2.096A4.001 4.001 0 003 15z'],
|
|
|
|
|
server: ['M5 12h14M5 12a2 2 0 01-2-2V6a2 2 0 012-2h14a2 2 0 012 2v4a2 2 0 01-2 2M5 12a2 2 0 00-2 2v4a2 2 0 002 2h14a2 2 0 002-2v-4a2 2 0 00-2-2m-2-4h.01M17 16h.01'],
|
|
|
|
|
web5: ['M21 12a9 9 0 01-9 9m9-9a9 9 0 00-9-9m9 9H3m9 9a9 9 0 01-9-9m9 9c1.657 0 3-4.03 3-9s-1.343-9-3-9m0 18c-1.657 0-3-4.03-3-9s1.343-9 3-9m-9 9a9 9 0 019-9'],
|
2026-03-17 00:03:08 +00:00
|
|
|
mesh: ['M8.111 16.404a5.5 5.5 0 017.778 0M12 20h.01M5.636 13.636a9 9 0 0112.728 0M1.5 10.5a14 14 0 0121 0'],
|
2026-03-04 07:09:31 +00:00
|
|
|
chat: ['M8 12h.01M12 12h.01M16 12h.01M21 12c0 4.418-4.03 8-9 8a9.863 9.863 0 01-4.255-.949L3 20l1.395-3.72C3.512 15.042 3 13.574 3 12c0-4.418 4.03-8 9-8s9 3.582 9 8z'],
|
2026-01-24 22:59:20 +00:00
|
|
|
settings: [
|
|
|
|
|
'M10.325 4.317c.426-1.756 2.924-1.756 3.35 0a1.724 1.724 0 002.573 1.066c1.543-.94 3.31.826 2.37 2.37a1.724 1.724 0 001.065 2.572c1.756.426 1.756 2.924 0 3.35a1.724 1.724 0 00-1.066 2.573c.94 1.543-.826 3.31-2.37 2.37a1.724 1.724 0 00-2.572 1.065c-.426 1.756-2.924 1.756-3.35 0a1.724 1.724 0 00-2.573-1.066c-1.543.94-3.31-.826-2.37-2.37a1.724 1.724 0 00-1.065-2.572c-1.756-.426-1.756-2.924 0-3.35a1.724 1.724 0 001.066-2.573c-.94-1.543.826-3.31 2.37-2.37.996.608 2.296.07 2.572-1.065z',
|
|
|
|
|
'M15 12a3 3 0 11-6 0 3 3 0 016 0z',
|
|
|
|
|
],
|
|
|
|
|
}
|
|
|
|
|
return icons[iconName] || []
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
async function handleLogout() {
|
2026-03-01 17:53:18 +00:00
|
|
|
try {
|
|
|
|
|
await store.logout()
|
|
|
|
|
} catch {
|
|
|
|
|
/* proceed to login regardless */
|
|
|
|
|
}
|
|
|
|
|
router.push('/login').catch(() => {
|
|
|
|
|
window.location.href = '/login'
|
|
|
|
|
})
|
2026-01-24 22:59:20 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Track previous route for transition logic
|
|
|
|
|
let previousPath = ''
|
feat: v1.2.0-alpha — E2E encrypted mesh relay, steganography, relay status polling
Phase 5 mesh networking:
- E2E encrypted TX relay (X25519 + ChaCha20-Poly1305) — non-Archy nodes
relay encrypted blobs transparently via Meshcore native routing
- Steganographic encoding modes (WeatherStation, SensorNetwork) — traffic
looks like sensor data on the wire, 0xAA marker, configurable per-node
- Pre-flight Bitcoin Core health check on relay node — specific error codes
(bitcoin_unreachable, bitcoin_syncing, tx_rejected) instead of generic fails
- mesh.relay-status RPC endpoint — frontend polls for relay result every 3s
- On-Chain / Lightning tabs in Off-Grid Bitcoin panel
- Archy Peers vs Mesh Broadcast relay mode selector
- Mesh view fills viewport (no page scroll), internal panel scrolling
- Version bump to 1.2.0-alpha
Also includes: deploy hardening, container fixes, IndeedHub updates,
boot screen, dashboard improvements, MASTER_PLAN task tracking
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-17 23:56:37 +00:00
|
|
|
let previousTab = ''
|
2026-01-24 22:59:20 +00:00
|
|
|
|
|
|
|
|
// Tab order for vertical transitions
|
|
|
|
|
const tabOrder = [
|
|
|
|
|
'/dashboard',
|
|
|
|
|
'/dashboard/apps',
|
|
|
|
|
'/dashboard/marketplace',
|
|
|
|
|
'/dashboard/cloud',
|
2026-03-17 00:03:08 +00:00
|
|
|
'/dashboard/mesh',
|
2026-01-24 22:59:20 +00:00
|
|
|
'/dashboard/server',
|
|
|
|
|
'/dashboard/web5',
|
feat: AIUI chat mode integration with iframe, context broker, overnight loop
- Chat mode: AIUI loads in sandboxed iframe at /dashboard/chat with transparent bg
- Mode switcher: Easy + Pro tabs only, Chat is a launcher button
- Keyboard shortcuts: Cmd+1 (Easy), Cmd+2 (Pro), Cmd+3 (Chat), Cmd+M (cycle)
- Directional transitions: chat slides from/to left, dashboard from/to right
- Context broker: postMessage protocol for quarantined AIUI communication
- AI permissions store: user-controlled toggles for data access categories
- Settings UI: AI Data Access section with per-category toggles
- AIUI container manifest and nginx proxy config for /aiui/
- Deploy script builds AIUI with /aiui/ base path
- Overnight loop infrastructure (loop.sh, prepare.sh, plan.md, prompt.md)
- Security hooks for autonomous overnight runs
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-04 12:06:20 +00:00
|
|
|
'/dashboard/chat',
|
2026-01-24 22:59:20 +00:00
|
|
|
'/dashboard/settings'
|
|
|
|
|
]
|
|
|
|
|
|
|
|
|
|
// Determine transition direction based on route depth
|
2026-03-11 13:04:31 +00:00
|
|
|
function getTransitionName(currentRoute: RouteLocationNormalizedLoaded) {
|
2026-01-24 22:59:20 +00:00
|
|
|
const currentPath = currentRoute.path
|
|
|
|
|
|
|
|
|
|
// If no previous path, use fade transition for initial load
|
|
|
|
|
if (!previousPath) {
|
|
|
|
|
previousPath = currentPath
|
|
|
|
|
return 'fade'
|
|
|
|
|
}
|
feat: AIUI chat mode integration with iframe, context broker, overnight loop
- Chat mode: AIUI loads in sandboxed iframe at /dashboard/chat with transparent bg
- Mode switcher: Easy + Pro tabs only, Chat is a launcher button
- Keyboard shortcuts: Cmd+1 (Easy), Cmd+2 (Pro), Cmd+3 (Chat), Cmd+M (cycle)
- Directional transitions: chat slides from/to left, dashboard from/to right
- Context broker: postMessage protocol for quarantined AIUI communication
- AI permissions store: user-controlled toggles for data access categories
- Settings UI: AI Data Access section with per-category toggles
- AIUI container manifest and nginx proxy config for /aiui/
- Deploy script builds AIUI with /aiui/ base path
- Overnight loop infrastructure (loop.sh, prepare.sh, plan.md, prompt.md)
- Security hooks for autonomous overnight runs
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-04 12:06:20 +00:00
|
|
|
|
|
|
|
|
// Chat transitions: directional slide (chat from/to left, dashboard from/to right)
|
|
|
|
|
const isChat = currentPath === '/dashboard/chat'
|
|
|
|
|
const wasChat = previousPath === '/dashboard/chat'
|
|
|
|
|
if (isChat) {
|
|
|
|
|
previousPath = currentPath
|
|
|
|
|
return 'chat-open'
|
|
|
|
|
}
|
|
|
|
|
if (wasChat) {
|
|
|
|
|
previousPath = currentPath
|
|
|
|
|
return 'chat-close'
|
|
|
|
|
}
|
2026-01-24 22:59:20 +00:00
|
|
|
|
|
|
|
|
const isAppDetails = currentPath.includes('/apps/') && !currentPath.endsWith('/apps')
|
|
|
|
|
const isAppsList = currentPath === '/dashboard/apps'
|
|
|
|
|
const wasAppDetails = previousPath.includes('/apps/') && !previousPath.endsWith('/apps')
|
|
|
|
|
const wasAppsList = previousPath === '/dashboard/apps'
|
|
|
|
|
|
|
|
|
|
// Marketplace detail transitions
|
|
|
|
|
const isMarketplaceDetails = currentPath.includes('/marketplace/') && !currentPath.endsWith('/marketplace')
|
|
|
|
|
const isMarketplaceList = currentPath === '/dashboard/marketplace'
|
|
|
|
|
const wasMarketplaceDetails = previousPath.includes('/marketplace/') && !previousPath.endsWith('/marketplace')
|
|
|
|
|
const wasMarketplaceList = previousPath === '/dashboard/marketplace'
|
|
|
|
|
|
|
|
|
|
// Cloud folder transitions
|
|
|
|
|
const isCloudFolder = currentPath.includes('/cloud/') && !currentPath.endsWith('/cloud')
|
|
|
|
|
const isCloudList = currentPath === '/dashboard/cloud'
|
|
|
|
|
const wasCloudFolder = previousPath.includes('/cloud/') && !previousPath.endsWith('/cloud')
|
|
|
|
|
const wasCloudList = previousPath === '/dashboard/cloud'
|
|
|
|
|
|
|
|
|
|
let transitionName = 'fade'
|
|
|
|
|
|
feat: v1.2.0-alpha — E2E encrypted mesh relay, steganography, relay status polling
Phase 5 mesh networking:
- E2E encrypted TX relay (X25519 + ChaCha20-Poly1305) — non-Archy nodes
relay encrypted blobs transparently via Meshcore native routing
- Steganographic encoding modes (WeatherStation, SensorNetwork) — traffic
looks like sensor data on the wire, 0xAA marker, configurable per-node
- Pre-flight Bitcoin Core health check on relay node — specific error codes
(bitcoin_unreachable, bitcoin_syncing, tx_rejected) instead of generic fails
- mesh.relay-status RPC endpoint — frontend polls for relay result every 3s
- On-Chain / Lightning tabs in Off-Grid Bitcoin panel
- Archy Peers vs Mesh Broadcast relay mode selector
- Mesh view fills viewport (no page scroll), internal panel scrolling
- Version bump to 1.2.0-alpha
Also includes: deploy hardening, container fixes, IndeedHub updates,
boot screen, dashboard improvements, MASTER_PLAN task tracking
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-17 23:56:37 +00:00
|
|
|
// Mobile: Horizontal slide transitions between sub-tabs
|
2026-01-24 22:59:20 +00:00
|
|
|
if (typeof window !== 'undefined' && window.innerWidth < 768) {
|
feat: v1.2.0-alpha — E2E encrypted mesh relay, steganography, relay status polling
Phase 5 mesh networking:
- E2E encrypted TX relay (X25519 + ChaCha20-Poly1305) — non-Archy nodes
relay encrypted blobs transparently via Meshcore native routing
- Steganographic encoding modes (WeatherStation, SensorNetwork) — traffic
looks like sensor data on the wire, 0xAA marker, configurable per-node
- Pre-flight Bitcoin Core health check on relay node — specific error codes
(bitcoin_unreachable, bitcoin_syncing, tx_rejected) instead of generic fails
- mesh.relay-status RPC endpoint — frontend polls for relay result every 3s
- On-Chain / Lightning tabs in Off-Grid Bitcoin panel
- Archy Peers vs Mesh Broadcast relay mode selector
- Mesh view fills viewport (no page scroll), internal panel scrolling
- Version bump to 1.2.0-alpha
Also includes: deploy hardening, container fixes, IndeedHub updates,
boot screen, dashboard improvements, MASTER_PLAN task tracking
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-17 23:56:37 +00:00
|
|
|
// Apps group: My Apps (0) → App Store (1) → Services (2)
|
|
|
|
|
const isServices = currentPath === '/dashboard/apps' && currentRoute.query.tab === 'services'
|
|
|
|
|
const wasServices = previousTab === 'services'
|
|
|
|
|
const currentAppsIdx = isServices ? 2
|
|
|
|
|
: currentPath === '/dashboard/marketplace' ? 1
|
|
|
|
|
: currentPath === '/dashboard/apps' ? 0 : -1
|
|
|
|
|
const prevAppsIdx = wasServices ? 2
|
|
|
|
|
: previousPath === '/dashboard/marketplace' ? 1
|
|
|
|
|
: previousPath === '/dashboard/apps' ? 0 : -1
|
|
|
|
|
|
|
|
|
|
// Web5 group: Web5 (0) → Cloud (1) → Network (2) → Mesh (3)
|
|
|
|
|
const web5TabOrder = ['/dashboard/web5', '/dashboard/cloud', '/dashboard/server', '/dashboard/mesh']
|
|
|
|
|
const currentWeb5Idx = web5TabOrder.indexOf(currentPath)
|
|
|
|
|
const prevWeb5Idx = web5TabOrder.indexOf(previousPath)
|
|
|
|
|
|
|
|
|
|
// Apps sub-tab transitions
|
|
|
|
|
if (currentAppsIdx !== -1 && prevAppsIdx !== -1 && currentAppsIdx !== prevAppsIdx) {
|
|
|
|
|
transitionName = currentAppsIdx > prevAppsIdx ? 'slide-left' : 'slide-right'
|
2026-01-24 22:59:20 +00:00
|
|
|
}
|
feat: v1.2.0-alpha — E2E encrypted mesh relay, steganography, relay status polling
Phase 5 mesh networking:
- E2E encrypted TX relay (X25519 + ChaCha20-Poly1305) — non-Archy nodes
relay encrypted blobs transparently via Meshcore native routing
- Steganographic encoding modes (WeatherStation, SensorNetwork) — traffic
looks like sensor data on the wire, 0xAA marker, configurable per-node
- Pre-flight Bitcoin Core health check on relay node — specific error codes
(bitcoin_unreachable, bitcoin_syncing, tx_rejected) instead of generic fails
- mesh.relay-status RPC endpoint — frontend polls for relay result every 3s
- On-Chain / Lightning tabs in Off-Grid Bitcoin panel
- Archy Peers vs Mesh Broadcast relay mode selector
- Mesh view fills viewport (no page scroll), internal panel scrolling
- Version bump to 1.2.0-alpha
Also includes: deploy hardening, container fixes, IndeedHub updates,
boot screen, dashboard improvements, MASTER_PLAN task tracking
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-17 23:56:37 +00:00
|
|
|
// Web5 sub-tab transitions
|
|
|
|
|
else if (currentWeb5Idx !== -1 && prevWeb5Idx !== -1 && currentWeb5Idx !== prevWeb5Idx) {
|
|
|
|
|
transitionName = currentWeb5Idx > prevWeb5Idx ? 'slide-left' : 'slide-right'
|
2026-01-24 22:59:20 +00:00
|
|
|
}
|
feat: v1.2.0-alpha — E2E encrypted mesh relay, steganography, relay status polling
Phase 5 mesh networking:
- E2E encrypted TX relay (X25519 + ChaCha20-Poly1305) — non-Archy nodes
relay encrypted blobs transparently via Meshcore native routing
- Steganographic encoding modes (WeatherStation, SensorNetwork) — traffic
looks like sensor data on the wire, 0xAA marker, configurable per-node
- Pre-flight Bitcoin Core health check on relay node — specific error codes
(bitcoin_unreachable, bitcoin_syncing, tx_rejected) instead of generic fails
- mesh.relay-status RPC endpoint — frontend polls for relay result every 3s
- On-Chain / Lightning tabs in Off-Grid Bitcoin panel
- Archy Peers vs Mesh Broadcast relay mode selector
- Mesh view fills viewport (no page scroll), internal panel scrolling
- Version bump to 1.2.0-alpha
Also includes: deploy hardening, container fixes, IndeedHub updates,
boot screen, dashboard improvements, MASTER_PLAN task tracking
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-17 23:56:37 +00:00
|
|
|
// Vertical transition: between main bottom nav tabs
|
2026-01-24 22:59:20 +00:00
|
|
|
else {
|
|
|
|
|
const currentIndex = tabOrder.indexOf(currentPath)
|
|
|
|
|
const previousIndex = tabOrder.indexOf(previousPath)
|
feat: v1.2.0-alpha — E2E encrypted mesh relay, steganography, relay status polling
Phase 5 mesh networking:
- E2E encrypted TX relay (X25519 + ChaCha20-Poly1305) — non-Archy nodes
relay encrypted blobs transparently via Meshcore native routing
- Steganographic encoding modes (WeatherStation, SensorNetwork) — traffic
looks like sensor data on the wire, 0xAA marker, configurable per-node
- Pre-flight Bitcoin Core health check on relay node — specific error codes
(bitcoin_unreachable, bitcoin_syncing, tx_rejected) instead of generic fails
- mesh.relay-status RPC endpoint — frontend polls for relay result every 3s
- On-Chain / Lightning tabs in Off-Grid Bitcoin panel
- Archy Peers vs Mesh Broadcast relay mode selector
- Mesh view fills viewport (no page scroll), internal panel scrolling
- Version bump to 1.2.0-alpha
Also includes: deploy hardening, container fixes, IndeedHub updates,
boot screen, dashboard improvements, MASTER_PLAN task tracking
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-17 23:56:37 +00:00
|
|
|
|
2026-01-24 22:59:20 +00:00
|
|
|
if (currentIndex !== -1 && previousIndex !== -1 && currentIndex !== previousIndex) {
|
feat: v1.2.0-alpha — E2E encrypted mesh relay, steganography, relay status polling
Phase 5 mesh networking:
- E2E encrypted TX relay (X25519 + ChaCha20-Poly1305) — non-Archy nodes
relay encrypted blobs transparently via Meshcore native routing
- Steganographic encoding modes (WeatherStation, SensorNetwork) — traffic
looks like sensor data on the wire, 0xAA marker, configurable per-node
- Pre-flight Bitcoin Core health check on relay node — specific error codes
(bitcoin_unreachable, bitcoin_syncing, tx_rejected) instead of generic fails
- mesh.relay-status RPC endpoint — frontend polls for relay result every 3s
- On-Chain / Lightning tabs in Off-Grid Bitcoin panel
- Archy Peers vs Mesh Broadcast relay mode selector
- Mesh view fills viewport (no page scroll), internal panel scrolling
- Version bump to 1.2.0-alpha
Also includes: deploy hardening, container fixes, IndeedHub updates,
boot screen, dashboard improvements, MASTER_PLAN task tracking
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-17 23:56:37 +00:00
|
|
|
transitionName = currentIndex > previousIndex ? 'slide-down' : 'slide-up'
|
2026-01-24 22:59:20 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
// Horizontal depth transition: apps list <-> app details
|
|
|
|
|
else if (wasAppsList && isAppDetails) {
|
|
|
|
|
transitionName = 'depth-forward'
|
|
|
|
|
} else if (wasAppDetails && isAppsList) {
|
|
|
|
|
transitionName = 'depth-back'
|
|
|
|
|
}
|
|
|
|
|
// Horizontal depth transition: marketplace list <-> marketplace details
|
|
|
|
|
else if (wasMarketplaceList && isMarketplaceDetails) {
|
|
|
|
|
transitionName = 'depth-forward'
|
|
|
|
|
} else if (wasMarketplaceDetails && isMarketplaceList) {
|
|
|
|
|
transitionName = 'depth-back'
|
|
|
|
|
}
|
|
|
|
|
// Horizontal depth transition: cloud list <-> cloud folder
|
|
|
|
|
else if (wasCloudList && isCloudFolder) {
|
|
|
|
|
transitionName = 'depth-forward'
|
|
|
|
|
} else if (wasCloudFolder && isCloudList) {
|
|
|
|
|
transitionName = 'depth-back'
|
|
|
|
|
}
|
|
|
|
|
// Horizontal depth transition: marketplace list <-> installed app details
|
|
|
|
|
// (when clicking installed app from marketplace)
|
|
|
|
|
else if (wasMarketplaceList && isAppDetails) {
|
|
|
|
|
transitionName = 'depth-forward'
|
|
|
|
|
} else if (wasAppDetails && isMarketplaceList) {
|
|
|
|
|
transitionName = 'depth-back'
|
|
|
|
|
}
|
2026-03-14 17:12:41 +00:00
|
|
|
// Desktop: no transition between Apps ↔ Marketplace (same-page tab feel)
|
|
|
|
|
else if ((wasAppsList && isMarketplaceList) || (wasMarketplaceList && isAppsList)) {
|
|
|
|
|
transitionName = 'fade'
|
|
|
|
|
}
|
2026-01-24 22:59:20 +00:00
|
|
|
// Vertical transition: between main tabs (desktop)
|
|
|
|
|
else {
|
|
|
|
|
const currentIndex = tabOrder.indexOf(currentPath)
|
|
|
|
|
const previousIndex = tabOrder.indexOf(previousPath)
|
|
|
|
|
|
|
|
|
|
if (currentIndex !== -1 && previousIndex !== -1 && currentIndex !== previousIndex) {
|
|
|
|
|
// Moving down the menu (visual down)
|
|
|
|
|
if (currentIndex > previousIndex) {
|
|
|
|
|
transitionName = 'slide-down'
|
|
|
|
|
}
|
|
|
|
|
// Moving up the menu (visual up)
|
|
|
|
|
else {
|
|
|
|
|
transitionName = 'slide-up'
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Update previous path for next transition
|
|
|
|
|
previousPath = currentPath
|
feat: v1.2.0-alpha — E2E encrypted mesh relay, steganography, relay status polling
Phase 5 mesh networking:
- E2E encrypted TX relay (X25519 + ChaCha20-Poly1305) — non-Archy nodes
relay encrypted blobs transparently via Meshcore native routing
- Steganographic encoding modes (WeatherStation, SensorNetwork) — traffic
looks like sensor data on the wire, 0xAA marker, configurable per-node
- Pre-flight Bitcoin Core health check on relay node — specific error codes
(bitcoin_unreachable, bitcoin_syncing, tx_rejected) instead of generic fails
- mesh.relay-status RPC endpoint — frontend polls for relay result every 3s
- On-Chain / Lightning tabs in Off-Grid Bitcoin panel
- Archy Peers vs Mesh Broadcast relay mode selector
- Mesh view fills viewport (no page scroll), internal panel scrolling
- Version bump to 1.2.0-alpha
Also includes: deploy hardening, container fixes, IndeedHub updates,
boot screen, dashboard improvements, MASTER_PLAN task tracking
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-17 23:56:37 +00:00
|
|
|
previousTab = (currentRoute.query.tab as string) || ''
|
2026-03-11 13:04:31 +00:00
|
|
|
|
2026-01-24 22:59:20 +00:00
|
|
|
return transitionName
|
|
|
|
|
}
|
2026-03-11 13:04:31 +00:00
|
|
|
|
2026-03-14 04:14:04 +00:00
|
|
|
// Health notifications from WebSocket data — deduplicated by container name
|
2026-03-11 13:04:31 +00:00
|
|
|
const dismissedNotifications = ref<Set<string>>(new Set())
|
|
|
|
|
|
|
|
|
|
const healthNotifications = computed(() => {
|
|
|
|
|
const notifs = store.data?.notifications ?? []
|
2026-03-14 04:14:04 +00:00
|
|
|
const visible = notifs.filter(n => !dismissedNotifications.value.has(n.id))
|
|
|
|
|
// Deduplicate: keep only the latest notification per container/title
|
|
|
|
|
const seen = new Map<string, typeof visible[0]>()
|
|
|
|
|
for (const n of visible) {
|
|
|
|
|
seen.set(n.title, n)
|
|
|
|
|
}
|
|
|
|
|
return [...seen.values()].slice(-3)
|
2026-03-11 13:04:31 +00:00
|
|
|
})
|
|
|
|
|
|
|
|
|
|
function dismissNotification(id: string) {
|
2026-03-14 04:14:04 +00:00
|
|
|
// Dismiss all notifications with the same title (container name)
|
|
|
|
|
const notif = (store.data?.notifications ?? []).find(n => n.id === id)
|
|
|
|
|
if (notif) {
|
|
|
|
|
for (const n of store.data?.notifications ?? []) {
|
|
|
|
|
if (n.title === notif.title) dismissedNotifications.value.add(n.id)
|
|
|
|
|
}
|
|
|
|
|
}
|
2026-03-11 13:04:31 +00:00
|
|
|
dismissedNotifications.value.add(id)
|
|
|
|
|
}
|
2026-01-24 22:59:20 +00:00
|
|
|
</script>
|
|
|
|
|
|
|
|
|
|
<style>
|
2026-02-17 19:19:54 +00:00
|
|
|
/* 2advanced-style: fluid, cinematic, layered motion */
|
|
|
|
|
/* Strong easeInOut - smooth acceleration/deceleration, no bounce */
|
|
|
|
|
|
|
|
|
|
/* Background - zoom in from depth with motion blur */
|
|
|
|
|
.zoom-reveal-bg {
|
|
|
|
|
animation: zoom-reveal 2.8s cubic-bezier(0.25, 0.46, 0.45, 0.94) forwards;
|
|
|
|
|
transform-origin: center center;
|
|
|
|
|
opacity: 0;
|
|
|
|
|
transform: scale(0.15);
|
|
|
|
|
filter: blur(24px);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@keyframes zoom-reveal {
|
|
|
|
|
0% {
|
|
|
|
|
opacity: 0;
|
|
|
|
|
transform: scale(0.15);
|
|
|
|
|
filter: blur(24px);
|
|
|
|
|
}
|
|
|
|
|
35% {
|
|
|
|
|
opacity: 0.5;
|
|
|
|
|
transform: scale(0.5);
|
|
|
|
|
filter: blur(20px);
|
|
|
|
|
}
|
|
|
|
|
65% {
|
|
|
|
|
opacity: 0.85;
|
|
|
|
|
transform: scale(0.88);
|
|
|
|
|
filter: blur(6px);
|
|
|
|
|
}
|
|
|
|
|
100% {
|
|
|
|
|
opacity: 1;
|
|
|
|
|
transform: scale(1);
|
|
|
|
|
filter: blur(0);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* 2advanced-style glass assembly - fluid, layered, deliberate timing */
|
|
|
|
|
.glass-throw-active {
|
|
|
|
|
perspective: 1400px;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.glass-piece {
|
|
|
|
|
will-change: transform, opacity;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Sidebar - animates in at end with separate parts (like cards) */
|
|
|
|
|
.sidebar-shell {
|
|
|
|
|
width: 100%;
|
|
|
|
|
height: 100%;
|
|
|
|
|
min-height: 100vh;
|
|
|
|
|
background: rgba(0, 0, 0, 0.25);
|
|
|
|
|
backdrop-filter: blur(18px);
|
|
|
|
|
-webkit-backdrop-filter: blur(18px);
|
|
|
|
|
border-right: 1px solid transparent;
|
|
|
|
|
box-shadow: 4px 0 24px rgba(0, 0, 0, 0.3);
|
|
|
|
|
overflow: hidden;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.sidebar-animate .sidebar-shell {
|
|
|
|
|
animation: sidebar-shell-fly 1.2s cubic-bezier(0.25, 0.46, 0.45, 0.94) forwards;
|
|
|
|
|
animation-delay: 5.2s;
|
|
|
|
|
opacity: 0;
|
|
|
|
|
transform: translateX(-100%);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@keyframes sidebar-shell-fly {
|
|
|
|
|
0% {
|
|
|
|
|
opacity: 0;
|
|
|
|
|
transform: translateX(-100%);
|
|
|
|
|
border-color: transparent;
|
|
|
|
|
}
|
|
|
|
|
70% {
|
|
|
|
|
opacity: 1;
|
|
|
|
|
transform: translateX(0);
|
|
|
|
|
border-color: transparent;
|
|
|
|
|
}
|
|
|
|
|
100% {
|
|
|
|
|
opacity: 1;
|
|
|
|
|
transform: translateX(0);
|
|
|
|
|
border-color: rgba(255, 255, 255, 0.18);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.sidebar-inner {
|
|
|
|
|
overflow: hidden;
|
|
|
|
|
}
|
|
|
|
|
|
feat: rootless podman, session hardening, boot stability, sidebar fix
Rootless podman migration (TASK-11):
- Remove sudo from all podman calls in PodmanClient + 8 backend files
- Remove sudo from all podman/docker calls in deploy script
- Restore full systemd security hardening: NoNewPrivileges,
RestrictAddressFamilies, MemoryDenyWriteExecute, RestrictRealtime,
RestrictNamespaces, RestrictSUIDSGID, SystemCallFilter, ProtectSystem=strict
- Enable loginctl linger for rootless container persistence
- Remove Ollama from auto-deploy (marketplace-only)
Session & auth hardening:
- Increase MAX_CONCURRENT_SESSIONS 20→50 (prevents eviction storms)
- Debounced 401 redirect in rpc-client.ts (prevents redirect storms)
Boot stability:
- optimize-debian.sh: adds chrony, swap, removes policy-rc.d
- deploy script: pre-restart chrony + swap setup
- ISO build: chrony package, swap file creation
- BootScreen: no longer clears localStorage (prevents splash replay)
- RootRedirect: sole owner of localStorage clearing on server ready
UI fixes:
- Sidebar opacity default changed from 0→visible (fixes missing sidebar
after page-persistence login without entrance animation)
- Console.log/error wrapped in import.meta.env.DEV guards
- Remove unused route import from RootRedirect
Beta tracking:
- CLAUDE.md: beta freeze protocol added
- MASTER_PLAN.md: TASK-11, TASK-17, phase structure
- BETA-PROGRESS.md: initial tracking doc
- Tagged v1.2.0-alpha.1 as pre-rootless baseline
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-18 13:53:27 +00:00
|
|
|
/* Only hide sidebar content when doing the login entrance animation */
|
2026-02-17 19:19:54 +00:00
|
|
|
.sidebar-animate .sidebar-inner {
|
feat: rootless podman, session hardening, boot stability, sidebar fix
Rootless podman migration (TASK-11):
- Remove sudo from all podman calls in PodmanClient + 8 backend files
- Remove sudo from all podman/docker calls in deploy script
- Restore full systemd security hardening: NoNewPrivileges,
RestrictAddressFamilies, MemoryDenyWriteExecute, RestrictRealtime,
RestrictNamespaces, RestrictSUIDSGID, SystemCallFilter, ProtectSystem=strict
- Enable loginctl linger for rootless container persistence
- Remove Ollama from auto-deploy (marketplace-only)
Session & auth hardening:
- Increase MAX_CONCURRENT_SESSIONS 20→50 (prevents eviction storms)
- Debounced 401 redirect in rpc-client.ts (prevents redirect storms)
Boot stability:
- optimize-debian.sh: adds chrony, swap, removes policy-rc.d
- deploy script: pre-restart chrony + swap setup
- ISO build: chrony package, swap file creation
- BootScreen: no longer clears localStorage (prevents splash replay)
- RootRedirect: sole owner of localStorage clearing on server ready
UI fixes:
- Sidebar opacity default changed from 0→visible (fixes missing sidebar
after page-persistence login without entrance animation)
- Console.log/error wrapped in import.meta.env.DEV guards
- Remove unused route import from RootRedirect
Beta tracking:
- CLAUDE.md: beta freeze protocol added
- MASTER_PLAN.md: TASK-11, TASK-17, phase structure
- BETA-PROGRESS.md: initial tracking doc
- Tagged v1.2.0-alpha.1 as pre-rootless baseline
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-18 13:53:27 +00:00
|
|
|
opacity: 0;
|
2026-02-17 19:19:54 +00:00
|
|
|
animation: sidebar-inner-draw 0.7s cubic-bezier(0.25, 0.46, 0.45, 0.94) forwards;
|
|
|
|
|
animation-delay: 6.1s;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@keyframes sidebar-inner-draw {
|
|
|
|
|
0% {
|
|
|
|
|
opacity: 0;
|
|
|
|
|
clip-path: inset(0 100% 0 0);
|
|
|
|
|
}
|
|
|
|
|
20% { opacity: 1; }
|
|
|
|
|
100% {
|
|
|
|
|
opacity: 1;
|
|
|
|
|
clip-path: inset(0 0 0 0);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.sidebar-nav-item {
|
|
|
|
|
opacity: 0;
|
|
|
|
|
transform: translateX(-12px);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.sidebar-animate .sidebar-nav-item {
|
|
|
|
|
animation: sidebar-nav-item-in 0.4s cubic-bezier(0.25, 0.46, 0.45, 0.94) forwards;
|
|
|
|
|
animation-delay: calc(6.3s + var(--nav-stagger, 0) * 0.06s);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@keyframes sidebar-nav-item-in {
|
|
|
|
|
0% {
|
|
|
|
|
opacity: 0;
|
|
|
|
|
transform: translateX(-12px);
|
|
|
|
|
}
|
|
|
|
|
100% {
|
|
|
|
|
opacity: 1;
|
|
|
|
|
transform: translateX(0);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.sidebar-controller {
|
|
|
|
|
opacity: 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.sidebar-animate .sidebar-controller {
|
|
|
|
|
animation: sidebar-fade-in 0.4s ease-out forwards;
|
|
|
|
|
animation-delay: 6.9s;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.sidebar-logout-btn {
|
|
|
|
|
opacity: 0;
|
|
|
|
|
transform: scale(0.95);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.sidebar-animate .sidebar-logout-btn {
|
|
|
|
|
animation: sidebar-logout-pop 0.45s cubic-bezier(0.34, 1.56, 0.64, 1) forwards;
|
|
|
|
|
animation-delay: 7.1s;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@keyframes sidebar-fade-in {
|
|
|
|
|
0% { opacity: 0; }
|
|
|
|
|
100% { opacity: 1; }
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@keyframes sidebar-logout-pop {
|
|
|
|
|
0% {
|
|
|
|
|
opacity: 0;
|
|
|
|
|
transform: scale(0.95);
|
|
|
|
|
}
|
|
|
|
|
100% {
|
|
|
|
|
opacity: 1;
|
|
|
|
|
transform: scale(1);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.sidebar-logo {
|
|
|
|
|
opacity: 0;
|
|
|
|
|
transform: translateY(-8px);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.sidebar-animate .sidebar-logo {
|
|
|
|
|
animation: sidebar-logo-in 0.5s cubic-bezier(0.25, 0.46, 0.45, 0.94) forwards;
|
|
|
|
|
animation-delay: 6.15s;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@keyframes sidebar-logo-in {
|
|
|
|
|
0% {
|
|
|
|
|
opacity: 0;
|
|
|
|
|
transform: translateY(-8px);
|
|
|
|
|
}
|
|
|
|
|
100% {
|
|
|
|
|
opacity: 1;
|
|
|
|
|
transform: translateY(0);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2026-02-17 19:42:59 +00:00
|
|
|
/* When not animating, show everything (direct load / hard refresh) */
|
2026-02-17 19:19:54 +00:00
|
|
|
aside:not(.sidebar-animate) .sidebar-shell {
|
|
|
|
|
border-color: rgba(255, 255, 255, 0.18);
|
2026-02-17 19:42:59 +00:00
|
|
|
opacity: 1;
|
|
|
|
|
transform: none;
|
2026-02-17 19:19:54 +00:00
|
|
|
}
|
|
|
|
|
aside:not(.sidebar-animate) .sidebar-inner,
|
|
|
|
|
aside:not(.sidebar-animate) .sidebar-logo,
|
|
|
|
|
aside:not(.sidebar-animate) .sidebar-nav-item,
|
|
|
|
|
aside:not(.sidebar-animate) .sidebar-controller,
|
|
|
|
|
aside:not(.sidebar-animate) .sidebar-logout-btn {
|
|
|
|
|
opacity: 1;
|
|
|
|
|
transform: none;
|
|
|
|
|
animation: none;
|
|
|
|
|
clip-path: none;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Smooth easeInOut - no overshoot, refined deceleration */
|
|
|
|
|
|
|
|
|
|
.glass-throw-main {
|
|
|
|
|
animation: glass-throw-main 1.6s cubic-bezier(0.25, 0.46, 0.45, 0.94) 0.15s forwards;
|
|
|
|
|
opacity: 0;
|
|
|
|
|
transform: translateX(20%) scale(0.2);
|
|
|
|
|
filter: blur(14px);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.glass-throw-content {
|
|
|
|
|
animation: glass-throw-content 1.5s cubic-bezier(0.25, 0.46, 0.45, 0.94) 0.22s forwards;
|
|
|
|
|
opacity: 0;
|
|
|
|
|
transform: translateY(12%) scale(0.25);
|
|
|
|
|
filter: blur(10px);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.glass-throw-mobile-tabs {
|
|
|
|
|
animation: glass-throw-top 1.3s cubic-bezier(0.25, 0.46, 0.45, 0.94) 0.08s forwards;
|
|
|
|
|
opacity: 0;
|
|
|
|
|
transform: translateY(-90%) scale(0.28);
|
|
|
|
|
filter: blur(10px);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.glass-throw-mobile-tabs-2 {
|
|
|
|
|
animation: glass-throw-top 1.35s cubic-bezier(0.25, 0.46, 0.45, 0.94) 0.18s forwards;
|
|
|
|
|
opacity: 0;
|
|
|
|
|
transform: translateY(-90%) scale(0.28);
|
|
|
|
|
filter: blur(10px);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.glass-throw-tabbar {
|
|
|
|
|
animation: glass-throw-bottom 1.4s cubic-bezier(0.25, 0.46, 0.45, 0.94) 0.2s forwards;
|
|
|
|
|
opacity: 0;
|
|
|
|
|
transform: translateY(85%) scale(0.25);
|
|
|
|
|
filter: blur(10px);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Motion blur peaks mid-transition, smooth settle */
|
|
|
|
|
@keyframes glass-throw-sidebar {
|
|
|
|
|
0% {
|
|
|
|
|
opacity: 0;
|
|
|
|
|
transform: translateX(-100%) scale(0.25);
|
|
|
|
|
filter: blur(12px);
|
|
|
|
|
}
|
|
|
|
|
45% {
|
|
|
|
|
opacity: 0.9;
|
|
|
|
|
transform: translateX(-15%) scale(0.85);
|
|
|
|
|
filter: blur(8px);
|
|
|
|
|
}
|
|
|
|
|
100% {
|
|
|
|
|
opacity: 1;
|
|
|
|
|
transform: translateX(0) scale(1);
|
|
|
|
|
filter: blur(0);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@keyframes glass-throw-main {
|
|
|
|
|
0% {
|
|
|
|
|
opacity: 0;
|
|
|
|
|
transform: translateX(20%) scale(0.2);
|
|
|
|
|
filter: blur(14px);
|
|
|
|
|
}
|
|
|
|
|
50% {
|
|
|
|
|
opacity: 0.85;
|
|
|
|
|
transform: translateX(0) scale(0.9);
|
|
|
|
|
filter: blur(6px);
|
|
|
|
|
}
|
|
|
|
|
100% {
|
|
|
|
|
opacity: 1;
|
|
|
|
|
transform: translateX(0) scale(1);
|
|
|
|
|
filter: blur(0);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@keyframes glass-throw-content {
|
|
|
|
|
0% {
|
|
|
|
|
opacity: 0;
|
|
|
|
|
transform: translateY(12%) scale(0.25);
|
|
|
|
|
filter: blur(10px);
|
|
|
|
|
}
|
|
|
|
|
50% {
|
|
|
|
|
opacity: 0.9;
|
|
|
|
|
transform: translateY(0) scale(0.9);
|
|
|
|
|
filter: blur(4px);
|
|
|
|
|
}
|
|
|
|
|
100% {
|
|
|
|
|
opacity: 1;
|
|
|
|
|
transform: translateY(0) scale(1);
|
|
|
|
|
filter: blur(0);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@keyframes glass-throw-top {
|
|
|
|
|
0% {
|
|
|
|
|
opacity: 0;
|
|
|
|
|
transform: translateY(-90%) scale(0.28);
|
|
|
|
|
filter: blur(10px);
|
|
|
|
|
}
|
|
|
|
|
50% {
|
|
|
|
|
opacity: 0.9;
|
|
|
|
|
transform: translateY(0) scale(0.95);
|
|
|
|
|
filter: blur(4px);
|
|
|
|
|
}
|
|
|
|
|
100% {
|
|
|
|
|
opacity: 1;
|
|
|
|
|
transform: translateY(0) scale(1);
|
|
|
|
|
filter: blur(0);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@keyframes glass-throw-bottom {
|
|
|
|
|
0% {
|
|
|
|
|
opacity: 0;
|
|
|
|
|
transform: translateY(85%) scale(0.25);
|
|
|
|
|
filter: blur(10px);
|
|
|
|
|
}
|
|
|
|
|
50% {
|
|
|
|
|
opacity: 0.9;
|
|
|
|
|
transform: translateY(0) scale(0.95);
|
|
|
|
|
filter: blur(4px);
|
|
|
|
|
}
|
|
|
|
|
100% {
|
|
|
|
|
opacity: 1;
|
|
|
|
|
transform: translateY(0) scale(1);
|
|
|
|
|
filter: blur(0);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Oomph accent - subtle 2advanced-style flash synced with boot thud */
|
|
|
|
|
.oomph-flash {
|
|
|
|
|
background: radial-gradient(ellipse at center, rgba(255, 255, 255, 0.08) 0%, transparent 65%);
|
|
|
|
|
animation: oomph-flash 0.7s cubic-bezier(0.25, 0.46, 0.45, 0.94) forwards;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@keyframes oomph-flash {
|
|
|
|
|
0% { opacity: 0; }
|
|
|
|
|
25% { opacity: 0.9; }
|
|
|
|
|
100% { opacity: 0; }
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Reveal flashes - enthralling entrance during zoom */
|
|
|
|
|
.reveal-flash-glitch {
|
|
|
|
|
background: radial-gradient(ellipse at center, rgba(255, 255, 255, 0.12) 0%, transparent 70%);
|
|
|
|
|
animation: reveal-flash-sequence 2.8s ease-out forwards;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@keyframes reveal-flash-sequence {
|
|
|
|
|
0% { opacity: 0; }
|
|
|
|
|
12% { opacity: 0.6; }
|
|
|
|
|
18% { opacity: 0; }
|
|
|
|
|
42% { opacity: 0.4; }
|
|
|
|
|
48% { opacity: 0; }
|
|
|
|
|
70% { opacity: 0.35; }
|
|
|
|
|
78% { opacity: 0; }
|
|
|
|
|
100% { opacity: 0; }
|
|
|
|
|
}
|
|
|
|
|
|
2026-01-24 22:59:20 +00:00
|
|
|
/* Wrapper to contain perspective without clipping */
|
2026-03-16 12:58:35 +00:00
|
|
|
/* Panel mode app session — fills content area, sidebar stays untouched */
|
|
|
|
|
.app-panel-container {
|
|
|
|
|
position: absolute;
|
|
|
|
|
inset: 0;
|
|
|
|
|
z-index: 100;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.panel-slide-enter-active {
|
|
|
|
|
transition: opacity 0.25s ease;
|
|
|
|
|
}
|
|
|
|
|
.panel-slide-leave-active {
|
|
|
|
|
transition: transform 0.3s ease, opacity 0.3s ease;
|
|
|
|
|
}
|
|
|
|
|
.panel-slide-enter-from {
|
|
|
|
|
opacity: 0;
|
|
|
|
|
}
|
|
|
|
|
.panel-slide-leave-to {
|
|
|
|
|
transform: translateX(40px) scale(0.97);
|
|
|
|
|
opacity: 0;
|
|
|
|
|
}
|
|
|
|
|
|
2026-01-24 22:59:20 +00:00
|
|
|
.perspective-container-wrapper {
|
|
|
|
|
position: relative;
|
|
|
|
|
overflow: hidden;
|
|
|
|
|
height: 100%;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Perspective container for 3D depth effect */
|
|
|
|
|
.perspective-container {
|
|
|
|
|
perspective: 2000px;
|
|
|
|
|
perspective-origin: 50% 50%;
|
|
|
|
|
position: relative;
|
|
|
|
|
height: 100%;
|
|
|
|
|
overflow: hidden;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* View wrapper - allows smooth transitions with absolute positioning */
|
|
|
|
|
.view-wrapper {
|
|
|
|
|
position: absolute;
|
|
|
|
|
inset: 0;
|
|
|
|
|
transform-style: preserve-3d;
|
|
|
|
|
backface-visibility: hidden;
|
|
|
|
|
will-change: transform, opacity;
|
|
|
|
|
opacity: 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.view-container {
|
2026-03-14 17:12:41 +00:00
|
|
|
/* No forced height — content sizes naturally, spacer below provides clearance */
|
2026-01-24 22:59:20 +00:00
|
|
|
}
|
|
|
|
|
|
2026-02-17 19:19:54 +00:00
|
|
|
/* Forward transition: 2advanced fluid depth */
|
2026-01-24 22:59:20 +00:00
|
|
|
.depth-forward-enter-active.view-wrapper,
|
|
|
|
|
.depth-forward-leave-active.view-wrapper {
|
2026-02-17 19:19:54 +00:00
|
|
|
transition: all 0.8s cubic-bezier(0.25, 0.46, 0.45, 0.94);
|
2026-01-24 22:59:20 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.depth-forward-enter-from.view-wrapper {
|
|
|
|
|
opacity: 0;
|
|
|
|
|
transform: translateZ(-800px) scale(0.75);
|
|
|
|
|
filter: blur(4px);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.depth-forward-enter-to.view-wrapper {
|
|
|
|
|
opacity: 1;
|
|
|
|
|
transform: translateZ(0) scale(1);
|
|
|
|
|
filter: blur(0px);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.depth-forward-leave-from.view-wrapper {
|
|
|
|
|
opacity: 1;
|
|
|
|
|
transform: translateZ(0) scale(1);
|
|
|
|
|
filter: blur(0px);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.depth-forward-leave-to.view-wrapper {
|
|
|
|
|
opacity: 0;
|
|
|
|
|
transform: translateZ(400px) scale(1.2);
|
|
|
|
|
filter: blur(8px);
|
|
|
|
|
}
|
|
|
|
|
|
2026-02-17 19:19:54 +00:00
|
|
|
/* Back transition: 2advanced fluid depth */
|
2026-01-24 22:59:20 +00:00
|
|
|
.depth-back-enter-active.view-wrapper,
|
|
|
|
|
.depth-back-leave-active.view-wrapper {
|
2026-02-17 19:19:54 +00:00
|
|
|
transition: all 0.8s cubic-bezier(0.25, 0.46, 0.45, 0.94);
|
2026-01-24 22:59:20 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.depth-back-enter-from.view-wrapper {
|
|
|
|
|
opacity: 0;
|
|
|
|
|
transform: translateZ(400px) scale(1.2);
|
|
|
|
|
filter: blur(8px);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.depth-back-enter-to.view-wrapper {
|
|
|
|
|
opacity: 1;
|
|
|
|
|
transform: translateZ(0) scale(1);
|
|
|
|
|
filter: blur(0px);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.depth-back-leave-from.view-wrapper {
|
|
|
|
|
opacity: 1;
|
|
|
|
|
transform: translateZ(0) scale(1);
|
|
|
|
|
filter: blur(0px);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.depth-back-leave-to.view-wrapper {
|
|
|
|
|
opacity: 0;
|
|
|
|
|
transform: translateZ(-800px) scale(0.75);
|
|
|
|
|
filter: blur(4px);
|
|
|
|
|
}
|
|
|
|
|
|
2026-02-17 19:19:54 +00:00
|
|
|
/* Subtle 3D tilt - 2advanced layered depth */
|
2026-01-24 22:59:20 +00:00
|
|
|
@media (min-width: 768px) {
|
|
|
|
|
.depth-forward-enter-from.view-wrapper {
|
2026-02-17 19:19:54 +00:00
|
|
|
transform: translateZ(-800px) scale(0.75) rotateX(5deg);
|
2026-01-24 22:59:20 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.depth-forward-leave-to.view-wrapper {
|
2026-02-17 19:19:54 +00:00
|
|
|
transform: translateZ(400px) scale(1.2) rotateX(-4deg);
|
2026-01-24 22:59:20 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.depth-back-enter-from.view-wrapper {
|
2026-02-17 19:19:54 +00:00
|
|
|
transform: translateZ(400px) scale(1.2) rotateX(-4deg);
|
2026-01-24 22:59:20 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.depth-back-leave-to.view-wrapper {
|
2026-02-17 19:19:54 +00:00
|
|
|
transform: translateZ(-800px) scale(0.75) rotateX(5deg);
|
2026-01-24 22:59:20 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
feat: AIUI chat mode integration with iframe, context broker, overnight loop
- Chat mode: AIUI loads in sandboxed iframe at /dashboard/chat with transparent bg
- Mode switcher: Easy + Pro tabs only, Chat is a launcher button
- Keyboard shortcuts: Cmd+1 (Easy), Cmd+2 (Pro), Cmd+3 (Chat), Cmd+M (cycle)
- Directional transitions: chat slides from/to left, dashboard from/to right
- Context broker: postMessage protocol for quarantined AIUI communication
- AI permissions store: user-controlled toggles for data access categories
- Settings UI: AI Data Access section with per-category toggles
- AIUI container manifest and nginx proxy config for /aiui/
- Deploy script builds AIUI with /aiui/ base path
- Overnight loop infrastructure (loop.sh, prepare.sh, plan.md, prompt.md)
- Security hooks for autonomous overnight runs
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-04 12:06:20 +00:00
|
|
|
/* Chat open transition — chat slides in from left, dashboard slides out to right */
|
|
|
|
|
.chat-open-enter-active.view-wrapper,
|
|
|
|
|
.chat-open-leave-active.view-wrapper {
|
|
|
|
|
transition: opacity 0.5s cubic-bezier(0.22, 1, 0.36, 1), transform 0.5s cubic-bezier(0.22, 1, 0.36, 1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.chat-open-enter-from.view-wrapper {
|
|
|
|
|
opacity: 0;
|
|
|
|
|
transform: translateX(-60px) scale(0.96);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.chat-open-enter-to.view-wrapper {
|
|
|
|
|
opacity: 1;
|
|
|
|
|
transform: translateX(0) scale(1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.chat-open-leave-from.view-wrapper {
|
|
|
|
|
opacity: 1;
|
|
|
|
|
transform: translateX(0) scale(1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.chat-open-leave-to.view-wrapper {
|
|
|
|
|
opacity: 0;
|
|
|
|
|
transform: translateX(60px) scale(0.96);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Chat close transition — chat slides out to left, dashboard slides in from right */
|
|
|
|
|
.chat-close-enter-active.view-wrapper,
|
|
|
|
|
.chat-close-leave-active.view-wrapper {
|
|
|
|
|
transition: opacity 0.5s cubic-bezier(0.22, 1, 0.36, 1), transform 0.5s cubic-bezier(0.22, 1, 0.36, 1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.chat-close-enter-from.view-wrapper {
|
|
|
|
|
opacity: 0;
|
|
|
|
|
transform: translateX(60px) scale(0.96);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.chat-close-enter-to.view-wrapper {
|
|
|
|
|
opacity: 1;
|
|
|
|
|
transform: translateX(0) scale(1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.chat-close-leave-from.view-wrapper {
|
|
|
|
|
opacity: 1;
|
|
|
|
|
transform: translateX(0) scale(1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.chat-close-leave-to.view-wrapper {
|
|
|
|
|
opacity: 0;
|
|
|
|
|
transform: translateX(-60px) scale(0.96);
|
|
|
|
|
}
|
|
|
|
|
|
2026-01-24 22:59:20 +00:00
|
|
|
/* Fade transition for initial loads and default cases */
|
|
|
|
|
.fade-enter-active,
|
|
|
|
|
.fade-leave-active {
|
|
|
|
|
transition: opacity 0.3s ease;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.fade-enter-from,
|
|
|
|
|
.fade-leave-to {
|
|
|
|
|
opacity: 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.fade-enter-to,
|
|
|
|
|
.fade-leave-from {
|
|
|
|
|
opacity: 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Mobile: Slide left transition (Apps -> Marketplace) */
|
|
|
|
|
.slide-left-enter-active.view-wrapper,
|
|
|
|
|
.slide-left-leave-active.view-wrapper {
|
2026-03-09 07:43:12 +00:00
|
|
|
transition: transform 0.3s cubic-bezier(0.4, 0, 0.2, 1), opacity 0.3s ease;
|
2026-01-24 22:59:20 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.slide-left-enter-from.view-wrapper {
|
|
|
|
|
transform: translateX(100%);
|
2026-03-09 07:43:12 +00:00
|
|
|
opacity: 0;
|
2026-01-24 22:59:20 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.slide-left-enter-to.view-wrapper {
|
|
|
|
|
transform: translateX(0);
|
2026-03-09 07:43:12 +00:00
|
|
|
opacity: 1;
|
2026-01-24 22:59:20 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.slide-left-leave-from.view-wrapper {
|
|
|
|
|
transform: translateX(0);
|
2026-03-09 07:43:12 +00:00
|
|
|
opacity: 1;
|
2026-01-24 22:59:20 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.slide-left-leave-to.view-wrapper {
|
|
|
|
|
transform: translateX(-100%);
|
2026-03-09 07:43:12 +00:00
|
|
|
opacity: 0;
|
2026-01-24 22:59:20 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Mobile: Slide right transition (Marketplace -> Apps) */
|
|
|
|
|
.slide-right-enter-active.view-wrapper,
|
|
|
|
|
.slide-right-leave-active.view-wrapper {
|
2026-03-09 07:43:12 +00:00
|
|
|
transition: transform 0.3s cubic-bezier(0.4, 0, 0.2, 1), opacity 0.3s ease;
|
2026-01-24 22:59:20 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.slide-right-enter-from.view-wrapper {
|
|
|
|
|
transform: translateX(-100%);
|
2026-03-09 07:43:12 +00:00
|
|
|
opacity: 0;
|
2026-01-24 22:59:20 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.slide-right-enter-to.view-wrapper {
|
|
|
|
|
transform: translateX(0);
|
2026-03-09 07:43:12 +00:00
|
|
|
opacity: 1;
|
2026-01-24 22:59:20 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.slide-right-leave-from.view-wrapper {
|
|
|
|
|
transform: translateX(0);
|
2026-03-09 07:43:12 +00:00
|
|
|
opacity: 1;
|
2026-01-24 22:59:20 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.slide-right-leave-to.view-wrapper {
|
|
|
|
|
transform: translateX(100%);
|
2026-03-09 07:43:12 +00:00
|
|
|
opacity: 0;
|
2026-01-24 22:59:20 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Slide down: Moving down the menu (content slides up like a scroll) */
|
|
|
|
|
.slide-down-enter-active.view-wrapper {
|
|
|
|
|
transition: all 0.5s cubic-bezier(0.25, 0.46, 0.45, 0.94);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.slide-down-leave-active.view-wrapper {
|
|
|
|
|
transition: transform 0.5s cubic-bezier(0.25, 0.46, 0.45, 0.94),
|
|
|
|
|
opacity 0.5s cubic-bezier(0.4, 0, 0.2, 1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.slide-down-enter-from.view-wrapper {
|
|
|
|
|
opacity: 0;
|
|
|
|
|
transform: translateY(40vh);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.slide-down-enter-to.view-wrapper {
|
|
|
|
|
opacity: 1;
|
|
|
|
|
transform: translateY(0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.slide-down-leave-from.view-wrapper {
|
|
|
|
|
opacity: 1;
|
|
|
|
|
transform: translateY(0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.slide-down-leave-to.view-wrapper {
|
|
|
|
|
opacity: 0;
|
|
|
|
|
transform: translateY(-30vh);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Slide up: Moving up the menu (content slides down like a scroll) */
|
|
|
|
|
.slide-up-enter-active.view-wrapper {
|
|
|
|
|
transition: all 0.5s cubic-bezier(0.25, 0.46, 0.45, 0.94);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.slide-up-leave-active.view-wrapper {
|
|
|
|
|
transition: transform 0.5s cubic-bezier(0.25, 0.46, 0.45, 0.94),
|
|
|
|
|
opacity 0.5s cubic-bezier(0.4, 0, 0.2, 1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.slide-up-enter-from.view-wrapper {
|
|
|
|
|
opacity: 0;
|
|
|
|
|
transform: translateY(-40vh);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.slide-up-enter-to.view-wrapper {
|
|
|
|
|
opacity: 1;
|
|
|
|
|
transform: translateY(0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.slide-up-leave-from.view-wrapper {
|
|
|
|
|
opacity: 1;
|
|
|
|
|
transform: translateY(0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.slide-up-leave-to.view-wrapper {
|
|
|
|
|
opacity: 0;
|
|
|
|
|
transform: translateY(30vh);
|
|
|
|
|
}
|
|
|
|
|
|
2026-02-17 19:19:54 +00:00
|
|
|
/* Background 3D container - full width, black fill during zoom to avoid letterboxing */
|
|
|
|
|
.dashboard-view .bg-perspective-container {
|
2026-01-24 22:59:20 +00:00
|
|
|
position: fixed;
|
|
|
|
|
inset: 0;
|
|
|
|
|
z-index: -10;
|
|
|
|
|
perspective: 1000px;
|
|
|
|
|
perspective-origin: 50% 50%;
|
|
|
|
|
overflow: hidden;
|
2026-02-17 19:19:54 +00:00
|
|
|
left: 0 !important;
|
|
|
|
|
right: 0 !important;
|
|
|
|
|
width: 100% !important;
|
|
|
|
|
min-width: 100% !important;
|
|
|
|
|
background: #000;
|
2026-01-24 22:59:20 +00:00
|
|
|
}
|
|
|
|
|
|
2026-02-17 19:19:54 +00:00
|
|
|
/* Background layers with 3D transitions - full width like login */
|
|
|
|
|
.dashboard-view .bg-layer {
|
2026-01-24 22:59:20 +00:00
|
|
|
position: absolute;
|
|
|
|
|
inset: 0;
|
2026-02-17 19:19:54 +00:00
|
|
|
background-size: cover !important;
|
|
|
|
|
background-position: center center !important;
|
|
|
|
|
background-repeat: no-repeat !important;
|
2026-01-24 22:59:20 +00:00
|
|
|
transition: all 0.45s cubic-bezier(0.68, -0.55, 0.265, 1.55);
|
|
|
|
|
transform-style: preserve-3d;
|
|
|
|
|
will-change: transform, opacity;
|
|
|
|
|
}
|
|
|
|
|
|
2026-02-18 08:18:14 +00:00
|
|
|
/* Default state - bg-intro visible, bg-intro-3 hidden back */
|
2026-02-17 19:19:54 +00:00
|
|
|
.dashboard-view .bg-layer:first-of-type {
|
2026-01-24 22:59:20 +00:00
|
|
|
opacity: 1;
|
|
|
|
|
transform: translateZ(0) scale(1);
|
|
|
|
|
}
|
|
|
|
|
|
2026-02-17 19:19:54 +00:00
|
|
|
.dashboard-view .bg-layer:nth-of-type(2) {
|
2026-01-24 22:59:20 +00:00
|
|
|
opacity: 0;
|
|
|
|
|
transform: translateZ(-200px) scale(0.9) rotateY(-15deg);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Transitioning out - current background moves away with zoom */
|
2026-02-17 19:19:54 +00:00
|
|
|
.dashboard-view .bg-layer.bg-transitioning-out {
|
2026-01-24 22:59:20 +00:00
|
|
|
opacity: 0;
|
|
|
|
|
transform: translateZ(200px) scale(1.15) rotateY(15deg) !important;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Transitioning in - new background comes forward with zoom */
|
2026-02-17 19:19:54 +00:00
|
|
|
.dashboard-view .bg-layer.bg-transitioning-in {
|
2026-01-24 22:59:20 +00:00
|
|
|
opacity: 1;
|
|
|
|
|
transform: translateZ(0) scale(1.05) rotateY(0deg) !important;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Background glitch effect layers - World Fair style */
|
|
|
|
|
.bg-glitch-layer-1,
|
|
|
|
|
.bg-glitch-layer-2,
|
|
|
|
|
.bg-glitch-scan {
|
|
|
|
|
content: '';
|
|
|
|
|
position: fixed;
|
|
|
|
|
inset: 0;
|
|
|
|
|
pointer-events: none;
|
|
|
|
|
z-index: 10;
|
|
|
|
|
opacity: 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.bg-glitch-layer-1 {
|
|
|
|
|
background-size: cover;
|
|
|
|
|
background-position: center;
|
|
|
|
|
mix-blend-mode: lighten;
|
|
|
|
|
filter: brightness(1.8) contrast(2) saturate(1.5) hue-rotate(180deg);
|
|
|
|
|
will-change: transform, clip-path, opacity;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.bg-glitch-layer-2 {
|
|
|
|
|
background-size: cover;
|
|
|
|
|
background-position: center;
|
|
|
|
|
mix-blend-mode: color-dodge;
|
|
|
|
|
filter: brightness(2) contrast(2) saturate(2) hue-rotate(90deg);
|
|
|
|
|
will-change: transform, clip-path, opacity;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.bg-glitch-scan {
|
|
|
|
|
background:
|
|
|
|
|
linear-gradient(90deg,
|
|
|
|
|
rgba(255,0,255,0.2) 0%,
|
|
|
|
|
rgba(0,255,255,0.2) 25%,
|
|
|
|
|
rgba(255,255,0,0.2) 50%,
|
|
|
|
|
rgba(0,255,255,0.2) 75%,
|
|
|
|
|
rgba(255,0,255,0.2) 100%
|
|
|
|
|
),
|
|
|
|
|
repeating-linear-gradient(0deg,
|
|
|
|
|
rgba(255,255,255,0.05) 0px,
|
|
|
|
|
rgba(255,255,255,0.05) 2px,
|
|
|
|
|
transparent 2px,
|
|
|
|
|
transparent 4px
|
|
|
|
|
);
|
|
|
|
|
will-change: transform, opacity;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Trigger glitch animation when active */
|
|
|
|
|
.bg-glitch-layer-1.glitch-active {
|
|
|
|
|
animation: bg-glitch-shift 0.375s steps(15, end) forwards;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.bg-glitch-layer-2.glitch-active {
|
|
|
|
|
animation: bg-glitch-shift-2 0.375s steps(12, end) forwards;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.bg-glitch-scan.glitch-active {
|
|
|
|
|
animation: bg-glitch-scan 0.375s linear forwards;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* World Fair style - visible but tasteful glitch */
|
|
|
|
|
@keyframes bg-glitch-shift {
|
|
|
|
|
0% { transform: translate(0,0); clip-path: inset(0% 0 0 0); opacity: 0; }
|
|
|
|
|
5% { opacity: 0.5; }
|
|
|
|
|
12% { transform: translate(15px,-8px); clip-path: inset(12% 0 70% 0); }
|
|
|
|
|
20% { transform: translate(-20px,10px); clip-path: inset(45% 0 35% 0); }
|
|
|
|
|
28% { transform: translate(18px,-5px); clip-path: inset(68% 0 15% 0); }
|
|
|
|
|
36% { transform: translate(-15px,12px); clip-path: inset(20% 0 60% 0); }
|
|
|
|
|
44% { transform: translate(22px,-10px); clip-path: inset(52% 0 28% 0); }
|
|
|
|
|
52% { transform: translate(-18px,8px); clip-path: inset(10% 0 75% 0); }
|
|
|
|
|
60% { transform: translate(12px,-6px); clip-path: inset(58% 0 22% 0); }
|
|
|
|
|
68% { transform: translate(-10px,15px); clip-path: inset(32% 0 48% 0); }
|
|
|
|
|
76% { transform: translate(16px,-4px); clip-path: inset(72% 0 12% 0); }
|
|
|
|
|
84% { transform: translate(-12px,7px); clip-path: inset(18% 0 65% 0); }
|
|
|
|
|
92% { transform: translate(8px,-3px); clip-path: inset(42% 0 40% 0); }
|
|
|
|
|
96% { opacity: 0.4; }
|
|
|
|
|
100% { transform: translate(0,0); clip-path: inset(0% 0 0 0); opacity: 0; }
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@keyframes bg-glitch-shift-2 {
|
|
|
|
|
0% { transform: translate(0,0) skewX(0deg); clip-path: inset(0% 0 0 0); opacity: 0; }
|
|
|
|
|
8% { opacity: 0.5; }
|
|
|
|
|
15% { transform: translate(-18px,10px) skewX(4deg); clip-path: inset(25% 0 55% 0); }
|
|
|
|
|
23% { transform: translate(22px,-12px) skewX(-5deg); clip-path: inset(50% 0 30% 0); }
|
|
|
|
|
31% { transform: translate(-16px,8px) skewX(3deg); clip-path: inset(72% 0 12% 0); }
|
|
|
|
|
39% { transform: translate(20px,-15px) skewX(-4deg); clip-path: inset(18% 0 65% 0); }
|
|
|
|
|
47% { transform: translate(-22px,12px) skewX(5deg); clip-path: inset(42% 0 38% 0); }
|
|
|
|
|
55% { transform: translate(18px,-8px) skewX(-3deg); clip-path: inset(62% 0 20% 0); }
|
|
|
|
|
63% { transform: translate(-14px,14px) skewX(4deg); clip-path: inset(30% 0 52% 0); }
|
|
|
|
|
71% { transform: translate(16px,-6px) skewX(-2deg); clip-path: inset(8% 0 78% 0); }
|
|
|
|
|
79% { transform: translate(-12px,10px) skewX(3deg); clip-path: inset(55% 0 28% 0); }
|
|
|
|
|
87% { transform: translate(10px,-4px) skewX(-2deg); clip-path: inset(35% 0 45% 0); }
|
|
|
|
|
95% { opacity: 0.4; }
|
|
|
|
|
100% { transform: translate(0,0) skewX(0deg); clip-path: inset(0% 0 0 0); opacity: 0; }
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@keyframes bg-glitch-scan {
|
|
|
|
|
0% { opacity: 0; transform: translateX(-120%); }
|
|
|
|
|
5% { opacity: 0.5; }
|
|
|
|
|
15% { opacity: 0.55; transform: translateX(-80%); }
|
|
|
|
|
30% { opacity: 0.6; transform: translateX(-40%); }
|
|
|
|
|
50% { opacity: 0.6; transform: translateX(0%); }
|
|
|
|
|
70% { opacity: 0.55; transform: translateX(40%); }
|
|
|
|
|
85% { opacity: 0.5; transform: translateX(80%); }
|
|
|
|
|
95% { opacity: 0.45; }
|
|
|
|
|
100% { opacity: 0; transform: translateX(120%); }
|
|
|
|
|
}
|
2026-02-17 19:19:54 +00:00
|
|
|
|
|
|
|
|
/* Full width background - same as login */
|
|
|
|
|
.dashboard-view .bg-fullwidth {
|
|
|
|
|
min-width: 100%;
|
|
|
|
|
width: 100%;
|
|
|
|
|
background-size: cover !important;
|
|
|
|
|
background-position: center center !important;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Continuous glitch overlays - same as login, every 5s */
|
|
|
|
|
.dashboard-glitch-layer {
|
|
|
|
|
position: absolute;
|
|
|
|
|
inset: 0;
|
|
|
|
|
pointer-events: none;
|
|
|
|
|
z-index: 5;
|
|
|
|
|
background-size: cover;
|
|
|
|
|
background-position: center;
|
|
|
|
|
background-repeat: no-repeat;
|
|
|
|
|
opacity: 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.dashboard-glitch-1 {
|
|
|
|
|
mix-blend-mode: screen;
|
|
|
|
|
filter: hue-rotate(22deg) saturate(1.35);
|
|
|
|
|
animation: dashboard-glitch-shift 5s steps(10, end) infinite;
|
|
|
|
|
background-size: cover !important;
|
|
|
|
|
background-position: center center !important;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.dashboard-glitch-2 {
|
|
|
|
|
mix-blend-mode: screen;
|
|
|
|
|
filter: hue-rotate(-30deg) saturate(1.45);
|
|
|
|
|
animation: dashboard-glitch-shift-2 5s steps(9, end) infinite;
|
|
|
|
|
background-size: cover !important;
|
|
|
|
|
background-position: center center !important;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.dashboard-glitch-scan {
|
|
|
|
|
position: absolute;
|
|
|
|
|
inset: 0;
|
|
|
|
|
pointer-events: none;
|
|
|
|
|
z-index: 6;
|
|
|
|
|
background:
|
|
|
|
|
linear-gradient(180deg, rgba(255,255,255,0.16), rgba(0,0,0,0) 60%),
|
|
|
|
|
repeating-linear-gradient(180deg, rgba(255,255,255,0.05) 0 2px, rgba(0,0,0,0) 2px 4px),
|
|
|
|
|
radial-gradient(ellipse at center, rgba(0,0,0,0) 40%, rgba(0,0,0,0.35) 100%);
|
|
|
|
|
opacity: 0;
|
|
|
|
|
animation: dashboard-glitch-scan 5s ease-out infinite;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@keyframes dashboard-glitch-shift {
|
|
|
|
|
0%, 82% { transform: translate(0,0); clip-path: inset(0% 0 0 0); opacity: 0; }
|
|
|
|
|
82.1% { opacity: 0.28; }
|
|
|
|
|
84% { transform: translate(6px,-2px); clip-path: inset(8% 0 70% 0); }
|
|
|
|
|
86% { transform: translate(-5px,2px); clip-path: inset(42% 0 40% 0); }
|
|
|
|
|
88% { transform: translate(3px,0); clip-path: inset(68% 0 10% 0); }
|
|
|
|
|
91% { transform: translate(-4px,3px); clip-path: inset(18% 0 60% 0); }
|
|
|
|
|
93% { transform: translate(5px,-3px); clip-path: inset(55% 0 20% 0); }
|
|
|
|
|
95% { transform: translate(-3px,1px); clip-path: inset(10% 0 80% 0); }
|
|
|
|
|
100% { transform: translate(0,0); clip-path: inset(0% 0 0 0); opacity: 0; }
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@keyframes dashboard-glitch-shift-2 {
|
|
|
|
|
0%, 82% { transform: translate(0,0); clip-path: inset(0% 0 0 0); opacity: 0; }
|
|
|
|
|
82.1% { opacity: 0.24; }
|
|
|
|
|
84% { transform: translate(-6px,2px); clip-path: inset(12% 0 65% 0); }
|
|
|
|
|
86% { transform: translate(5px,-1px) skewX(0.6deg); clip-path: inset(36% 0 42% 0); }
|
|
|
|
|
89% { transform: translate(-3px,2px); clip-path: inset(72% 0 8% 0); }
|
|
|
|
|
92% { transform: translate(4px,-3px); clip-path: inset(22% 0 58% 0); }
|
|
|
|
|
95% { transform: translate(-4px,1px); clip-path: inset(50% 0 26% 0); }
|
|
|
|
|
100% { transform: translate(0,0); clip-path: inset(0% 0 0 0); opacity: 0; }
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@keyframes dashboard-glitch-scan {
|
|
|
|
|
0%, 82% { opacity: 0; transform: translateY(-20%); }
|
|
|
|
|
84% { opacity: 0.5; }
|
|
|
|
|
90% { opacity: 0.35; }
|
|
|
|
|
100% { opacity: 0; transform: translateY(115%); }
|
|
|
|
|
}
|
2026-01-24 22:59:20 +00:00
|
|
|
</style>
|
|
|
|
|
|