/* ═══════════════════════════════════════════════════════════════════════════ OpenFang Layout — Premium Glassmorphism Grid System ═══════════════════════════════════════════════════════════════════════════ Architecture: - CSS Grid + Flexbox hybrid - Glassmorphism sidebar with blur effects - 5-level responsive breakpoints - Safe area support for mobile ═══════════════════════════════════════════════════════════════════════════ */ /* ═══════════════════════════════════════════════════════════════════════════ APP LAYOUT — Main container ═══════════════════════════════════════════════════════════════════════════ */ .app-layout { display: flex; height: 100vh; overflow: hidden; position: relative; } /* ═══════════════════════════════════════════════════════════════════════════ SIDEBAR — Glassmorphism navigation ═══════════════════════════════════════════════════════════════════════════ */ .sidebar { width: var(--sidebar-width); background: var(--glass-bg-strong); backdrop-filter: blur(var(--glass-blur-strong)); -webkit-backdrop-filter: blur(var(--glass-blur-strong)); border-right: 1px solid var(--glass-border); display: flex; flex-direction: column; flex-shrink: 0; transition: width var(--transition-spring); z-index: var(--z-sticky); position: relative; } /* Sidebar glow line */ .sidebar::before { content: ''; position: absolute; top: 0; right: 0; width: 1px; height: 100%; background: linear-gradient( 180deg, transparent 0%, var(--accent-glow) 20%, var(--accent-glow) 80%, transparent 100% ); opacity: 0.5; } /* Collapsed sidebar */ .sidebar.collapsed { width: var(--sidebar-collapsed); } .sidebar.collapsed .sidebar-label, .sidebar.collapsed .sidebar-header-text, .sidebar.collapsed .nav-label { display: none; } .sidebar.collapsed .nav-item { justify-content: center; padding: 12px; } .sidebar.collapsed .sidebar-status { padding: 8px 12px; justify-content: center; } .sidebar.collapsed .sidebar-header { padding: 12px; justify-content: center; } .sidebar.collapsed .theme-switcher { display: none; } /* ═══════════════════════════════════════════════════════════════════════════ SIDEBAR HEADER — Logo and branding ═══════════════════════════════════════════════════════════════════════════ */ .sidebar-header { padding: 16px 18px; border-bottom: 1px solid var(--border-subtle); display: flex; align-items: center; justify-content: space-between; min-height: 64px; position: sticky; top: 0; background: var(--glass-bg-strong); z-index: 10; } .sidebar-logo { display: flex; align-items: center; gap: 12px; } .sidebar-logo img { width: 32px; height: 32px; opacity: 0.9; transition: all var(--transition-fast); filter: drop-shadow(0 2px 4px rgba(0,0,0,0.1)); } .sidebar-logo img:hover { opacity: 1; transform: scale(1.05); } .sidebar-header h1 { font-size: 13px; font-weight: 700; color: var(--accent); letter-spacing: 3px; font-family: var(--font-mono); text-shadow: 0 0 20px var(--accent-glow); } .sidebar-header .version { font-size: 10px; color: var(--text-muted); margin-top: 2px; letter-spacing: 0.5px; } /* Theme switcher in sidebar */ .theme-switcher { display: flex; gap: 2px; background: var(--surface2); padding: 3px; border-radius: var(--radius-full); border: 1px solid var(--border); } .theme-opt { width: 26px; height: 26px; border: none; background: transparent; border-radius: var(--radius-full); cursor: pointer; font-size: 12px; color: var(--text-dim); transition: all var(--transition-fast); display: flex; align-items: center; justify-content: center; } .theme-opt:hover { color: var(--text); } .theme-opt.active { background: var(--surface); color: var(--accent); box-shadow: var(--shadow-sm); } /* ═══════════════════════════════════════════════════════════════════════════ SIDEBAR STATUS — Connection indicator ═══════════════════════════════════════════════════════════════════════════ */ .sidebar-status { font-size: 11px; color: var(--success); display: flex; align-items: center; gap: 8px; padding: 10px 18px; border-bottom: 1px solid var(--border-subtle); font-weight: 500; } .sidebar-status.offline { color: var(--error); } .status-dot { width: 6px; height: 6px; border-radius: 50%; background: currentColor; flex-shrink: 0; box-shadow: 0 0 8px currentColor; animation: pulse-ring 2s infinite; } .conn-badge { font-size: 9px; padding: 2px 6px; border-radius: var(--radius-sm); font-weight: 700; letter-spacing: 0.5px; margin-left: auto; font-family: var(--font-mono); } .conn-badge.ws { background: var(--success-subtle); color: var(--success); } .conn-badge.http { background: var(--warning-subtle); color: var(--warning); } /* ═══════════════════════════════════════════════════════════════════════════ SIDEBAR NAVIGATION ═══════════════════════════════════════════════════════════════════════════ */ .sidebar-nav { flex: 1; overflow-y: auto; overflow-x: hidden; padding: 12px; scrollbar-width: none; } .sidebar-nav::-webkit-scrollbar { width: 0; } .nav-section { margin-bottom: 8px; } .nav-section-title { font-size: 10px; text-transform: uppercase; letter-spacing: 1.5px; color: var(--text-muted); padding: 12px 12px 6px; font-weight: 600; display: flex; align-items: center; justify-content: space-between; cursor: pointer; transition: color var(--transition-fast); } .nav-section-title:hover { color: var(--text-dim); } .sidebar.collapsed .nav-section-title { display: none; } .nav-section-chevron { font-size: 14px; transition: transform var(--transition-fast); opacity: 0.5; } .nav-item { display: flex; align-items: center; gap: 12px; padding: 10px 14px; border-radius: var(--radius-lg); cursor: pointer; font-size: 13px; color: var(--text-dim); transition: all var(--transition-fast); text-decoration: none; border: 1px solid transparent; white-space: nowrap; font-weight: 500; min-height: 40px; position: relative; overflow: hidden; } /* Nav item hover glow */ .nav-item::before { content: ''; position: absolute; inset: 0; background: var(--gradient-accent-subtle); opacity: 0; transition: opacity var(--transition-fast); } .nav-item:hover { background: var(--surface2); color: var(--text); transform: translateX(3px); } .nav-item:hover::before { opacity: 1; } .nav-item.active { background: var(--accent); color: var(--text-on-accent); font-weight: 600; box-shadow: var(--shadow-accent); } .nav-item.active::before { opacity: 0; } .nav-item.active:hover { background: var(--accent-hover); } /* Nav icon */ .nav-icon { width: 20px; height: 20px; display: inline-flex; align-items: center; justify-content: center; flex-shrink: 0; position: relative; z-index: 1; } .nav-icon svg { width: 18px; height: 18px; fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; } .nav-label { position: relative; z-index: 1; } /* ═══════════════════════════════════════════════════════════════════════════ SIDEBAR FOOTER ═══════════════════════════════════════════════════════════════════════════ */ .sidebar-footer { padding: 12px 16px; border-top: 1px solid var(--border-subtle); } .sidebar-toggle { padding: 12px 16px; border-top: 1px solid var(--border-subtle); cursor: pointer; text-align: center; font-size: 14px; color: var(--text-muted); transition: all var(--transition-fast); } .sidebar-toggle:hover { color: var(--text); background: var(--surface2); } /* ═══════════════════════════════════════════════════════════════════════════ MAIN CONTENT AREA ═══════════════════════════════════════════════════════════════════════════ */ .main-content { flex: 1; display: flex; flex-direction: column; min-width: 0; overflow: hidden; background: var(--bg); position: relative; } /* Aurora background effect */ .main-content::before { content: ''; position: absolute; inset: 0; background: var(--gradient-mesh); pointer-events: none; opacity: 0.5; } /* Page wrapper divs (rendered by x-if) must fill the column */ .main-content > div { display: flex; flex-direction: column; flex: 1; min-height: 0; overflow: hidden; position: relative; z-index: 1; } /* ═══════════════════════════════════════════════════════════════════════════ PAGE HEADER ═══════════════════════════════════════════════════════════════════════════ */ .page-header { padding: 16px 28px; border-bottom: 1px solid var(--border); background: var(--glass-bg); backdrop-filter: blur(var(--glass-blur-subtle)); -webkit-backdrop-filter: blur(var(--glass-blur-subtle)); display: flex; align-items: center; justify-content: space-between; min-height: var(--header-height); position: sticky; top: 0; z-index: var(--z-elevated); } .page-header h2 { font-size: 16px; font-weight: 600; letter-spacing: -0.01em; color: var(--text); } /* ═══════════════════════════════════════════════════════════════════════════ PAGE BODY ═══════════════════════════════════════════════════════════════════════════ */ .page-body { flex: 1; min-height: 0; overflow-y: auto; overflow-x: hidden; padding: var(--page-padding); scroll-behavior: smooth; overscroll-behavior: contain; } /* ═══════════════════════════════════════════════════════════════════════════ CARD GRIDS ═══════════════════════════════════════════════════════════════════════════ */ .card-grid { display: grid; gap: 20px; grid-template-columns: repeat(auto-fill, minmax(300px, 1fr)); } .overview-grid { display: grid; gap: 16px; grid-template-columns: repeat(auto-fill, minmax(280px, 1fr)); } .security-grid { display: grid; gap: 16px; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); } .cost-charts-row { display: grid; gap: 20px; grid-template-columns: repeat(2, 1fr); } /* ═══════════════════════════════════════════════════════════════════════════ MOBILE OVERLAY ═══════════════════════════════════════════════════════════════════════════ */ .sidebar-overlay { display: none; position: fixed; inset: 0; background: rgba(0, 0, 0, 0.6); backdrop-filter: blur(4px); -webkit-backdrop-filter: blur(4px); z-index: calc(var(--z-sticky) - 1); animation: fadeIn 0.2s ease; } /* ═══════════════════════════════════════════════════════════════════════════ MOBILE MENU BUTTON ═══════════════════════════════════════════════════════════════════════════ */ .mobile-menu-btn { position: fixed; top: 12px; left: 12px; z-index: var(--z-fixed); padding: 10px 14px; border-radius: var(--radius-lg); background: var(--glass-bg-strong); backdrop-filter: blur(var(--glass-blur)); -webkit-backdrop-filter: blur(var(--glass-blur)); border: 1px solid var(--glass-border); box-shadow: var(--shadow-md); transition: all var(--transition-fast); } .mobile-menu-btn:hover { background: var(--surface2); transform: scale(1.02); } .mobile-menu-btn:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; } /* ═══════════════════════════════════════════════════════════════════════════ FOCUS MODE — Distraction-free chat ═══════════════════════════════════════════════════════════════════════════ */ .app-layout.focus-mode .sidebar { display: none; } .app-layout.focus-mode .sidebar-overlay { display: none; } .app-layout.focus-mode .main-content { max-width: 100%; margin-left: 0; } .app-layout.focus-mode .mobile-menu-btn { display: none !important; } /* ═══════════════════════════════════════════════════════════════════════════ RESPONSIVE BREAKPOINTS ═══════════════════════════════════════════════════════════════════════════ */ /* Extra large devices (1401px and above) */ @media (min-width: 1401px) { .card-grid { grid-template-columns: repeat(auto-fill, minmax(340px, 1fr)); } .overview-grid { grid-template-columns: repeat(auto-fill, minmax(320px, 1fr)); } .page-body { padding: 32px; } } /* Large devices (1025px to 1400px) */ @media (min-width: 1025px) and (max-width: 1400px) { .card-grid { grid-template-columns: repeat(auto-fill, minmax(300px, 1fr)); } .overview-grid { grid-template-columns: repeat(auto-fill, minmax(280px, 1fr)); } } /* Medium devices (769px to 1024px) — Tablets landscape */ @media (min-width: 769px) and (max-width: 1024px) { .card-grid { grid-template-columns: repeat(auto-fill, minmax(260px, 1fr)); } .overview-grid { grid-template-columns: repeat(auto-fill, minmax(240px, 1fr)); } .sidebar { width: 220px; } .cost-charts-row { grid-template-columns: 1fr; } .page-body { padding: 20px; } } /* Small devices (481px to 768px) — Tablets portrait */ @media (min-width: 481px) and (max-width: 768px) { .sidebar { position: fixed; left: -280px; top: 0; bottom: 0; width: 260px; transition: left var(--transition-spring); z-index: var(--z-fixed); } .sidebar.mobile-open { left: 0; } .sidebar.mobile-open + .sidebar-overlay { display: block; } .sidebar.collapsed { width: 260px; left: -280px; } .card-grid { grid-template-columns: repeat(auto-fill, minmax(240px, 1fr)); } .overview-grid { grid-template-columns: 1fr; } .cost-charts-row { grid-template-columns: 1fr; } .security-grid { grid-template-columns: 1fr; } .page-body { padding: 16px; } .page-header { padding: 14px 20px; } .mobile-menu-btn { display: flex !important; } } /* Extra small devices (480px and below) — Phones */ @media (max-width: 480px) { .sidebar { position: fixed; left: -100%; top: 0; bottom: 0; width: 100%; max-width: 280px; transition: left var(--transition-spring); z-index: var(--z-fixed); } .sidebar.mobile-open { left: 0; } .sidebar.mobile-open + .sidebar-overlay { display: block; } .sidebar.collapsed { width: 100%; max-width: 280px; left: -100%; } .mobile-menu-btn { display: flex !important; } .page-header { flex-direction: column; gap: 10px; align-items: flex-start; padding: 12px 16px; min-height: auto; } .page-header h2 { font-size: 14px; } .page-body { padding: 12px; } .stats-row { gap: 10px; } .stat-card, .stat-card-lg { padding: 14px 16px; min-width: unset; flex: 1 1 calc(50% - 5px); border-radius: var(--radius-lg); } .stat-card-lg .stat-value { font-size: 22px; } .card-grid, .overview-grid { grid-template-columns: 1fr; gap: 12px; } .card { padding: 16px; border-radius: var(--radius-lg); } .cost-charts-row { grid-template-columns: 1fr; } .security-grid { grid-template-columns: 1fr; } .input-area { padding: 10px 14px; } .main-content { padding: 0; } .modal { margin: 12px; max-height: calc(100vh - 24px); width: calc(100% - 24px); border-radius: var(--radius-xl); } .quick-action-card { padding: 14px 16px; } .btn { padding: 10px 14px; } .btn-sm { padding: 8px 12px; } } /* ═══════════════════════════════════════════════════════════════════════════ TOUCH DEVICE OPTIMIZATIONS ═══════════════════════════════════════════════════════════════════════════ */ @media (pointer: coarse) { .btn { min-height: 44px; min-width: 44px; } .nav-item { min-height: 44px; padding: 12px 14px; } .form-input, .form-select, .form-textarea { min-height: 48px; font-size: 16px; /* Prevents iOS zoom */ } .toggle { min-width: 48px; min-height: 28px; } .tab { min-height: 44px; padding: 12px 18px; } .badge[onclick] { min-height: 32px; padding: 6px 12px; } } /* ═══════════════════════════════════════════════════════════════════════════ SAFE AREA INSETS — iOS devices ═══════════════════════════════════════════════════════════════════════════ */ @supports (padding: env(safe-area-inset-bottom)) { .input-area { padding-bottom: calc(16px + env(safe-area-inset-bottom)); } .sidebar { padding-bottom: env(safe-area-inset-bottom); } .modal { padding-bottom: calc(24px + env(safe-area-inset-bottom)); } .toast-container { bottom: calc(24px + env(safe-area-inset-bottom)); } } /* ═══════════════════════════════════════════════════════════════════════════ CONTAINER QUERIES — Component-level responsiveness ═══════════════════════════════════════════════════════════════════════════ */ @container (min-width: 400px) { .card-grid { grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); } } /* ═══════════════════════════════════════════════════════════════════════════ CHAT LAYOUT — Message area specific ═══════════════════════════════════════════════════════════════════════════ */ .chat-wrapper { display: flex; flex-direction: column; flex: 1; min-height: 0; overflow: hidden; } .messages { flex: 1; min-height: 0; overflow-y: auto; padding: 20px; display: flex; flex-direction: column; gap: 16px; } .input-area { padding: 16px 20px; border-top: 1px solid var(--border); background: var(--glass-bg); backdrop-filter: blur(var(--glass-blur-subtle)); -webkit-backdrop-filter: blur(var(--glass-blur-subtle)); } /* ═══════════════════════════════════════════════════════════════════════════ TABLE WRAPPER — Responsive tables ═══════════════════════════════════════════════════════════════════════════ */ .table-wrap { overflow-x: auto; -webkit-overflow-scrolling: touch; } .table-wrap table { width: 100%; border-collapse: collapse; font-size: 13px; } .table-wrap th, .table-wrap td { padding: 12px 16px; text-align: left; border-bottom: 1px solid var(--border); } .table-wrap th { font-weight: 600; color: var(--text-dim); font-size: 11px; text-transform: uppercase; letter-spacing: 0.05em; background: var(--surface2); } .table-wrap tr:hover td { background: var(--surface2); } /* ═══════════════════════════════════════════════════════════════════════════ SESSION DROPDOWN ═══════════════════════════════════════════════════════════════════════════ */ .session-dropdown { position: absolute; top: calc(100% + 4px); right: 0; min-width: 220px; background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius-lg); box-shadow: var(--shadow-lg); z-index: var(--z-dropdown); overflow: hidden; } .session-dropdown-header { display: flex; justify-content: space-between; align-items: center; padding: 12px 14px; border-bottom: 1px solid var(--border); background: var(--surface2); } .session-item { display: flex; align-items: center; gap: 10px; padding: 10px 14px; cursor: pointer; transition: background var(--transition-fast); } .session-item:hover { background: var(--surface2); } .session-item.active { background: var(--accent-subtle); } .session-dot { width: 8px; height: 8px; border-radius: 50%; background: var(--text-muted); flex-shrink: 0; } .session-dot.active { background: var(--success); box-shadow: 0 0 8px var(--success-glow); } .session-count-badge { position: absolute; top: -4px; right: -4px; min-width: 16px; height: 16px; padding: 0 4px; background: var(--accent); color: var(--text-on-accent); border-radius: var(--radius-full); font-size: 10px; font-weight: 700; display: flex; align-items: center; justify-content: center; } /* ═══════════════════════════════════════════════════════════════════════════ CHAT SEARCH BAR ═══════════════════════════════════════════════════════════════════════════ */ .chat-search-bar { display: flex; align-items: center; gap: 10px; padding: 10px 16px; background: var(--surface2); border-bottom: 1px solid var(--border); } .chat-search-input { flex: 1; border: none; background: transparent; color: var(--text); font-size: 14px; outline: none; } .chat-search-input::placeholder { color: var(--text-muted); } /* ═══════════════════════════════════════════════════════════════════════════ QUEUE BADGE ═══════════════════════════════════════════════════════════════════════════ */ .queue-badge { font-size: 10px; padding: 2px 8px; background: var(--info-subtle); color: var(--info); border-radius: var(--radius-full); font-weight: 600; animation: pulse-ring 2s infinite; } /* ═══════════════════════════════════════════════════════════════════════════ MESSAGE STYLES ═══════════════════════════════════════════════════════════════════════════ */ .message { display: flex; gap: 12px; max-width: 85%; animation: slideUp 0.3s var(--ease-spring); } .message.user { flex-direction: row-reverse; margin-left: auto; } .message.agent { margin-right: auto; } .message-avatar { width: 32px; height: 32px; border-radius: var(--radius-md); overflow: hidden; flex-shrink: 0; background: var(--surface2); display: flex; align-items: center; justify-content: center; } .message-avatar img { width: 100%; height: 100%; object-fit: cover; } .message-body { flex: 1; min-width: 0; } .message.grouped .message-avatar { visibility: hidden; } .message-actions { display: flex; gap: 4px; opacity: 0; transition: opacity var(--transition-fast); } .message:hover .message-actions { opacity: 1; } .message-action-btn { padding: 4px 8px; border: none; background: var(--surface2); border-radius: var(--radius-sm); cursor: pointer; color: var(--text-dim); font-size: 11px; transition: all var(--transition-fast); } .message-action-btn:hover { background: var(--surface3); color: var(--text); } .message-action-btn.copied { background: var(--success-subtle); color: var(--success); }