Files
smart-home-tablet/app/globals.css
d.klimov e6dab09c38
All checks were successful
Deploy / deploy (push) Successful in 3m43s
voice: локальный агент (fast-path), tool control_light, смелая тема, RUNBOOK
- lib/agent-local.ts + route.ts: команды-действия исполняет локальная intent-служба
  (под AGENT_URL, с fallback на LLM); инфо-запросы остаются у LLM
- lib/tools/lights.ts: голосовое управление светом через HA (control_light)
- app/globals.css + page.tsx: космическая indigo/aurora тема (токены, kiosk-safe)
- agent/: sidecar-служба (Dockerfile, predict.py), веса монтируются томом
- RUNBOOK.md: вывод в продакшен на мини-ПК
2026-07-22 21:48:24 +03:00

451 lines
15 KiB
CSS
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
* {
box-sizing: border-box;
margin: 0;
padding: 0;
}
/* ——————————————————————————————
Tokens — dark (default)
—————————————————————————————— */
:root {
/* Surfaces — глубокий индиго с холодным подтоном (тема «Космо») */
--bg: #07070f;
--bg-secondary: #0c0c1c;
--surface-1: #14142c;
--surface-2: #1c1c3e;
--surface-3: #26264f;
--surface-hover: #22224a;
/* Borders */
--border-subtle: rgba(255, 255, 255, 0.07);
--border-strong: rgba(150, 160, 255, 0.18);
--hairline: rgba(255, 255, 255, 0.08);
/* Text */
--text-primary: rgba(255, 255, 255, 0.96);
--text-secondary: rgba(200, 205, 240, 0.62);
--text-tertiary: rgba(190, 195, 235, 0.4);
/* Accents — UI (ярче и насыщеннее для смелого визуала) */
--accent: #8b93ff;
--accent-strong: #6d5efc;
--accent-secondary: #2ee6f6;
--accent-glow: rgba(139, 120, 252, 0.32);
/* Data palette — semantic, theme-aware */
--data-cool: #38bdf8; /* небо, влажность, охлаждение */
--data-info: #60a5fa; /* ссылки, second-accent */
--data-good: #34d399; /* успех, здоровье, streak */
--data-warm: #fbbf24; /* свет, тепло, утро */
--data-hot: #fb923c; /* обострение, urgent-minor */
--data-danger: #f87171; /* критичное, истёк, ошибка */
--data-rose: #f472b6; /* Света, романтика */
--data-violet: #a78bfa; /* Cosmo, индиго-вариант */
--data-mood: #8b5cf6; /* секреты, события 2-го уровня */
/* Soft backgrounds for data (color-mix with surface-2) */
--data-cool-bg: color-mix(in srgb, var(--data-cool) 12%, var(--surface-2));
--data-good-bg: color-mix(in srgb, var(--data-good) 12%, var(--surface-2));
--data-warm-bg: color-mix(in srgb, var(--data-warm) 12%, var(--surface-2));
--data-hot-bg: color-mix(in srgb, var(--data-hot) 14%, var(--surface-2));
--data-danger-bg: color-mix(in srgb, var(--data-danger) 12%, var(--surface-2));
--data-rose-bg: color-mix(in srgb, var(--data-rose) 12%, var(--surface-2));
--data-violet-bg: color-mix(in srgb, var(--data-violet) 12%, var(--surface-2));
/* Brand gradients — многоступенчатые, живые (смелый визуал) */
--gradient-primary: linear-gradient(135deg, #6d5efc 0%, #a855f7 50%, #2ee6f6 100%);
--gradient-warm: linear-gradient(135deg, #fbbf24 0%, #fb7185 100%);
--gradient-cool: linear-gradient(135deg, #22d3ee 0%, #6366f1 100%);
--gradient-green: linear-gradient(135deg, #10b981 0%, #5eead4 100%);
--gradient-aurora: linear-gradient(120deg, #6d5efc 0%, #a855f7 40%, #2ee6f6 100%);
/* Shadows */
--shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.4);
--shadow-md: 0 4px 12px rgba(0, 0, 0, 0.35);
--shadow-lg: 0 12px 32px rgba(0, 0, 0, 0.45);
--shadow-xl: 0 24px 60px rgba(0, 0, 0, 0.5);
/* State */
--on-color: #818cf8;
--off-color: rgba(255, 255, 255, 0.15);
/* Radius */
--radius-xs: 8px;
--radius-sm: 12px;
--radius-md: 16px;
--radius-lg: 22px;
--radius-xl: 28px;
/* Layout rhythm */
--space-1: 4px;
--space-2: 8px;
--space-3: 12px;
--space-4: 16px;
--space-5: 22px;
--space-6: 28px;
/* Touch */
--touch-min: 44px;
--touch-comfy: 56px;
/* Legacy aliases */
--sidebar-bg: var(--bg);
--card-bg: var(--surface-1);
--card-bg-hover: var(--surface-2);
--card-border: var(--border-subtle);
--card-border-hover: var(--border-strong);
--glass: var(--surface-1);
--glass-border: var(--border-subtle);
}
/* ——————————————————————————————
Tokens — light
—————————————————————————————— */
.light {
--bg: #f6f7fb;
--bg-secondary: #eef0f5;
--surface-1: #ffffff;
--surface-2: #f3f4f8;
--surface-3: #eaebf0;
--surface-hover: #f8f9fc;
--border-subtle: rgba(15, 20, 40, 0.06);
--border-strong: rgba(15, 20, 40, 0.12);
--hairline: rgba(15, 20, 40, 0.08);
--text-primary: rgba(15, 20, 40, 0.94);
--text-secondary: rgba(15, 20, 40, 0.62);
--text-tertiary: rgba(15, 20, 40, 0.38);
--accent: #5b63e0;
--accent-strong: #4f46e5;
--accent-secondary: #0891b2;
--accent-glow: rgba(91, 99, 224, 0.14);
/* Data palette — slightly darker in light theme for contrast */
--data-cool: #0284c7;
--data-info: #2563eb;
--data-good: #059669;
--data-warm: #d97706;
--data-hot: #ea580c;
--data-danger: #dc2626;
--data-rose: #db2777;
--data-violet: #7c3aed;
--data-mood: #6d28d9;
/* Soft backgrounds — lighter mix for light theme */
--data-cool-bg: color-mix(in srgb, var(--data-cool) 9%, var(--surface-1));
--data-good-bg: color-mix(in srgb, var(--data-good) 9%, var(--surface-1));
--data-warm-bg: color-mix(in srgb, var(--data-warm) 9%, var(--surface-1));
--data-hot-bg: color-mix(in srgb, var(--data-hot) 10%, var(--surface-1));
--data-danger-bg: color-mix(in srgb, var(--data-danger) 9%, var(--surface-1));
--data-rose-bg: color-mix(in srgb, var(--data-rose) 9%, var(--surface-1));
--data-violet-bg: color-mix(in srgb, var(--data-violet) 9%, var(--surface-1));
--shadow-sm: 0 1px 2px rgba(15, 20, 40, 0.05);
--shadow-md: 0 2px 6px rgba(15, 20, 40, 0.06), 0 12px 28px -8px rgba(15, 20, 40, 0.1);
--shadow-lg: 0 4px 10px rgba(15, 20, 40, 0.06), 0 24px 60px -12px rgba(15, 20, 40, 0.14);
--shadow-xl: 0 8px 16px rgba(15, 20, 40, 0.06), 0 40px 100px -24px rgba(15, 20, 40, 0.2);
--on-color: #5b63e0;
--off-color: rgba(15, 20, 40, 0.12);
}
/* ——————————————————————————————
Base
—————————————————————————————— */
html, body {
background: var(--bg);
color: var(--text-primary);
font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'SF Pro Display', 'Segoe UI', system-ui, sans-serif;
height: 100%;
overflow: hidden;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
transition: background 0.3s ease, color 0.3s ease;
}
#__next, main { height: 100%; }
/* Better tabular numbers across the app */
.num, .num-display {
font-variant-numeric: tabular-nums slashed-zero;
font-feature-settings: "tnum", "zero";
}
.num-display {
letter-spacing: -0.02em;
font-weight: 800;
line-height: 0.95;
}
/* ——————————————————————————————
Grain overlay
——— subtle SVG-noise; cheap, no image asset needed
—————————————————————————————— */
.grain {
position: relative;
}
.grain::after {
content: '';
position: absolute;
inset: 0;
pointer-events: none;
border-radius: inherit;
opacity: 0.035;
mix-blend-mode: overlay;
background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='120' height='120'><filter id='n'><feTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='2' stitchTiles='stitch'/><feColorMatrix values='0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 1 0'/></filter><rect width='100%25' height='100%25' filter='url(%23n)'/></svg>");
background-size: 120px 120px;
}
.light .grain::after {
opacity: 0.05;
mix-blend-mode: multiply;
filter: invert(1);
}
/* ——————————————————————————————
Aurora
—————————————————————————————— */
.bg-ambient {
position: fixed;
inset: 0;
z-index: 0;
overflow: hidden;
pointer-events: none;
}
.bg-ambient::before,
.bg-ambient::after {
content: '';
position: absolute;
border-radius: 50%;
filter: blur(80px);
}
.bg-ambient::before {
width: 680px; height: 680px;
background: radial-gradient(circle, var(--accent-glow) 0%, transparent 68%);
top: -200px; right: -100px;
animation: float1 22s ease-in-out infinite;
}
.bg-ambient::after {
width: 600px; height: 600px;
background: radial-gradient(circle, rgba(46, 230, 246, 0.16) 0%, transparent 68%);
bottom: -180px; left: -80px;
animation: float2 27s ease-in-out infinite;
}
.light .bg-ambient::after {
background: radial-gradient(circle, rgba(8, 145, 178, 0.12) 0%, transparent 70%);
}
/* Третий, центральный ореол — глубина «космоса» */
.bg-ambient .aurora-3 {
position: absolute;
width: 520px; height: 520px;
border-radius: 50%;
filter: blur(90px);
background: radial-gradient(circle, rgba(168, 85, 247, 0.14) 0%, transparent 70%);
top: 30%; left: 40%;
animation: float1 31s ease-in-out infinite reverse;
}
.light .bg-ambient .aurora-3 {
background: radial-gradient(circle, rgba(124, 58, 237, 0.08) 0%, transparent 70%);
}
@keyframes float1 {
0%, 100% { transform: translate(0, 0) scale(1); }
33% { transform: translate(30px, 40px) scale(1.05); }
66% { transform: translate(-20px, 20px) scale(0.95); }
}
@keyframes float2 {
0%, 100% { transform: translate(0, 0) scale(1); }
33% { transform: translate(-40px, -30px) scale(1.1); }
66% { transform: translate(20px, -10px) scale(0.9); }
}
/* ——————————————————————————————
Cards
—————————————————————————————— */
.card {
background: var(--surface-1);
border: 1px solid var(--border-subtle);
border-radius: var(--radius-lg);
box-shadow: var(--shadow-sm);
}
.card-raised {
background: var(--surface-1);
border: 1px solid var(--border-subtle);
border-radius: var(--radius-lg);
box-shadow: var(--shadow-md);
}
.card-hero {
background: var(--surface-1);
border: 1px solid var(--border-subtle);
border-radius: var(--radius-xl);
box-shadow: var(--shadow-lg);
}
/* Focus-card styling — for the context-aware hero */
.focus-card {
position: relative;
background: var(--surface-1);
border: 1px solid var(--border-subtle);
border-radius: var(--radius-xl);
box-shadow: var(--shadow-lg);
overflow: hidden;
}
.focus-card-accent::before {
content: '';
position: absolute;
inset: 0;
background: radial-gradient(circle at top right, var(--accent-glow), transparent 58%);
pointer-events: none;
}
.focus-card-accent::after {
content: '';
position: absolute;
inset: 0;
height: 3px;
background: var(--gradient-aurora);
opacity: 0.9;
pointer-events: none;
}
.glass-card {
background: var(--surface-1);
border: 1px solid var(--border-subtle);
border-radius: var(--radius-lg);
box-shadow: var(--shadow-sm);
}
.glass-card:hover { background: var(--surface-hover); }
/* ——— Смелые опциональные утилиты (opt-in, раскладку не меняют) ——— */
/* Светящаяся рамка-акцент для избранных карточек */
.card-glow {
box-shadow: var(--shadow-md),
0 0 0 1px color-mix(in srgb, var(--accent) 35%, transparent),
0 0 28px -6px var(--accent-glow);
}
/* Верхний блик — тонкая градиентная кромка сверху */
.sheen-top { box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.06); }
/* Крупные числа в цвете aurora-градиента */
.num-aurora {
background: var(--gradient-aurora);
-webkit-background-clip: text;
background-clip: text;
-webkit-text-fill-color: transparent;
}
/* Hairline divider helper */
.divider {
height: 1px;
width: 100%;
background: var(--hairline);
}
/* Chip / hit-zone — wraps small icons into 44px tap surface */
.hit-zone {
display: inline-flex;
align-items: center;
justify-content: center;
min-width: var(--touch-min);
min-height: var(--touch-min);
border-radius: 12px;
}
/* Small uppercase label */
.eyebrow {
font-size: 10px;
font-weight: 700;
letter-spacing: 0.1em;
text-transform: uppercase;
color: var(--text-tertiary);
}
.gradient-text {
background: var(--gradient-primary);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-clip: text;
}
button {
cursor: pointer;
border: none;
outline: none;
background: none;
-webkit-tap-highlight-color: transparent;
touch-action: manipulation;
font-family: inherit;
color: inherit;
}
button:focus-visible {
outline: 2px solid var(--accent);
outline-offset: 3px;
border-radius: 14px;
}
::-webkit-scrollbar { width: 6px; height: 6px; }
::-webkit-scrollbar-track { background: transparent; }
::-webkit-scrollbar-thumb { background: var(--border-strong); border-radius: 3px; }
::-webkit-scrollbar-thumb:hover { background: var(--text-tertiary); }
/* ——————————————————————————————
Motion
—————————————————————————————— */
@keyframes pulse-glow {
0%, 100% { box-shadow: 0 0 20px var(--accent-glow); }
50% { box-shadow: 0 0 30px var(--accent-glow); }
}
@keyframes slideUp {
from { opacity: 0; transform: translateY(10px); }
to { opacity: 1; transform: translateY(0); }
}
.animate-slide-up { animation: slideUp 0.4s cubic-bezier(0.4, 0, 0.2, 1) forwards; }
@keyframes fan-spin { from { transform: rotate(0deg); } to { transform: rotate(360deg); } }
@keyframes light-pulse {
0%, 100% { filter: drop-shadow(0 0 4px rgba(251, 191, 36, 0.3)); }
50% { filter: drop-shadow(0 0 12px rgba(251, 191, 36, 0.6)); }
}
@keyframes device-breathe { 0%, 100% { opacity: 0.7; } 50% { opacity: 1; } }
.fan-spinning { animation: fan-spin 2s linear infinite; }
.light-on-pulse { animation: light-pulse 3s ease-in-out infinite; }
.device-active-breathe { animation: device-breathe 3s ease-in-out infinite; }
@keyframes spin-slow { from { transform: rotate(0deg); } to { transform: rotate(360deg); } }
@keyframes cloud-float { 0%, 100% { transform: translateX(0); } 50% { transform: translateX(4px); } }
@keyframes rain-fall {
0% { transform: translateY(0); opacity: 0.7; }
80% { opacity: 0.7; }
100% { transform: translateY(16px); opacity: 0; }
}
@keyframes snow-fall {
0% { transform: translateY(0) translateX(0); opacity: 0.9; }
25% { transform: translateY(5px) translateX(2px); opacity: 0.8; }
50% { transform: translateY(10px) translateX(-1px); opacity: 0.7; }
75% { transform: translateY(15px) translateX(3px); opacity: 0.4; }
100% { transform: translateY(22px) translateX(0); opacity: 0; }
}
@keyframes thunder-flash {
0%, 100% { opacity: 0; }
5%, 7% { opacity: 1; }
6% { opacity: 0.3; }
50%, 52% { opacity: 0.8; }
51% { opacity: 0.2; }
}
@keyframes fog-drift {
0%, 100% { transform: translateX(0); opacity: 0.4; }
50% { transform: translateX(8px); opacity: 0.6; }
}
/* Weather ambient tints via accent-glow */
.weather-bg-clear { --accent-glow: rgba(251, 191, 36, 0.18); }
.weather-bg-cloudy { --accent-glow: rgba(148, 163, 184, 0.18); }
.weather-bg-rain { --accent-glow: rgba(59, 130, 246, 0.18); }
.weather-bg-snow { --accent-glow: rgba(186, 230, 253, 0.22); }
.weather-bg-thunder { --accent-glow: rgba(139, 92, 246, 0.22); }
.weather-bg-night { --accent-glow: rgba(67, 56, 202, 0.16); }
.light.weather-bg-clear { --accent-glow: rgba(234, 169, 27, 0.16); }
.light.weather-bg-cloudy { --accent-glow: rgba(100, 116, 139, 0.14); }
.light.weather-bg-rain { --accent-glow: rgba(37, 99, 235, 0.14); }
.light.weather-bg-snow { --accent-glow: rgba(125, 211, 252, 0.22); }
.light.weather-bg-thunder { --accent-glow: rgba(109, 40, 217, 0.14); }
.light.weather-bg-night { --accent-glow: rgba(55, 48, 163, 0.14); }