/* =================================================================== CSS Reset & Base =================================================================== */ *, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; } :root { --bg-primary: #f5f6fa; --bg-secondary: #ffffff; --bg-phone: #1a1a2e; --bg-display: #16213e; --text-primary: #2c3e50; --text-secondary: #7f8c8d; --text-light: #ffffff; --accent: #2196F3; --accent-dark: #1976D2; --success: #4CAF50; --warning: #FF9800; --danger: #f44336; --border: #e0e0e0; --shadow: 0 2px 8px rgba(0,0,0,0.1); --radius: 12px; --safe-top: env(safe-area-inset-top, 0px); --safe-bottom: env(safe-area-inset-bottom, 0px); } @media (prefers-color-scheme: dark) { :root:not(.light-mode) { --bg-primary: #0f0f23; --bg-secondary: #1a1a2e; --bg-phone: #16213e; --bg-display: #0a0a1a; --text-primary: #ecf0f1; --text-secondary: #95a5a6; --border: #2c3e50; --shadow: 0 2px 8px rgba(0,0,0,0.4); } } /* Manual dark mode override via class on */ :root.dark-mode { --bg-primary: #0f0f23; --bg-secondary: #1a1a2e; --bg-phone: #16213e; --bg-display: #0a0a1a; --text-primary: #ecf0f1; --text-secondary: #95a5a6; --border: #2c3e50; --shadow: 0 2px 8px rgba(0,0,0,0.4); } html, body { height: 100%; overflow: hidden; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, sans-serif; background: var(--bg-primary); color: var(--text-primary); -webkit-text-size-adjust: 100%; -webkit-tap-highlight-color: transparent; } /* =================================================================== Layout — full-screen flex column =================================================================== */ .twp-app { display: flex; flex-direction: column; height: 100%; max-width: 500px; margin: 0 auto; padding-top: var(--safe-top); padding-bottom: var(--safe-bottom); } /* =================================================================== Agent Status Bar (compact) =================================================================== */ .agent-status-bar { display: flex; align-items: center; justify-content: space-between; padding: 8px 12px; background: var(--bg-secondary); border-bottom: 1px solid var(--border); flex-shrink: 0; gap: 8px; flex-wrap: wrap; } .status-info { display: flex; align-items: center; gap: 8px; font-size: 13px; flex-wrap: wrap; } .extension-badge { background: var(--accent); color: #fff; padding: 2px 8px; border-radius: 10px; font-size: 12px; font-weight: 600; } .agent-stats { display: flex; gap: 10px; font-size: 11px; color: var(--text-secondary); } #login-toggle-btn, #agent-status-select { font-size: 12px; padding: 3px 10px; border-radius: 4px; border: 1px solid var(--border); background: var(--bg-secondary); color: var(--text-primary); cursor: pointer; } #login-toggle-btn.logged-in { background: var(--danger); color: #fff; border-color: var(--danger); } /* =================================================================== Notices =================================================================== */ .twp-notice { padding: 8px 12px; margin: 6px 10px; border-radius: 6px; font-size: 13px; animation: fadeIn 0.2s ease; } .twp-notice-success { background: #e8f5e9; color: #2e7d32; } .twp-notice-error { background: #ffebee; color: #c62828; } .twp-notice-info { background: #e3f2fd; color: #1565c0; } @media (prefers-color-scheme: dark) { :root:not(.light-mode) .twp-notice-success { background: #1b5e20; color: #a5d6a7; } :root:not(.light-mode) .twp-notice-error { background: #b71c1c; color: #ef9a9a; } :root:not(.light-mode) .twp-notice-info { background: #0d47a1; color: #90caf9; } } .dark-mode .twp-notice-success { background: #1b5e20; color: #a5d6a7; } .dark-mode .twp-notice-error { background: #b71c1c; color: #ef9a9a; } .dark-mode .twp-notice-info { background: #0d47a1; color: #90caf9; } @keyframes fadeIn { from { opacity: 0; transform: translateY(-4px); } to { opacity: 1; transform: translateY(0); } } /* =================================================================== Tab Navigation =================================================================== */ .tab-nav { display: flex; background: var(--bg-secondary); border-bottom: 1px solid var(--border); flex-shrink: 0; } .tab-btn { flex: 1; padding: 10px 0; text-align: center; font-size: 13px; font-weight: 600; background: none; border: none; border-bottom: 3px solid transparent; color: var(--text-secondary); cursor: pointer; transition: color 0.2s, border-color 0.2s; } .tab-btn.active { color: var(--accent); border-bottom-color: var(--accent); } /* =================================================================== Tab Content =================================================================== */ .tab-content { flex: 1; overflow-y: auto; -webkit-overflow-scrolling: touch; } .tab-pane { display: none; height: 100%; } .tab-pane.active { display: flex; flex-direction: column; } /* =================================================================== Phone Interface =================================================================== */ .phone-interface { display: flex; flex-direction: column; height: 100%; padding: 12px; gap: 12px; } /* Display */ .phone-display { background: var(--bg-display); color: var(--text-light); padding: 16px; border-radius: var(--radius); text-align: center; } #phone-status { font-size: 14px; color: var(--success); margin-bottom: 4px; } #device-connection-status { font-size: 11px; color: var(--text-secondary); margin-top: 2px; } #phone-number-display { font-size: 20px; min-height: 28px; font-weight: 600; letter-spacing: 1px; } #call-timer { font-size: 16px; margin-top: 6px; font-variant-numeric: tabular-nums; } /* Input */ #phone-number-input { width: 100%; padding: 12px; font-size: 20px; text-align: center; border: 1px solid var(--border); border-radius: var(--radius); background: var(--bg-secondary); color: var(--text-primary); outline: none; } #phone-number-input:focus { border-color: var(--accent); box-shadow: 0 0 0 2px rgba(33,150,243,0.2); } /* Dialpad */ .dialpad-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 8px; } .dialpad-btn { padding: 14px 0; font-size: 22px; font-weight: 500; border: 1px solid var(--border); background: var(--bg-secondary); color: var(--text-primary); border-radius: var(--radius); cursor: pointer; -webkit-user-select: none; user-select: none; position: relative; transition: background 0.1s; min-height: 54px; display: flex; flex-direction: column; align-items: center; justify-content: center; } .dialpad-btn:active { background: var(--accent); color: #fff; border-color: var(--accent); } .dialpad-btn span { display: block; font-size: 9px; color: var(--text-secondary); margin-top: 1px; letter-spacing: 2px; } .dialpad-btn:active span { color: rgba(255,255,255,0.8); } /* Phone Controls */ .phone-controls { display: flex; gap: 8px; } .phone-controls .btn-phone { flex: 1; height: 50px; font-size: 16px; font-weight: 600; border: none; border-radius: var(--radius); cursor: pointer; display: flex; align-items: center; justify-content: center; gap: 8px; transition: opacity 0.2s; } .btn-call { background: var(--success); color: #fff; } .btn-hangup { background: var(--danger); color: #fff; } .btn-answer { background: var(--success); color: #fff; animation: pulse 1.5s infinite; } @keyframes pulse { 0%, 100% { box-shadow: 0 0 0 0 rgba(76,175,80,0.4); } 50% { box-shadow: 0 0 0 10px rgba(76,175,80,0); } } /* Call Controls (hold/transfer/requeue/record) */ .call-controls-grid { display: grid; grid-template-columns: repeat(2, 1fr); gap: 8px; } .call-controls-grid .btn-ctrl { padding: 10px 8px; font-size: 13px; font-weight: 500; border: 1px solid var(--border); background: var(--bg-secondary); color: var(--text-primary); border-radius: 8px; cursor: pointer; display: flex; align-items: center; justify-content: center; gap: 6px; transition: background 0.1s; } .btn-ctrl:active { background: #e3f2fd; } .btn-ctrl.btn-active { background: var(--accent); color: #fff; border-color: var(--accent); } /* Error display */ #browser-phone-error { background: #ffebee; color: #c62828; padding: 10px 12px; border-radius: 8px; font-size: 13px; margin: 0 12px; } @media (prefers-color-scheme: dark) { :root:not(.light-mode) #browser-phone-error { background: #b71c1c; color: #ef9a9a; } } .dark-mode #browser-phone-error { background: #b71c1c; color: #ef9a9a; } /* =================================================================== Settings Tab =================================================================== */ .settings-panel { padding: 12px; display: flex; flex-direction: column; gap: 16px; overflow-y: auto; } .settings-section { background: var(--bg-secondary); padding: 14px; border-radius: var(--radius); border: 1px solid var(--border); } .settings-section h4 { font-size: 14px; margin-bottom: 10px; color: var(--accent-dark); } .settings-section label { font-size: 13px; display: flex; align-items: center; gap: 6px; } .settings-section select { width: 100%; padding: 8px; border: 1px solid var(--border); border-radius: 6px; font-size: 14px; background: var(--bg-primary); color: var(--text-primary); margin-top: 6px; } /* Call mode radio cards */ .mode-selection { display: flex; gap: 10px; margin: 10px 0; } .mode-option { display: flex; align-items: center; padding: 12px; border: 2px solid var(--border); border-radius: 8px; cursor: pointer; transition: all 0.2s; flex: 1; background: var(--bg-primary); } .mode-option.active { border-color: var(--accent); background: #e3f2fd; } @media (prefers-color-scheme: dark) { :root:not(.light-mode) .mode-option.active { background: #0d47a1; } } .dark-mode .mode-option.active { background: #0d47a1; } .mode-option input[type="radio"] { margin: 0 8px 0 0; } .mode-icon { font-size: 20px; margin-right: 8px; } .mode-details strong { display: block; font-size: 13px; } .mode-details small { font-size: 11px; color: var(--text-secondary); } .mode-status { display: flex; align-items: center; justify-content: space-between; padding: 8px; background: var(--bg-primary); border-radius: 6px; font-size: 13px; } .mode-info { margin-top: 8px; font-size: 12px; color: var(--text-secondary); } #save-mode-btn { padding: 6px 16px; border: none; background: var(--accent); color: #fff; border-radius: 6px; font-size: 13px; cursor: pointer; } /* Setup info box */ .setup-info { background: #fff3cd; padding: 12px; border-radius: 8px; border-left: 4px solid #ffc107; font-size: 12px; } @media (prefers-color-scheme: dark) { :root:not(.light-mode) .setup-info { background: #4a3800; color: #ffe082; } } .dark-mode .setup-info { background: #4a3800; color: #ffe082; } .setup-info h4 { margin-bottom: 6px; color: #856404; font-size: 13px; } .setup-info code { display: block; padding: 6px 8px; background: rgba(0,0,0,0.05); border-radius: 4px; font-size: 11px; word-break: break-all; margin: 6px 0; } .btn-copy { font-size: 11px; padding: 2px 8px; border: 1px solid var(--border); background: var(--bg-secondary); border-radius: 4px; cursor: pointer; } /* =================================================================== Queue Tab =================================================================== */ .queue-panel { padding: 12px; display: flex; flex-direction: column; gap: 10px; overflow-y: auto; } .queue-header { display: flex; justify-content: space-between; align-items: center; } .queue-header h4 { font-size: 15px; } .user-extension-admin { background: var(--bg-secondary); padding: 4px 10px; border-radius: 4px; font-size: 12px; color: var(--accent-dark); border: 1px solid var(--border); } .queue-item { display: flex; justify-content: space-between; align-items: center; padding: 12px; background: var(--bg-secondary); border: 1px solid var(--border); border-radius: 8px; } .queue-item.queue-type-personal { border-left: 4px solid var(--success); } .queue-item.queue-type-hold { border-left: 4px solid var(--warning); } .queue-item.queue-type-general { border-left: 4px solid var(--accent); } .queue-item.has-calls { background: #fff3cd; } @media (prefers-color-scheme: dark) { :root:not(.light-mode) .queue-item.has-calls { background: #4a3800; } } .dark-mode .queue-item.has-calls { background: #4a3800; } .queue-info { flex: 1; } .queue-name { display: flex; align-items: center; gap: 6px; font-weight: 600; font-size: 14px; } .queue-details { font-size: 12px; color: var(--text-secondary); margin-top: 3px; display: flex; gap: 10px; } .queue-waiting.has-calls { color: var(--danger); font-weight: bold; } .queue-loading { text-align: center; color: var(--text-secondary); font-style: italic; padding: 20px; } .queue-actions { text-align: center; } .btn-sm { font-size: 12px; padding: 6px 12px; border: 1px solid var(--border); background: var(--bg-secondary); color: var(--text-primary); border-radius: 6px; cursor: pointer; } .btn-sm:active { background: #e3f2fd; } .btn-refresh { padding: 8px 16px; border: 1px solid var(--border); background: var(--bg-secondary); color: var(--text-primary); border-radius: 6px; cursor: pointer; font-size: 13px; } /* =================================================================== Recent Tab =================================================================== */ .recent-panel { padding: 12px; display: flex; flex-direction: column; gap: 10px; overflow-y: auto; height: 100%; } .recent-header { display: flex; justify-content: space-between; align-items: center; } .recent-header h4 { font-size: 15px; } .recent-empty { text-align: center; color: var(--text-secondary); font-style: italic; padding: 40px 20px; font-size: 14px; } .recent-item { display: flex; align-items: center; padding: 12px; background: var(--bg-secondary); border: 1px solid var(--border); border-radius: 8px; gap: 10px; cursor: pointer; transition: background 0.1s; } .recent-item:active { background: var(--bg-primary); } .recent-direction { font-size: 18px; flex-shrink: 0; width: 28px; text-align: center; } .recent-info { flex: 1; min-width: 0; } .recent-number { font-weight: 600; font-size: 14px; color: var(--accent); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; } .recent-meta { font-size: 12px; color: var(--text-secondary); margin-top: 2px; display: flex; gap: 10px; } .recent-callback { flex-shrink: 0; padding: 6px 12px; background: var(--success); color: #fff; border: none; border-radius: 6px; font-size: 12px; cursor: pointer; } /* =================================================================== Dialog / Overlay (transfer, requeue) =================================================================== */ .twp-overlay { position: fixed; top: 0; left: 0; right: 0; bottom: 0; background: rgba(0,0,0,0.5); z-index: 9999; } .twp-dialog { position: fixed; top: 50%; left: 50%; transform: translate(-50%, -50%); background: var(--bg-secondary); padding: 20px; border-radius: var(--radius); box-shadow: 0 4px 20px rgba(0,0,0,0.3); z-index: 10000; width: 90%; max-width: 420px; max-height: 80vh; overflow-y: auto; color: var(--text-primary); } .twp-dialog h3 { margin: 0 0 12px 0; font-size: 16px; } .twp-dialog input[type="text"], .twp-dialog input[type="tel"] { width: 100%; padding: 10px; border: 1px solid var(--border); border-radius: 6px; font-size: 14px; background: var(--bg-primary); color: var(--text-primary); margin: 8px 0; } .twp-dialog .dialog-actions { display: flex; justify-content: flex-end; gap: 8px; margin-top: 14px; } .btn-primary { padding: 8px 18px; border: none; background: var(--accent); color: #fff; border-radius: 6px; font-size: 13px; cursor: pointer; } .btn-primary:disabled { opacity: 0.5; cursor: default; } .btn-secondary { padding: 8px 18px; border: 1px solid var(--border); background: var(--bg-secondary); color: var(--text-primary); border-radius: 6px; font-size: 13px; cursor: pointer; } .agent-option, .queue-option { padding: 10px; border: 1px solid var(--border); border-radius: 6px; margin-bottom: 6px; cursor: pointer; background: var(--bg-primary); display: flex; justify-content: space-between; align-items: center; } .agent-option.selected, .queue-option.selected { background: #e3f2fd; border-color: var(--accent); } @media (prefers-color-scheme: dark) { :root:not(.light-mode) .agent-option.selected, :root:not(.light-mode) .queue-option.selected { background: #0d47a1; } } .dark-mode .agent-option.selected, .dark-mode .queue-option.selected { background: #0d47a1; } /* =================================================================== Z-Index Layering & Overlap Fixes =================================================================== */ .twp-app { position: relative; z-index: 1; } .agent-status-bar { position: relative; z-index: 10; } .tab-nav { position: relative; z-index: 10; } .tab-content { position: relative; z-index: 1; } .phone-interface { position: relative; z-index: 1; overflow-y: auto; } .phone-controls { position: relative; z-index: 2; } #admin-call-controls-panel { position: relative; z-index: 2; margin-top: 4px; } .call-controls-grid { position: relative; z-index: 2; } .twp-overlay { z-index: 9999; } .twp-dialog { z-index: 10000; } /* Ensure tab panes scroll properly */ .tab-pane.active { overflow-y: auto; -webkit-overflow-scrolling: touch; } #tab-phone.active { overflow: hidden; } .phone-interface { flex: 1; overflow-y: auto; min-height: 0; } /* Prevent call controls from overlapping dialpad */ .dialpad-grid { position: relative; z-index: 1; flex-shrink: 0; } /* Dark mode for btn-ctrl active state */ @media (prefers-color-scheme: dark) { :root:not(.light-mode) .btn-ctrl:active { background: #0d47a1; color: #fff; } :root:not(.light-mode) .btn-sm:active { background: #0d47a1; color: #fff; } } .dark-mode .btn-ctrl:active { background: #0d47a1; color: #fff; } .dark-mode .btn-sm:active { background: #0d47a1; color: #fff; } /* =================================================================== Comprehensive Dark Mode Enhancements =================================================================== */ /* Shared dark mode rules — applied by media query or manual toggle */ @media (prefers-color-scheme: dark) { :root:not(.light-mode) input[type="tel"], :root:not(.light-mode) input[type="text"], :root:not(.light-mode) select { background: var(--bg-secondary); color: var(--text-primary); border-color: var(--border); } :root:not(.light-mode) .settings-section h4 { color: #64b5f6; } :root:not(.light-mode) .setup-info h4 { color: #ffe082; } :root:not(.light-mode) .setup-info code { background: rgba(255,255,255,0.08); color: #ffe082; } :root:not(.light-mode) .btn-copy { background: var(--bg-secondary); color: var(--text-primary); border-color: var(--border); } :root:not(.light-mode) .btn-refresh { background: var(--bg-secondary); color: var(--text-primary); } :root:not(.light-mode) .btn-secondary { background: var(--bg-secondary); color: var(--text-primary); } } .dark-mode input[type="tel"], .dark-mode input[type="text"], .dark-mode select { background: var(--bg-secondary); color: var(--text-primary); border-color: var(--border); } .dark-mode .settings-section h4 { color: #64b5f6; } .dark-mode .setup-info h4 { color: #ffe082; } .dark-mode .setup-info code { background: rgba(255,255,255,0.08); color: #ffe082; } .dark-mode .btn-copy { background: var(--bg-secondary); color: var(--text-primary); border-color: var(--border); } .dark-mode .btn-refresh { background: var(--bg-secondary); color: var(--text-primary); } .dark-mode .btn-secondary { background: var(--bg-secondary); color: var(--text-primary); } /* Dark mode toggle switch styling */ .dark-mode-toggle { display: flex; align-items: center; justify-content: space-between; padding: 4px 0; } .dark-mode-toggle .toggle-label { font-size: 13px; color: var(--text-primary); } .toggle-switch { position: relative; width: 48px; height: 26px; cursor: pointer; } .toggle-switch input { opacity: 0; width: 0; height: 0; } .toggle-slider { position: absolute; top: 0; left: 0; right: 0; bottom: 0; background: var(--border); border-radius: 26px; transition: background 0.2s; } .toggle-slider::before { content: ''; position: absolute; width: 20px; height: 20px; left: 3px; bottom: 3px; background: #fff; border-radius: 50%; transition: transform 0.2s; } .toggle-switch input:checked + .toggle-slider { background: var(--accent); } .toggle-switch input:checked + .toggle-slider::before { transform: translateX(22px); } .dark-mode-options { display: flex; gap: 8px; margin-top: 8px; } .dark-mode-opt { flex: 1; padding: 8px 4px; text-align: center; font-size: 12px; font-weight: 500; border: 1px solid var(--border); background: var(--bg-primary); color: var(--text-primary); border-radius: 6px; cursor: pointer; transition: all 0.2s; } .dark-mode-opt.active { border-color: var(--accent); background: var(--accent); color: #fff; }