ipepe/YOLO26-WebGPU
1
1/* ============ CSS Variables ============ */2:root {3 --bg-primary: #0f0f13;4 --bg-secondary: #1a1a23;5 --bg-tertiary: #252532;6 --accent: #6366f1;7 --accent-hover: #818cf8;8 --text-primary: #f4f4f5;9 --text-secondary: #a1a1aa;10 --text-muted: #71717a;11 --border: #2e2e3a;12 --success: #22c55e;13 --warning: #f59e0b;14 --error: #ef4444;15 --radius: 12px;16 --shadow: 0 4px 24px rgba(0, 0, 0, 0.4);17}18 19/* ============ Reset & Base ============ */20*, *::before, *::after {21 box-sizing: border-box;22 margin: 0;23 padding: 0;24}25 26body {27 font-family: 'Inter', system-ui, -apple-system, sans-serif;28 background: var(--bg-primary);29 color: var(--text-primary);30 min-height: 100vh;31 line-height: 1.6;32 -webkit-font-smoothing: antialiased;33}34 35/* ============ Layout ============ */36.container {37 max-width: 1000px;38 margin: 0 auto;39 padding: 2rem 1.5rem;40 display: flex;41 flex-direction: column;42 gap: 2rem;43 min-height: 100vh;44}45 46.main-content {47 display: grid;48 grid-template-columns: 1fr 320px;49 gap: 1.5rem;50 align-items: start;51}52 53/* ============ Header ============ */54.header {55 text-align: center;56}57 58.title {59 font-size: 2rem;60 font-weight: 700;61 letter-spacing: -0.02em;62 margin-bottom: 0.5rem;63}64 65.accent {66 background: linear-gradient(135deg, var(--accent), #a855f7);67 -webkit-background-clip: text;68 -webkit-text-fill-color: transparent;69 background-clip: text;70}71 72.subtitle {73 color: var(--text-secondary);74 font-size: 0.95rem;75}76 77/* ============ Video Section ============ */78.video-section {79 display: flex;80 justify-content: center;81}82 83.video-container {84 position: relative;85 width: 100%;86 aspect-ratio: 1;87 background: var(--bg-secondary);88 border-radius: var(--radius);89 overflow: hidden;90 border: 1px solid var(--border);91 box-shadow: var(--shadow);92}93 94#video, #canvas {95 position: absolute;96 top: 0;97 left: 0;98 width: 100%;99 height: 100%;100 object-fit: cover;101}102 103#canvas {104 z-index: 10;105 pointer-events: none;106}107 108/* ============ Loader Overlay ============ */109.loader-overlay {110 position: absolute;111 inset: 0;112 z-index: 20;113 display: flex;114 flex-direction: column;115 align-items: center;116 justify-content: center;117 background: rgba(15, 15, 19, 0.95);118 opacity: 0;119 visibility: hidden;120 transition: opacity 0.3s, visibility 0.3s;121}122 123.loader-overlay.visible {124 opacity: 1;125 visibility: visible;126}127 128.spinner {129 width: 32px;130 height: 32px;131 border: 3px solid var(--border);132 border-top-color: var(--accent);133 border-radius: 50%;134 animation: spin 0.8s linear infinite;135 margin-bottom: 1rem;136}137 138@keyframes spin {139 to { transform: rotate(360deg); }140}141 142.loader-overlay p {143 color: var(--text-secondary);144 font-size: 0.9rem;145}146 147/* ============ Status & FPS Badges ============ */148.status-badge, .fps-badge {149 position: absolute;150 top: 1rem;151 z-index: 15;152 display: flex;153 align-items: center;154 gap: 0.5rem;155 padding: 0.4rem 0.75rem;156 background: rgba(0, 0, 0, 0.6);157 backdrop-filter: blur(8px);158 border-radius: 20px;159 font-size: 0.75rem;160 font-weight: 500;161 border: 1px solid rgba(255, 255, 255, 0.1);162}163 164.status-badge {165 left: 1rem;166}167 168.fps-badge {169 right: 1rem;170 font-family: 'SF Mono', 'Fira Code', monospace;171 color: var(--text-secondary);172}173 174.fps-badge #fps {175 color: var(--accent);176 font-weight: 600;177}178 179.status-dot {180 width: 8px;181 height: 8px;182 border-radius: 50%;183 background: var(--text-muted);184}185 186.status-dot.loading {187 background: var(--warning);188 animation: pulse 1.5s infinite;189}190 191.status-dot.ready {192 background: var(--success);193}194 195.status-dot.running {196 background: var(--success);197 animation: pulse 1.5s infinite;198}199 200.status-dot.error {201 background: var(--error);202}203 204@keyframes pulse {205 0%, 100% { opacity: 1; }206 50% { opacity: 0.5; }207}208 209/* ============ Controls ============ */210.controls {211 display: flex;212 flex-direction: column;213 gap: 1.25rem;214 background: var(--bg-secondary);215 padding: 1.5rem;216 border-radius: var(--radius);217 border: 1px solid var(--border);218}219 220.control-group {221 display: flex;222 flex-direction: column;223 gap: 0.5rem;224}225 226.control-group label {227 font-size: 0.85rem;228 font-weight: 500;229 color: var(--text-secondary);230}231 232/* Select */233select {234 appearance: none;235 background: var(--bg-tertiary);236 border: 1px solid var(--border);237 color: var(--text-primary);238 padding: 0.75rem 1rem;239 border-radius: 8px;240 font-size: 0.9rem;241 cursor: pointer;242 transition: border-color 0.2s;243 background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' fill='%23a1a1aa' viewBox='0 0 16 16'%3E%3Cpath d='M8 11L3 6h10l-5 5z'/%3E%3C/svg%3E");244 background-repeat: no-repeat;245 background-position: right 0.75rem center;246}247 248select:hover {249 border-color: var(--accent);250}251 252select:focus {253 outline: none;254 border-color: var(--accent);255 box-shadow: 0 0 0 3px rgba(99, 102, 241, 0.2);256}257 258/* Toggle Group */259.toggle-group {260 display: flex;261 gap: 1.5rem;262}263 264.toggle {265 display: flex;266 align-items: center;267 gap: 0.75rem;268 cursor: pointer;269 user-select: none;270}271 272.toggle input {273 display: none;274}275 276.toggle-slider {277 width: 44px;278 height: 24px;279 background: var(--bg-tertiary);280 border-radius: 12px;281 position: relative;282 transition: background 0.2s;283 border: 1px solid var(--border);284}285 286.toggle-slider::after {287 content: '';288 position: absolute;289 top: 2px;290 left: 2px;291 width: 18px;292 height: 18px;293 background: var(--text-secondary);294 border-radius: 50%;295 transition: transform 0.2s, background 0.2s;296}297 298.toggle input:checked + .toggle-slider {299 background: var(--accent);300 border-color: var(--accent);301}302 303.toggle input:checked + .toggle-slider::after {304 transform: translateX(20px);305 background: white;306}307 308.toggle-label {309 font-size: 0.9rem;310 color: var(--text-primary);311}312 313/* Threshold Range */314.threshold-control label {315 display: flex;316 justify-content: space-between;317 align-items: center;318}319 320.threshold-control #threshold-value {321 background: var(--bg-tertiary);322 padding: 0.25rem 0.5rem;323 border-radius: 4px;324 font-family: 'SF Mono', 'Fira Code', monospace;325 font-size: 0.8rem;326 color: var(--accent);327}328 329input[type="range"] {330 -webkit-appearance: none;331 appearance: none;332 width: 100%;333 height: 6px;334 background: var(--bg-tertiary);335 border-radius: 3px;336 cursor: pointer;337}338 339input[type="range"]::-webkit-slider-thumb {340 -webkit-appearance: none;341 width: 18px;342 height: 18px;343 background: var(--accent);344 border-radius: 50%;345 cursor: pointer;346 box-shadow: 0 2px 8px rgba(99, 102, 241, 0.4);347 transition: transform 0.2s;348}349 350input[type="range"]::-webkit-slider-thumb:hover {351 transform: scale(1.1);352}353 354input[type="range"]::-moz-range-thumb {355 width: 18px;356 height: 18px;357 background: var(--accent);358 border: none;359 border-radius: 50%;360 cursor: pointer;361}362 363/* Primary Button */364.btn-primary {365 display: flex;366 align-items: center;367 justify-content: center;368 gap: 0.75rem;369 padding: 0.875rem 1.5rem;370 background: var(--accent);371 color: white;372 border: none;373 border-radius: 8px;374 font-size: 0.95rem;375 font-weight: 600;376 cursor: pointer;377 transition: background 0.2s, transform 0.1s, box-shadow 0.2s;378 box-shadow: 0 4px 12px rgba(99, 102, 241, 0.3);379}380 381.btn-primary:hover:not(:disabled) {382 background: var(--accent-hover);383 transform: translateY(-1px);384 box-shadow: 0 6px 16px rgba(99, 102, 241, 0.4);385}386 387.btn-primary:active:not(:disabled) {388 transform: translateY(0);389}390 391.btn-primary:disabled {392 opacity: 0.5;393 cursor: not-allowed;394}395 396.btn-primary.running {397 background: var(--error);398 box-shadow: 0 4px 12px rgba(239, 68, 68, 0.3);399}400 401.btn-primary.running:hover:not(:disabled) {402 background: #f87171;403 box-shadow: 0 6px 16px rgba(239, 68, 68, 0.4);404}405 406#btn-icon {407 font-size: 0.8rem;408}409 410/* ============ Footer ============ */411.footer {412 text-align: center;413 margin-top: auto;414 padding-top: 1rem;415}416 417.footer p {418 font-size: 0.85rem;419 color: var(--text-muted);420}421 422.footer a {423 color: var(--accent);424 text-decoration: none;425 transition: color 0.2s;426}427 428.footer a:hover {429 color: var(--accent-hover);430}431 432/* ============ Responsive ============ */433@media (max-width: 768px) {434 .main-content {435 grid-template-columns: 1fr;436 }437 438 .controls {439 order: 1;440 }441 442 .video-section {443 order: 0;444 }445}446 447@media (max-width: 480px) {448 .container {449 padding: 1.5rem 1rem;450 gap: 1.5rem;451 }452 453 .title {454 font-size: 1.5rem;455 }456 457 .toggle-group {458 flex-direction: column;459 gap: 1rem;460 }461 462 .controls {463 padding: 1.25rem;464 }465}466 