commit e922e2dbd3d0b14124201d50e291a250766b798c Author: olsch01 Date: Tue Mar 3 08:58:15 2026 -0500 Initial commit of existing project diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 0000000..5008ddf Binary files /dev/null and b/.DS_Store differ diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..9f77d70 --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +node_modules/ +data/ +.env diff --git a/app.js b/app.js new file mode 100644 index 0000000..170396d --- /dev/null +++ b/app.js @@ -0,0 +1,134 @@ +/* HOA LedgerIQ — Frontend form handler + countdown */ + +// ── Dynamic Countdown ──────────────────────────────────── +// Launch date = March 1, 2026 + 60 days = April 30, 2026 +// On 3/1/2026 the banner shows "60 days", then counts down daily. +(function initCountdown() { + const launchDate = new Date('2026-04-30T00:00:00'); + const now = new Date(); + const msPerDay = 1000 * 60 * 60 * 24; + const daysLeft = Math.max(0, Math.ceil((launchDate - now) / msPerDay)); + + const label = daysLeft === 1 ? 'Day' : 'Days'; + const text = daysLeft > 0 + ? `Launching in ${daysLeft} ${label}` + : 'Now Live!'; + + const bannerEl = document.getElementById('bannerCountdown'); + const signupEl = document.getElementById('signupCountdown'); + if (bannerEl) bannerEl.textContent = text; + if (signupEl) signupEl.textContent = text; +})(); + +// ── Form Handler ───────────────────────────────────────── +document.addEventListener('DOMContentLoaded', () => { + const form = document.getElementById('signupForm'); + const submitBtn = document.getElementById('submitBtn'); + const btnText = submitBtn?.querySelector('.btn-text'); + const btnLoading = submitBtn?.querySelector('.btn-loading'); + const successDiv = document.getElementById('signupSuccess'); + + if (!form) return; + + form.addEventListener('submit', async (e) => { + e.preventDefault(); + + const firstName = form.firstName.value.trim(); + const lastName = form.lastName.value.trim(); + const email = form.email.value.trim(); + + const orgName = form.orgName?.value.trim() || ''; + const state = form.state?.value || ''; + + // Basic client-side validation + if (!firstName || !lastName || !email || !orgName || !state) { + highlightEmpty(form); + return; + } + if (!isValidEmail(email)) { + form.email.style.borderColor = '#ef4444'; + form.email.focus(); + return; + } + + // Show loading state + setLoading(true); + + const payload = { + firstName, + lastName, + email, + orgName: form.orgName?.value.trim() || '', + state: form.state?.value || '', + role: form.role.value, + unitCount: form.unitCount.value, + betaInterest: form.betaInterest?.checked || false, + source: 'landing_page', + timestamp: new Date().toISOString(), + }; + + try { + const res = await fetch('/api/leads', { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify(payload), + }); + + if (res.ok) { + showSuccess(); + } else { + const data = await res.json().catch(() => ({})); + if (res.status === 409) { + // Already registered + showSuccess('You\'re already on the list! We\'ll be in touch soon.'); + } else { + alert(data.error || 'Something went wrong. Please try again.'); + setLoading(false); + } + } + } catch (err) { + // Network error — fall back to localStorage so we don't lose the lead + saveLocally(payload); + showSuccess(); + } + }); + + function setLoading(on) { + if (!btnText || !btnLoading) return; + submitBtn.disabled = on; + btnText.classList.toggle('hidden', on); + btnLoading.classList.toggle('hidden', !on); + } + + function showSuccess(msg) { + form.classList.add('hidden'); + if (msg && successDiv) { + const p = successDiv.querySelector('p'); + if (p) p.textContent = msg; + } + successDiv?.classList.remove('hidden'); + } + + function highlightEmpty(f) { + ['firstName', 'lastName', 'email', 'orgName', 'state'].forEach(name => { + const el = f[name]; + if (el && !el.value.trim()) { + el.style.borderColor = '#ef4444'; + el.addEventListener('input', () => { el.style.borderColor = ''; }, { once: true }); + el.addEventListener('change', () => { el.style.borderColor = ''; }, { once: true }); + } + }); + } + + function isValidEmail(email) { + return /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email); + } + + function saveLocally(payload) { + try { + const existing = JSON.parse(localStorage.getItem('hoa_leads') || '[]'); + existing.push(payload); + localStorage.setItem('hoa_leads', JSON.stringify(existing)); + } catch (_) { /* best-effort */ } + } +}); diff --git a/hoa-cd-rates.log b/hoa-cd-rates.log new file mode 100644 index 0000000..0f6b59d --- /dev/null +++ b/hoa-cd-rates.log @@ -0,0 +1 @@ +Error response from daemon: No such container: hoa_financial_platform-backend diff --git a/index.html b/index.html new file mode 100644 index 0000000..89a115d --- /dev/null +++ b/index.html @@ -0,0 +1,441 @@ + + + + + + HOA LedgerIQ — AI-Powered HOA Finance Management + + + + + + + + + + + +
+ + + +
+ + + + + +
+
+
+
+ + AI-Powered HOA Finance Management +
+

+ Your HOA Finances,
+ Finally Under Control +

+

+ HOA LedgerIQ brings enterprise-grade AI analytics to community associations of any size. + Bank and Investment tracking, real-time budget insights, delinquency tracking, and intelligent + forecasting and planning — all in one beautifully simple platform. Stop wasting time with + outdated & manual spreadsheets, while optimizing your community's finances. +

+ +
+ Built for property managers, board members & CPAs +
+
+ + +
+
+
+ + + + LedgerIQ Dashboard +
+
+
+
Total Collected YTD
+
$412,850
+
↑ 8.2% vs last year
+
+
+
Delinquency Rate
+
3.4%
+
↓ 1.1% this quarter
+
+
+
Reserve Fund Health
+
92%
+
AI Forecast: On Track
+
+
+
+
+
+
+
+
+
+
+ + AI Insight: Reserve funding on pace for full replenishment by Q3. +
+
+
+
+
+ + +
+
+ Trusted workflow for +
+ Self-Managed HOAs + · + Property Management Firms + · + Community CPAs + · + Board Treasurers +
+
+
+ + +
+
+ +

Everything your HOA's
finances demand

+

From dues collection to reserve fund forecasting, LedgerIQ handles the heavy lifting so your board can focus on the community.

+ +
+
+
+

AI Financial Analytics

+

Receive intelligent AI Powered investment recommendations designed to maximize investment income while ensuring sufficient funding for operating costs and capital projects.

+
Powered by GPT-4
+
+
+
📊
+

Intelligent Cash Flow Visibility

+

Understand budget vs. actuals in real time, accurately forecast your cash management throughout the year to make intelligent decisions, and optimize capital project timing.

+
+
+
🏦
+

Reserve Fund Forecasting

+

AI-Enabled 5 Year Comprehensive Capital Project Planning. Easily understand the community's full inventory of assets, date of last repair and expected lifespan, estimated costs and timing to enable continuous planning capability around capital projects and ensure your community is on track — before the board meeting.

+
+
+
🔔
+

Delinquency Tracking & Alerts

+

Automated late-fee calculations, escalation workflows, and homeowner reminders. Reduce delinquencies without awkward board calls.

+
+
+
📄
+

One-Click Board Reports

+

Beautiful, professional PDF and Excel reports ready for every board meeting — income statements, balance sheets, variance analysis, and more.

+
+
+
🔒
+

Audit-Ready Compliance

+

Every transaction is timestamped, signed, and stored with a complete audit trail. Year-end CPA handoffs take minutes, not weeks.

+
+
+
+
+ + +
+
+
+ +

Optimize your Community's Finances

+

LedgerIQ's AI engine doesn't just review your data — it understands it. Get proactive anomaly alerts, funding shortfalls, investment strategy ideas around your predicted cash flow, spending pattern insights, and plain-English answers to complex financial questions without needing a CPA on speed dial.

+
    +
  • Anomaly detection on every transaction
  • +
  • Budget vs. actual variance alerts
  • +
  • Predictive cash flow modeling
  • +
  • Natural language financial Q&A
  • +
  • Automated year-end closing insights
  • +
+
+
+
What investment strategy should we implement given our forecasted cash flow?
+
+ ✦ LedgerIQ AI + Operating funds are currently under-utilized. With over $100k projected in cash by April, deploying $40k into a short-term CD significantly boosts interest income without compromising the ability to pay monthly expenses or handle emergencies. +
+
Are we on track to fund reserves fully by year-end?
+
+ ✦ LedgerIQ AI + Yes — at current contribution rate you'll hit 98% reserve funding by Dec 31. No corrective action needed. Reserve study renewal is due in March. +
+
+
+
+ + +
+
+ +

Pick the plan that fits your community

+

No setup fees. No contracts. Cancel anytime. All plans include a 30-day free trial.

+ +
+ + +
+
Starter
+
Perfect for small self-managed HOAs
+
$49/mo
+
Up to 75 units
+
    +
  • Account balance tracking
  • +
  • Investment account tracking
  • +
  • Dues collection tracking
  • +
  • Basic delinquency alerts
  • +
  • Monthly board-ready PDF reports
  • +
  • Monthly Actuals reconciliation
  • +
  • Role based access for board members (Up to 5 user accounts)
  • +
  • Email support
  • +
  • AI Analytics
  • +
  • Reserve forecasting
  • +
  • Multi-property management
  • +
+ Get Early Access +
+ + + + + +
+
Enterprise
+
For management companies & large communities
+
Request Quote
+
Unlimited units
+
    +
  • Everything in Professional
  • +
  • Multi-property management
  • +
  • 10-year reserve forecasting
  • +
  • Custom API integrations
  • +
  • Advanced AI anomaly detection
  • +
  • SLA-backed uptime guarantee
  • +
  • Custom onboarding & training
  • +
+ Get Early Access +
+ +
+
+
+ + +
+ +
+ +
+
+ + + + + + + diff --git a/logo_house copy 2.svg b/logo_house copy 2.svg new file mode 100644 index 0000000..f26d80b --- /dev/null +++ b/logo_house copy 2.svg @@ -0,0 +1,47 @@ + + + + diff --git a/logo_house copy.png b/logo_house copy.png new file mode 100644 index 0000000..196dbd1 Binary files /dev/null and b/logo_house copy.png differ diff --git a/logo_house copy.svg b/logo_house copy.svg new file mode 100644 index 0000000..3700d1e --- /dev/null +++ b/logo_house copy.svg @@ -0,0 +1,72 @@ + + + + diff --git a/logo_house-cropped.svg b/logo_house-cropped.svg new file mode 100644 index 0000000..7c6eeb9 --- /dev/null +++ b/logo_house-cropped.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/logo_house.svg b/logo_house.svg new file mode 100644 index 0000000..f26d80b --- /dev/null +++ b/logo_house.svg @@ -0,0 +1,47 @@ + + + + diff --git a/package.json b/package.json new file mode 100644 index 0000000..db44a55 --- /dev/null +++ b/package.json @@ -0,0 +1,14 @@ +{ + "name": "hoaledgeriq-website", + "version": "1.0.0", + "description": "HOA LedgerIQ marketing site + lead capture backend", + "main": "server.js", + "scripts": { + "start": "node server.js", + "dev": "node --watch server.js" + }, + "dependencies": { + "better-sqlite3": "^9.4.3", + "express": "^4.18.3" + } +} diff --git a/privacy.html b/privacy.html new file mode 100644 index 0000000..3f226d0 --- /dev/null +++ b/privacy.html @@ -0,0 +1,183 @@ + + + + + + Privacy Policy — HOA LedgerIQ + + + + + + + + + + + + + + + + + + + diff --git a/server.js b/server.js new file mode 100644 index 0000000..e3f9c33 --- /dev/null +++ b/server.js @@ -0,0 +1,137 @@ +/** + * HOA LedgerIQ — Lead Capture Backend + * Stack: Node.js + Express + better-sqlite3 + * + * Start: node server.js + * Leads DB: ./data/leads.db + */ + +'use strict'; + +require('dotenv').config(); + +const path = require('path'); +const fs = require('fs'); +const express = require('express'); +const Database = require('better-sqlite3'); + +// ── Config ────────────────────────────────────────────── +const PORT = process.env.PORT || 3000; +const DB_DIR = path.join(__dirname, 'data'); +const DB_PATH = path.join(DB_DIR, 'leads.db'); + +// ── DB setup ───────────────────────────────────────────── +fs.mkdirSync(DB_DIR, { recursive: true }); + +const db = new Database(DB_PATH); +db.pragma('journal_mode = WAL'); + +db.exec(` + CREATE TABLE IF NOT EXISTS leads ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + first_name TEXT NOT NULL, + last_name TEXT NOT NULL, + email TEXT NOT NULL UNIQUE, + org_name TEXT, + state TEXT, + role TEXT, + unit_count TEXT, + beta_interest INTEGER DEFAULT 0, + source TEXT DEFAULT 'landing_page', + created_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%fZ','now')) + ); +`); + +// Migrate existing DBs: add new columns if they don't exist yet +const cols = db.pragma('table_info(leads)').map(c => c.name); +if (!cols.includes('org_name')) db.exec('ALTER TABLE leads ADD COLUMN org_name TEXT'); +if (!cols.includes('state')) db.exec('ALTER TABLE leads ADD COLUMN state TEXT'); +if (!cols.includes('beta_interest')) db.exec('ALTER TABLE leads ADD COLUMN beta_interest INTEGER DEFAULT 0'); + +// Prepared statements +const insertLead = db.prepare(` + INSERT INTO leads (first_name, last_name, email, org_name, state, role, unit_count, beta_interest, source) + VALUES (@firstName, @lastName, @email, @orgName, @state, @role, @unitCount, @betaInterest, @source) +`); + +const findByEmail = db.prepare(`SELECT id FROM leads WHERE email = ? LIMIT 1`); + +const getAllLeads = db.prepare(` + SELECT id, first_name, last_name, email, org_name, state, role, unit_count, beta_interest, source, created_at + FROM leads + ORDER BY created_at DESC +`); + +// ── App ─────────────────────────────────────────────────── +const app = express(); +app.use(express.json()); +app.use(express.static(__dirname)); // serve the marketing site + +// POST /api/leads — capture a new preview sign-up +app.post('/api/leads', (req, res) => { + const { firstName, lastName, email, orgName, state, role, unitCount, betaInterest, source } = req.body ?? {}; + + // Validate required fields + if (!firstName?.trim() || !lastName?.trim() || !email?.trim()) { + return res.status(400).json({ error: 'firstName, lastName, and email are required.' }); + } + if (!orgName?.trim()) { + return res.status(400).json({ error: 'Organization name is required.' }); + } + if (!state?.trim()) { + return res.status(400).json({ error: 'State is required.' }); + } + + // Simple email format check + const emailRx = /^[^\s@]+@[^\s@]+\.[^\s@]+$/; + if (!emailRx.test(email.trim())) { + return res.status(400).json({ error: 'Invalid email address.' }); + } + + // Check for duplicate + const existing = findByEmail.get(email.trim().toLowerCase()); + if (existing) { + return res.status(409).json({ error: 'This email is already on the list.', id: existing.id }); + } + + try { + const info = insertLead.run({ + firstName: firstName.trim(), + lastName: lastName.trim(), + email: email.trim().toLowerCase(), + orgName: orgName?.trim() ?? null, + state: state?.trim() ?? null, + role: role ?? null, + unitCount: unitCount ?? null, + betaInterest: betaInterest ? 1 : 0, + source: source ?? 'landing_page', + }); + + return res.status(201).json({ success: true, id: info.lastInsertRowid }); + } catch (err) { + if (err.code === 'SQLITE_CONSTRAINT_UNIQUE') { + return res.status(409).json({ error: 'This email is already on the list.' }); + } + console.error('DB error:', err); + return res.status(500).json({ error: 'Internal server error.' }); + } +}); + +// GET /api/leads — internal: list all leads (add auth before exposing publicly) +app.get('/api/leads', (req, res) => { + const secret = req.headers['x-admin-key']; + if (!secret || secret !== process.env.ADMIN_KEY) { + return res.status(401).json({ error: 'Unauthorized.' }); + } + const leads = getAllLeads.all(); + res.json({ count: leads.length, leads }); +}); + +// Health check +app.get('/api/health', (_req, res) => res.json({ status: 'ok', ts: new Date().toISOString() })); + +// ── Start ───────────────────────────────────────────────── +app.listen(PORT, () => { + console.log(`\n HOA LedgerIQ server running at http://localhost:${PORT}`); + console.log(` Leads DB: ${DB_PATH}\n`); +}); diff --git a/styles.css b/styles.css new file mode 100644 index 0000000..898466f --- /dev/null +++ b/styles.css @@ -0,0 +1,691 @@ +/* ============================================= + HOA LedgerIQ — Marketing Site Styles + ============================================= */ + +*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; } + +:root { + --blue: #2563eb; + --blue-dark: #1d4ed8; + --blue-glow: rgba(37, 99, 235, 0.25); + --indigo: #4f46e5; + --teal: #0ea5e9; + --green: #22c55e; + --amber: #f59e0b; + --red: #ef4444; + --gray-50: #f8fafc; + --gray-100: #f1f5f9; + --gray-200: #e2e8f0; + --gray-400: #94a3b8; + --gray-600: #475569; + --gray-700: #334155; + --gray-800: #1e293b; + --gray-900: #0f172a; + --surface: #ffffff; + --radius: 12px; + --radius-lg: 20px; + --shadow: 0 4px 24px rgba(0,0,0,0.08); + --shadow-lg: 0 16px 64px rgba(0,0,0,0.14); +} + +html { scroll-behavior: smooth; } + +body { + font-family: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif; + background: var(--gray-900); + color: var(--gray-100); + line-height: 1.65; + -webkit-font-smoothing: antialiased; +} + +.container { + max-width: 1120px; + margin: 0 auto; + padding: 0 24px; +} + +/* ---- Buttons ---- */ +.btn { + display: inline-flex; + align-items: center; + gap: 8px; + padding: 12px 24px; + border-radius: 8px; + font-size: 15px; + font-weight: 600; + cursor: pointer; + text-decoration: none; + border: 2px solid transparent; + transition: all 0.18s ease; + white-space: nowrap; +} +.btn-primary { + background: var(--blue); + color: #fff; + border-color: var(--blue); +} +.btn-primary:hover { background: var(--blue-dark); border-color: var(--blue-dark); transform: translateY(-1px); box-shadow: 0 8px 24px var(--blue-glow); } +.btn-outline { + background: transparent; + color: var(--gray-100); + border-color: var(--gray-600); +} +.btn-outline:hover { border-color: var(--blue); color: var(--blue); transform: translateY(-1px); } +.btn-ghost { + background: transparent; + color: var(--gray-400); + border-color: transparent; +} +.btn-ghost:hover { color: var(--gray-100); } +.btn-lg { padding: 16px 32px; font-size: 16px; border-radius: 10px; } +.hidden { display: none !important; } + +/* ---- Coming Soon Banner ---- */ +.coming-soon-banner { + background: linear-gradient(90deg, var(--indigo), var(--blue), var(--teal)); + padding: 12px 24px; + display: flex; + align-items: center; + justify-content: center; + gap: 16px; + flex-wrap: wrap; + font-size: 14px; + font-weight: 500; + text-align: center; +} +.banner-badge { + background: rgba(255,255,255,0.2); + border: 1px solid rgba(255,255,255,0.35); + padding: 3px 10px; + border-radius: 99px; + font-size: 12px; + font-weight: 700; + text-transform: uppercase; + letter-spacing: 0.06em; + color: #fff; + flex-shrink: 0; +} +.banner-text { color: rgba(255,255,255,0.9); } +.banner-cta { + background: #fff; + color: var(--indigo); + padding: 5px 14px; + border-radius: 6px; + font-weight: 700; + font-size: 13px; + text-decoration: none; + flex-shrink: 0; + transition: opacity 0.15s; +} +.banner-cta:hover { opacity: 0.9; } + +/* ---- Nav ---- */ +.nav { + position: sticky; + top: 0; + z-index: 100; + background: rgba(15, 23, 42, 0.85); + backdrop-filter: blur(16px); + border-bottom: 1px solid rgba(255,255,255,0.06); +} +.nav-inner { + max-width: 1120px; + margin: 0 auto; + padding: 0 24px; + height: 68px; + display: flex; + align-items: center; + gap: 32px; +} +.nav-logo { display: flex; align-items: center; text-decoration: none; } +.logo-img { height: 36px; width: auto; } +.logo-img--footer { height: 30px; } +.nav-links { + display: flex; + gap: 28px; + list-style: none; + margin-left: auto; +} +.nav-links a { + color: var(--gray-400); + text-decoration: none; + font-size: 15px; + font-weight: 500; + transition: color 0.15s; +} +.nav-links a:hover { color: var(--gray-100); } +.nav-btn { margin-left: 16px; padding: 9px 20px; font-size: 14px; } + +/* ---- Pulse dot ---- */ +.pulse-dot { + display: inline-block; + width: 8px; height: 8px; + background: var(--green); + border-radius: 50%; + position: relative; + flex-shrink: 0; +} +.pulse-dot::after { + content: ''; + position: absolute; + inset: -4px; + border-radius: 50%; + background: var(--green); + opacity: 0.4; + animation: pulse 1.8s infinite; +} +.pulse-dot--white { background: #fff; } +.pulse-dot--white::after { background: #fff; } +@keyframes pulse { + 0% { transform: scale(1); opacity: 0.4; } + 70% { transform: scale(2.2); opacity: 0; } + 100% { transform: scale(1); opacity: 0; } +} + +/* ---- Hero ---- */ +.hero { + position: relative; + overflow: hidden; + padding: 100px 0 80px; + text-align: center; +} +.hero-glow { + position: absolute; + top: -200px; left: 50%; + transform: translateX(-50%); + width: 900px; height: 600px; + background: radial-gradient(ellipse at center, rgba(79,70,229,0.35) 0%, transparent 70%); + pointer-events: none; +} +.hero-badge { + display: inline-flex; + align-items: center; + gap: 8px; + background: rgba(79,70,229,0.15); + border: 1px solid rgba(79,70,229,0.4); + color: #a5b4fc; + padding: 6px 16px; + border-radius: 99px; + font-size: 13px; + font-weight: 600; + letter-spacing: 0.02em; + margin-bottom: 28px; +} +.hero-headline { + font-size: clamp(40px, 7vw, 76px); + font-weight: 900; + line-height: 1.08; + letter-spacing: -0.03em; + color: #fff; + margin-bottom: 24px; +} +.gradient-text { + background: linear-gradient(135deg, #60a5fa, #a78bfa, #38bdf8); + -webkit-background-clip: text; + -webkit-text-fill-color: transparent; + background-clip: text; +} +.hero-sub { + max-width: 620px; + margin: 0 auto 36px; + font-size: 18px; + color: var(--gray-400); + line-height: 1.7; +} +.hero-actions { + display: flex; + gap: 16px; + justify-content: center; + flex-wrap: wrap; + margin-bottom: 20px; +} +.hero-trust { + font-size: 13px; + color: var(--gray-600); + margin-top: 8px; +} + +/* ---- Dashboard card (hero visual) ---- */ +.hero-visual { + margin: 60px auto 0; + max-width: 680px; + padding: 0 24px; +} +.dashboard-card { + background: var(--gray-800); + border: 1px solid rgba(255,255,255,0.08); + border-radius: var(--radius-lg); + overflow: hidden; + box-shadow: var(--shadow-lg), 0 0 80px rgba(79,70,229,0.18); + text-align: left; +} +.dash-header { + background: var(--gray-900); + padding: 12px 16px; + display: flex; + align-items: center; + gap: 7px; + border-bottom: 1px solid rgba(255,255,255,0.06); +} +.dash-dot { width: 12px; height: 12px; border-radius: 50%; } +.dash-dot.red { background: #ff5f57; } +.dash-dot.yellow { background: #febc2e; } +.dash-dot.green { background: #28c840; } +.dash-title { margin-left: 8px; font-size: 12px; color: var(--gray-600); font-weight: 500; } +.dash-body { padding: 24px; display: grid; grid-template-columns: repeat(3, 1fr); gap: 16px; } +.dash-stat { } +.stat-label { font-size: 11px; color: var(--gray-600); font-weight: 500; text-transform: uppercase; letter-spacing: 0.06em; margin-bottom: 6px; } +.stat-value { font-size: 22px; font-weight: 800; letter-spacing: -0.02em; } +.stat-delta { font-size: 11px; color: var(--gray-600); margin-top: 3px; } +.green-text { color: var(--green); } +.amber-text { color: var(--amber); } +.dash-chart { + grid-column: 1 / -1; + display: flex; + align-items: flex-end; + gap: 6px; + height: 72px; + background: rgba(255,255,255,0.02); + border-radius: 8px; + padding: 10px 12px 0; +} +.chart-bar { + flex: 1; + background: rgba(79,70,229,0.35); + border-radius: 4px 4px 0 0; + transition: background 0.2s; +} +.chart-bar.active { background: var(--blue); } +.dash-ai-chip { + grid-column: 1 / -1; + background: rgba(79,70,229,0.12); + border: 1px solid rgba(79,70,229,0.3); + border-radius: 8px; + padding: 10px 14px; + font-size: 12px; + color: #a5b4fc; + display: flex; + align-items: flex-start; + gap: 8px; +} +.ai-icon { font-size: 14px; flex-shrink: 0; } + +/* ---- Proof strip ---- */ +.proof-strip { + border-top: 1px solid rgba(255,255,255,0.06); + border-bottom: 1px solid rgba(255,255,255,0.06); + padding: 20px 0; + background: rgba(255,255,255,0.02); +} +.proof-inner { + display: flex; + align-items: center; + gap: 20px; + flex-wrap: wrap; + justify-content: center; +} +.proof-label { font-size: 12px; text-transform: uppercase; letter-spacing: 0.08em; color: var(--gray-600); font-weight: 600; } +.proof-items { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; justify-content: center; font-size: 14px; color: var(--gray-400); font-weight: 500; } +.sep { color: var(--gray-700); } + +/* ---- Section shared ---- */ +.section-label { + font-size: 12px; + text-transform: uppercase; + letter-spacing: 0.1em; + color: var(--blue); + font-weight: 700; + margin-bottom: 12px; +} +.section-title { + font-size: clamp(28px, 4vw, 46px); + font-weight: 800; + letter-spacing: -0.025em; + color: #fff; + line-height: 1.15; + margin-bottom: 16px; +} +.section-sub { + font-size: 17px; + color: var(--gray-400); + max-width: 560px; + margin-bottom: 56px; +} + +/* ---- Features ---- */ +.features { padding: 100px 0; } +.features-grid { + display: grid; + grid-template-columns: repeat(3, 1fr); + gap: 20px; +} +.feature-card { + background: var(--gray-800); + border: 1px solid rgba(255,255,255,0.07); + border-radius: var(--radius); + padding: 28px; + transition: transform 0.18s, box-shadow 0.18s; +} +.feature-card:hover { transform: translateY(-3px); box-shadow: var(--shadow-lg); } +.feature-card--highlight { + background: linear-gradient(135deg, rgba(79,70,229,0.2), rgba(37,99,235,0.15)); + border-color: rgba(79,70,229,0.4); +} +.feature-icon { font-size: 24px; margin-bottom: 14px; } +.feature-card h3 { font-size: 17px; font-weight: 700; color: #fff; margin-bottom: 10px; } +.feature-card p { font-size: 14px; color: var(--gray-400); line-height: 1.65; } +.feature-tag { + display: inline-block; + background: rgba(79,70,229,0.18); + border: 1px solid rgba(79,70,229,0.35); + color: #a5b4fc; + font-size: 11px; + font-weight: 700; + padding: 3px 10px; + border-radius: 99px; + margin-top: 14px; + letter-spacing: 0.04em; +} + +/* ---- AI Section ---- */ +.ai-section { + background: linear-gradient(180deg, rgba(79,70,229,0.07) 0%, transparent 100%); + border-top: 1px solid rgba(255,255,255,0.06); + border-bottom: 1px solid rgba(255,255,255,0.06); + padding: 100px 0; +} +.ai-inner { + display: grid; + grid-template-columns: 1fr 1fr; + gap: 64px; + align-items: center; +} +.ai-text h2 { + font-size: clamp(26px, 3.5vw, 42px); + font-weight: 800; + color: #fff; + line-height: 1.15; + letter-spacing: -0.02em; + margin-bottom: 16px; +} +.ai-text p { font-size: 16px; color: var(--gray-400); margin-bottom: 28px; line-height: 1.7; } +.ai-bullets { list-style: none; display: flex; flex-direction: column; gap: 12px; } +.ai-bullets li { font-size: 15px; color: var(--gray-300); display: flex; gap: 10px; align-items: flex-start; } +.check { color: var(--green); font-weight: 700; flex-shrink: 0; } +.ai-visual { display: flex; flex-direction: column; gap: 14px; } +.chat-bubble { + padding: 14px 18px; + border-radius: 12px; + font-size: 14px; + line-height: 1.6; + max-width: 90%; +} +.user-bubble { + background: var(--gray-700); + color: var(--gray-200); + align-self: flex-end; + border-bottom-right-radius: 4px; +} +.ai-bubble { + background: rgba(79,70,229,0.15); + border: 1px solid rgba(79,70,229,0.3); + color: var(--gray-200); + align-self: flex-start; + border-bottom-left-radius: 4px; +} +.ai-label { + display: block; + font-size: 11px; + font-weight: 700; + color: #a5b4fc; + margin-bottom: 6px; + text-transform: uppercase; + letter-spacing: 0.06em; +} + +/* ---- Pricing ---- */ +.pricing { padding: 100px 0; } +.pricing-grid { + display: grid; + grid-template-columns: repeat(3, 1fr); + gap: 20px; + align-items: stretch; +} +.pricing-card { + background: var(--gray-800); + border: 1px solid rgba(255,255,255,0.08); + border-radius: var(--radius-lg); + padding: 36px; + display: flex; + flex-direction: column; + position: relative; + transition: transform 0.18s, box-shadow 0.18s; +} +.pricing-card:hover { transform: translateY(-4px); box-shadow: var(--shadow-lg); } +.pricing-card--featured { + background: linear-gradient(160deg, rgba(79,70,229,0.25) 0%, rgba(37,99,235,0.15) 100%); + border-color: rgba(79,70,229,0.5); + box-shadow: 0 0 60px rgba(79,70,229,0.2); +} +.plan-badge { + position: absolute; + top: -14px; + left: 50%; + transform: translateX(-50%); + background: linear-gradient(90deg, var(--indigo), var(--blue)); + color: #fff; + font-size: 11px; + font-weight: 700; + padding: 4px 16px; + border-radius: 99px; + text-transform: uppercase; + letter-spacing: 0.07em; + white-space: nowrap; +} +.plan-name { font-size: 20px; font-weight: 800; color: #fff; margin-bottom: 4px; } +.plan-tagline { font-size: 13px; color: var(--gray-500); margin-bottom: 24px; } +.plan-price { display: flex; align-items: baseline; gap: 4px; margin-bottom: 4px; } +.price-amount { font-size: 46px; font-weight: 900; letter-spacing: -0.03em; color: #fff; } +.price-period { font-size: 16px; color: var(--gray-500); } +.plan-units { font-size: 13px; color: var(--gray-500); margin-bottom: 28px; } +.plan-features { list-style: none; display: flex; flex-direction: column; gap: 11px; flex: 1; margin-bottom: 32px; } +.plan-features li { font-size: 14px; color: var(--gray-400); display: flex; align-items: flex-start; gap: 9px; } +.plan-features li.dim { color: var(--gray-700); } +.plan-features .check { color: var(--green); font-weight: 700; flex-shrink: 0; } +.plan-btn { width: 100%; justify-content: center; margin-top: auto; } + +/* ---- Signup Section ---- */ +.signup-section { + position: relative; + overflow: hidden; + padding: 100px 0 120px; +} +.signup-glow { + position: absolute; + top: 50%; left: 50%; + transform: translate(-50%, -50%); + width: 800px; height: 600px; + background: radial-gradient(ellipse, rgba(79,70,229,0.3) 0%, transparent 70%); + pointer-events: none; +} +.signup-card { + position: relative; + background: var(--gray-800); + border: 1px solid rgba(79,70,229,0.35); + border-radius: var(--radius-lg); + padding: 56px; + max-width: 760px; + margin: 0 auto; + text-align: center; + box-shadow: 0 0 80px rgba(79,70,229,0.2), var(--shadow-lg); +} +.countdown-badge { + display: inline-flex; + align-items: center; + gap: 10px; + background: rgba(79,70,229,0.18); + border: 1px solid rgba(79,70,229,0.4); + color: #a5b4fc; + padding: 6px 16px; + border-radius: 99px; + font-size: 13px; + font-weight: 700; + margin-bottom: 20px; + letter-spacing: 0.02em; +} +.signup-card h2 { + font-size: clamp(24px, 3.5vw, 38px); + font-weight: 800; + color: #fff; + letter-spacing: -0.025em; + margin-bottom: 12px; +} +.signup-card > p { + color: var(--gray-400); + font-size: 16px; + margin-bottom: 40px; + max-width: 480px; + margin-left: auto; + margin-right: auto; +} +.signup-form { text-align: left; } +.form-row { display: grid; grid-template-columns: 1fr 1fr; gap: 16px; } +.form-group { + display: flex; + flex-direction: column; + gap: 6px; + margin-bottom: 16px; +} +.form-group label { font-size: 13px; font-weight: 600; color: var(--gray-400); } +.form-group input, +.form-group select { + background: var(--gray-900); + border: 1px solid rgba(255,255,255,0.1); + border-radius: 8px; + padding: 12px 14px; + color: var(--gray-100); + font-size: 15px; + font-family: inherit; + width: 100%; + outline: none; + transition: border-color 0.15s; + -webkit-appearance: none; +} +.form-group select { + background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8'%3E%3Cpath d='M1 1l5 5 5-5' stroke='%2394a3b8' stroke-width='1.5' fill='none' stroke-linecap='round'/%3E%3C/svg%3E"); + background-repeat: no-repeat; + background-position: right 14px center; + padding-right: 36px; +} +.form-group input:focus, +.form-group select:focus { border-color: var(--blue); box-shadow: 0 0 0 3px rgba(37,99,235,0.2); } +.form-group input::placeholder { color: var(--gray-700); } +.form-group select option { background: var(--gray-800); color: var(--gray-100); } +.signup-btn { width: 100%; justify-content: center; margin-top: 8px; } +.form-fine { font-size: 12px; color: var(--gray-600); text-align: center; margin-top: 14px; } + +/* ---- Success state ---- */ +.signup-success { padding: 20px 0; } +.success-icon { + width: 64px; height: 64px; + background: rgba(34,197,94,0.15); + border: 2px solid var(--green); + border-radius: 50%; + display: flex; + align-items: center; + justify-content: center; + font-size: 26px; + color: var(--green); + margin: 0 auto 20px; + font-weight: 700; +} +.signup-success h3 { font-size: 24px; font-weight: 800; color: #fff; margin-bottom: 10px; } +.signup-success p { font-size: 16px; color: var(--gray-400); } + +/* ---- Footer ---- */ +.footer { border-top: 1px solid rgba(255,255,255,0.06); padding: 60px 0 0; } +.footer-inner { + display: grid; + grid-template-columns: 1.5fr 1fr; + gap: 48px; + padding-bottom: 48px; + border-bottom: 1px solid rgba(255,255,255,0.06); +} +.footer-logo p { font-size: 14px; color: var(--gray-600); margin-top: 12px; line-height: 1.6; } +.footer-links { display: flex; gap: 48px; } +.footer-col { display: flex; flex-direction: column; gap: 12px; } +.footer-col-title { font-size: 12px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.08em; color: var(--gray-600); margin-bottom: 4px; } +.footer-col a { color: var(--gray-500); text-decoration: none; font-size: 14px; transition: color 0.15s; } +.footer-col a:hover { color: var(--gray-200); } +.footer-bottom { + padding: 20px 0; + font-size: 13px; + color: var(--gray-700); +} + +/* ---- Request Quote pricing ---- */ +.price-amount--quote { + font-size: 32px; + background: linear-gradient(135deg, #60a5fa, #a78bfa); + -webkit-background-clip: text; + -webkit-text-fill-color: transparent; + background-clip: text; +} + +/* ---- Login nav button ---- */ +.nav-login { + padding: 9px 20px; + font-size: 14px; +} + +/* ---- Beta checkbox group ---- */ +.beta-group { + display: flex; + align-items: flex-start; + gap: 10px; + margin: 20px 0 4px; + cursor: pointer; +} +.beta-group input[type="checkbox"] { + width: 18px; + height: 18px; + accent-color: var(--blue); + margin-top: 2px; + flex-shrink: 0; + cursor: pointer; +} +.beta-group label { + font-size: 14px; + color: var(--gray-200); + cursor: pointer; + font-weight: 500; +} +.beta-disclaimer { + font-size: 12px; + color: var(--gray-600); + line-height: 1.55; + margin-bottom: 16px; + padding-left: 28px; +} + +/* ---- Responsive ---- */ +@media (max-width: 900px) { + .features-grid { grid-template-columns: repeat(2, 1fr); } + .pricing-grid { grid-template-columns: 1fr; max-width: 440px; margin: 0 auto; } + .pricing-card--featured { order: -1; } + .ai-inner { grid-template-columns: 1fr; gap: 48px; } + .footer-inner { grid-template-columns: 1fr; } + .footer-links { flex-wrap: wrap; gap: 32px; } + .dash-body { grid-template-columns: 1fr 1fr; } +} + +@media (max-width: 640px) { + .features-grid { grid-template-columns: 1fr; } + .form-row { grid-template-columns: 1fr; } + .signup-card { padding: 36px 24px; } + .nav-links { display: none; } + .hero-headline { font-size: 36px; } + .coming-soon-banner { gap: 10px; } + .banner-text { display: none; } + .dash-body { grid-template-columns: 1fr; } +} diff --git a/terms.html b/terms.html new file mode 100644 index 0000000..1ef86e5 --- /dev/null +++ b/terms.html @@ -0,0 +1,174 @@ + + + + + + Terms of Service — HOA LedgerIQ + + + + + + + + + + + + + + + + + + +