/* ========================================================================== 2. UI Components: Auth, Navbar, Drawer, Buttons, Modals & Mobile Tab Bar ========================================================================== */ /* Auth Screen / Login Overlay */ .auth-screen, .login-overlay { position: fixed; inset: 0; z-index: 10000; min-height: 100vh; display: flex; align-items: center; justify-content: center; padding: 20px; background-color: var(--bg-main); background-image: radial-gradient(circle at top, rgba(56, 189, 248, 0.15), transparent 70%); } .auth-card, .login-card { background-color: var(--bg-surface); border: 1px solid var(--border-color); border-radius: var(--radius-lg); padding: 36px 32px; width: 100%; max-width: 420px; box-shadow: var(--shadow-lg); animation: fadeInScale 0.2s ease-out; } @keyframes fadeInScale { from { opacity: 0; transform: scale(0.96); } to { opacity: 1; transform: scale(1); } } @keyframes slideUpSheet { from { transform: translateY(100%); opacity: 0; } to { transform: translateY(0); opacity: 1; } } .auth-header, .login-header { text-align: center; margin-bottom: 28px; } .auth-header .app-logo, .login-header .login-logo { font-size: 48px; margin-bottom: 8px; display: block; } .auth-header h2, .login-header h1 { font-size: 24px; font-weight: 700; color: var(--text-main); } .auth-header p, .login-header p { color: var(--text-muted); font-size: 14px; margin-top: 4px; } .login-form { display: flex; flex-direction: column; } .login-error { background-color: var(--danger-dim); color: var(--danger); border: 1px solid var(--danger); padding: 10px 14px; border-radius: var(--radius-sm); font-size: 13px; margin-bottom: 16px; text-align: center; } .auth-footer, .login-footer { margin-top: 24px; text-align: center; font-size: 12px; color: var(--text-dim); } .form-group { margin-bottom: 18px; } .form-group label { display: block; font-size: 13px; font-weight: 600; color: var(--text-muted); margin-bottom: 6px; } .form-group input { width: 100%; padding: 12px 14px; background-color: var(--bg-input); border: 1px solid var(--border-color); border-radius: var(--radius-sm); color: var(--text-main); font-size: 15px; outline: none; transition: var(--transition); } .form-group input:focus { border-color: var(--border-focus); box-shadow: 0 0 0 3px var(--primary-dim); } .error-banner { background-color: var(--danger-dim); border: 1px solid var(--danger); color: #fca5a5; padding: 10px 14px; border-radius: var(--radius-sm); font-size: 13px; margin-bottom: 16px; } .success-banner { background-color: var(--success-dim, rgba(16, 185, 129, 0.15)); border: 1px solid var(--success, #10b981); color: #86efac; padding: 10px 14px; border-radius: var(--radius-sm); font-size: 13px; margin-bottom: 16px; } /* App Navbar */ .app-container { display: flex; flex-direction: column; min-height: 100vh; } /* App Navbar (Unified Layout) */ .navbar { background-color: var(--bg-surface); border-bottom: 1px solid var(--border-color); padding: 8px 20px; display: flex; align-items: center; justify-content: space-between; gap: 16px; position: sticky; top: 0; z-index: 100; min-height: var(--navbar-height); box-sizing: border-box; } .nav-left { display: flex; align-items: center; gap: 10px; flex-shrink: 0; } .drawer-toggle-btn { display: inline-flex; align-items: center; justify-content: center; width: 36px; height: 36px; border-radius: var(--radius-sm); background-color: transparent; border: 1px solid transparent; color: var(--text-main); cursor: pointer; font-size: 20px; line-height: 1; transition: var(--transition); } .drawer-toggle-btn:hover { background-color: var(--bg-surface-hover); border-color: var(--border-color); color: var(--primary); } .nav-brand { display: flex; align-items: center; gap: 8px; cursor: pointer; user-select: none; transition: opacity 0.15s ease; } .nav-brand:hover { opacity: 0.85; } .brand-icon { font-size: 24px; } .brand-title { font-size: 20px; font-weight: 800; color: var(--text-main); letter-spacing: -0.5px; } .brand-sub { font-size: 12px; background-color: var(--primary-dim); color: var(--primary); padding: 2px 8px; border-radius: var(--radius-full); font-weight: 600; margin-left: 4px; } .nav-center { display: flex; align-items: center; justify-content: center; gap: 14px; flex: 1; min-width: 0; } .nav-stats { display: flex; gap: 8px; } .stat-badge { font-size: 13px; background-color: var(--bg-main); border: 1px solid var(--border-color); padding: 4px 12px; border-radius: var(--radius-full); color: var(--text-muted); } .stat-badge strong { color: var(--text-main); } .stat-badge.stat-today strong { color: var(--success); } .nav-actions { display: flex; align-items: center; gap: 10px; flex-shrink: 0; } .user-profile-btn { display: inline-flex; align-items: center; gap: 8px; padding: 5px 12px; border-radius: var(--radius-full); background-color: var(--bg-surface-hover); border: 1px solid var(--border-color); color: var(--text-main); font-size: 13px; font-weight: 600; cursor: pointer; transition: var(--transition); } .user-profile-btn:hover { border-color: var(--primary); color: var(--primary); background-color: var(--primary-dim); } .user-avatar-icon { font-size: 15px; } .user-badge { font-size: 13px; color: var(--text-main); font-weight: 600; } /* ----------------------------------------------------------------------- Unified Navigation Drawer (Desktop & Mobile) ----------------------------------------------------------------------- */ .drawer-backdrop { position: fixed; top: 0; left: 0; width: 100vw; height: 100vh; background-color: rgba(0, 0, 0, 0.65); backdrop-filter: blur(4px); -webkit-backdrop-filter: blur(4px); z-index: 1999; opacity: 0; pointer-events: none; transition: opacity 0.26s cubic-bezier(0.16, 1, 0.3, 1); } .drawer-backdrop.active { opacity: 1; pointer-events: auto; } .app-drawer { position: fixed; top: 0; left: 0; bottom: 0; width: min(340px, 86vw); background-color: var(--bg-surface); border-right: 1px solid var(--border-color); box-shadow: 4px 0 28px rgba(0, 0, 0, 0.5); z-index: 2000; display: flex; flex-direction: column; transform: translateX(-100%); transition: transform 0.28s cubic-bezier(0.16, 1, 0.3, 1); will-change: transform; overflow-y: auto; -webkit-overflow-scrolling: touch; } .app-drawer.active { transform: translateX(0); } body.drawer-open { overflow: hidden !important; } .drawer-header { display: flex; align-items: center; justify-content: space-between; padding: calc(16px + env(safe-area-inset-top, 0px)) 16px 14px 18px; border-bottom: 1px solid var(--border-color); background-color: var(--bg-surface); position: sticky; top: 0; z-index: 10; } .drawer-user-card { display: flex; align-items: center; gap: 12px; min-width: 0; } .drawer-user-avatar { width: 42px; height: 42px; border-radius: var(--radius-full); background: linear-gradient(135deg, var(--primary), #6366f1); color: #ffffff; display: flex; align-items: center; justify-content: center; font-size: 20px; flex-shrink: 0; box-shadow: var(--shadow-sm); } .drawer-user-info { display: flex; flex-direction: column; min-width: 0; } .drawer-user-name { font-size: 15px; font-weight: 700; color: var(--text-main); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } .drawer-user-desc { font-size: 12px; color: var(--text-muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } .drawer-close-btn { width: 34px; height: 34px; border-radius: var(--radius-sm); display: flex; align-items: center; justify-content: center; font-size: 18px; color: var(--text-muted); background: transparent; border: none; cursor: pointer; transition: var(--transition); } .drawer-close-btn:hover { background-color: var(--bg-surface-hover); color: var(--text-main); } .drawer-stats-summary { display: grid; grid-template-columns: repeat(3, 1fr); gap: 8px; padding: 12px 14px; margin: 12px 14px 4px 14px; background-color: var(--bg-main); border: 1px solid var(--border-color); border-radius: var(--radius-md); text-align: center; } .drawer-stat-item { display: flex; flex-direction: column; gap: 2px; } .drawer-stat-val { font-size: 16px; font-weight: 800; color: var(--text-main); } .drawer-stat-lbl { font-size: 10px; font-weight: 600; color: var(--text-dim); text-transform: uppercase; letter-spacing: 0.3px; } .drawer-nav { flex: 1; padding: 8px 12px; display: flex; flex-direction: column; gap: 4px; } .drawer-section-title { font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.6px; color: var(--text-dim); padding: 12px 8px 4px 8px; } .drawer-nav-list { list-style: none; padding: 0; margin: 0; display: flex; flex-direction: column; gap: 3px; } .drawer-nav-item { width: 100%; display: flex; align-items: center; gap: 12px; padding: 10px 12px; border-radius: var(--radius-sm); background: transparent; border: 1px solid transparent; color: var(--text-main); font-size: 14px; font-weight: 500; text-align: left; cursor: pointer; transition: var(--transition); text-decoration: none; } .drawer-nav-item:hover { background-color: var(--bg-surface-hover); color: var(--primary); border-color: var(--border-color); } .drawer-nav-item.active { background-color: var(--primary-dim); color: var(--primary); border-color: rgba(56, 189, 248, 0.3); font-weight: 700; } .drawer-item-icon { font-size: 18px; width: 24px; text-align: center; flex-shrink: 0; } .drawer-item-label { flex: 1; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; } .drawer-badge { padding: 2px 7px; font-size: 11px; font-weight: 700; border-radius: var(--radius-full); background-color: var(--primary); color: #0f172a; line-height: 1.2; } .drawer-footer { padding: 14px 16px calc(14px + env(safe-area-inset-bottom, 0px)) 16px; border-top: 1px solid var(--border-color); font-size: 12px; color: var(--text-dim); text-align: center; } /* Buttons */ .btn { display: inline-flex; align-items: center; justify-content: center; gap: 6px; padding: 10px 18px; border-radius: var(--radius-sm); font-size: 14px; font-weight: 600; cursor: pointer; border: none; transition: var(--transition); } .btn-primary { background-color: var(--primary); color: #0f172a; } .btn-primary:hover { background-color: var(--primary-hover); } .btn-success { background-color: var(--success); color: #ffffff; } .btn-success:hover { background-color: var(--success-hover); } .btn-outline { background-color: transparent; border: 1px solid var(--border-color); color: var(--text-muted); } .btn-outline:hover { border-color: var(--text-main); color: var(--text-main); } .btn-sm { padding: 6px 12px; font-size: 12px; } .btn-lg { padding: 14px 24px; font-size: 16px; } .btn-block { width: 100%; } .btn-subtext { font-size: 11px; opacity: 0.8; margin-left: 4px; } .icon-btn { background: transparent; border: 1px solid var(--border-color); border-radius: var(--radius-sm); padding: 6px 10px; cursor: pointer; color: var(--text-muted); font-size: 16px; transition: var(--transition); } .icon-btn:hover { color: var(--text-main); border-color: var(--text-main); } /* Spinner */ .lookup-spinner { display: flex; align-items: center; justify-content: center; gap: 12px; padding: 24px; color: var(--primary); font-size: 14px; font-weight: 500; } .spinner { width: 24px; height: 24px; border: 3px solid var(--border-color); border-top-color: var(--primary); border-radius: 50%; animation: spin 0.8s linear infinite; } @keyframes spin { to { transform: rotate(360deg); } } /* Modal */ .modal-backdrop { position: fixed; top: 0; left: 0; width: 100%; height: 100%; background-color: rgba(0, 0, 0, 0.7); backdrop-filter: blur(4px); display: flex; align-items: center; justify-content: center; z-index: 1000; padding: 20px; } .modal-window { background-color: var(--bg-surface); border: 1px solid var(--border-color); border-radius: var(--radius-lg); width: 100%; max-width: 520px; box-shadow: var(--shadow-lg); display: flex; flex-direction: column; } .modal-header { display: flex; justify-content: space-between; align-items: center; padding: 16px 20px; border-bottom: 1px solid var(--border-color); } .modal-header h3 { font-size: 18px; font-weight: 700; } .modal-body { padding: 20px; display: flex; flex-direction: column; gap: 14px; } .modal-footer { display: flex; justify-content: flex-end; gap: 10px; padding: 14px 20px; border-top: 1px solid var(--border-color); } .modal-sm { max-width: 420px; } /* Navigation Additions */ .nav-center { display: flex; align-items: center; } .btn-trainer { background: linear-gradient(135deg, #0284c7, #38bdf8); color: #0f172a; font-weight: 700; box-shadow: 0 2px 10px rgba(56, 189, 248, 0.25); display: inline-flex; align-items: center; gap: 8px; padding: 7px 14px; border-radius: var(--radius-sm); border: none; cursor: pointer; transition: var(--transition); } .btn-trainer:hover { box-shadow: 0 4px 14px rgba(56, 189, 248, 0.45); transform: translateY(-1px); } .srs-due-badge { background-color: #0f172a; color: #38bdf8; font-size: 11px; font-weight: 800; padding: 1px 7px; border-radius: var(--radius-full); min-width: 18px; text-align: center; } .srs-due-badge.has-due { background-color: #ef4444; color: #ffffff; animation: pulseDue 2s infinite; } @keyframes pulseDue { 0%, 100% { transform: scale(1); } 50% { transform: scale(1.15); } } /* Export Modal */ .export-modal-window { max-width: 620px; } .modal-lead { font-size: 14px; color: var(--text-muted); margin-bottom: 8px; } .export-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; } .export-tile { background-color: var(--bg-input); border: 1px solid var(--border-color); border-radius: var(--radius-md); padding: 16px; display: flex; flex-direction: column; justify-content: space-between; gap: 12px; transition: var(--transition); } .export-tile:hover { border-color: var(--primary); transform: translateY(-2px); box-shadow: var(--shadow-md); } .export-tile-icon { font-size: 28px; } .export-tile-info h4 { font-size: 15px; font-weight: 700; color: var(--text-main); margin-bottom: 4px; } .export-tile-info p { font-size: 12px; color: var(--text-dim); line-height: 1.4; } /* Voice Settings Modal */ .voice-modal-window { max-width: 680px; width: 95%; } .voice-modal-body { padding: 20px 24px; display: flex; flex-direction: column; gap: 16px; max-height: 80vh; overflow-y: auto; } .modal-desc-sub { font-size: 13px; color: var(--text-muted); margin: 0 0 10px 0; } .voice-group-title { font-size: 14px; font-weight: 700; color: var(--text-main); display: block; margin-bottom: 10px; } .voice-options-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 12px; } @media (max-width: 680px) { .voice-options-grid { grid-template-columns: 1fr; } } .voice-card-label { cursor: pointer; display: block; position: relative; user-select: none; } .voice-card-label input[type="radio"] { position: absolute; opacity: 0; pointer-events: none; } .voice-card { border: 1px solid var(--border-color); background: var(--bg-card); border-radius: var(--radius-md); padding: 14px 14px; display: flex; flex-direction: column; gap: 8px; height: 100%; transition: var(--transition); } .voice-card:hover { border-color: var(--primary-dim); } .voice-card-label input[type="radio"]:checked + .voice-card { border-color: var(--primary); background: var(--bg-main); box-shadow: 0 0 0 2px var(--primary-dim); } .voice-card-head { display: flex; justify-content: space-between; align-items: center; gap: 6px; } .voice-card-desc { font-size: 12px; line-height: 1.4; color: var(--text-muted); flex: 1; } .badge-recommended { background: rgba(16, 185, 129, 0.15); color: #10b981; font-size: 10px; font-weight: 700; padding: 2px 6px; border-radius: 4px; white-space: nowrap; } .badge-uk { background: rgba(59, 130, 246, 0.15); color: #3b82f6; font-size: 10px; font-weight: 700; padding: 2px 6px; border-radius: 4px; white-space: nowrap; } .voice-test-btn { align-self: flex-start; margin-top: 4px; } /* Mobile Navigation & Tab Bar (iOS Native Style Base) */ .mobile-only-btn, .mobile-tab-bar, .mobile-only { display: none; } .mobile-tab-bar { position: fixed; bottom: 0; left: 0; right: 0; height: calc(56px + env(safe-area-inset-bottom, 0px)); padding-bottom: env(safe-area-inset-bottom, 0px); background-color: rgba(30, 41, 59, 0.94); backdrop-filter: blur(16px); -webkit-backdrop-filter: blur(16px); border-top: 1px solid var(--border-color); z-index: 1000; align-items: center; justify-content: space-around; } [data-theme="light"] .mobile-tab-bar { background-color: rgba(255, 255, 255, 0.94); } .tab-item { flex: 1; height: 100%; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 3px; background: none; border: none; color: var(--text-muted); cursor: pointer; position: relative; padding: 6px 0; -webkit-tap-highlight-color: transparent; transition: var(--transition); } .tab-item:active { transform: scale(0.92); } .tab-item.active { color: var(--primary); } .tab-icon { font-size: 19px; line-height: 1; } .tab-label { font-size: 10px; font-weight: 600; letter-spacing: -0.2px; } .tab-badge { position: absolute; top: 5px; right: calc(50% - 18px); background-color: #ef4444; color: #ffffff; font-size: 10px; font-weight: 700; padding: 1px 5px; border-radius: 9999px; line-height: 1.2; } /* Mobile Sheet / Menu */ .mobile-sheet-window { max-width: 440px; } .mobile-user-card { display: flex; align-items: center; gap: 12px; padding: 14px 16px; background: var(--bg-input); border: 1px solid var(--border-color); border-radius: var(--radius-md); margin-bottom: 16px; } .mobile-user-avatar { font-size: 28px; background: var(--bg-surface-hover); width: 48px; height: 48px; display: flex; align-items: center; justify-content: center; border-radius: var(--radius-full); } .mobile-user-info strong { font-size: 16px; color: var(--text-main); } .mobile-user-info .subtitle { font-size: 12px; color: var(--text-muted); } .mobile-menu-actions { display: flex; flex-direction: column; gap: 10px; } /* Sheet drag handle for mobile bottom sheets */ .sheet-drag-handle { width: 38px; height: 4px; border-radius: 2px; background-color: var(--border-color); margin: 0 auto 10px auto; } /* --- Responsive Mobile Overrides (max-width: 768px) --- */ @media (max-width: 768px) { /* 3. Header & Navigation: Unified Responsive Header */ .navbar { padding: calc(8px + env(safe-area-inset-top, 0px)) 10px 8px 10px; gap: 8px; } .brand-sub, .nav-stats { display: none !important; } .btn-trainer .trainer-text { display: none !important; } .btn-trainer { padding: 6px 10px !important; font-size: 13px !important; min-height: 36px; } .user-profile-btn #user-display-name { display: none !important; } .user-profile-btn { padding: 6px 10px !important; border-radius: var(--radius-sm); min-height: 36px; } .mobile-tab-bar { display: flex !important; } .mobile-only { display: block !important; } /* 8. Modals: Mobile Bottom-Sheet style */ .modal-backdrop { padding: 0; align-items: flex-end; } .modal-window { max-width: 100%; max-height: calc(90dvh - env(safe-area-inset-top, 0px)); border-radius: 20px 20px 0 0; border-bottom: none; overflow-y: auto; -webkit-overflow-scrolling: touch; padding-bottom: env(safe-area-inset-bottom, 0px); animation: slideUpSheet 0.22s cubic-bezier(0.16, 1, 0.3, 1); } .stats-modal-window { width: 100%; max-width: 100%; } .stats-hero-grid { grid-template-columns: 1fr 1fr; gap: 8px; } .heatmap-container-wrap { -webkit-overflow-scrolling: touch; } /* 9. Batch action bar */ .batch-action-bar { flex-direction: column; gap: 10px; bottom: calc(64px + env(safe-area-inset-bottom, 0px)) !important; left: 10px; right: 10px; } .batch-actions { width: 100%; justify-content: space-between; } }