diff --git a/README.md b/README.md
index acce182..5924b35 100644
--- a/README.md
+++ b/README.md
@@ -127,6 +127,7 @@ docker build -t alwisp_web:latest .
| `DB_NAME` | `alwisp` |
| `DB_USER` | `alwisp_user` |
| `DB_PASS` | *(same password set in Step 3)* |
+| `ADMIN_PASS` | *(password for the staff inbox at `/staff-portal`)* |
4. Add **Path/Volume Mappings**:
@@ -216,6 +217,7 @@ Because the web container has a dedicated LAN IP, reverse proxy setup is straigh
| `DB_NAME` | Database name (default: `alwisp`) |
| `DB_USER` | Application DB user (default: `alwisp_user`) |
| `DB_PASS` | Application DB password — make this strong |
+| `ADMIN_PASS` | Password for the staff inbox (`/staff-portal`) — change before going live |
---
@@ -243,13 +245,15 @@ alwisp/
├── assets/ # Logos, images
├── includes/
│ ├── header.php # Global nav
- │ └── footer.php # Global footer
+ │ ├── footer.php # Global footer
+ │ └── db.php # PDO helper (auto-migrates schema)
└── pages/
├── home.php
├── services.php
├── coverage.php
├── about.php
- ├── contact.php
+ ├── contact.php # Stores submissions in MySQL
+ ├── admin-inbox.php # Staff inbox at /staff-portal (password-gated)
└── 404.php
```
@@ -262,7 +266,7 @@ alwisp/
- [x] Front-controller PHP router
- [x] Responsive site skeleton with brand design system
- [x] Homepage: hero, stats bar, services preview, why section, coverage CTA
-- [x] Contact form with server-side validation
+- [x] Contact form with server-side validation and MySQL storage
- [x] Stub pages for all top-level routes (services, coverage, about, contact, 404)
- [x] Security headers, OPcache, and Apache hardening
- [x] Unraid-ready deployment via Docker Compose
@@ -288,10 +292,11 @@ alwisp/
---
### Milestone 4 — Customer Portal (Phase 1)
+- [x] Contact form stores submissions in MySQL
+- [x] Staff inbox (`/staff-portal`) — password-gated, mark read/unread, no email required
+- [ ] Email notification on new submission (PHPMailer)
- [ ] Customer account creation and login (PHP sessions)
- [ ] Account dashboard — plan details, billing status, support tickets
-- [ ] Contact form wired to database and email notification (PHPMailer)
-- [ ] Admin panel — view and respond to contact submissions
- [ ] Password reset via email token
---
diff --git a/www/pages/admin-inbox.php b/www/pages/admin-inbox.php
index e23455c..c4b8f76 100644
--- a/www/pages/admin-inbox.php
+++ b/www/pages/admin-inbox.php
@@ -101,11 +101,14 @@ $messages = $db->query("SELECT * FROM contacts ORDER BY created_at DESC")->fe
$unread_count = (int)$db->query("SELECT COUNT(*) FROM contacts WHERE is_read = 0")->fetchColumn();
$subject_labels = [
- 'new-service' => 'New Service Inquiry',
- 'support' => 'Technical Support',
- 'billing' => 'Billing Question',
- 'coverage' => 'Coverage Question',
- 'other' => 'Other',
+ 'new-project' => 'New Project Inquiry',
+ 'mesh-networking' => 'Mesh Networking',
+ 'managed-services' => 'Managed Services',
+ 'structured-cabling'=> 'Structured Cabling',
+ 'access-control' => 'Access Control',
+ 'ip-cameras' => 'IP Camera Systems',
+ 'support' => 'Technical Support',
+ 'other' => 'Other',
];
function h(string $s): string { return htmlspecialchars($s, ENT_QUOTES); }
diff --git a/www/pages/contact.php b/www/pages/contact.php
index a864afb..edbd258 100644
--- a/www/pages/contact.php
+++ b/www/pages/contact.php
@@ -88,10 +88,13 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {