diff --git a/charts.js b/charts.js deleted file mode 100644 index f1fe16024..000000000 --- a/charts.js +++ /dev/null @@ -1,105 +0,0 @@ -/* ============================================================ - PROJECT ECHO – CHARTS.JS - Simple canvas-based charts (no external libraries) - Currently renders: - - Alerts severity bar chart (alerts.html → ) - ============================================================ */ - -document.addEventListener("DOMContentLoaded", () => { - drawAlertsChart(); -}); - -/** - * Draw a simple bar chart for alert severity. - * Canvas: - */ -function drawAlertsChart() { - const canvas = document.getElementById("alertsChart"); - if (!canvas) return; // not on this page - - const ctx = canvas.getContext("2d"); - - // Data (you can adjust these values to match your narrative) - const labels = ["Critical", "High", "Medium", "Low"]; - const values = [3, 5, 7, 2]; - - // Colours aligned to your UI palette - const colors = [ - "#C8473C", // Critical (danger) - "#D29B38", // High (warning) - "#F59E0B", // Medium (amber) - "#2F6E4F" // Low (green) - ]; - - // Canvas dimensions - const width = canvas.width; - const height = canvas.height; - - // Chart area padding - const padding = 30; - const bottomPadding = 40; - const topPadding = 20; - - // Compute scaling - const maxValue = Math.max(...values); - const chartHeight = height - bottomPadding - topPadding; - const scaleY = chartHeight / maxValue; - - const barWidth = 32; - const gap = 26; - - // Clear canvas - ctx.clearRect(0, 0, width, height); - - // Background (optional light grid line) - ctx.strokeStyle = "rgba(148, 163, 184, 0.25)"; - ctx.lineWidth = 1; - - // Horizontal baseline - ctx.beginPath(); - ctx.moveTo(padding, height - bottomPadding); - ctx.lineTo(width - padding, height - bottomPadding); - ctx.stroke(); - - // Draw bars - ctx.font = "12px Inter, system-ui, sans-serif"; - ctx.textAlign = "center"; - - values.forEach((value, i) => { - const x = padding + i * (barWidth + gap) + barWidth / 2; - const barHeight = value * scaleY; - const y = height - bottomPadding - barHeight; - - // Bar - ctx.fillStyle = colors[i]; - ctx.beginPath(); - ctx.roundRect(x - barWidth / 2, y, barWidth, barHeight, 6); - ctx.fill(); - - // Value label on top - ctx.fillStyle = "#111827"; - ctx.fillText(value, x, y - 6); - - // X-axis label - ctx.fillStyle = "#6F7B74"; - ctx.fillText(labels[i], x, height - bottomPadding + 18); - }); -} - -/** - * Polyfill for roundRect on older browsers. - * (Most modern browsers support it, but this keeps it safe.) - */ -if (!CanvasRenderingContext2D.prototype.roundRect) { - CanvasRenderingContext2D.prototype.roundRect = function (x, y, w, h, r) { - r = Math.min(r, w / 2, h / 2); - this.beginPath(); - this.moveTo(x + r, y); - this.arcTo(x + w, y, x + w, y + h, r); - this.arcTo(x + w, y + h, x, y + h, r); - this.arcTo(x, y + h, x, y, r); - this.arcTo(x, y, x + w, y, r); - this.closePath(); - return this; - }; -} diff --git a/new 1.html b/new 1.html deleted file mode 100644 index 4a5c81785..000000000 --- a/new 1.html +++ /dev/null @@ -1,192 +0,0 @@ - - - - - Sensor Health Management - - - -
-
-

Sensor Health Management

-
Web Prototype
-
- - - -
-

Overview

-

- High-level summary of sensor health, alerts and active projects. -

- - - - - -
MetricValueStatus
Total Sensors128Healthy
Active Alerts5Attention
Projects7Running
-
- -
-

Sensor Health Management

-

- Real-time status of sensors, battery and connectivity. -

- - - - - - - - - - - - - - - - -
Sensor IDProjectStatusBatteryLast Contact
SEN-01Rainforest AOnline87%2 min ago
SEN-14Rainforest ADegraded21%15 min ago
SEN-77Savannah TrialOffline2 h ago
-
- -
-

Alerts by Exception

-

- Low battery, offline, not functioning, and last-audio issues. -

- - - - - - - - - - - - - - - - - - - - - - -
Sensor IDAlert TypeDetailsLast Audio
SEN-14Low BatteryBattery 21% – threshold 25%32 min ago
SEN-77OfflineNo contact for 2 h2 h 5 min ago
SEN-88Last audio missingNo audio in last 6 h6 h ago
-
- -
-

Reboot Sensors

-

- Queue a reboot for specific sensors. -

-
-
- - -

Comma-separated list allowed.

-
-
- - -
-
- - -

-
- -
-

Adjust Settings

-

- Configure recording and alert behaviour for sensors. -

-
-
- - -
-
- - -
-
- - -
-
- - -
-
- - -

- - -

-
- -
-

Add a Project

-

- Create a project and assign sensors to it (this fulfils “Able to add a project”). -

-
-
- - -
-
- - -
-
- - -
-
- - -
-
- - -

- - -

IDs, ranges or group names.

- - - -

-
-
- - - - diff --git a/script.js b/script.js deleted file mode 100644 index 14f15f014..000000000 --- a/script.js +++ /dev/null @@ -1,176 +0,0 @@ -/* ============================================================ - PROJECT ECHO – SCRIPT.JS - Handles: - - Mobile sidebar toggle - - Theme toggle (light/dark) - - Fake actions (Reboot, Settings, Project creation) - - UI message helpers - ============================================================ */ - - -/* ------------------------------------------------------------ - 1) MOBILE SIDEBAR TOGGLE - ------------------------------------------------------------ */ - -const menuToggle = document.getElementById("menu-toggle"); -const mobileBackdrop = document.getElementById("mobile-backdrop"); - -if (menuToggle) { - menuToggle.addEventListener("click", () => { - document.body.classList.toggle("sidebar-open"); - }); -} - -if (mobileBackdrop) { - mobileBackdrop.addEventListener("click", () => { - document.body.classList.remove("sidebar-open"); - }); -} - - - -/* ------------------------------------------------------------ - 2) THEME TOGGLE (LIGHT ↔ DARK) - ------------------------------------------------------------ */ - -const themeToggle = document.getElementById("theme-toggle"); - -function setTheme(darkMode) { - if (darkMode) { - document.documentElement.setAttribute("data-theme", "dark"); - themeToggle.textContent = "☀️"; - localStorage.setItem("echo-theme", "dark"); - } else { - document.documentElement.removeAttribute("data-theme"); - themeToggle.textContent = "🌙"; - localStorage.setItem("echo-theme", "light"); - } -} - -if (themeToggle) { - // Load saved theme - const savedTheme = localStorage.getItem("echo-theme"); - setTheme(savedTheme === "dark"); - - // Toggle on click - themeToggle.addEventListener("click", () => { - const isDark = document.documentElement.getAttribute("data-theme") === "dark"; - setTheme(!isDark); - }); -} - - - -/* ------------------------------------------------------------ - 3) UI MESSAGE HELPER - ------------------------------------------------------------ */ - -function showMessage(elementId, message, type = "success") { - const el = document.getElementById(elementId); - if (!el) return; - - const colors = { - success: "var(--primary)", - warning: "var(--warning)", - danger: "var(--danger)" - }; - - el.style.color = colors[type] || colors.success; - el.style.marginTop = "10px"; - el.style.fontWeight = "600"; - el.textContent = message; - - // Fade animation - el.style.opacity = 0; - setTimeout(() => { - el.style.opacity = 1; - el.style.transition = "opacity .4s"; - }, 30); -} - - - -/* ------------------------------------------------------------ - 4) FAKE REBOOT ACTION - ------------------------------------------------------------ */ - -function fakeReboot() { - const sensors = document.getElementById("reboot-sensor")?.value.trim(); - const reason = document.getElementById("reboot-reason")?.value.trim(); - - if (!sensors) { - showMessage("reboot-message", "Please enter at least one sensor ID.", "warning"); - return; - } - - showMessage( - "reboot-message", - `Reboot queued for ${sensors}. Reason: ${reason || "No reason provided"}.` - ); -} - - - -/* ------------------------------------------------------------ - 5) FAKE SAVE SETTINGS (Settings Page) - ------------------------------------------------------------ */ - -function fakeSaveSettings() { - const interval = document.getElementById("record-interval")?.value; - const sensitivity = document.getElementById("sensitivity")?.value; - const battery = document.getElementById("battery-threshold")?.value; - - showMessage( - "settings-message", - `Settings saved: ${interval}, ${sensitivity} sensitivity, battery alert at ${battery}%.` - ); -} - - - -/* ------------------------------------------------------------ - 6) FAKE CREATE PROJECT - ------------------------------------------------------------ */ - -function fakeCreateProject() { - const name = document.getElementById("project-name")?.value.trim(); - const loc = document.getElementById("project-location")?.value.trim(); - const sensors = document.getElementById("project-sensors")?.value.trim(); - - if (!name || !loc) { - showMessage("project-message", "Project name and location are required.", "warning"); - return; - } - - showMessage( - "project-message", - `Project "${name}" created successfully. Assigned sensors: ${sensors || "None"}.` - ); -} - - - -/* ------------------------------------------------------------ - 7) GENERAL UI ENHANCEMENTS - ------------------------------------------------------------ */ - -// Smooth fade-in for all cards -document.querySelectorAll(".card").forEach((card) => { - card.style.opacity = 0; - - setTimeout(() => { - card.style.opacity = 1; - card.style.transition = "opacity .45s ease"; - }, 120); -}); - -// Smooth fade for dashboard-shell -const shell = document.querySelector(".dashboard-shell"); -if (shell) { - shell.style.opacity = 0; - - setTimeout(() => { - shell.style.opacity = 1; - shell.style.transition = "opacity .5s ease"; - }, 80); -} diff --git a/sensor-health.html b/sensor-health.html deleted file mode 100644 index f8be972d5..000000000 --- a/sensor-health.html +++ /dev/null @@ -1,210 +0,0 @@ - - - - - Sensor Health – Project Echo - - - - - - - - - -
- - - - - - - - - - - - - - - -
- - - - -
- - - - - - -
- - -
-

Sensor health

-

real-time device status across all deployed locations

-
- - - - -
-

Filter

-

Narrow down sensors by project or status.

- -
- -
- - -
- -
- - -
- -
-
- - - - -
-

Live sensor overview

-

Updated continuously as sensors report in.

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Sensor IDProjectStatusBatteryLast contact
SEN-01Rainforest AOnline87%2m ago
SEN-14Rainforest ADegraded21%15m ago
SEN-77Savannah TrialOffline2h ago
SEN-88Wetlands 2025Low Battery18%8m ago
-
- -
- -
- -
- - - diff --git a/add-project.html b/src/Components/HMI/ui/public/admin/add-project.html similarity index 96% rename from add-project.html rename to src/Components/HMI/ui/public/admin/add-project.html index bd2dae401..ceab232fb 100644 --- a/add-project.html +++ b/src/Components/HMI/ui/public/admin/add-project.html @@ -1,159 +1,159 @@ - - - - - Add Project – Project Echo - - - - - - -
- - - - - - - -
- - - - -
- - - - - -
- - -
-

Create project

-

add a new deployment area and assign sensors to it

-
- -

- - - - -
-

Project details

-

Fill in the core information for the project.

- -
-
- - -
- -
- - -
- -
- - -
- -
- - -
-
- - - - -
- - - - -
-

Assign sensors

-

Specify sensor IDs, ID ranges, or group names.

- - - - -

Use commas, ranges (e.g. SEN-01–SEN-20), or group names.

- - - -
- -
- -
-
- - - + + + + + Add Project – Project Echo + + + + + + +
+ + + + + + + +
+ + + + +
+ + + + + +
+ + +
+

Create project

+

add a new deployment area and assign sensors to it

+
+ +

+ + + + +
+

Project details

+

Fill in the core information for the project.

+ +
+
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+
+ + + + +
+ + + + +
+

Assign sensors

+

Specify sensor IDs, ID ranges, or group names.

+ + + + +

Use commas, ranges (e.g. SEN-01–SEN-20), or group names.

+ + + +
+ +
+ +
+
+ + + diff --git a/alerts.html b/src/Components/HMI/ui/public/admin/alerts.html similarity index 96% rename from alerts.html rename to src/Components/HMI/ui/public/admin/alerts.html index ec47fbdfe..f41eb5ba0 100644 --- a/alerts.html +++ b/src/Components/HMI/ui/public/admin/alerts.html @@ -1,178 +1,178 @@ - - - - - Alerts – Project Echo - - - - - - - -
- - - - - - - - - - - - - -
- - - - -
- - - - - -
- - -
-

Alerts

-

real-time detection of issues across deployed sensors

-
- - - - -
-

Alert Severity Overview

-

Distribution of active alerts

- - -
- - - - -
-

Active Alerts

-

Sensors requiring immediate or near-term attention

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
SensorIssueDetailsLast Audio
SEN-14Low BatteryBattery at 21% (threshold 25%)32m ago
SEN-77OfflineNo contact for 2 hours2h 5m ago
SEN-88No AudioNo audio in last 6 hours6h ago
SEN-104DegradedPacket loss detected (18%)22m ago
-
- -
- -
- -
- - - + + + + + Alerts – Project Echo + + + + + + + +
+ + + + + + + + + + + + + +
+ + + + +
+ + + + + +
+ + +
+

Alerts

+

real-time detection of issues across deployed sensors

+
+ + + + +
+

Alert Severity Overview

+

Distribution of active alerts

+ + +
+ + + + +
+

Active Alerts

+

Sensors requiring immediate or near-term attention

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
SensorIssueDetailsLast Audio
SEN-14Low BatteryBattery at 21% (threshold 25%)32m ago
SEN-77OfflineNo contact for 2 hours2h 5m ago
SEN-88No AudioNo audio in last 6 hours6h ago
SEN-104DegradedPacket loss detected (18%)22m ago
+
+ +
+ +
+ +
+ + + diff --git a/index.html b/src/Components/HMI/ui/public/admin/new 1.html similarity index 57% rename from index.html rename to src/Components/HMI/ui/public/admin/new 1.html index 868af35f8..7e62ff32f 100644 --- a/index.html +++ b/src/Components/HMI/ui/public/admin/new 1.html @@ -1,226 +1,188 @@ - - - - - Project Echo – Dashboard - - - - - - - - - - -
- - - - - - - - - - - - - - - - - -
- - - - -
- - - - - - -
- - -
-

Project echo

-

wildlife sound monitoring & sensor management

- -
- - -
-
- - - - -
-
-

ACTIVE PROJECTS

-

7

-
- -
-

REGISTERED ECOLOGISTS

-

69

-
- -
-

SENSORS DEPLOYED

-

420

-
-
- - - - -
-

Active Projects

-

Overview of ongoing conservation deployments

- -
- -
-

Rainforest A

-

- Amazon Basin — Zone A1
- 32 active sensors -

- ACTIVE -
- -
-

Savannah Trial

-

- Serengeti — West Ridge
- 18 active sensors -

- ACTIVE -
- -
-

Wetlands 2025

-

- New Plymouth — Zone Delta
- 12 sensors in queue -

- PLANNING -
- -
-
- - - - - - -
- -
- -
- - - + + + + + + Project Echo – Admin Dashboard + + + + + + + +
+ + + + + +
+ + +
+ + + +
+
+ + +
+

Project echo

+

wildlife sound monitoring & sensor management

+ +
+ + +
+
+ + + + +
+
+

ACTIVE PROJECTS

+

7

+
+ +
+

REGISTERED ECOLOGISTS

+

69

+
+ +
+

SENSORS DEPLOYED

+

420

+
+
+ + + + +
+

Active Projects

+

Overview of ongoing conservation deployments

+ +
+ +
+

Rainforest A

+

+ Amazon Basin — Zone A1
+ 32 active sensors +

+ ACTIVE +
+ +
+

Savannah Trial

+

+ Serengeti — West Ridge
+ 18 active sensors +

+ ACTIVE +
+ +
+

Wetlands 2025

+

+ New Plymouth — Zone Delta
+ 12 sensors in queue +

+ PLANNING +
+ +
+
+ + + + + + +
+
+
+ +
+ + + diff --git a/reboot.html b/src/Components/HMI/ui/public/admin/reboot.html similarity index 96% rename from reboot.html rename to src/Components/HMI/ui/public/admin/reboot.html index 80f87cc12..04aad2fe7 100644 --- a/reboot.html +++ b/src/Components/HMI/ui/public/admin/reboot.html @@ -1,186 +1,186 @@ - - - - - Reboot Sensors – Project Echo - - - - - - -
- - - - - - - - - - - - - - - -
- - - - -
- - - - - - -
- - -
-

Reboot sensors

-

queue reboot commands for malfunctioning or frozen devices

-
- - - - -
-

Queue a reboot

-

Send a reboot instruction to one or more sensors.

- -
-
- - -
- -
- - -
-
- - -

-
- - - - -
-

Reboot history

-

Recent reboot attempts and their outcomes.

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
SensorStatusTime
SEN-14Success13:22
SEN-04Pending13:10
SEN-77Failed12:44
SEN-101Success11:58
- -
- -
- -
- -
- - - + + + + + Reboot Sensors – Project Echo + + + + + + +
+ + + + + + + + + + + + + + + +
+ + + + +
+ + + + + + +
+ + +
+

Reboot sensors

+

queue reboot commands for malfunctioning or frozen devices

+
+ + + + +
+

Queue a reboot

+

Send a reboot instruction to one or more sensors.

+ +
+
+ + +
+ +
+ + +
+
+ + +

+
+ + + + +
+

Reboot history

+

Recent reboot attempts and their outcomes.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
SensorStatusTime
SEN-14Success13:22
SEN-04Pending13:10
SEN-77Failed12:44
SEN-101Success11:58
+ +
+ +
+ +
+ +
+ + + diff --git a/src/Components/HMI/ui/public/admin/sensor-health.html b/src/Components/HMI/ui/public/admin/sensor-health.html index f5717dbea..344ae219a 100644 --- a/src/Components/HMI/ui/public/admin/sensor-health.html +++ b/src/Components/HMI/ui/public/admin/sensor-health.html @@ -2,121 +2,183 @@ - Sensor Health – Project Echo + + Project Echo – Admin Dashboard - - - + + +
- + + + +
+
-
+ +
+
+ +
-

Sensor health

-

real-time device status across all deployed locations

+

Project echo

+

wildlife sound monitoring & sensor management

+ +
+ + +
+ + + +
+
+

ACTIVE PROJECTS

+

7

+
+ +
+

REGISTERED ECOLOGISTS

+

69

+
+ +
+

SENSORS DEPLOYED

+

420

+
+
+ + + +
-

Filter

-

Narrow down sensors by project or status.

+

Active Projects

+

Overview of ongoing conservation deployments

+
-
- - + +
+

Rainforest A

+

+ Amazon Basin — Zone A1
+ 32 active sensors +

+ ACTIVE
-
- - + +
+

Savannah Trial

+

+ Serengeti — West Ridge
+ 18 active sensors +

+ ACTIVE
+ +
+

Wetlands 2025

+

+ New Plymouth — Zone Delta
+ 12 sensors in queue +

+ PLANNING +
+
-
-

Live sensor overview

-

Updated continuously as sensors report in.

- - - - - - - - - - - - - - - -
Sensor IDProjectStatusBatteryLast contact
Loading…
+ + + + +
diff --git a/settings.html b/src/Components/HMI/ui/public/admin/settings.html similarity index 96% rename from settings.html rename to src/Components/HMI/ui/public/admin/settings.html index ef4bd51b4..250fa10d4 100644 --- a/settings.html +++ b/src/Components/HMI/ui/public/admin/settings.html @@ -1,162 +1,162 @@ - - - - - Settings – Project Echo - - - - - - -
- - - - - - - - - - - - - - - -
- - - - -
- - - - - - -
- - -
-

Settings

-

configure recording behaviour and alert thresholds

-
- - -

- - - -
-

Recording & alert settings

-

- Adjust global defaults for sensor recording interval, sensitivity and low-battery alerts. -

- -
- -
- - -
- -
- - -
- -
- - -
- -
- - -
- -
- -
- -
- - - + + + + + Settings – Project Echo + + + + + + +
+ + + + + + + + + + + + + + + +
+ + + + +
+ + + + + + +
+ + +
+

Settings

+

configure recording behaviour and alert thresholds

+
+ + +

+ + + +
+

Recording & alert settings

+

+ Adjust global defaults for sensor recording interval, sensitivity and low-battery alerts. +

+ +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ +
+ +
+ + + diff --git a/style.css b/src/Components/HMI/ui/public/admin/styles.css similarity index 86% rename from style.css rename to src/Components/HMI/ui/public/admin/styles.css index cc24d58b4..46d1f6cae 100644 --- a/style.css +++ b/src/Components/HMI/ui/public/admin/styles.css @@ -1,551 +1,634 @@ -/* ============================================================ - PROJECT ECHO — FULL UI SYSTEM - Hybrid (v0.1 Sidebar + v0.2 Dashboard) - Primary Theme: GREEN - ============================================================ */ - -/* ------------------------------------------------------------ - 1) THEME TOKENS (v0.2 spec) - ------------------------------------------------------------ */ -:root { - - /* Core Canvas */ - --page: #F5F1EA; - --bg: #FFFFFF; - - /* Text */ - --ink: #1F2D23; - --muted: #6F7B74; - - /* Borders / Surfaces */ - --border: #E4E1D9; - --shadow-card: 0 18px 40px rgba(15, 23, 42, .12); - - /* Primary Theme (GREEN ACTIONS) */ - --primary: #2F6E4F; /* action buttons, accents */ - --primary-hover: #25553D; - - /* Pills */ - --success: #2F6E4F; - --warning: #D29B38; - --danger: #C8473C; - - /* Accents */ - --accent: #DDECE3; - - /* Radius */ - --radius-window: 24px; - --radius: 8px; - - /* Spacing */ - --sp1: 8px; - --sp2: 16px; - --sp3: 24px; - - /* Typography */ - --font: "Inter", system-ui, sans-serif; -} - -/* ------------------------------------------------------------ - 2) GLOBAL RESET - ------------------------------------------------------------ */ -*, -*::before, -*::after { - box-sizing: border-box; -} - -html, body { - margin: 0; - padding: 0; - font-family: var(--font); - background: var(--page); - color: var(--ink); - min-height: 100%; -} - -/* ------------------------------------------------------------ - 3) SIDEBAR (v0.1 exact style) - ------------------------------------------------------------ */ -/* ========================= - SIDEBAR — white (like screenshot) - ========================= */ - -.sidebar{ - width: 250px; - background: #FFFFFF; - border-right: 1px solid #E6E6E6; - padding: 18px 14px; - display: flex; - flex-direction: column; -} - -/* brand logo top */ -.sidebar-brand{ - display:flex; - justify-content:center; - align-items:center; - padding: 6px 0 14px; -} -.brand-logo{ - width: 64px; - height: 64px; - object-fit: contain; - border-radius: 999px; -} - -/* menu */ -.sidebar-menu{ - display:flex; - flex-direction:column; - gap: 14px; - overflow: auto; - padding-right: 4px; -} - -.nav-section{ - display:flex; - flex-direction:column; - gap: 6px; -} - -.nav-title{ - font-size: 10px; - letter-spacing: .12em; - font-weight: 700; - color: #9AA0A6; - padding: 2px 8px; - text-transform: uppercase; -} - -.nav-subtitle{ - font-size: 10px; - letter-spacing: .10em; - font-weight: 700; - color: #B0B6BC; - padding: 8px 8px 2px; - text-transform: uppercase; -} - -/* links */ -.nav-link{ - position: relative; - display:flex; - align-items:center; - gap: 10px; - padding: 8px 10px 8px 12px; - border-radius: 10px; - text-decoration:none; - color: #374151; - font-size: 13px; - transition: background .15s ease, color .15s ease; -} - -.nav-link:hover{ - background: #F6F7F9; -} - -.nav-icon{ - width: 22px; - height: 22px; - display:inline-flex; - align-items:center; - justify-content:center; - font-size: 14px; - color: #6B7280; -} - -/* active marker (pink dot + subtle bg) */ -.nav-link.active{ - background: #FFF2F6; - color: #111827; - font-weight: 600; -} -.nav-link.active::before{ - content:""; - position:absolute; - left: 6px; - width: 8px; - height: 8px; - border-radius: 999px; - background: #F7BACE; /* pink indicator */ -} - -/* footer like screenshot */ -.sidebar-footer{ - margin-top:auto; - display:flex; - align-items:center; - gap: 8px; - padding: 12px 10px 0; - color: #9AA0A6; - font-size: 12px; -} -.footer-dot{ - width: 12px; - height: 12px; - border-radius: 999px; - background: #F7BACE; -} -.footer-text{ - font-weight: 600; - letter-spacing: .06em; -} - -/* mobile slide (still works with your script.js) */ -.mobile-backdrop{ - display:none; -} -body.sidebar-open .mobile-backdrop{ - display:block; - position:fixed; - inset:0; - background:rgba(0,0,0,.35); - z-index:40; -} -@media (max-width: 960px){ - .sidebar{ - position:fixed; - top:0; bottom:0; left:-270px; - z-index:50; - transition:left .2s ease; - } - body.sidebar-open .sidebar{ left:0; } -} - - -/* Sidebar footer */ -.sidebar-footer { - margin-top: auto; - margin-bottom: 6px; - color: #9CA3AF; - font-size: 12px; -} - -/* Mobile sidebar backdrop */ -.mobile-backdrop { - display: none; -} - -body.sidebar-open .mobile-backdrop { - display: block; - position: fixed; - inset: 0; - background: rgba(0, 0, 0, .5); - z-index: 40; -} - -@media (max-width: 960px) { - .sidebar { - position: fixed; - top: 0; bottom: 0; left: -260px; - transition: left .2s ease; - z-index: 50; - } - body.sidebar-open .sidebar { - left: 0; - } -} - -/* ------------------------------------------------------------ - 4) LAYOUT WRAPPER - ------------------------------------------------------------ */ -.layout { - display: flex; - min-height: 100vh; -} - -/* ------------------------------------------------------------ - 5) MAIN AREA + TOP ICON BUTTONS - ------------------------------------------------------------ */ -.main { - flex: 1; - padding: 24px 32px; - display: flex; - flex-direction: column; -} - -.page-header { - display: flex; - align-items: center; - margin-bottom: var(--sp2); -} - -.page-header-actions { - margin-left: auto; - display: flex; - align-items: center; - gap: 10px; -} - -.icon-button { - width: 36px; - height: 36px; - border-radius: 999px; - border: none; - background: transparent; - cursor: pointer; - font-size: 18px; - color: var(--muted); - transition: .15s; -} -.icon-button:hover { - background: #EDEDED; - color: var(--ink); -} - -/* ------------------------------------------------------------ - 6) DASHBOARD SHELL (v0.2 design) - ------------------------------------------------------------ */ -.dashboard-shell { - background: var(--page); - border-radius: var(--radius-window); - padding: 40px; - box-shadow: var(--shadow-card); - max-width: 1100px; - margin: 0 auto; - width: 100%; -} - -/* ------------------------------------------------------------ - 7) HERO HEADER (v0.2 spec) - ------------------------------------------------------------ */ -.hero-header { - text-align: center; - margin-bottom: var(--sp3); -} - -.hero-header h1 { - margin: 0; - font-size: 32px; - color: var(--ink); -} - -.hero-header .subtitle { - margin: 4px 0 16px 0; - color: var(--muted); - font-size: 14px; -} - -.hero-actions { - display: flex; - justify-content: center; - gap: 12px; -} - -/* ------------------------------------------------------------ - 8) KPI CARDS (v0.2 spec) - ------------------------------------------------------------ */ -.kpi-grid { - display: grid; - grid-template-columns: repeat(3, minmax(0, 1fr)); - gap: var(--sp2); - margin-bottom: var(--sp3); -} - -.kpi-card { - background: #FFFFFF; - border: 1px solid var(--border); - border-radius: 20px; - padding: 20px; - box-shadow: var(--shadow-card); -} - -.kpi-card p { - margin: 0; - font-size: 11px; - letter-spacing: .08em; - color: var(--muted); -} - -.kpi-card h3 { - margin: 4px 0 0 0; - font-size: 26px; - font-weight: 600; - color: var(--ink); -} - -/* ------------------------------------------------------------ - 9) CARD COMPONENT (v0.2) - ------------------------------------------------------------ */ -.card { - background: #FFFFFF; - border: 1px solid var(--border); - border-radius: 20px; - padding: var(--sp2) var(--sp3); - margin-bottom: var(--sp2); - box-shadow: var(--shadow-card); -} - -.card h3 { - margin: 0; - font-size: 20px; - color: var(--ink); -} - -.card-subtitle { - margin: 4px 0 16px 0; - font-size: 13px; - color: var(--muted); -} - -/* ------------------------------------------------------------ - 10) TABLES (v0.2) - ------------------------------------------------------------ */ -table { - width: 100%; - border-collapse: collapse; - font-size: 14px; -} - -th { - text-align: left; - padding: 12px 8px; - font-weight: 600; - border-bottom: 1px solid var(--border); - color: var(--ink); -} - -td { - padding: 12px 8px; - border-bottom: 1px solid var(--border); -} - -tbody tr:hover { - background: #FAFAFA; -} - -/* ------------------------------------------------------------ - 11) FORMS (v0.2) - ------------------------------------------------------------ */ -.form-grid { - display: grid; - grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); - gap: var(--sp2); -} - -label { - font-size: 13px; - color: var(--muted); - margin-bottom: 4px; - display: inline-block; -} - -input, select, textarea { - width: 100%; - padding: 8px 12px; - height: 38px; - border: 1px solid var(--border); - border-radius: var(--radius); - font-size: 14px; - color: var(--ink); - background: #FFFFFF; - transition: .15s; -} - -textarea { - height: auto; - min-height: 80px; -} - -input:focus, select:focus, textarea:focus { - outline: none; - border-color: var(--primary); - box-shadow: 0 0 0 2px rgba(47, 110, 79, .35); -} - -/* ------------------------------------------------------------ - 12) BUTTONS (GREEN PRIMARY) - ------------------------------------------------------------ */ -.btn-primary, -.btn-secondary { - padding: 8px 20px; - border-radius: 999px; - font-size: 14px; - cursor: pointer; - border: 1px solid transparent; - transition: .15s; -} - -.btn-primary { - background: var(--primary); - color: #FFF; -} -.btn-primary:hover { - background: var(--primary-hover); -} - -.btn-secondary { - background: transparent; - border-color: var(--border); - color: var(--ink); -} -.btn-secondary:hover { - background: #F0F0F0; -} - -/* ------------------------------------------------------------ - 13) PILLS (STATUS LABELS) - ------------------------------------------------------------ */ -.pill { - padding: 2px 10px; - border-radius: 999px; - font-size: 12px; - font-weight: 600; -} - -.pill-success { - background: rgba(47, 110, 79, 0.15); - color: var(--success); -} - -.pill-warning { - background: rgba(210, 155, 56, 0.20); - color: var(--warning); -} - -.pill-danger { - background: rgba(200, 71, 60, 0.18); - color: var(--danger); -} - -/* ------------------------------------------------------------ - 14) FOOTER GRID (v0.2) - ------------------------------------------------------------ */ -.footer-columns { - display: grid; - grid-template-columns: repeat(3, minmax(0,1fr)); - gap: 32px; - margin-top: 32px; - font-size: 13px; -} - -.footer-columns h4 { - margin: 0 0 6px 0; - font-size: 13px; - font-weight: 600; -} - -.footer-columns ul { - padding: 0; - margin: 0; - list-style: none; -} - -.footer-columns li { - margin: 4px 0; - color: var(--muted); -} - -/* ------------------------------------------------------------ - 15) ANIMATIONS - ------------------------------------------------------------ */ -@keyframes fade { - from { opacity: 0; transform: translateY(8px); } - to { opacity: 1; transform: translateY(0); } -} - -.card, .kpi-card { - animation: fade .35s; -} - +/* ============================================================ + PROJECT ECHO — FULL UI SYSTEM + Hybrid (v0.1 Sidebar + v0.2 Dashboard) + Primary Theme: GREEN + ============================================================ */ + +/* ------------------------------------------------------------ + 1) THEME TOKENS (v0.2 spec) + ------------------------------------------------------------ */ +:root { + + /* Core Canvas */ + --page: #F5F1EA; + --bg: #FFFFFF; + + /* Text */ + --ink: #1F2D23; + --muted: #6F7B74; + + /* Borders / Surfaces */ + --border: #E4E1D9; + --shadow-card: 0 18px 40px rgba(15, 23, 42, .12); + + /* Primary Theme (GREEN ACTIONS) */ + --primary: #2F6E4F; /* action buttons, accents */ + --primary-hover: #25553D; + + /* Pills */ + --success: #2F6E4F; + --warning: #D29B38; + --danger: #C8473C; + + /* Accents */ + --accent: #DDECE3; + + /* Radius */ + --radius-window: 24px; + --radius: 8px; + + /* Spacing */ + --sp1: 8px; + --sp2: 16px; + --sp3: 24px; + + /* Typography */ + --font: "Inter", system-ui, sans-serif; +} + +/* ------------------------------------------------------------ + 2) GLOBAL RESET + ------------------------------------------------------------ */ +*, +*::before, +*::after { + box-sizing: border-box; +} + +html, body { + margin: 0; + padding: 0; + font-family: var(--font); + background: var(--page); + color: var(--ink); + min-height: 100%; +} + +/* ------------------------------------------------------------ + 3) SIDEBAR (v0.1 exact style) + ------------------------------------------------------------ */ +/* ========================= + SIDEBAR — white (like screenshot) + ========================= */ + +.sidebar{ + /* width: 250px; + background: #FFFFFF; + border-right: 1px solid #E6E6E6; + padding: 18px 14px; + display: flex; + flex-direction: column; + /* Accordion controls */ +.nav-accordion { + width: 100%; + border: 0; + background: transparent; + text-align: left; + cursor: pointer; + display: flex; + align-items: center; +} + +.nav-caret { + margin-left: auto; + font-size: 12px; + color: #9AA0A6; + transition: transform .15s ease; +} + +/* Children container */ +.nav-children { + margin-left: 22px; /* indent */ + margin-top: 6px; + display: none; + flex-direction: column; + gap: 6px; + padding-left: 10px; + border-left: 1px solid #ECECEC; +} + +.nav-children.open { + display: flex; +} + +/* Child links */ +.nav-sublink { + text-decoration: none; + color: #4B5563; + font-size: 13px; + padding: 6px 10px; + border-radius: 10px; + transition: background .15s ease; +} + +.nav-sublink:hover { + background: #F6F7F9; +} + +/* Active sublink */ +.nav-sublink.active { + background: #FFF2F6; + color: #111827; + font-weight: 600; + position: relative; +} + +.nav-sublink.active::before { + content:""; + position:absolute; + left: -16px; + top: 50%; + transform: translateY(-50%); + width: 8px; + height: 8px; + border-radius: 999px; + background: #F7BACE; /* same pink indicator */ +} + +/* Rotate caret when expanded */ +.nav-accordion[aria-expanded="true"] .nav-caret { + transform: rotate(180deg); +} + +} + +/* brand logo top */ +.sidebar-brand{ + display:flex; + justify-content:center; + align-items:center; + padding: 6px 0 14px; +} +.brand-logo{ + width: 64px; + height: 64px; + object-fit: contain; + border-radius: 999px; +} + +/* menu */ +.sidebar-menu{ + display:flex; + flex-direction:column; + gap: 14px; + overflow: auto; + padding-right: 4px; +} + +.nav-section{ + display:flex; + flex-direction:column; + gap: 6px; +} + +.nav-title{ + font-size: 10px; + letter-spacing: .12em; + font-weight: 700; + color: #9AA0A6; + padding: 2px 8px; + text-transform: uppercase; +} + +.nav-subtitle{ + font-size: 10px; + letter-spacing: .10em; + font-weight: 700; + color: #B0B6BC; + padding: 8px 8px 2px; + text-transform: uppercase; +} + +/* links */ +.nav-link{ + position: relative; + display:flex; + align-items:center; + gap: 10px; + padding: 8px 10px 8px 12px; + border-radius: 10px; + text-decoration:none; + color: #374151; + font-size: 13px; + transition: background .15s ease, color .15s ease; +} + +.nav-link:hover{ + background: #F6F7F9; +} + +.nav-icon{ + width: 22px; + height: 22px; + display:inline-flex; + align-items:center; + justify-content:center; + font-size: 14px; + color: #6B7280; +} + +/* active marker (pink dot + subtle bg) */ +.nav-link.active{ + background: #FFF2F6; + color: #111827; + font-weight: 600; +} +.nav-link.active::before{ + content:""; + position:absolute; + left: 6px; + width: 8px; + height: 8px; + border-radius: 999px; + background: #F7BACE; /* pink indicator */ +} + +/* footer like screenshot */ +.sidebar-footer{ + margin-top:auto; + display:flex; + align-items:center; + gap: 8px; + padding: 12px 10px 0; + color: #9AA0A6; + font-size: 12px; +} +.footer-dot{ + width: 12px; + height: 12px; + border-radius: 999px; + background: #F7BACE; +} +.footer-text{ + font-weight: 600; + letter-spacing: .06em; +} + +/* mobile slide (still works with your script.js) */ +.mobile-backdrop{ + display:none; +} +body.sidebar-open .mobile-backdrop{ + display:block; + position:fixed; + inset:0; + background:rgba(0,0,0,.35); + z-index:40; +} +@media (max-width: 960px){ + .sidebar{ + position:fixed; + top:0; bottom:0; left:-270px; + z-index:50; + transition:left .2s ease; + } + body.sidebar-open .sidebar{ left:0; } +} + + +/* Sidebar footer */ +.sidebar-footer { + margin-top: auto; + margin-bottom: 6px; + color: #9CA3AF; + font-size: 12px; +} + +/* Mobile sidebar backdrop */ +.mobile-backdrop { + display: none; +} + +body.sidebar-open .mobile-backdrop { + display: block; + position: fixed; + inset: 0; + background: rgba(0, 0, 0, .5); + z-index: 40; +} + +@media (max-width: 960px) { + .sidebar { + position: fixed; + top: 0; bottom: 0; left: -260px; + transition: left .2s ease; + z-index: 50; + } + body.sidebar-open .sidebar { + left: 0; + } +} + +/* ------------------------------------------------------------ + 4) LAYOUT WRAPPER + ------------------------------------------------------------ */ +.layout { + display: flex; + min-height: 100vh; +} + +/* ------------------------------------------------------------ + 5) MAIN AREA + TOP ICON BUTTONS + ------------------------------------------------------------ */ +.main { + flex: 1; + padding: 24px 32px; + display: flex; + flex-direction: column; +} + +.page-header { + display: flex; + align-items: center; + margin-bottom: var(--sp2); +} + +.page-header-actions { + margin-left: auto; + display: flex; + align-items: center; + gap: 10px; +} + +.icon-button { + width: 36px; + height: 36px; + border-radius: 999px; + border: none; + background: transparent; + cursor: pointer; + font-size: 18px; + color: var(--muted); + transition: .15s; +} +.icon-button:hover { + background: #EDEDED; + color: var(--ink); +} + +/* ------------------------------------------------------------ + 6) DASHBOARD SHELL (v0.2 design) + ------------------------------------------------------------ */ +.dashboard-shell { + background: var(--page); + border-radius: var(--radius-window); + padding: 40px; + box-shadow: var(--shadow-card); + max-width: 1100px; + margin: 0 auto; + width: 100%; +} + +/* ------------------------------------------------------------ + 7) HERO HEADER (v0.2 spec) + ------------------------------------------------------------ */ +.hero-header { + text-align: center; + margin-bottom: var(--sp3); +} + +.hero-header h1 { + margin: 0; + font-size: 32px; + color: var(--ink); +} + +.hero-header .subtitle { + margin: 4px 0 16px 0; + color: var(--muted); + font-size: 14px; +} + +.hero-actions { + display: flex; + justify-content: center; + gap: 12px; +} + +/* ------------------------------------------------------------ + 8) KPI CARDS (v0.2 spec) + ------------------------------------------------------------ */ +.kpi-grid { + display: grid; + grid-template-columns: repeat(3, minmax(0, 1fr)); + gap: var(--sp2); + margin-bottom: var(--sp3); +} + +.kpi-card { + background: #FFFFFF; + border: 1px solid var(--border); + border-radius: 20px; + padding: 20px; + box-shadow: var(--shadow-card); +} + +.kpi-card p { + margin: 0; + font-size: 11px; + letter-spacing: .08em; + color: var(--muted); +} + +.kpi-card h3 { + margin: 4px 0 0 0; + font-size: 26px; + font-weight: 600; + color: var(--ink); +} + +/* ------------------------------------------------------------ + 9) CARD COMPONENT (v0.2) + ------------------------------------------------------------ */ +.card { + background: #FFFFFF; + border: 1px solid var(--border); + border-radius: 20px; + padding: var(--sp2) var(--sp3); + margin-bottom: var(--sp2); + box-shadow: var(--shadow-card); +} + +.card h3 { + margin: 0; + font-size: 20px; + color: var(--ink); +} + +.card-subtitle { + margin: 4px 0 16px 0; + font-size: 13px; + color: var(--muted); +} + +/* ------------------------------------------------------------ + 10) TABLES (v0.2) + ------------------------------------------------------------ */ +table { + width: 100%; + border-collapse: collapse; + font-size: 14px; +} + +th { + text-align: left; + padding: 12px 8px; + font-weight: 600; + border-bottom: 1px solid var(--border); + color: var(--ink); +} + +td { + padding: 12px 8px; + border-bottom: 1px solid var(--border); +} + +tbody tr:hover { + background: #FAFAFA; +} + +/* ------------------------------------------------------------ + 11) FORMS (v0.2) + ------------------------------------------------------------ */ +.form-grid { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); + gap: var(--sp2); +} + +label { + font-size: 13px; + color: var(--muted); + margin-bottom: 4px; + display: inline-block; +} + +input, select, textarea { + width: 100%; + padding: 8px 12px; + height: 38px; + border: 1px solid var(--border); + border-radius: var(--radius); + font-size: 14px; + color: var(--ink); + background: #FFFFFF; + transition: .15s; +} + +textarea { + height: auto; + min-height: 80px; +} + +input:focus, select:focus, textarea:focus { + outline: none; + border-color: var(--primary); + box-shadow: 0 0 0 2px rgba(47, 110, 79, .35); +} + +/* ------------------------------------------------------------ + 12) BUTTONS (GREEN PRIMARY) + ------------------------------------------------------------ */ +.btn-primary, +.btn-secondary { + padding: 8px 20px; + border-radius: 999px; + font-size: 14px; + cursor: pointer; + border: 1px solid transparent; + transition: .15s; +} + +.btn-primary { + background: var(--primary); + color: #FFF; +} +.btn-primary:hover { + background: var(--primary-hover); +} + +.btn-secondary { + background: transparent; + border-color: var(--border); + color: var(--ink); +} +.btn-secondary:hover { + background: #F0F0F0; +} + +/* ------------------------------------------------------------ + 13) PILLS (STATUS LABELS) + ------------------------------------------------------------ */ +.pill { + padding: 2px 10px; + border-radius: 999px; + font-size: 12px; + font-weight: 600; +} + +.pill-success { + background: rgba(47, 110, 79, 0.15); + color: var(--success); +} + +.pill-warning { + background: rgba(210, 155, 56, 0.20); + color: var(--warning); +} + +.pill-danger { + background: rgba(200, 71, 60, 0.18); + color: var(--danger); +} + +/* ------------------------------------------------------------ + 14) FOOTER GRID (v0.2) + ------------------------------------------------------------ */ +.footer-columns { + display: grid; + grid-template-columns: repeat(3, minmax(0,1fr)); + gap: 32px; + margin-top: 32px; + font-size: 13px; +} + +.footer-columns h4 { + margin: 0 0 6px 0; + font-size: 13px; + font-weight: 600; +} + +.footer-columns ul { + padding: 0; + margin: 0; + list-style: none; +} + +.footer-columns li { + margin: 4px 0; + color: var(--muted); +} + +/* ------------------------------------------------------------ + 15) ANIMATIONS + ------------------------------------------------------------ */ +@keyframes fade { + from { opacity: 0; transform: translateY(8px); } + to { opacity: 1; transform: translateY(0); } +} + +.card, .kpi-card { + animation: fade .35s; +} + + +/* ============================================================ + ACCORDION SIDEBAR OVERRIDES (SPA) + ============================================================ */ + +.nav-link{ background: transparent; border: 0; width: 100%; cursor: pointer; } +.nav-sublink{ border:0; background:transparent; width:100%; cursor:pointer; text-align:left; } + +.nav-children{ display:none; } +.nav-children.open{ display:flex; } + diff --git a/styles.css b/styles.css deleted file mode 100644 index 2b712120d..000000000 --- a/styles.css +++ /dev/null @@ -1,100 +0,0 @@ -/* General page setup */ -body { - font-family: 'Poppins', 'Segoe UI', sans-serif; - margin: 0; - padding: 30px; - background-color: #f0f2f5; -} - -/* Page heading */ -h1 { - text-align: center; - color: #222; - margin-bottom: 40px; - font-size: 32px; -} - -/* Card-style container for the table */ -.container { - background: #ffffff; - padding: 25px; - border-radius: 12px; - box-shadow: 0 6px 20px rgba(0, 0, 0, 0.08); - max-width: 1200px; - margin: 0 auto; -} - -/* Submissions Table */ -table { - width: 100%; - border-collapse: collapse; - margin-top: 10px; -} - -th, td { - padding: 16px 20px; - text-align: left; - border-bottom: 1px solid #e0e0e0; -} - -th { - background-color: #4CAF50; - color: white; - font-weight: 600; - letter-spacing: 0.5px; - font-size: 15px; -} - -td { - color: #555; - font-size: 14px; -} - -tr:hover { - background-color: #f9f9f9; -} - -/* Special styling for file names and animals */ -.file-name { - font-weight: 600; - color: #333; -} - -.detected-animals { - font-style: italic; - color: #666; -} - -.upload-date { - color: #999; - font-size: 13px; -} - -/* Make the table responsive */ -@media (max-width: 768px) { - table, thead, tbody, th, td, tr { - display: block; - } - - thead tr { - display: none; - } - - td { - position: relative; - padding-left: 50%; - margin-bottom: 12px; - } - - td::before { - position: absolute; - top: 16px; - left: 16px; - width: 45%; - padding-right: 10px; - white-space: nowrap; - font-weight: bold; - color: #777; - content: attr(data-label); - } -}