diff --git a/docs/AURA_UI_PLAN.md b/docs/AURA_UI_PLAN.md
new file mode 100644
index 0000000..47e3c40
--- /dev/null
+++ b/docs/AURA_UI_PLAN.md
@@ -0,0 +1,64 @@
+# AuraUI Integration Plan and Audit
+
+## Snapshot Info
+
+- **Commit Hash**: `da5af8c` (Before AuraUI)
+- **Rollback Command**: `git reset --hard da5af8c && git push -f origin main`
+
+## Component Audit
+
+We have selected the following components from the [AuraUI Library](https://auraui.com) to enhance the `ca-grow-ops-manager`:
+
+### 1. 3D Digital Twin Hero (`feature-4-3d`)
+
+- **Visuals**: Dark mode, floating 3D elements (cubes/spheres) with lime/purple accents.
+- **Use Case**: **Facility 3D Viewer Loading/Landing State**.
+- **Reason**: Perfectly aligns with the "Digital Twin" core pillar. Replaces the generic "Loading..." spinner with a technical, high-end visual.
+
+### 2. High-Trust Hero (`hero-1`)
+
+- **Visuals**: Centered H1, clear subtext, primary/secondary action buttons.
+- **Use Case**: **Main Dashboard Header**.
+- **Reason**: Provides immediate access to critical actions ("Emergency Stop", "Metrc Sync") and sets the tone for the application.
+
+### 3. Split-Screen Auth Form (`signup-1`)
+
+- **Visuals**: Left side form, Right side high-quality operational image.
+- **Use Case**: **Visitor Kiosk Check-In** and **SOP Acknowledgement**.
+- **Reason**: The "Compliance" aspect needs to feel authoritative and polished. The split view allows us to show legal text/images alongside the signature input.
+
+### 4. Minimal Navbar (`header-6`)
+
+- **Visuals**: Dark background, subtle hover effects, active state indicators.
+- **Use Case**: **Global App Shell Navigation**.
+- **Reason**: The current sidebar is functional but bulky. Moving to a sleek top-nav (or refined side-nav) using these styles cleans up screen real estate for the 3D viewer.
+
+### 5. Bento Grid (`feature-14`)
+
+- **Visuals**: Grid of varied-size cards, bento-box style.
+- **Use Case**: **Operations Dashboard**.
+- **Reason**: We have too many disparate metrics (Temp, Humidity, Task Count, Compliance Status). A bento grid unifies them into a single "Command Center" view.
+
+## Integration Strategy
+
+### Prerequisites (Checked)
+
+- [x] `clsx` (Installed)
+- [x] `tailwind-merge` (Installed)
+- [x] `class-variance-authority` (Installed)
+- [x] `lucide-react` (Installed)
+- [ ] `framer-motion` (Missing - **Install Required**)
+
+### Implementation Order
+
+1. **Install `framer-motion`**: Required for AuraUI animations.
+2. **Setup Utils**: Ensure `lib/utils.ts` has the standard `cn()` helper (it likely does, but verify).
+3. **Implement `Hero-1`**: Replace the Dashboard header first as a low-risk, high-impact test.
+4. **Implement `Feature-4-3d`**: Add to the 3D Viewer page.
+
+### Rollback Plan
+
+If the new components break the build or styling:
+
+1. Revert to the snapshot commit.
+2. Clean `node_modules` if `framer-motion` causes issues.
diff --git a/frontend/package-lock.json b/frontend/package-lock.json
index 92b8a05..d47cf52 100644
--- a/frontend/package-lock.json
+++ b/frontend/package-lock.json
@@ -19,6 +19,7 @@
"browser-image-compression": "^2.0.2",
"class-variance-authority": "^0.7.1",
"clsx": "^2.1.1",
+ "framer-motion": "^12.23.26",
"i18next": "^25.7.2",
"i18next-browser-languagedetector": "^8.2.0",
"immer": "^11.0.1",
@@ -5200,6 +5201,33 @@
"url": "https://github.com/sponsors/rawify"
}
},
+ "node_modules/framer-motion": {
+ "version": "12.23.26",
+ "resolved": "https://registry.npmjs.org/framer-motion/-/framer-motion-12.23.26.tgz",
+ "integrity": "sha512-cPcIhgR42xBn1Uj+PzOyheMtZ73H927+uWPDVhUMqxy8UHt6Okavb6xIz9J/phFUHUj0OncR6UvMfJTXoc/LKA==",
+ "license": "MIT",
+ "dependencies": {
+ "motion-dom": "^12.23.23",
+ "motion-utils": "^12.23.6",
+ "tslib": "^2.4.0"
+ },
+ "peerDependencies": {
+ "@emotion/is-prop-valid": "*",
+ "react": "^18.0.0 || ^19.0.0",
+ "react-dom": "^18.0.0 || ^19.0.0"
+ },
+ "peerDependenciesMeta": {
+ "@emotion/is-prop-valid": {
+ "optional": true
+ },
+ "react": {
+ "optional": true
+ },
+ "react-dom": {
+ "optional": true
+ }
+ }
+ },
"node_modules/fs.realpath": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
@@ -6577,6 +6605,21 @@
"dev": true,
"license": "MIT"
},
+ "node_modules/motion-dom": {
+ "version": "12.23.23",
+ "resolved": "https://registry.npmjs.org/motion-dom/-/motion-dom-12.23.23.tgz",
+ "integrity": "sha512-n5yolOs0TQQBRUFImrRfs/+6X4p3Q4n1dUEqt/H58Vx7OW6RF+foWEgmTVDhIWJIMXOuNNL0apKH2S16en9eiA==",
+ "license": "MIT",
+ "dependencies": {
+ "motion-utils": "^12.23.6"
+ }
+ },
+ "node_modules/motion-utils": {
+ "version": "12.23.6",
+ "resolved": "https://registry.npmjs.org/motion-utils/-/motion-utils-12.23.6.tgz",
+ "integrity": "sha512-eAWoPgr4eFEOFfg2WjIsMoqJTW6Z8MTUCgn/GZ3VRpClWBdnbjryiA3ZSNLyxCTmCQx4RmYX6jX1iWHbenUPNQ==",
+ "license": "MIT"
+ },
"node_modules/ms": {
"version": "2.1.3",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
diff --git a/frontend/package.json b/frontend/package.json
index 718a7af..d0b2ca9 100644
--- a/frontend/package.json
+++ b/frontend/package.json
@@ -22,6 +22,7 @@
"browser-image-compression": "^2.0.2",
"class-variance-authority": "^0.7.1",
"clsx": "^2.1.1",
+ "framer-motion": "^12.23.26",
"i18next": "^25.7.2",
"i18next-browser-languagedetector": "^8.2.0",
"immer": "^11.0.1",
@@ -58,4 +59,4 @@
"vite": "^5.0.8",
"vitest": "^1.0.0"
}
-}
\ No newline at end of file
+}
diff --git a/frontend/src/components/aura/Hero.tsx b/frontend/src/components/aura/Hero.tsx
new file mode 100644
index 0000000..9a0dab7
--- /dev/null
+++ b/frontend/src/components/aura/Hero.tsx
@@ -0,0 +1,245 @@
+import { useState, useEffect } from "react";
+import { Button } from "@/components/ui/button";
+import { Badge } from "@/components/ui/badge";
+import {
+ Download,
+ Github,
+ Sparkles,
+ Loader,
+ Copy,
+ Check,
+ StopCircle,
+ Activity,
+ Leaf
+} from "lucide-react";
+import { Card, CardContent } from "@/components/ui/card";
+import { cn } from "@/lib/utils";
+
+/**
+ * AuraUI Hero 1 Component
+ * Customized for CA Grow Ops Manager
+ * Displays the main dashboard header with 'Digital Command Center' branding
+ */
+const Hero1 = () => {
+ const [isVisible, setIsVisible] = useState(false);
+ const [currentSentence, setCurrentSentence] = useState(0);
+ const [isAnimating, setIsAnimating] = useState(false);
+ const [showCorrected, setShowCorrected] = useState(false);
+ const [typingText, setTypingText] = useState("");
+ const [isTyping, setIsTyping] = useState(false);
+ const [isSelected, setIsSelected] = useState(false);
+ const [showPopup, setShowPopup] = useState(false);
+
+ // Customized demo text for Grow Ops context
+ const demoSentences = [
+ {
+ original: "Room 4 temp is 82 humidity 65 check veg lighting",
+ corrected:
+ "Room 4: Temp 82°F, Humidity 65%. Veg lighting inspection required.",
+ },
+ {
+ original: "feed batch 156 with heavy bloom schedule today",
+ corrected:
+ "Action: Feed Batch B-23-156. Schedule: Heavy Bloom. Date: Today.",
+ },
+ {
+ original: "visitor arrived for checkin name is john doe",
+ corrected:
+ "Visitor Log: John Doe checked in. NDA signature pending.",
+ },
+ ];
+
+ useEffect(() => {
+ const timer = setTimeout(() => {
+ setIsVisible(true);
+ }, 300);
+ return () => clearTimeout(timer);
+ }, []);
+
+ useEffect(() => {
+ const startDemo = () => {
+ // Reset all states
+ setIsTyping(true);
+ setIsSelected(false);
+ setShowCorrected(false);
+ setTypingText("");
+
+ // Type the text character by character - much faster
+ const text = demoSentences[currentSentence].original;
+ let i = 0;
+
+ const typeInterval = setInterval(() => {
+ if (i < text.length) {
+ setTypingText(text.substring(0, i + 1));
+ i++;
+ } else {
+ clearInterval(typeInterval);
+ setIsTyping(false);
+
+ // Wait a bit, then select text
+ setTimeout(() => {
+ setIsSelected(true);
+
+ // Wait for selection, then start refining
+ setTimeout(() => {
+ setIsAnimating(true);
+
+ // Show refined text after processing
+ setTimeout(() => {
+ setShowCorrected(true);
+ setIsAnimating(false);
+ setIsSelected(false);
+
+ // Wait before next cycle
+ setTimeout(() => {
+ setCurrentSentence(
+ (prev) => (prev + 1) % demoSentences.length,
+ );
+ }, 2500);
+ }, 1800);
+ }, 1200);
+ }, 800);
+ }
+ }, 25); // Much faster typing speed
+ };
+
+ const interval = setInterval(startDemo, 8500);
+ startDemo(); // Start immediately
+
+ return () => clearInterval(interval);
+ }, [currentSentence]);
+
+ return (
+
+ Real-time compliance, environmental monitoring, and task management in a single digital twin interface.
+
+ Command Center for Modern Cultivation
+
+
+
Demo Mode
-- METRC API not connected. Data shown is for demonstration purposes. -
-Demo Mode
++ METRC API not connected. Data shown is for demonstration purposes. +
+Connected to METRC
++ Last sync: {lastSync ? lastSync.toLocaleString() : 'Never'} +
+Connected to METRC
-- Last sync: {lastSync ? lastSync.toLocaleString() : 'Never'} -
-{report?.plantCount || 0}
-Total Plants
-{audit?.summary.totalMoves || 0}
-Plant Moves (30d)
-100%
-Sync Rate
-0
-Discrepancies
-Open METRC
-State portal
-Location changes requiring METRC update
-{move.plantTag}
-- {move.from} → {move.to} -
-- {new Date(move.movedAt).toLocaleDateString()} -
+{report?.plantCount || 0}
+Total Plants
{audit?.summary.totalMoves || 0}
+Plant Moves (30d)
+100%
+Sync Rate
+0
+Discrepancies
+| Tag | -METRC Location | -Room | -Section | -Position | -Status | -Actions | -
|---|---|---|---|---|---|---|
| {plant.tagNumber} | -{plant.location || '-'} | -{plant.room} | -{plant.section || '-'} | -{plant.position || '-'} | -
-
- |
-
-
-
-
-
- |
-
| Tag | +METRC Location | +Room | +Section | +Position | +Status | +Actions | +
|---|---|---|---|---|---|---|
| {plant.tagNumber} | +{plant.location || '-'} | +{plant.room} | +{plant.section || '-'} | +{plant.position || '-'} | +
+
+ |
+
+
+
+
+
+ |
+
+ {new Date(audit.dateRange.start).toLocaleDateString()} - {new Date(audit.dateRange.end).toLocaleDateString()} +
+{audit.summary.totalPlants}
+Total Plants
+{audit.summary.totalMoves}
+Location Changes
+{audit.summary.uniquePlantsMoved}
+Plants Moved
+No location changes in this period
+| Plant Tag | +From | +To | +Date | +Reason | +
|---|---|---|---|---|
| {move.plantTag} | +{move.from} | +{move.to} | ++ {new Date(move.movedAt).toLocaleDateString()} + | +{move.reason || '-'} | +
- {new Date(audit.dateRange.start).toLocaleDateString()} - {new Date(audit.dateRange.end).toLocaleDateString()} -
+{selectedHistoryPlant.tagNumber}
{audit.summary.totalPlants}
-Total Plants
+Current Room
+{selectedHistoryPlant.room}
+Current Section
+{selectedHistoryPlant.section || 'N/A'}
+{audit.summary.totalMoves}
-Location Changes
-{audit.summary.uniquePlantsMoved}
-Plants Moved
-No recorded movements found for this plant.
++ From {move.from} • Reason: {move.reason || 'Routine Maintenance'} +
+No location changes in this period
-| Plant Tag | -From | -To | -Date | -Reason | -
|---|---|---|---|---|
| {move.plantTag} | -{move.from} | -{move.to} | -- {new Date(move.movedAt).toLocaleDateString()} - | -{move.reason || '-'} | -
{selectedHistoryPlant.tagNumber}
-Current Room
-{selectedHistoryPlant.room}
-Current Section
-{selectedHistoryPlant.section || 'N/A'}
-No recorded movements found for this plant.
-- From {move.from} • Reason: {move.reason || 'Routine Maintenance'} -
-