* { margin: 0; padding: 0; box-sizing: border-box; -webkit-tap-highlight-color: transparent; } button, a, input, select, label { touch-action: manipulation; } :root { --primary: #6366f1; --primary-dark: #4f46e5; --secondary: #475569; --success: #22c55e; --danger: #ef4444; --warning: #f59e0b; --bg: #0f172a; --surface: #1e293b; --surface-light: #334155; --text: #f1f5f9; --text-muted: #94a3b8; --border: #475569; } body { font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; background: var(--bg); color: var(--text); min-height: 100vh; min-height: 100dvh; padding-bottom: env(safe-area-inset-bottom); padding-left: env(safe-area-inset-left); padding-right: env(safe-area-inset-right); overflow-x: hidden; -webkit-text-size-adjust: 100%; } /* Header */ .header { background: linear-gradient(135deg, var(--primary) 0%, var(--primary-dark) 100%); padding: 10px 16px; position: sticky; top: 0; z-index: 100; display: flex; justify-content: space-between; align-items: center; flex-wrap: wrap; gap: 8px; } .header h1 { font-size: 1.1em; font-weight: 700; letter-spacing: 1px; } .header-controls { display: flex; align-items: center; gap: 8px; } .connection-status { font-size: 0.75em; padding: 3px 10px; border-radius: 20px; background: rgba(0,0,0,0.3); } .connection-status.connected { background: var(--success); } .connection-status.disconnected { background: var(--danger); } .btn-icon { width: 34px; height: 34px; border: none; border-radius: 8px; background: rgba(255,255,255,0.2); color: var(--text); font-size: 1em; cursor: pointer; } .btn-icon:active { transform: scale(0.95); background: rgba(255,255,255,0.3); } @media (hover: hover) { .btn-icon:hover { background: rgba(255,255,255,0.3); } } .btn-icon.locked { background: rgba(255,255,255,0.4); } /* ---- Tab Bar ---- */ .tab-bar { display: flex; gap: 4px; } .tab-btn { padding: 6px 16px; border: none; border-radius: 6px; background: rgba(255,255,255,0.15); color: white; font-weight: 600; font-size: 0.85em; cursor: pointer; transition: background 0.2s; } @media (hover: hover) { .tab-btn:hover { background: rgba(255,255,255,0.25); } } .tab-btn.active { background: rgba(255,255,255,0.35); } .tab-content { display: none; } .tab-content.active { display: block; } /* Health Bar */ .health-bar { display: flex; gap: 12px; padding: 8px 16px; background: var(--surface); border-bottom: 1px solid var(--border); overflow-x: auto; flex-wrap: wrap; } .health-item { display: flex; align-items: center; gap: 5px; font-size: 0.75em; color: var(--text-muted); white-space: nowrap; } .health-dot { width: 8px; height: 8px; border-radius: 50%; display: inline-block; } .health-dot.online { background: var(--success); box-shadow: 0 0 6px var(--success); } .health-dot.offline { background: var(--secondary); } .health-dot.recording { background: var(--danger); box-shadow: 0 0 6px var(--danger); animation: pulse 1s infinite; } @keyframes pulse { 0%,100%{opacity:1} 50%{opacity:0.4} } /* ---- GridStack Overrides ---- */ .grid-stack { padding: 8px; min-height: calc(100vh - 90px); min-height: calc(100dvh - 90px); } .grid-stack-item-content { background: var(--surface); border-radius: 10px; overflow: hidden; border: 1px solid transparent; transition: border-color 0.2s; } @media (hover: hover) { .grid-stack-item-content:hover { border-color: rgba(255,255,255,0.08); } } .grid-stack-placeholder > .placeholder-content { background: rgba(99, 102, 241, 0.15) !important; border: 2px dashed var(--primary) !important; border-radius: 10px; } .gs-resizable-handle { z-index: 10; } /* Widget */ .widget { display: flex; flex-direction: column; height: 100%; } .widget-header { padding: 8px 12px; background: var(--surface-light); display: flex; align-items: center; justify-content: space-between; cursor: move; user-select: none; flex-shrink: 0; } .widget-title { font-weight: 600; font-size: 0.9em; display: flex; align-items: center; gap: 8px; } .widget-close { width: 22px; height: 22px; border: none; border-radius: 4px; background: transparent; color: var(--text-muted); cursor: pointer; font-size: 0.85em; display: flex; align-items: center; justify-content: center; flex-shrink: 0; } @media (hover: hover) { .widget-close:hover { background: rgba(239, 68, 68, 0.3); color: var(--danger); } } .widget-body { padding: 10px; flex: 1; overflow-y: auto; } /* Badge */ .section-badge { background: var(--primary); color: white; font-size: 0.7em; padding: 1px 7px; border-radius: 10px; } /* Button Grid */ .button-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(120px, 1fr)); gap: 6px; margin-bottom: 8px; } /* Buttons */ .btn { padding: 10px 12px; border: none; border-radius: 8px; font-size: 0.82em; font-weight: 600; cursor: pointer; transition: transform 0.1s, background 0.2s; text-align: center; word-break: break-word; } .btn:active { transform: scale(0.96); } .btn-primary { background: var(--primary); color: white; } @media (hover: hover) { .btn-primary:hover { background: var(--primary-dark); } } .btn-secondary { background: var(--secondary); color: white; } @media (hover: hover) { .btn-secondary:hover { background: #566a82; } } .btn-danger { background: var(--danger); color: white; } @media (hover: hover) { .btn-danger:hover { background: #dc2626; } } .btn-sm { padding: 8px 10px; font-size: 0.78em; } /* Preset Buttons (Dashboard) */ .preset-btn { padding: 10px 8px; border: 2px solid transparent; border-radius: 8px; background: rgba(0,0,0,0.3); color: var(--text); font-size: 0.8em; cursor: pointer; text-align: center; word-break: break-word; transition: all 0.2s; } .preset-btn:active { transform: scale(0.96); } .preset-btn.active { background: var(--primary); border-color: #818cf8; font-weight: 600; } .preset-btn.item-active { background: var(--success); border-color: #4ade80; } .preset-btn.event-btn:active { background: var(--warning); } /* Action Row */ .action-row { display: flex; gap: 6px; flex-wrap: wrap; } /* Avatar Section */ .avatar-group { margin-bottom: 12px; padding-bottom: 10px; border-bottom: 1px solid rgba(255,255,255,0.05); } .avatar-group:last-child { border-bottom: none; margin-bottom: 0; padding-bottom: 0; } .avatar-name { font-size: 0.82em; font-weight: 600; margin-bottom: 6px; color: var(--text-muted); } .outfit-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(100px, 1fr)); gap: 4px; } /* System Groups */ .system-group { margin-bottom: 12px; } .system-group:last-child { margin-bottom: 0; } .system-group-title { font-size: 0.75em; color: var(--text-muted); margin-bottom: 6px; padding-bottom: 3px; border-bottom: 1px solid rgba(255,255,255,0.05); } /* ---- Settings Overlay ---- */ .settings-overlay { display: none; position: fixed; top: 0; left: 0; right: 0; bottom: 0; background: rgba(0,0,0,0.5); z-index: 200; justify-content: center; align-items: center; } .settings-overlay.show { display: flex; } .settings-panel { background: var(--surface); border-radius: 12px; border: 1px solid var(--border); min-width: 280px; max-width: 90%; box-shadow: 0 20px 60px rgba(0,0,0,0.5); } .settings-header { padding: 12px 16px; display: flex; justify-content: space-between; align-items: center; border-bottom: 1px solid var(--border); font-weight: 600; } .settings-close { width: 28px; height: 28px; border: none; border-radius: 6px; background: transparent; color: var(--text-muted); cursor: pointer; font-size: 1em; } @media (hover: hover) { .settings-close:hover { background: rgba(255,255,255,0.1); } } .settings-body { padding: 16px; } .settings-body label { display: flex; align-items: center; gap: 10px; padding: 8px 4px; cursor: pointer; color: var(--text); font-size: 0.9em; border-radius: 6px; } @media (hover: hover) { .settings-body label:hover { background: rgba(255,255,255,0.05); } } .settings-body input[type="checkbox"] { width: 16px; height: 16px; accent-color: var(--primary); } .settings-footer { padding: 12px 16px; border-top: 1px solid var(--border); text-align: center; } /* Toast */ .toast { position: fixed; bottom: 20px; left: 50%; transform: translateX(-50%); padding: 10px 20px; border-radius: 8px; background: var(--surface-light); color: var(--text); font-size: 0.85em; opacity: 0; transition: opacity 0.3s; z-index: 1000; max-width: 85%; text-align: center; } .toast.show { opacity: 1; } .toast.success { background: var(--success); } .toast.error { background: var(--danger); } /* ======== Retargeting Tab Styles ======== */ /* Retargeting Status Bar */ .rt-status-bar { display: flex; align-items: center; justify-content: flex-end; padding: 6px 16px; background: var(--surface); border-bottom: 1px solid var(--border); } .rt-connection-status { font-size: 0.75em; padding: 3px 10px; border-radius: 20px; background: rgba(0,0,0,0.3); } .rt-connection-status.connected { background: var(--success); } .rt-connection-status.disconnected { background: var(--danger); } /* Characters Container - horizontal scroll */ .characters-container { display: flex; flex-wrap: nowrap; overflow-x: auto; padding: 12px; padding-bottom: 20px; gap: 12px; min-height: calc(100vh - 110px); min-height: calc(100dvh - 110px); align-items: flex-start; -webkit-overflow-scrolling: touch; } .characters-container::-webkit-scrollbar { height: 12px; } .characters-container::-webkit-scrollbar-track { background: var(--surface); border-radius: 6px; } .characters-container::-webkit-scrollbar-thumb { background: var(--primary); border-radius: 6px; } @media (hover: hover) { .characters-container::-webkit-scrollbar-thumb:hover { background: var(--primary-dark); } } .loading-message { color: var(--text-muted); padding: 20px; text-align: center; width: 100%; } /* Character Panel */ .character-panel { width: 480px; min-width: 480px; background: var(--surface); border-radius: 12px; flex-shrink: 0; } .character-header { background: var(--surface-light); padding: 12px; border-radius: 12px 12px 0 0; } .character-header h2 { font-size: 1em; font-weight: 600; display: flex; align-items: center; gap: 8px; margin: 0; } .character-header h2::before { content: '\1F464'; } .character-content { padding: 12px; } /* Retargeting Section (rt-section to avoid dashboard collision) */ .rt-section { background: rgba(0,0,0,0.2); border-radius: 8px; margin-bottom: 8px; overflow: hidden; } .rt-section-header { padding: 10px 12px; font-weight: 600; font-size: 0.85em; cursor: pointer; display: flex; align-items: center; justify-content: space-between; background: rgba(0,0,0,0.2); } .rt-section-header::after { content: '\25BC'; font-size: 0.6em; transition: transform 0.3s; } .rt-section-header.collapsed::after { transform: rotate(-90deg); } .rt-section-content { padding: 10px; } .rt-section-content.hidden { display: none; } /* Retargeting Controls */ .rt-control-group { margin-bottom: 12px; } .rt-slider-header { display: flex; justify-content: space-between; margin-bottom: 4px; } .rt-slider-header label { font-size: 0.8em; color: var(--text-muted); } .rt-value-input { font-family: monospace; background: var(--bg); border: 1px solid var(--surface-light); border-radius: 4px; padding: 4px 6px; font-size: 0.8em; color: var(--text); width: 80px; text-align: right; } .rt-value-input:focus { outline: none; border-color: var(--primary); } .rt-value-input::-webkit-inner-spin-button, .rt-value-input::-webkit-outer-spin-button { -webkit-appearance: none; margin: 0; } .rt-slider-row { display: flex; align-items: center; gap: 4px; } #tabRetargeting input[type="range"] { flex: 1; height: 32px; -webkit-appearance: none; background: transparent; } #tabRetargeting input[type="range"]::-webkit-slider-track { height: 5px; background: var(--bg); border-radius: 3px; } #tabRetargeting input[type="range"]::-webkit-slider-thumb { -webkit-appearance: none; width: 20px; height: 20px; background: var(--primary); border-radius: 50%; cursor: pointer; margin-top: -7px; } #tabRetargeting input[type="range"]::-moz-range-track { height: 5px; background: var(--bg); border-radius: 3px; border: none; } #tabRetargeting input[type="range"]::-moz-range-thumb { width: 20px; height: 20px; background: var(--primary); border-radius: 50%; cursor: pointer; border: none; } .rt-btn-fine { width: 32px; height: 32px; border: none; border-radius: 6px; background: var(--bg); color: var(--text); font-size: 1em; font-weight: bold; cursor: pointer; } .rt-btn-fine:active { background: var(--primary); } .rt-button-group { display: flex; gap: 6px; } .rt-button-group .btn { flex: 1; margin-top: 0; } .rt-calibration-status { text-align: center; padding: 6px; border-radius: 6px; margin-bottom: 10px; background: var(--bg); font-size: 0.8em; } .rt-calibration-status.has-data { background: var(--success); color: white; } #tabRetargeting select { width: 100%; padding: 8px; border: none; border-radius: 6px; background: var(--bg); color: var(--text); font-size: 0.85em; } .rt-sub-section-title { font-size: 0.75em; color: var(--text-muted); margin: 10px 0 6px 0; padding-bottom: 3px; border-bottom: 1px solid var(--bg); } .rt-toggle-row { display: flex; gap: 12px; margin-bottom: 10px; flex-wrap: wrap; } .rt-toggle-label { display: flex; align-items: center; gap: 5px; cursor: pointer; font-size: 0.8em; } .rt-toggle-label input[type="checkbox"] { width: 16px; height: 16px; accent-color: var(--primary); } .rt-preset-hint { font-size: 0.7em; color: var(--text-muted); margin-bottom: 6px; text-align: center; } .rt-preset-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 4px; } .rt-preset-btn { padding: 8px 4px; border: none; border-radius: 6px; background: var(--bg); color: var(--text); font-size: 0.7em; cursor: pointer; text-align: center; word-break: break-word; } .rt-preset-btn:active { background: var(--primary); } /* Range Slider (MinMax) */ .rt-range-slider-group { margin-bottom: 12px; } .rt-range-slider-header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 4px; } .rt-range-slider-header label { font-size: 0.8em; color: var(--text-muted); } .rt-range-slider-values { display: flex; gap: 8px; font-family: monospace; font-size: 0.75em; } .rt-range-slider-values input { width: 50px; padding: 2px 4px; background: var(--bg); border: 1px solid var(--surface-light); border-radius: 4px; color: var(--text); text-align: center; } .rt-range-slider-container { position: relative; height: 32px; display: flex; align-items: center; } .rt-range-slider-track { position: absolute; width: 100%; height: 5px; background: var(--bg); border-radius: 3px; } .rt-range-slider-fill { position: absolute; height: 5px; background: var(--primary); border-radius: 3px; } .rt-range-slider-container input[type="range"] { position: absolute; width: 100%; pointer-events: none; -webkit-appearance: none; background: transparent; height: 32px; } .rt-range-slider-container input[type="range"]::-webkit-slider-thumb { pointer-events: auto; -webkit-appearance: none; width: 18px; height: 18px; background: var(--primary); border-radius: 50%; cursor: pointer; border: 2px solid white; box-shadow: 0 2px 4px rgba(0,0,0,0.3); } .rt-range-slider-container input[type="range"]::-webkit-slider-track { background: transparent; } .rt-range-slider-container input[type="range"]::-moz-range-thumb { width: 18px; height: 18px; background: var(--primary); border-radius: 50%; cursor: pointer; border: 2px solid white; box-shadow: 0 2px 4px rgba(0,0,0,0.3); } .rt-range-slider-container input[type="range"]::-moz-range-track { background: transparent; border: none; } .setting-description { font-size: 0.75em; color: var(--text-muted); margin-bottom: 8px; } /* ======== Mobile: Tablet (<=768px) ======== */ @media (max-width: 768px) { .header { padding: 8px 12px; flex-wrap: wrap; } .header h1 { font-size: 1em; } .tab-bar { gap: 2px; order: 10; width: 100%; justify-content: center; } .tab-btn { padding: 7px 14px; font-size: 0.82em; flex: 1; text-align: center; } .header-controls { gap: 6px; } .btn-icon { width: 40px; height: 40px; font-size: 1.05em; } .button-grid { grid-template-columns: repeat(auto-fill, minmax(100px, 1fr)); } .preset-btn { padding: 12px 8px; font-size: 0.85em; min-height: 44px; } .btn { padding: 12px 14px; min-height: 44px; } .btn-sm { min-height: 40px; } .characters-container { flex-direction: column; flex-wrap: nowrap; overflow-x: visible; padding: 8px; } .character-panel { width: 100%; min-width: 100%; max-width: 100%; } /* Slider thumb bigger for touch */ #tabRetargeting input[type="range"]::-webkit-slider-thumb { width: 28px; height: 28px; margin-top: -11px; } .rt-range-slider-container input[type="range"]::-webkit-slider-thumb { width: 26px; height: 26px; } .rt-btn-fine { width: 40px; height: 40px; font-size: 1.1em; } .rt-preset-btn { padding: 10px 6px; font-size: 0.75em; min-height: 40px; } .rt-section-header { padding: 12px; font-size: 0.9em; } .rt-toggle-label { font-size: 0.85em; padding: 4px 0; } .rt-toggle-label input[type="checkbox"] { width: 20px; height: 20px; } .settings-body label { padding: 10px 4px; } .settings-body input[type="checkbox"] { width: 20px; height: 20px; } #tabRetargeting select { padding: 10px; font-size: 0.9em; min-height: 44px; } .widget-body { padding: 8px; } /* Preview tablet */ .preview-toolbar { flex-wrap: wrap; gap: 8px; } .preview-controls { flex-wrap: wrap; gap: 6px 10px; } .preview-controls select { padding: 8px 10px; font-size: 0.9em; min-height: 40px; } .preview-grid { grid-template-columns: repeat(auto-fill, minmax(240px, 1fr)); gap: 10px; padding: 10px; } .preview-card-label { padding: 10px 12px; } .preview-card-expand { width: 36px; height: 36px; font-size: 0.9em; } } /* ======== Mobile: Small Phone (<=480px) ======== */ @media (max-width: 480px) { .header h1 { font-size: 0.9em; letter-spacing: 0; } .tab-btn { padding: 6px 8px; font-size: 0.78em; } .connection-status { font-size: 0.7em; padding: 2px 8px; } .health-bar { padding: 6px 10px; gap: 8px; } .health-item { font-size: 0.7em; } .button-grid { grid-template-columns: repeat(auto-fill, minmax(85px, 1fr)); gap: 4px; } .outfit-grid { grid-template-columns: repeat(auto-fill, minmax(80px, 1fr)); } .rt-preset-grid { grid-template-columns: repeat(2, 1fr); } .grid-stack { padding: 4px; } .characters-container { padding: 6px; gap: 8px; } .character-content { padding: 8px; } .rt-range-slider-values input { width: 42px; font-size: 0.7em; } .settings-panel { min-width: 0; width: 95%; } .toast { max-width: 92%; font-size: 0.8em; bottom: 12px; } .preview-toolbar { flex-direction: column; gap: 8px; align-items: flex-start; } .preview-controls select { padding: 10px 12px; min-height: 44px; font-size: 0.9em; } .preview-grid { gap: 8px; padding: 8px; } .preview-grid.mobile-single-col { grid-template-columns: 1fr !important; } .preview-card-label { padding: 10px 12px; font-size: 0.9em; } .preview-card-expand { width: 40px; height: 40px; font-size: 1em; } .preview-fullscreen { padding: env(safe-area-inset-top) env(safe-area-inset-right) env(safe-area-inset-bottom) env(safe-area-inset-left); } .preview-fullscreen-close { top: calc(16px + env(safe-area-inset-top)); right: calc(16px + env(safe-area-inset-right)); width: 48px; height: 48px; font-size: 1.4em; } } /* ---- Camera Preview Tab ---- */ .preview-toolbar { display: flex; justify-content: space-between; align-items: center; padding: 10px 16px; background: var(--surface); border-bottom: 1px solid var(--border); } .preview-info { font-size: 0.85em; color: var(--text-muted); } .preview-controls { display: flex; align-items: center; gap: 8px; font-size: 0.8em; } .preview-controls select { background: var(--surface-light); color: var(--text); border: 1px solid var(--border); border-radius: 4px; padding: 4px 8px; font-size: 0.9em; } .preview-controls label { color: var(--text-muted); } .preview-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(300px, 1fr)); gap: 12px; padding: 16px; } .preview-card { position: relative; background: var(--surface); border-radius: 8px; overflow: hidden; border: 2px solid transparent; cursor: pointer; transition: border-color 0.2s, transform 0.1s; } @media (hover: hover) { .preview-card:hover { border-color: var(--primary); transform: translateY(-2px); } } .preview-card.active { border-color: var(--success); } .preview-canvas { width: 100%; aspect-ratio: 16/9; display: block; background: #111; object-fit: cover; } .preview-card-label { padding: 8px 10px; font-size: 0.85em; display: flex; justify-content: space-between; align-items: center; } .preview-card-name { font-weight: 600; } .preview-card-badge { font-size: 0.7em; padding: 2px 8px; border-radius: 10px; background: var(--success); color: white; font-weight: 600; } .preview-fullscreen { position: fixed; top: 0; left: 0; right: 0; bottom: 0; background: rgba(0,0,0,0.92); z-index: 200; display: flex; flex-direction: column; align-items: center; justify-content: center; } .preview-fullscreen-canvas { max-width: 95vw; max-height: 85vh; object-fit: contain; border-radius: 4px; } .preview-fullscreen-close { position: absolute; top: 16px; right: 16px; background: rgba(255,255,255,0.2); border: none; color: white; width: 40px; height: 40px; border-radius: 50%; font-size: 1.2em; cursor: pointer; } @media (hover: hover) { .preview-fullscreen-close:hover { background: rgba(255,255,255,0.35); } } .preview-fullscreen-label { color: var(--text); margin-top: 12px; font-size: 1.1em; font-weight: 600; } .preview-card-expand { width: 30px; height: 30px; border: none; border-radius: 6px; background: rgba(255,255,255,0.15); color: var(--text); font-size: 0.8em; cursor: pointer; flex-shrink: 0; display: flex; align-items: center; justify-content: center; } @media (hover: hover) { .preview-card-expand:hover { background: rgba(255,255,255,0.3); } } .preview-placeholder { width: 100%; aspect-ratio: 16/9; display: flex; align-items: center; justify-content: center; background: #111; color: var(--text-muted); font-size: 0.8em; }