<!doctype html> <html lang="en"> <head> <meta charset="utf-8" /> <title>Sparrow Dashboard</title> <meta name="viewport" content="width=device-width, initial-scale=1" /> <style> body { font-family: system-ui, sans-serif; margin: 0; padding: 0; background: #111; color: #eee; } .container { max-width: 900px; margin: 0 auto; padding: 1.5rem; } h1, h2 { font-weight: 600; } .card { background: #1c1c1c; border-radius: 1rem; padding: 1rem 1.25rem; margin-bottom: 1rem; box-shadow: 0 10px 30px rgba(0,0,0,0.3); } input, button { font-size: 1rem; padding: 0.5rem 0.75rem; border-radius: 0.5rem; border: 1px solid #444; background: #222; color: #eee; margin: 0.25rem 0; } button { cursor: pointer; } button:hover { background: #333; } table { width: 100%; border-collapse: collapse; margin-top: 0.5rem; } th, td { border-bottom: 1px solid #333; text-align: left; padding: 0.35rem 0.5rem; font-size: 0.9rem; } .flex { display: flex; align-items: center; gap: 0.5rem; flex-wrap: wrap; } .right { float: right; } #dashboard { display: none; } #led-color { padding: 0; border: none; width: 3rem; height: 2rem; } .badge { display: inline-block; padding: 0.15rem 0.4rem; border-radius: 999px; font-size: 0.75rem; background: #333; } .chart-stack { display: flex; flex-direction: column; gap: 1rem; } .chart-card { background: #0d0d0d; border-radius: 0.75rem; padding: 0.75rem; } canvas { width: 100%; height: 220px; } </style> <!-- Firebase compat CDN (v9.x) --> <script defer src="https://www.gstatic.com/firebasejs/9.10.0/firebase-app-compat.js"></script> <script defer src="https://www.gstatic.com/firebasejs/9.10.0/firebase-auth-compat.js"></script> <script defer src="https://www.gstatic.com/firebasejs/9.10.0/firebase-database-compat.js"></script> <!-- Chart.js self-hosted for realtime plots (avoid CDN/CSP issues) --> <script defer src="chart.umd.min.js?v=1"></script> <script defer src="app.js"></script> </head> <body> <div class="container"> <!-- Login screen --> <div id="login-screen" class="card"> <h1>🔐 Sparrow Login</h1> <p>Enter your Firebase email & password.</p> <input id="login-email" type="email" placeholder="Email" style="width:100%" /> <input id="login-password" type="password" placeholder="Password" style="width:100%" /> <button id="login-btn">Login</button> <p id="login-error" style="color:#ff8080;"></p> </div> <!-- Dashboard --> <div id="dashboard"> <div class="card"> <div class="flex"> <h1 style="margin:0;">🌡️ Sparrow Dashboard</h1> <span class="badge" id="user-email"></span> <button id="logout-btn" class="right">Logout</button> </div> </div> <div class="card"> <h2>Latest reading</h2> <div id="latest-reading"> <p>No data yet…</p> </div> </div> <div class="card"> <h2>Realtime plots</h2> <p id="chart-status" style="margin:0 0 0.5rem 0; color:#aaa; font-size:0.9rem;">Loading charts…</p> <div class="chart-stack"> <div class="chart-card"> <div style="margin-bottom:0.25rem; color:#ccc; font-size:0.95rem;">Temperature (°C)</div> <canvas id="chart-temp"></canvas> </div> <div class="chart-card"> <div style="margin-bottom:0.25rem; color:#ccc; font-size:0.95rem;">Humidity (%)</div> <canvas id="chart-hum"></canvas> </div> <div class="chart-card"> <div style="margin-bottom:0.25rem; color:#ccc; font-size:0.95rem;">Pressure (hPa)</div> <canvas id="chart-press"></canvas> </div> </div> </div> <div class="card"> <h2>History (last 20)</h2> <table> <thead> <tr> <th>Time</th> <th>Temp (°C)</th> <th>Hum (%)</th> <th>Press (hPa)</th> </tr> </thead> <tbody id="history-body"> </tbody> </table> </div> <div class="card"> <h2>NeoPixel control</h2> <div class="flex"> <label><input type="checkbox" id="led-on" /> LED On</label> <label>Color <input type="color" id="led-color" value="#ffffff" /></label> <button id="led-apply-btn">Apply</button> </div> <p id="led-status"></p> </div> </div> </div> </body> </html>