Spaces:
Sleeping
Sleeping
| /* S437: import gerarchia z-index — variabili --z-* disponibili globalmente */ | |
| @import './styles/z-index.css'; | |
| /* S_THEME: theme.css source per --card-bg-streaming, .stream-progress-bar, | |
| --terminal-*, .agent-chip e token mancanti da index.css. | |
| index.css :root viene DOPO → sovrascrive token duplicati (Glow Glass prevale). */ | |
| @import './styles/theme.css'; | |
| /* ========================================================= | |
| GLOBAL RESET + TYPOGRAPHY | |
| min-width: 0 globale previene flex shrink collapse | |
| ========================================================= */ | |
| *, | |
| *::before, | |
| *::after { | |
| box-sizing: border-box; | |
| min-width: 0; | |
| } | |
| html, body, #root { | |
| margin: 0; | |
| padding: 0; | |
| height: 100%; | |
| width: 100%; | |
| overflow-x: hidden; | |
| font-family: Inter, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif; | |
| -webkit-text-size-adjust: 100%; | |
| } | |
| /* iOS: html deve bloccare lo scroll del documento root */ | |
| html { | |
| overflow: hidden; | |
| height: var(--vh, 100dvh); | |
| } | |
| /* ========================================================= | |
| STRUCTURAL TOKENS — radius, type stacks, transitions | |
| Color tokens live in theme.css (Glow Glass canonical source) | |
| ========================================================= */ | |
| :root { | |
| /* ─��� Font stacks ── */ | |
| --font-display: "Geist", "Inter", sans-serif; | |
| --font-mono: "JetBrains Mono", ui-monospace, "Cascadia Code", "Fira Code", monospace; | |
| --font-sans: Inter, system-ui, -apple-system, sans-serif; | |
| /* ── Radius — tight square corners ── */ | |
| --radius-sm: 6px; | |
| --radius-md: 8px; | |
| --radius-lg: 8px; /* P10-CSS: IDE-style compact */ | |
| --radius-xl: 10px; /* P10-CSS: IDE-style compact */ | |
| --radius-2xl: 16px; /* P10-CSS: ridotto da 24px */ | |
| /* ── Transitions ── */ | |
| --transition-fast: 130ms cubic-bezier(0.4, 0, 0.2, 1); | |
| --transition-normal: 220ms cubic-bezier(0.4, 0, 0.2, 1); | |
| /* G5: base font size token */ | |
| --base-font-size: 16px; | |
| } | |
| /* ========================================================= | |
| BUG #3: Focus outline — remove browser default dashed/yellow ring | |
| Use :focus-visible (keyboard only) for accessibility compliance | |
| Safari: outline: none on :focus is safe — Safari uses :focus-visible natively | |
| ========================================================= */ | |
| *:focus { | |
| outline: none; | |
| } | |
| *:focus-visible { | |
| outline: 2px solid rgba(99, 102, 241, 0.55); | |
| outline-offset: 2px; | |
| border-radius: 4px; | |
| } | |
| /* Touch/mobile users never need keyboard focus ring */ | |
| @media (hover: none) { | |
| *:focus-visible { | |
| outline: none; | |
| } | |
| } | |
| /* G5+G7: mobile-first overrides */ | |
| @media (max-width: 767px) { | |
| :root { | |
| --base-font-size: 14px; | |
| } | |
| body { | |
| font-size: var(--base-font-size); | |
| } | |
| /* G7: sidebar overlay full width on mobile */ | |
| .sidebar-overlay > div { | |
| width: calc(100vw - 24px) ; | |
| max-width: calc(100vw - 24px) ; | |
| } | |
| } | |
| /* ── Glass cards — glow edition (S250-GLASS) ── */ | |
| .glass-card { | |
| background: rgba(8, 10, 28, 0.58); /* Zen: semi-trasparente — il body gradient si intravede */ | |
| border: 1px solid rgba(255, 255, 255, 0.08); | |
| box-shadow: | |
| 0 0 0 1px rgba(99,102,241,0.08), | |
| 0 8px 32px rgba(0, 0, 0, 0.50), | |
| inset 0 1px 0 rgba(255, 255, 255, 0.06), | |
| inset 0 -1px 0 rgba(0,0,0,0.3); | |
| border-radius: var(--radius-lg); | |
| backdrop-filter: blur(8px) saturate(120%); /* P10-CSS: ridotto, mobile già disabilitato da @media */ | |
| -webkit-backdrop-filter: blur(8px) saturate(120%); | |
| } | |
| .glass-card:hover { | |
| border-color: rgba(99, 102, 241, 0.36); | |
| box-shadow: | |
| 0 0 0 1px rgba(99,102,241,0.18), | |
| 0 0 20px 0 rgba(99,102,241,0.12), | |
| 0 8px 32px rgba(0, 0, 0, 0.50), | |
| inset 0 1px 0 rgba(255, 255, 255, 0.06); | |
| transition: border-color var(--transition-fast), box-shadow var(--transition-fast); | |
| } | |
| .glass-card:active { | |
| will-change: transform; | |
| transform: scale(0.97); | |
| transition: transform 0.12s ease; | |
| } | |
| /* Glassmorphism — backdrop-filter attivo, sfondo intravisto (Zen/Manus) */ | |
| .glass-surface { | |
| background: rgba(6, 8, 22, 0.58); /* Zen: 0.94 → 0.58 */ | |
| border: 1px solid rgba(99, 102, 241, 0.18); | |
| box-shadow: | |
| 0 0 0 1px rgba(0,212,255,0.06), | |
| 0 8px 40px rgba(0, 0, 0, 0.65); | |
| } | |
| /* ========================================================= | |
| BODY — Deep space background with subtle radial depth | |
| ========================================================= */ | |
| body { | |
| background: | |
| radial-gradient(ellipse at 15% 0%, rgba(99, 102, 241, 0.12) 0%, transparent 48%), | |
| radial-gradient(ellipse at 85% 5%, rgba(139, 92, 246, 0.08) 0%, transparent 42%), | |
| radial-gradient(ellipse at 50% 100%, rgba(0, 212, 255, 0.07) 0%, transparent 50%), | |
| radial-gradient(ellipse at 90% 60%, rgba(99, 102, 241, 0.05) 0%, transparent 38%), | |
| #04050e; | |
| color: var(--text); | |
| -webkit-font-smoothing: antialiased; | |
| -moz-osx-font-smoothing: grayscale; | |
| height: var(--vh, 100dvh); | |
| overflow: hidden; | |
| overscroll-behavior: none; | |
| } | |
| /* ========================================================= | |
| MAIN APP LAYOUT | |
| ========================================================= */ | |
| .app-layout { | |
| display: flex; | |
| width: 100%; | |
| height: var(--vh, 100dvh); | |
| overflow: hidden; | |
| background: transparent; | |
| } | |
| #root { | |
| width: 100%; | |
| height: var(--vh, 100dvh); | |
| display: flex; | |
| } | |
| /* ========================================================= | |
| SIDEBAR DESKTOP — refined futuristic border | |
| ========================================================= */ | |
| .sidebar-desktop { | |
| flex-shrink: 0; | |
| width: 260px; | |
| border-right: 1px solid rgba(99, 102, 241, 0.18); | |
| box-shadow: | |
| 2px 0 32px -4px rgba(0, 0, 0, 0.70), | |
| 1px 0 0 0 rgba(99, 102, 241, 0.08), | |
| inset -1px 0 0 rgba(0, 212, 255, 0.04); | |
| background: rgba(5, 6, 16, 0.82); /* Zen: più trasparente */ | |
| backdrop-filter: blur(24px) saturate(180%); | |
| -webkit-backdrop-filter: blur(16px) saturate(160%); | |
| will-change: transform; /* GAP-8: forza GPU compositing layer — backdrop-filter safe su Safari */ | |
| z-index: 10; | |
| } | |
| [data-theme="light"] .sidebar-desktop { | |
| background: var(--bg2); | |
| box-shadow: 2px 0 16px -4px rgba(0, 0, 0, 0.10); | |
| } | |
| .main-content { | |
| flex: 1; | |
| display: flex; | |
| flex-direction: column; | |
| min-width: 0; | |
| background: transparent; | |
| position: relative; | |
| overflow: hidden; | |
| height: var(--vh, 100dvh); | |
| } | |
| /* ========================================================= | |
| CONV-ROW — ⋯ menu button visibility (S253) | |
| Desktop: hidden, shown on row hover or when menu open | |
| Touch devices: always visible at 45% opacity (no hover available) | |
| ========================================================= */ | |
| .conv-row .conv-menu-btn { opacity: 0; transition: opacity 0.15s; } | |
| .conv-row:hover .conv-menu-btn { opacity: 0.7; } | |
| .conv-row:hover .conv-menu-btn:hover { opacity: 1; background: rgba(59,130,246,0.08) ; } | |
| /* Touch / Mobile: no hover state → always show */ | |
| @media (hover: none) { | |
| .conv-row .conv-menu-btn { opacity: 0.45 ; } | |
| } | |
| /* Sidebar mobile overlay */ | |
| .sidebar-overlay { | |
| position: fixed; | |
| inset: 0; | |
| z-index: var(--z-modal-backdrop); | |
| background: rgba(0, 0, 0, 0.72); /* G2-S202: darker solid bg replaces expensive blur */ | |
| /* backdrop-filter removed — G2-S202: was expensive on mobile Safari */ | |
| display: flex; | |
| animation: overlay-fade-in 0.22s cubic-bezier(0.4, 0, 0.2, 1); | |
| } | |
| .sidebar-overlay > div { | |
| animation: sidebar-slide-in 0.24s cubic-bezier(0.16, 1, 0.3, 1); | |
| } | |
| /* ── S86-UX: Chat card animations ─────────────────────────────────────── */ | |
| @keyframes message-slide-in { | |
| from { opacity: 0; transform: translateY(10px) scale(0.985); } | |
| to { opacity: 1; transform: translateY(0) scale(1); } | |
| } | |
| @keyframes bounce-dot { | |
| 0%, 80%, 100% { transform: scale(0.55); opacity: 0.35; } | |
| 40% { transform: scale(1); opacity: 1; } | |
| } | |
| @keyframes stream-border-pulse { | |
| 0%, 100% { | |
| border-color: rgba(0,212,255,0.22); | |
| box-shadow: | |
| 0 0 0 1px rgba(0,212,255,0.08), | |
| 0 4px 20px rgba(0,0,0,0.38); | |
| } | |
| 50% { | |
| border-color: rgba(0,212,255,0.60); | |
| box-shadow: | |
| 0 0 0 1px rgba(0,212,255,0.20), | |
| 0 0 28px 0 rgba(0,212,255,0.22), | |
| 0 0 56px 0 rgba(99,102,241,0.10), | |
| 0 4px 20px rgba(0,0,0,0.38); | |
| } | |
| } | |
| @keyframes waveform-bar { | |
| 0%, 100% { transform: scaleY(0.4); opacity: 0.5; } | |
| 50% { transform: scaleY(1.0); opacity: 1.0; } | |
| } | |
| /* CSS class applied to AI card while streaming */ | |
| .chat-card-streaming { | |
| animation: stream-border-pulse 2.2s ease-in-out infinite; | |
| } | |
| /* S313-perf: content-visibility — browser skips rendering off-screen messages | |
| Riduce il tempo di paint su conversazioni lunghe del ~60% su mobile */ | |
| .chat-message-item { | |
| content-visibility: auto; | |
| contain-intrinsic-size: 0 90px; | |
| } | |
| @keyframes overlay-fade-in { | |
| from { opacity: 0; } | |
| to { opacity: 1; } | |
| } | |
| @keyframes sidebar-slide-in { | |
| from { transform: translateX(-100%); } | |
| to { transform: translateX(0); } | |
| } | |
| /* ── Tab pane fade+lift on switch ── */ | |
| .tab-pane-active { | |
| animation: tab-fade-in 0.18s cubic-bezier(0.16, 1, 0.3, 1) both; | |
| } | |
| @keyframes tab-fade-in { | |
| from { opacity: 0; transform: translateY(5px); } | |
| to { opacity: 1; transform: translateY(0); } | |
| } | |
| /* ========================================================= | |
| SCROLLBAR — minimal, indigo tint | |
| ========================================================= */ | |
| ::-webkit-scrollbar { | |
| width: 3px; | |
| height: 3px; | |
| } | |
| ::-webkit-scrollbar-thumb { | |
| background: rgba(99,102,241,0.28); | |
| border-radius: 999px; | |
| } | |
| ::-webkit-scrollbar-thumb:hover { | |
| background: rgba(99,102,241,0.50); | |
| box-shadow: 0 0 6px rgba(99,102,241,0.4); | |
| } | |
| ::-webkit-scrollbar-track { | |
| background: transparent; | |
| } | |
| /* ========================================================= | |
| CHAT INPUT CONTAINER — focus glow (CSS-only, no JS) | |
| ========================================================= */ | |
| .chat-input-container { | |
| max-width: 700px; | |
| margin: 0 auto; | |
| display: flex; | |
| flex-direction: column; | |
| border-radius: var(--radius-xl); | |
| background: rgba(8, 10, 28, 0.90); | |
| border: 1px solid rgba(99, 102, 241, 0.22); | |
| overflow: visible; | |
| backdrop-filter: none; | |
| -webkit-backdrop-filter: none; | |
| box-shadow: | |
| 0 0 0 1px rgba(99,102,241,0.06), | |
| 0 8px 32px rgba(0,0,0,0.40), | |
| inset 0 1px 0 rgba(255,255,255,0.05); | |
| transition: border-color var(--transition-normal), box-shadow var(--transition-normal); | |
| } | |
| .chat-input-container:focus-within { | |
| border-color: rgba(99, 102, 241, 0.55); | |
| box-shadow: | |
| 0 0 0 3px rgba(99, 102, 241, 0.14), | |
| 0 0 32px 0 rgba(99, 102, 241, 0.18), | |
| 0 0 64px 0 rgba(0, 212, 255, 0.08), | |
| 0 8px 32px rgba(0,0,0,0.40), | |
| inset 0 1px 0 rgba(255,255,255,0.06); | |
| } | |
| /* ========================================================= | |
| COMMIT BADGE — monospace futuristic | |
| ========================================================= */ | |
| .commit-badge { | |
| display: flex; | |
| align-items: center; | |
| gap: 4px; | |
| font-size: 0.62rem; | |
| padding: 3px 7px; | |
| border-radius: var(--radius-sm); | |
| background: rgba(99,102,241,0.06); | |
| border: 1px solid rgba(99,102,241,0.16); | |
| color: var(--text-muted); | |
| text-decoration: none; | |
| font-family: var(--font-mono); | |
| letter-spacing: 0.04em; | |
| transition: border-color var(--transition-fast), color var(--transition-fast), box-shadow var(--transition-fast); | |
| } | |
| .commit-badge:hover { | |
| border-color: rgba(0, 212, 255, 0.35); | |
| color: var(--accent); | |
| box-shadow: 0 0 8px rgba(0,212,255,0.18); | |
| } | |
| /* ========================================================= | |
| CODE / PRE | |
| ========================================================= */ | |
| pre, code { | |
| overflow-x: auto; | |
| font-family: var(--font-mono); | |
| } | |
| /* ========================================================= | |
| ANIMAZIONI — GPU-safe (opacity + box-shadow only) | |
| Tutte rispettano prefers-reduced-motion | |
| ========================================================= */ | |
| /* Glow che respira lentamente — tab attivo, elementi chiave */ | |
| @keyframes neon-breathe { | |
| 0%, 100% { text-shadow: 0 0 6px rgba(0, 212, 255, 0.25); } | |
| 50% { text-shadow: 0 0 14px rgba(0, 212, 255, 0.55), 0 0 4px rgba(59,130,246,0.3); } | |
| } | |
| /* Pulsazione dot streaming — più elettrico */ | |
| @keyframes brain-glow { | |
| 0%, 100% { filter: drop-shadow(0 0 2px rgba(59,130,246,0.2)); } | |
| 50% { filter: drop-shadow(0 0 10px rgba(0, 212, 255, 0.6)); } | |
| } | |
| @keyframes neuron-pulse { | |
| 0%, 100% { opacity: 0.3; transform: scale(0.7); } | |
| 50% { opacity: 1; transform: scale(1.3); } | |
| } | |
| @keyframes neuron-line-pulse { | |
| 0%, 100% { opacity: 0.08; } | |
| 50% { opacity: 0.5; } | |
| } | |
| @keyframes fadeIn { | |
| from { opacity: 0; transform: translateY(4px); } | |
| to { opacity: 1; transform: translateY(0); } | |
| } | |
| @keyframes fadeInUp { | |
| from { opacity: 0; transform: translateY(10px); } | |
| to { opacity: 1; transform: translateY(0); } | |
| } | |
| /* Dot streaming — più cyan, più elettrico */ | |
| @keyframes pulse-dot { | |
| 0%, 100% { opacity: 1; transform: scale(1); box-shadow: 0 0 4px var(--accent); } | |
| 50% { opacity: 0.3; transform: scale(0.7); box-shadow: 0 0 2px transparent; } | |
| } | |
| @keyframes pulse { | |
| 0%, 100% { opacity: 1; } | |
| 50% { opacity: 0.35; } | |
| } | |
| @keyframes chip-pulse { | |
| 0%, 100% { opacity: 1; } | |
| 50% { opacity: 0.4; } | |
| } | |
| @keyframes dot-blink { | |
| 0%, 100% { opacity: 0.15; } | |
| 50% { opacity: 1; } | |
| } | |
| @keyframes chip-fadein { | |
| from { opacity: 0; transform: translateY(3px); } | |
| to { opacity: 1; transform: translateY(0); } | |
| } | |
| @keyframes pulse-ring { | |
| 0% { transform: scale(1); opacity: 0.6; } | |
| 100% { transform: scale(1.6); opacity: 0; } | |
| } | |
| @keyframes mem-tab-pulse { | |
| 0% { transform: scale(1); opacity: 1; box-shadow: 0 0 0 0 rgba(59,130,246,0.7); } | |
| 50% { transform: scale(1.2); opacity: 0.85; box-shadow: 0 0 0 4px rgba(59,130,246,0); } | |
| 100% { transform: scale(1); opacity: 1; box-shadow: 0 0 0 0 rgba(59,130,246,0.7); } | |
| } | |
| @keyframes blink-cursor { | |
| 0%, 100% { opacity: 0.8; } | |
| 50% { opacity: 0; } | |
| } | |
| /* ========================================================= | |
| P42-REPLIT — Replit-style streaming text effect | |
| - replit-para-reveal : fade-in per nuovi <p> durante streaming | |
| - replit-chunk-flash : flash cyan al cursore ogni ~22 char | |
| Zero layout-thrashing: solo opacity (GPU-accelerated) | |
| ========================================================= */ | |
| @keyframes replit-para-reveal { | |
| from { opacity: 0; } | |
| to { opacity: 1; } | |
| } | |
| /* Ogni nuovo <p> dentro una card in streaming appare con fade-in */ | |
| .chat-card-streaming p, | |
| .chat-card-streaming li { | |
| animation: replit-para-reveal 0.30s cubic-bezier(0.16, 1, 0.3, 1) both; | |
| } | |
| @keyframes replit-chunk-flash { | |
| 0% { opacity: 0.85; width: 5px; } | |
| 60% { opacity: 0.25; width: 3px; } | |
| 100% { opacity: 0; width: 0; } | |
| } | |
| /* Span effimero — rimontato ogni ~22 char di streaming per dare il pop Replit */ | |
| .replit-chunk-glow { | |
| display: inline-block; | |
| height: 0.85em; | |
| width: 0; | |
| border-radius: 2px; | |
| background: rgba(0, 212, 255, 0.55); | |
| vertical-align: middle; | |
| margin-left: 1px; | |
| animation: replit-chunk-flash 0.42s ease-out forwards; | |
| pointer-events: none; | |
| flex-shrink: 0; | |
| } | |
| /* Shimmer skeleton — più freddo/cyan */ | |
| @keyframes shimmer { | |
| 0% { background-position: -200% 0; } | |
| 100% { background-position: 200% 0; } | |
| } | |
| /* Glow pulse — input / card attive */ | |
| @keyframes glow-pulse { | |
| 0%, 100% { box-shadow: 0 0 0 0 rgba(99,102,241,0); } | |
| 50% { | |
| box-shadow: | |
| 0 0 22px 2px rgba(99,102,241,0.22), | |
| 0 0 8px 0 rgba(0, 212, 255, 0.14); | |
| } | |
| } | |
| /* Glow breathe — per elementi accent (logo, avatar, dot attivo) */ | |
| @keyframes glow-breathe { | |
| 0%, 100% { | |
| box-shadow: 0 0 4px rgba(0,212,255,0.20), 0 0 12px rgba(99,102,241,0.10); | |
| } | |
| 50% { | |
| box-shadow: 0 0 16px rgba(0,212,255,0.55), 0 0 32px rgba(99,102,241,0.25), 0 0 48px rgba(139,92,246,0.12); | |
| } | |
| } | |
| /* Indigo glow for buttons */ | |
| @keyframes indigo-glow-pulse { | |
| 0%, 100% { box-shadow: 0 0 8px rgba(99,102,241,0.25); } | |
| 50% { box-shadow: 0 0 20px rgba(99,102,241,0.55), 0 0 40px rgba(99,102,241,0.18); } | |
| } | |
| @keyframes avatar-pulse { | |
| 0%, 100% { opacity: 1; filter: drop-shadow(0 0 0 rgba(0, 212, 255, 0)); } | |
| 50% { opacity: 0.7; filter: drop-shadow(0 0 5px rgba(0, 212, 255, 0.45)); } | |
| } | |
| @keyframes spin { | |
| to { transform: rotate(360deg); } | |
| } | |
| /* Scan line futuristica — solo per decorazione leggera su desktop */ | |
| @keyframes scan-line { | |
| 0% { transform: translateY(-100%); opacity: 0; } | |
| 10% { opacity: 0.025; } | |
| 90% { opacity: 0.025; } | |
| 100% { transform: translateY(200%); opacity: 0; } | |
| } | |
| /* ========================================================= | |
| PROSE — Markdown (ChatMessage) | |
| ========================================================= */ | |
| .prose { | |
| color: var(--text, #e4e4f0); | |
| font-size: 0.92rem; | |
| line-height: 1.72; | |
| word-break: break-word; | |
| overflow-wrap: anywhere; | |
| } | |
| .prose p { margin-bottom: 1.2rem; } | |
| .prose p:last-child { margin-bottom: 0; } | |
| /* S739: heading typography — erano completamente assenti, titoli Markdown invisibili */ | |
| .prose h1, .prose h2, .prose h3, .prose h4 { | |
| font-weight: 700; | |
| line-height: 1.3; | |
| margin-top: 1.5rem; | |
| margin-bottom: 0.55rem; | |
| color: var(--text-bright, #f0f0ff); | |
| } | |
| .prose h1:first-child, .prose h2:first-child, .prose h3:first-child { margin-top: 0; } | |
| .prose h1 { font-size: 1.45rem; } | |
| .prose h2 { font-size: 1.22rem; border-bottom: 1px solid rgba(99,102,241,0.18); padding-bottom: 0.2rem; } | |
| .prose h3 { font-size: 1.06rem; } | |
| .prose h4 { font-size: 0.97rem; font-weight: 600; } | |
| /* S739: liste, citazioni, tabelle, link */ | |
| .prose ul, .prose ol { padding-left: 1.4rem; margin-bottom: 1rem; } | |
| .prose li { margin-bottom: 0.28rem; } | |
| .prose li > ul, .prose li > ol { margin-bottom: 0; margin-top: 0.2rem; } | |
| .prose blockquote { | |
| border-left: 3px solid var(--accent, #6366f1); | |
| padding: 0.1rem 0 0.1rem 0.9rem; | |
| margin: 1rem 0; | |
| color: var(--text-muted, #a0a0b8); | |
| font-style: italic; | |
| } | |
| .prose hr { border: none; border-top: 1px solid var(--border-indigo); margin: 1.4rem 0; } | |
| .prose a { color: #818cf8; text-decoration: underline; text-underline-offset: 2px; } | |
| .prose a:hover { color: #a5b4fc; } | |
| .prose strong { font-weight: 700; color: var(--text-bright, #f0f0ff); } | |
| .prose em { font-style: italic; } | |
| .prose table { width: 100%; border-collapse: collapse; margin-bottom: 1rem; font-size: 0.87em; } | |
| .prose th { | |
| background: rgba(99,102,241,0.12); | |
| padding: 0.38rem 0.7rem; | |
| border: 1px solid var(--border-indigo); | |
| text-align: left; | |
| font-weight: 600; | |
| color: var(--text-bright, #f0f0ff); | |
| } | |
| .prose td { padding: 0.38rem 0.7rem; border: 1px solid rgba(99,102,241,0.12); } | |
| .prose tr:nth-child(even) td { background: rgba(99,102,241,0.04); } | |
| .prose pre { | |
| border-radius: 10px; | |
| overflow-x: auto; | |
| font-size: 0.82em; | |
| background: rgba(8, 8, 20, 0.8); | |
| border: 1px solid var(--border-indigo); | |
| } | |
| .prose code:not(pre code) { | |
| background: rgba(59,130,246,0.1); | |
| border: 1px solid rgba(59,130,246,0.15); | |
| border-radius: var(--radius-sm); | |
| padding: 1px 5px; | |
| font-size: 0.85em; | |
| color: #93c5fd; | |
| font-family: var(--font-mono); | |
| } | |
| /* ========================================================= | |
| AGENT TIMELINE — AgentStepsPanel | |
| ========================================================= */ | |
| .agent-step-card { | |
| border-radius: 10px; | |
| overflow: hidden; | |
| transition: border-color var(--transition-normal); | |
| } | |
| .agent-step-card-running { | |
| border-color: rgba(0, 212, 255, 0.25); | |
| background: rgba(0, 212, 255, 0.03); | |
| } | |
| .agent-step-card-done { | |
| border-color: rgba(74, 222, 128, 0.12); | |
| } | |
| .agent-step-card-error { | |
| border-color: rgba(239, 68, 68, 0.28); | |
| background: rgba(239, 68, 68, 0.03); | |
| } | |
| /* ========================================================= | |
| INPUT AREA — bottom safe area iOS | |
| ========================================================= */ | |
| .input-area { | |
| flex-shrink: 0; | |
| border-top: 1px solid rgba(99, 102, 241, 0.20); | |
| box-shadow: 0 -1px 0 0 rgba(0, 212, 255, 0.06), 0 -8px 32px rgba(99,102,241,0.04); | |
| background: rgba(4, 5, 14, 0.96); | |
| backdrop-filter: blur(20px) saturate(160%); | |
| -webkit-backdrop-filter: blur(20px) saturate(160%); | |
| will-change: transform; /* GAP-8: compositing layer per backdrop-filter corretto durante scroll */ | |
| padding-bottom: max(0.5rem, env(safe-area-inset-bottom)); | |
| } | |
| /* ========================================================= | |
| iOS / SAFARI PERFORMANCE | |
| ========================================================= */ | |
| /* S243: iOS Safari — DISABLE backdrop-filter (correzione: era un bug che aggiungeva blur invece di rimuoverlo) */ | |
| /* S437: aggiunto [aria-live] per AgentLiveBar (che usa backdropFilter inline) */ | |
| /* S741: aggiunto .input-area — blur(20px) durante scrolling era il principale bottleneck su iPhone */ | |
| .ios .sidebar-desktop, | |
| .ios .glass, | |
| .ios [aria-live] { backdrop-filter: none ; -webkit-backdrop-filter: none ; } | |
| .ios .token-overlay { backdrop-filter: none ; -webkit-backdrop-filter: none ; } | |
| /* S741: .input-area usa blur(20px) — visibile sempre durante scroll → rimosso su iOS */ | |
| /* .network-banner light-theme ha blur(14px) ma solo su [data-theme="light"] → impatto minore, invariato */ | |
| .ios .chat-input-glass { backdrop-filter: none ; -webkit-backdrop-filter: none ; } /* GAP-8: mancava */ | |
| .ios .network-banner { backdrop-filter: none ; -webkit-backdrop-filter: none ; } /* GAP-8: mancava */ | |
| .ios .input-area { backdrop-filter: none ; -webkit-backdrop-filter: none ; | |
| background: rgba(4, 5, 14, 0.99) ; } | |
| /* ========================================================= | |
| MOBILE | |
| ========================================================= */ | |
| @media (max-width: 768px) { | |
| .sidebar-desktop { display: none ; } | |
| .main-content { width: 100%; height: var(--vh, 100dvh); } | |
| } | |
| /* ========================================================= | |
| iOS SAFE AREA fallback | |
| ========================================================= */ | |
| @supports (-webkit-touch-callout: none) { | |
| .main-content { height: var(--vh, 100dvh); } | |
| } | |
| /* ========================================================= | |
| MOBILE KEYBOARD FIX | |
| ========================================================= */ | |
| textarea { | |
| touch-action: manipulation; /* previene zoom doppio tap e migliora risposta iOS */ | |
| } | |
| textarea:focus { | |
| scroll-margin-bottom: 0; /* rimosso: causava scroll jump aggiuntivo su Safari */ | |
| outline: none; | |
| } | |
| .messages-scroll { | |
| scroll-padding-bottom: 80px; | |
| overscroll-behavior-y: contain; | |
| } | |
| /* ========================================================= | |
| SUGGESTION CARDS | |
| ========================================================= */ | |
| .premium-suggestion-card { | |
| transition: background var(--transition-fast), border-color var(--transition-fast), box-shadow var(--transition-fast) ; | |
| border: 1px solid rgba(99,102,241,0.14); | |
| border-radius: var(--radius-md) ; | |
| } | |
| .premium-suggestion-card:hover { | |
| border-color: rgba(99,102,241,0.38); | |
| box-shadow: | |
| 0 0 0 1px rgba(99,102,241,0.12), | |
| 0 0 16px 0 rgba(99,102,241,0.12), | |
| 0 4px 16px rgba(0,0,0,0.28); | |
| background: rgba(99,102,241,0.06) ; | |
| } | |
| /* ========================================================= | |
| GPU LAYER HINTS — parsimoniosi | |
| ========================================================= */ | |
| [style*="pulse-dot"], | |
| [style*="spin-slow"], | |
| [style*="pulse-ring"] { | |
| will-change: transform, opacity; | |
| } | |
| /* ========================================================= | |
| PREFERS-REDUCED-MOTION — iPhone "Riduci movimento" | |
| ========================================================= */ | |
| @media (prefers-reduced-motion: reduce) { | |
| *, *::before, *::after { | |
| animation-duration: 0.01ms ; | |
| animation-iteration-count: 1 ; | |
| transition-duration: 0.01ms ; | |
| scroll-behavior: auto ; | |
| } | |
| @keyframes fadeIn { | |
| from { opacity: 1; transform: none; } | |
| to { opacity: 1; transform: none; } | |
| } | |
| @keyframes fadeInUp { | |
| from { opacity: 1; transform: none; } | |
| to { opacity: 1; transform: none; } | |
| } | |
| .chat-input-container:focus-within { | |
| box-shadow: none; | |
| } | |
| } | |
| /* ========================================================= | |
| DESKTOP ONLY — background depth grid (very subtle) | |
| Solo su schermi > 768px, non impatta mobile/iPhone | |
| ========================================================= */ | |
| @media (min-width: 769px) { | |
| body::after { | |
| content: ''; | |
| position: fixed; | |
| inset: 0; | |
| background-image: | |
| linear-gradient(rgba(99, 102, 241, 0.028) 1px, transparent 1px), | |
| linear-gradient(90deg, rgba(99, 102, 241, 0.028) 1px, transparent 1px); | |
| background-size: 42px 42px; | |
| pointer-events: none; | |
| z-index: 0; | |
| } | |
| .app-layout, .main-content, .sidebar-desktop { | |
| position: relative; | |
| z-index: 1; | |
| } | |
| } | |
| /* ========================================================= | |
| MIGLIORIA 1 — Waveform bars TypingIndicator | |
| ========================================================= */ | |
| @keyframes waveform-bar { | |
| 0%, 100% { transform: scaleY(0.3); opacity: 0.4; } | |
| 50% { transform: scaleY(1); opacity: 1; } | |
| } | |
| /* ========================================================= | |
| MIGLIORIA 4 — Cinematic message entrance | |
| ========================================================= */ | |
| @keyframes message-slide-in { | |
| from { opacity: 0; transform: translateY(10px); } | |
| to { opacity: 1; transform: translateY(0); } | |
| } | |
| /* ========================================================= | |
| MIGLIORIA 5 — EmptyState logo ring glow pulse | |
| ========================================================= */ | |
| @keyframes neon-ring-pulse { | |
| 0%, 100% { box-shadow: 0 0 0 0 rgba(0,212,255,0), 0 8px 24px rgba(59,130,246,0.12); } | |
| 50% { box-shadow: 0 0 0 8px rgba(0,212,255,0.06), 0 8px 32px rgba(59,130,246,0.22), 0 0 40px rgba(0,212,255,0.08); } | |
| } | |
| /* Boot flicker — per EmptyState title */ | |
| @keyframes boot-flicker { | |
| 0% { opacity: 0; } | |
| 10% { opacity: 0.9; } | |
| 12% { opacity: 0.2; } | |
| 14% { opacity: 1; } | |
| 100% { opacity: 1; } | |
| } | |
| /* Staggered fade for EmptyState cards */ | |
| @keyframes card-enter { | |
| from { opacity: 0; transform: translateY(8px); } | |
| to { opacity: 1; transform: translateY(0); } | |
| } | |
| /* ========================================================= | |
| TEMA CHIARO — S_THEME (light/dark/auto) | |
| Attivato dalla classe data-theme="light" su <html> | |
| ========================================================= */ | |
| [data-theme="light"] { | |
| --bg: #f2f3fc; | |
| --bg2: #e8eaf7; | |
| --bg3: #dfe1f4; | |
| --bg4: #d5d7ee; | |
| --bg-surface: #e4e6f5; | |
| --border: rgba(0, 0, 0, 0.08); | |
| --border-indigo: rgba(99,102,241,0.28); | |
| --border-cyan: rgba(0, 150, 200, 0.26); | |
| --border-glow: rgba(99, 102, 241, 0.45); | |
| --text: #0c0d24; | |
| --text-muted: #42446a; | |
| --text-dim: #7070a0; | |
| --primary: #6366f1; | |
| --primary-light: #818cf8; | |
| --primary-dark: #4f46e5; | |
| --accent: #0096c7; | |
| --accent-dim: rgba(0, 150, 200, 0.12); | |
| --accent-glow: rgba(0, 150, 200, 0.30); | |
| --glow-indigo: rgba(99,102,241,0.18); | |
| --glow-cyan: rgba(0, 150, 200, 0.14); | |
| --glow-violet: rgba(139,92,246,0.15); | |
| --avatar-primary: #6366f1; | |
| --avatar-accent: #0096c7; | |
| --narration-text: rgba(80, 60, 220, 0.75); | |
| /* footer button vars — S232 light theme */ | |
| --footer-btn-color: #4a4a6a; | |
| --footer-btn-bg: rgba(0,0,0,0.04); | |
| --footer-btn-border: rgba(0,0,0,0.12); | |
| /* ── Chat message card — light theme ── */ | |
| --card-bg: rgba(255, 255, 255, 0.90); | |
| --card-bg-error: rgba(255, 240, 240, 0.95); | |
| --card-border-streaming: rgba(0, 150, 200, 0.38); | |
| --card-border-idle: rgba(0, 0, 0, 0.10); | |
| --card-border-error: rgba(239, 68, 68, 0.32); | |
| --card-shadow-streaming: 0 0 0 1px rgba(0,150,200,0.12), 0 4px 24px rgba(0,0,0,0.10); | |
| --card-shadow-idle: 0 2px 12px rgba(0,0,0,0.08); | |
| /* ── User bubble — light theme ── */ | |
| --user-bubble-bg: rgba(59,130,246,0.16); | |
| --user-bubble-text: #0a1f3d; | |
| --user-bubble-border: rgba(59,130,246,0.32); | |
| } | |
| /* ── NetworkBanner — light theme overrides (bg più opaco per leggibilità) ── */ | |
| [data-theme="light"] .network-banner { | |
| background: rgba(200, 200, 220, 0.72) ; | |
| backdrop-filter: blur(14px) saturate(140%); | |
| -webkit-backdrop-filter: blur(14px) saturate(140%); | |
| } | |
| [data-theme="light"] .network-banner[data-quality="offline"], | |
| [data-theme="light"] .network-banner[data-quality="poor"] { | |
| background: rgba(254, 226, 226, 0.85) ; | |
| } | |
| [data-theme="light"] .network-banner[data-quality="reconnected"] { | |
| background: rgba(220, 252, 231, 0.85) ; | |
| } | |
| [data-theme="light"] body { | |
| background: | |
| radial-gradient(ellipse at 15% 0%, rgba(99, 102, 241, 0.10) 0%, transparent 48%), | |
| radial-gradient(ellipse at 85% 5%, rgba(139, 92, 246, 0.06) 0%, transparent 42%), | |
| radial-gradient(ellipse at 50% 100%, rgba(0, 150, 200, 0.07) 0%, transparent 50%), | |
| #eeeff9; | |
| color: var(--text); | |
| } | |
| /* ── Glass input bar + sidebar menu — glow edition ── */ | |
| .chat-input-glass { | |
| background: rgba(6, 7, 20, 0.90); | |
| border: 1px solid rgba(99, 102, 241, 0.22); | |
| backdrop-filter: none; | |
| -webkit-backdrop-filter: none; | |
| box-shadow: | |
| 0 -4px 32px rgba(0,0,0,0.38), | |
| 0 -1px 0 rgba(0,212,255,0.06), | |
| inset 0 1px 0 rgba(255,255,255,0.05); | |
| } | |
| [data-theme="light"] .chat-input-glass { | |
| background: rgba(242, 244, 255, 0.94); | |
| border: 1px solid rgba(99,102,241,0.18); | |
| backdrop-filter: blur(24px) saturate(180%); | |
| -webkit-backdrop-filter: blur(24px) saturate(180%); | |
| will-change: transform; /* GAP-8 */ | |
| box-shadow: 0 -4px 24px rgba(0,0,0,0.06), inset 0 1px 0 rgba(255,255,255,0.9); | |
| } | |
| .sidebar-glass { | |
| background: rgba(5, 6, 16, 0.96); | |
| border-right: 1px solid rgba(99,102,241,0.18); | |
| box-shadow: | |
| 2px 0 40px rgba(0,0,0,0.50), | |
| inset -1px 0 0 rgba(0,212,255,0.04); | |
| } | |
| [data-theme="light"] .sidebar-glass { | |
| background: rgba(246, 246, 255, 0.96); | |
| border-right: 1px solid rgba(99,102,241,0.12); | |
| box-shadow: 2px 0 18px rgba(0,0,0,0.05); | |
| } | |
| [data-theme="light"] .sidebar-desktop { | |
| background: rgba(245, 246, 255, 0.96); | |
| border-right: 1px solid rgba(37, 99, 235, 0.12); | |
| box-shadow: 2px 0 20px rgba(37,99,235,0.05); | |
| } | |
| /* S313-iOS: keyboard height compensation — set dynamically by ChatInputBar visualViewport */ | |
| :root { | |
| --keyboard-height: 0px; | |
| } | |
| /* ========================================================= | |
| S752-FE — Modern touch: gradient brand + micro-interactions | |
| ========================================================= */ | |
| /* Agent brand gradient — indigo→cyan, usato nella SidebarHeader */ | |
| .agent-brand-gradient { | |
| background: linear-gradient(90deg, | |
| var(--primary-light) 0%, | |
| var(--accent) 65%, | |
| var(--primary) 100% | |
| ); | |
| -webkit-background-clip: text; | |
| -webkit-text-fill-color: transparent; | |
| background-clip: text; | |
| font-weight: 700; | |
| letter-spacing: -0.025em; | |
| will-change: auto; | |
| } | |
| /* Send button active scale — micro-feedback su tap/click */ | |
| .send-action-btn:active { | |
| transform: scale(0.82) ; | |
| transition: transform 0.07s ease ; | |
| } | |
| /* New-chat button pulse on hover (Replit-style) */ | |
| .new-chat-btn:hover { | |
| box-shadow: | |
| 0 0 0 3px rgba(99,102,241,0.18), | |
| 0 6px 20px rgba(99,102,241,0.30) ; | |
| } | |
| .new-chat-btn:active { | |
| transform: scale(0.97) ; | |
| } | |
| /* Conv-row active: indigo left indicator bar */ | |
| .conv-row-active::before { | |
| content: ''; | |
| position: absolute; | |
| left: 0; | |
| top: 20%; | |
| height: 60%; | |
| width: 2px; | |
| border-radius: 0 2px 2px 0; | |
| background: var(--primary); | |
| opacity: 0.9; | |
| } | |
| /* ========================================================= | |
| GAP-7: Safari Performance Gate — mobile backdrop-filter | |
| backdrop-filter: blur() è MOLTO costoso su iPhone (Safari WebKit): | |
| - Forza GPU compositing layer su ogni elemento con la proprietà | |
| - Con molti elementi .glass-card in chat: frame drop visibili su A13 e inferiori | |
| Fix: su max-width 768px (mobile) → disabilita backdrop-filter, | |
| usa solid background come fallback visivamente accettabile. | |
| ChatMessage.tsx è già wrapped in memo() → nessuna modifica necessaria. | |
| content-visibility: auto su .chat-message-item già presente (S313-perf). | |
| ========================================================= */ | |
| @media (max-width: 768px) { | |
| .glass-card { | |
| backdrop-filter: none ; | |
| -webkit-backdrop-filter: none ; | |
| background: rgba(4, 5, 14, 0.94) ; | |
| } | |
| .glass-surface { | |
| backdrop-filter: none ; | |
| -webkit-backdrop-filter: none ; | |
| background: rgba(6, 8, 22, 0.96) ; | |
| } | |
| .sidebar-desktop { | |
| backdrop-filter: none ; | |
| -webkit-backdrop-filter: none ; | |
| background: rgba(5, 6, 16, 0.97) ; | |
| } | |
| /* Mantieni will-change: transform per GPU compositing — necessario per smooth scroll */ | |
| .sidebar-desktop, | |
| .glass-card { | |
| will-change: transform; | |
| } | |
| } | |
| /* ========================================================= | |
| P43-REPLIT: Typewriter reveal (risposte non-streaming) | |
| - .replit-typewriter : ogni <p> appare con stagger 50ms | |
| - .replit-stream-done : flash indigo al completamento streaming | |
| GPU-safe: solo opacity + transform (compositor-only). | |
| Rispetta prefers-reduced-motion. | |
| ========================================================= */ | |
| @keyframes replit-typewriter-reveal { | |
| from { opacity: 0; transform: translateY(4px); } | |
| to { opacity: 1; transform: translateY(0); } | |
| } | |
| /* Stagger per i primi 8 paragrafi, poi tutti a 350ms */ | |
| .replit-typewriter p:nth-child(1) { animation: replit-typewriter-reveal 0.32s cubic-bezier(0.16,1,0.3,1) 0ms both; } | |
| .replit-typewriter p:nth-child(2) { animation: replit-typewriter-reveal 0.32s cubic-bezier(0.16,1,0.3,1) 55ms both; } | |
| .replit-typewriter p:nth-child(3) { animation: replit-typewriter-reveal 0.32s cubic-bezier(0.16,1,0.3,1) 110ms both; } | |
| .replit-typewriter p:nth-child(4) { animation: replit-typewriter-reveal 0.32s cubic-bezier(0.16,1,0.3,1) 165ms both; } | |
| .replit-typewriter p:nth-child(5) { animation: replit-typewriter-reveal 0.32s cubic-bezier(0.16,1,0.3,1) 220ms both; } | |
| .replit-typewriter p:nth-child(6) { animation: replit-typewriter-reveal 0.32s cubic-bezier(0.16,1,0.3,1) 275ms both; } | |
| .replit-typewriter p:nth-child(7) { animation: replit-typewriter-reveal 0.32s cubic-bezier(0.16,1,0.3,1) 330ms both; } | |
| .replit-typewriter p:nth-child(n+8) { animation: replit-typewriter-reveal 0.32s cubic-bezier(0.16,1,0.3,1) 350ms both; } | |
| /* Liste inline stagger */ | |
| .replit-typewriter li:nth-child(1) { animation: replit-typewriter-reveal 0.28s cubic-bezier(0.16,1,0.3,1) 30ms both; } | |
| .replit-typewriter li:nth-child(2) { animation: replit-typewriter-reveal 0.28s cubic-bezier(0.16,1,0.3,1) 75ms both; } | |
| .replit-typewriter li:nth-child(3) { animation: replit-typewriter-reveal 0.28s cubic-bezier(0.16,1,0.3,1) 120ms both; } | |
| .replit-typewriter li:nth-child(4) { animation: replit-typewriter-reveal 0.28s cubic-bezier(0.16,1,0.3,1) 165ms both; } | |
| .replit-typewriter li:nth-child(n+5) { animation: replit-typewriter-reveal 0.28s cubic-bezier(0.16,1,0.3,1) 200ms both; } | |
| /* Completamento streaming: brightness flash indigo sottile */ | |
| @keyframes replit-stream-done { | |
| 0% { filter: brightness(1) drop-shadow(0 0 0px rgba(129,140,248,0)); } | |
| 20% { filter: brightness(1.06) drop-shadow(0 0 6px rgba(129,140,248,0.22)); } | |
| 100% { filter: brightness(1) drop-shadow(0 0 0px rgba(129,140,248,0)); } | |
| } | |
| .replit-stream-done { | |
| animation: replit-stream-done 0.65s ease-out forwards; | |
| } | |
| /* Rispetta prefers-reduced-motion */ | |
| @media (prefers-reduced-motion: reduce) { | |
| .replit-typewriter p, | |
| .replit-typewriter li, | |
| .replit-stream-done { | |
| animation: none ; | |
| opacity: 1 ; | |
| transform: none ; | |
| filter: none ; | |
| } | |
| } | |
| /* ========================================================= | |
| UI-MOB1 — Mobile header optimisation | |
| ========================================================= */ | |
| .chat-header-bar { | |
| backdrop-filter: blur(20px) saturate(160%); | |
| -webkit-backdrop-filter: blur(20px) saturate(160%); | |
| } | |
| .header-badge-desktop { display: contents; } | |
| @media (max-width: 768px) { | |
| .chat-header-bar { | |
| backdrop-filter: none ; | |
| -webkit-backdrop-filter: none ; | |
| } | |
| .header-badge-desktop { display: none ; } | |
| } | |
| /* ========================================================= | |
| REPLIT SPLIT LAYOUT — desktop: chat sx, workspace dx | |
| S-SPLIT: pannelli affiancati sempre visibili su desktop | |
| ========================================================= */ | |
| .split-chat-pane { | |
| width: 400px; | |
| flex-shrink: 0; | |
| display: flex; | |
| flex-direction: column; | |
| overflow: hidden; | |
| border-right: 1px solid rgba(99, 102, 241, 0.18); | |
| background: rgba(4, 5, 14, 0.97); | |
| } | |
| .split-divider { | |
| width: 4px; | |
| flex-shrink: 0; | |
| cursor: col-resize; | |
| background: rgba(99, 102, 241, 0.0); | |
| display: flex; | |
| align-items: center; | |
| justify-content: center; | |
| transition: background var(--transition-fast); | |
| } | |
| .split-divider::after { | |
| content: ""; | |
| display: block; | |
| width: 2px; | |
| height: 48px; | |
| border-radius: 9px; | |
| background: rgba(99, 102, 241, 0.28); | |
| transition: background var(--transition-fast), height var(--transition-fast); | |
| } | |
| .split-divider:hover { | |
| background: rgba(99, 102, 241, 0.06); | |
| } | |
| .split-divider:hover::after { | |
| background: rgba(99, 102, 241, 0.55); | |
| height: 64px; | |
| } | |
| .split-workspace-pane { | |
| flex: 1; | |
| display: flex; | |
| flex-direction: column; | |
| overflow: hidden; | |
| min-width: 0; | |
| } | |
| /* ========================================================= | |
| GAP-4/5: MOTION REDUCTION & MOBILE HOVER OPTIMIZATION | |
| ========================================================= */ | |
| @media (prefers-reduced-motion: reduce) { | |
| *, *::before, *::after { | |
| animation-duration: 0.01ms ; | |
| animation-iteration-count: 1 ; | |
| transition-duration: 0.01ms ; | |
| scroll-behavior: auto ; | |
| } | |
| .sidebar-overlay, .sidebar-overlay > div, .glass-card, .message-slide-in, | |
| .fadeIn, .fadeInUp, .aml-glow, .replit-typewriter *, .replit-stream-done { | |
| animation: none ; | |
| } | |
| } | |
| @media (hover: none) { | |
| /* Disable hover effects on touch devices to prevent "sticky" hover states */ | |
| .glass-card:hover, .glass-surface:hover, .chat-header-bar:hover { | |
| box-shadow: var(--shadow-default, none) ; | |
| border-color: rgba(255,255,255,0.1) ; | |
| transition: none ; | |
| } | |
| button:hover { background: initial ; } | |
| .conv-row:hover .conv-menu-btn { opacity: 0.45 ; } | |
| } | |
| @media (max-width: 768px) { | |
| .chat-header-bar { | |
| backdrop-filter: none ; | |
| -webkit-backdrop-filter: none ; | |
| will-change: auto; | |
| } | |
| } | |
| /* ========================================================= | |
| GAP-6: TOUCH INTERACTION OPTIMIZATION | |
| ========================================================= */ | |
| a, button, [role="button"], .clickable { | |
| touch-action: manipulation; /* Removes 300ms tap delay */ | |
| } | |
| .glass-card, .conv-row, .sidebar-item { | |
| user-select: none; /* Prevents accidental text selection during scroll */ | |
| -webkit-user-select: none; | |
| } | |
| /* Allow selection only in messages and inputs */ | |
| .message-content, input, textarea { | |
| user-select: text ; | |
| -webkit-user-select: text ; | |
| } | |
| /* Performance: content-visibility for off-screen sections */ | |
| .admin-panel-content, .settings-content { | |
| content-visibility: auto; | |
| contain-intrinsic-size: 0 500px; | |
| } | |
| /* S-MOBILE-ULTRA: iPhone Safari Optimization */ | |
| @media (max-width: 768px) { | |
| /* DOM Flattening: Rimuove ombre e layer complessi su mobile */ | |
| * { | |
| box-shadow: none ; | |
| text-shadow: none ; | |
| } | |
| /* Semplifica le transizioni per evitare jank */ | |
| .chat-message, .tool-result { | |
| transition: none ; | |
| will-change: auto ; | |
| } | |
| /* Forza il rendering accelerato solo per lo scroll principale */ | |
| .main-content { | |
| -webkit-overflow-scrolling: touch; | |
| scroll-behavior: auto; /* Disabilita smooth scroll su mobile per performance */ | |
| } | |
| /* Lazy Tool Rendering: Nasconde i dettagli dei tool di default su mobile */ | |
| .tool-details { | |
| display: none; | |
| } | |
| .tool-details.expanded { | |
| display: block; | |
| } | |
| } | |
| /* ========================================================= | |
| MIGLIORIA 6 — Caret blink animation (GAP-UI-CARET) | |
| ========================================================= */ | |
| @keyframes caret-blink { | |
| 0%, 70%, 100% { opacity: 1; } | |
| 20%, 50% { opacity: 0; } | |
| } | |
| .animate-caret-blink { | |
| animation: caret-blink 1.25s ease-in-out infinite; | |
| } | |