/* NISPS Playground - Dark theme, mobile-first */ :root { --bg: #0d0d0d; --bg-surface: #1a1a1a; --bg-elevated: #252525; --text: #ccc; --text-dim: #666; --accent: #00ff88; --accent-dim: #00cc6a; --danger: #ff3366; --good: #00ff88; --bad: #ff6644; } * { box-sizing: border-box; margin: 0; padding: 0; } html, body { background: var(--bg); color: var(--text); font-family: -apple-system, BlinkMacSystemFont, 'SF Pro', 'Segoe UI', system-ui, sans-serif; font-size: 14px; height: 100%; overflow: hidden; touch-action: manipulation; -webkit-user-select: none; user-select: none; } /* --- Layout --- */ .app { display: grid; grid-template-rows: auto 1fr auto auto auto; height: 100vh; height: 100dvh; max-width: 600px; margin: 0 auto; } /* Header */ .header { display: flex; align-items: center; justify-content: space-between; padding: 8px 12px; border-bottom: 1px solid #222; } .header h1 { font-size: 15px; font-weight: 600; letter-spacing: 0.5px; color: var(--accent); } .header button { background: none; border: 1px solid #333; color: var(--text-dim); width: 28px; height: 28px; border-radius: 50%; cursor: pointer; font-size: 14px; } /* Visual canvas */ .visual-container { position: relative; min-height: 0; } .visual-container canvas { width: 100%; height: 100%; display: block; } /* Preset pills */ .presets { position: absolute; top: 8px; left: 8px; display: flex; gap: 6px; z-index: 2; } .preset-pill { background: rgba(26, 26, 26, 0.8); border: 1px solid #333; color: var(--text-dim); padding: 4px 10px; border-radius: 12px; font-size: 11px; cursor: pointer; backdrop-filter: blur(4px); -webkit-backdrop-filter: blur(4px); } .preset-pill:active { background: rgba(0, 255, 136, 0.15); border-color: var(--accent-dim); color: var(--accent); } /* Parameter display */ .param-container { padding: 6px 12px; background: var(--bg-surface); border-top: 1px solid #222; } .param-row { display: flex; align-items: center; gap: 8px; height: 22px; } .param-label { width: 42px; font-size: 10px; color: var(--text-dim); text-transform: uppercase; letter-spacing: 0.5px; flex-shrink: 0; } .param-track { flex: 1; height: 8px; background: #222; border-radius: 4px; overflow: hidden; position: relative; } .draggable .param-track { cursor: ew-resize; height: 14px; border: 1px solid #333; } .draggable .param-track:active { border-color: var(--accent-dim); } .param-fill { height: 100%; border-radius: 4px; transition: width 0.05s ease-out; } .param-value { width: 32px; font-size: 10px; color: var(--text-dim); text-align: right; font-family: monospace; flex-shrink: 0; } /* Controls area */ .controls-area { display: flex; align-items: flex-start; gap: 12px; padding: 10px 12px; background: var(--bg-surface); border-top: 1px solid #222; } #joystick-container { flex-shrink: 0; } #controls-container { flex: 1; min-width: 0; } .controls-mode-toggle { display: flex; gap: 4px; margin-bottom: 8px; } .mode-btn { flex: 1; padding: 6px 0; background: var(--bg-elevated); border: 1px solid #333; color: var(--text-dim); font-size: 12px; border-radius: 6px; cursor: pointer; transition: all 0.15s; } .mode-btn.active { background: rgba(0, 255, 136, 0.1); border-color: var(--accent-dim); color: var(--accent); } .controls-actions { display: flex; flex-wrap: wrap; gap: 6px; margin-bottom: 8px; } .btn { padding: 8px 14px; background: var(--bg-elevated); border: 1px solid #333; color: var(--text); font-size: 12px; border-radius: 8px; cursor: pointer; transition: all 0.1s; white-space: nowrap; } .btn:active { transform: scale(0.96); } .btn-primary { background: rgba(0, 255, 136, 0.12); border-color: var(--accent-dim); color: var(--accent); } .btn-primary:active { background: rgba(0, 255, 136, 0.25); } .btn-danger { color: var(--danger); border-color: #552233; } .btn-danger:active { background: rgba(255, 51, 102, 0.15); } .btn-good { background: rgba(0, 255, 136, 0.12); border-color: var(--accent-dim); color: var(--good); font-size: 18px; padding: 8px 20px; } .btn-good:active { background: rgba(0, 255, 136, 0.3); } .btn-bad { background: rgba(255, 102, 68, 0.1); border-color: #553322; color: var(--bad); font-size: 18px; padding: 8px 20px; } .btn-bad:active { background: rgba(255, 102, 68, 0.25); } .flash { animation: flash-anim 0.2s ease-out; } @keyframes flash-anim { 0% { box-shadow: 0 0 12px var(--accent); } 100% { box-shadow: none; } } .controls-status { display: flex; gap: 12px; font-size: 11px; color: var(--text-dim); font-family: monospace; margin-bottom: 8px; } .metrics-grid { display: grid; grid-template-columns: auto 1fr; gap: 3px 10px; font-size: 10px; margin-bottom: 8px; font-family: monospace; } .metric-label { color: #707070; } .metric-value { color: #b5b5b5; text-align: right; } .loss-plot-wrap { width: 100%; border: 1px solid #2a2a2a; border-radius: 8px; overflow: hidden; } #loss-plot { width: 100%; height: 86px; display: block; } .hidden { display: none !important; } /* Help overlay */ .help-overlay { position: fixed; inset: 0; background: rgba(0, 0, 0, 0.85); z-index: 100; display: flex; align-items: center; justify-content: center; padding: 20px; backdrop-filter: blur(8px); -webkit-backdrop-filter: blur(8px); } .help-content { background: var(--bg-surface); border: 1px solid #333; border-radius: 12px; padding: 20px; max-width: 360px; max-height: 80vh; overflow-y: auto; font-size: 13px; line-height: 1.5; } .help-content h2 { color: var(--accent); font-size: 16px; margin-bottom: 12px; } .help-content h3 { color: var(--text); font-size: 13px; margin-top: 14px; margin-bottom: 4px; } .help-content p, .help-content li { color: var(--text-dim); margin-bottom: 6px; } .help-content ol { padding-left: 18px; } /* Responsive: wider screens (foldable inner, tablet) */ @media (min-width: 500px) { .app { max-width: 800px; } .controls-area { padding: 12px 16px; } .param-container { padding: 8px 16px; } }