# PROJECT: Aether App — Comprehensive Style Review

**Status:** Phase 1 & 2 Complete — Phase 3 Deferred (post-April 2026 conference)
**Priority:** Medium
**Created:** 2026-03-13
**Updated:** 2026-03-16
**Related:** `src/app.css`, `src/routes/+layout.svelte`, `documentation/AE__UI_Component_Patterns.md`

---

## 1. Objective

Audit and unify the visual design system across all Aether modules. The goal is consistent:
- Color token usage (Skeleton `preset-*` / `surface-*` / semantic tokens)
- Button and interactive element styling
- Dark mode handling
- Typography hierarchy
- Layout patterns (cards, lists, tables, modals, banners)
- Icon system (Lucide only)

This review covers all modules and their distinct use cases. Changes must be sequenced to avoid breaking live-production systems (Events Launcher, IDAA).

### Scope of Modules

| Module | Routes | Primary Users | Notes |
|---|---|---|---|
| Core / App Shell | `+layout.svelte`, `e_app_sys_bar.svelte` | All users | Foundation — impacts everything |
| Core Admin | `/core/` | OSIT staff / managers | Manager-only section |
| Journals | `/journals/` | Authenticated users | Canonical/frontier model |
| Events — General | `/events/`, `/events/[id]/` | Event staff, attendees | Hub page |
| Events — Pres Mgmt | `/events/[id]/(pres_mgmt)/` | Event coordinators | Operations tool |
| Events — Launcher | `/events/[id]/(launcher)/` | AV/tech staff (Electron kiosk) | ⚠️ Live production — April 2026 conference |
| Events — Badges | `/events/[id]/(badges)/` | Registration desk staff | On-site kiosk use |
| Events — Leads | `/events/[id]/(leads)/` | Exhibitor booth staff | On-site kiosk use |
| IDAA | `/idaa/` | IDAA members (iframe) | ⚠️ Privacy-critical, iframe context |

---

## 2. Current State: Dual-Generation Problem

The codebase has two parallel style generations that co-exist:

| Era | Pattern | Where Used |
|---|---|---|
| **Modern** | `preset-tonal-*`, `preset-filled-*`, Lucide icons, Svelte 5 runes | `sys_bar`, Journals, IDAA dashboard |
| **Legacy** | `variant-soft-*`, `variant-filled-*`, FontAwesome `fas fa-*` icons | Events routes (most), some Core |

The Journals module is the canonical reference for modern patterns — when in doubt, match it.

---

## 3. Color Token Architecture

Three overlapping systems are in use. The goal is to consolidate to two:

### ✅ System 1: Skeleton Semantic Tokens (keep, expand usage)
Used for colored/semantic elements.
```
primary, secondary, tertiary, success, warning, error, surface
```
Usage: `preset-tonal-primary`, `bg-primary-500/10`, `text-error-500`, `border-warning-500`

### ✅ System 2: Plain Tailwind Grayscale (keep for neutrals)
Used for neutral backgrounds, borders, and text. Predictable across all Skeleton themes.
```
gray-50/100/200/300/400/500/600/700/800/900
```
Usage: `bg-gray-50 dark:bg-gray-900`, `border-gray-200 dark:border-gray-700`

### ❌ System 3: Hardcoded RGB/HSL (eliminate)
```
bg-orange-600/90  — root layout banner
hsla(0, 100%, 50%, .5)  — journal entry eye icon
rgb(243 244 246)  — form dark mode hacks in <style> blocks
```
These are brittle, not theme-aware, and create maintenance debt.

### Decision Rule
> **Semantic color needed?** → Use Skeleton token (`preset-*`, `text-primary-*`, etc.)
> **Neutral background/border/text?** → Use `gray-*` with `dark:` pair
> **Hardcoded color?** → Replace with token. No exceptions.

---

## 4. Dark Mode Architecture

### Current Setup (already correct in app.css)
```css
@custom-variant dark (&:where(.dark, .dark *));  /* Tailwind v4 class-based dark mode */
html.dark  { color-scheme: dark; }               /* Native controls follow app theme */
html.light { color-scheme: light; }
```

### Gap: Skeleton Form Classes Lack Dark Mode
Skeleton's `.input`, `.select`, `.textarea` classes do not include dark mode styles. This causes white text on white backgrounds in dark mode. Currently patched with inline `<style>` blocks per-component (see `e_app_sys_bar.svelte` lines 693–707).

**Fix:** Global utility in `app.css` (see Phase 1, Step 1). Once added, remove per-component patches.

---

## 5. Button System

### Standard: `preset-*` (Skeleton v4 pattern) ✅
```html
<button class="btn preset-tonal-secondary">Secondary</button>
<button class="btn btn-sm preset-filled-primary">Primary</button>
<button class="btn preset-outlined-surface">Outlined</button>
```


> **Note:** All legacy `variant-*` classes have been fully removed from the codebase. Use only `preset-*` classes for all buttons and interactive elements.

### Custom `ae_btn_*` Classes (app.css)
These exist in `app.css` and wrap the `preset-*` system. They are valid but underused. Consider adopting where button groups need reuse.

---

## 6. Icon System

**Standard:** Lucide (`@lucide/svelte`) — SVG, tree-shakeable, consistent stroke weight
**Legacy:** FontAwesome (`fas fa-*` / `far fa-*`) — CSS class-based, heavier

FontAwesome is still imported (likely via global CSS). Goal: complete removal from all new work; migrate existing usage to Lucide progressively.

### FontAwesome → Lucide Reference Map (events module)

| FontAwesome | Lucide Component | Notes |
|---|---|---|
| `fa-cogs` | `Settings` | Settings/config |
| `fa-chart-line` | `TrendingUp` | Reports/charts |
| `fa-map-marked-alt` | `MapPinned` | Location with map |
| `fa-map-marker-alt` | `MapPin` | Location marker |
| `fa-tools` | `Wrench` | Tools/maintenance |
| `fa-search` | `Search` | Search |
| `fa-chalkboard-teacher` | `PresentationIcon` or `GraduationCap` | Presenter |
| `fa-plane` | `Plane` | Travel/remote |
| `fa-sync-alt fa-spin` | `RefreshCw` + CSS animation | Spinner |
| `fa-arrow-up` | `ArrowUp` | Up arrow |
| `fa-arrow-down` | `ArrowDown` | Down arrow |
| `fa-list-ol` | `ListOrdered` | Ordered list |
| `fa-file-csv` | `FileSpreadsheet` | CSV file |
| `fa-toggle-on` | `ToggleRight` | Toggle |
| `fa-calendar-alt` | `CalendarDays` | Calendar |
| `fa-exclamation-triangle` | `TriangleAlert` | Warning |
| `fa-lock` | `Lock` | Locked |
| `fa-unlock` | `Unlock` | Unlocked |
| `fa-eye` | `Eye` | Visible |
| `fa-eye-slash` | `EyeOff` | Hidden |
| `fa-trash` | `Trash2` | Delete |
| `fa-edit` / `fa-pencil` | `Pencil` | Edit |
| `fa-plus` | `Plus` | Add |
| `fa-times` / `fa-close` | `X` | Close/remove |
| `fa-check` | `Check` | Confirm |
| `fa-ban` | `Ban` | Denied/blocked |
| `fa-user` | `User` | Person |
| `fa-users` | `Users` | Group |
| `fa-tag` | `Tag` | Tag/label |
| `fa-print` | `Printer` | Print |
| `fa-download` | `Download` | Download |
| `fa-upload` | `Upload` | Upload |
| `fa-copy` | `Copy` | Copy |
| `fa-qrcode` | `QrCode` | QR code |
| `fa-id-card` | `IdCard` | Badge/ID |
| `fa-file-alt` | `FileText` | File |
| `fa-compress-arrows-alt` | `Minimize2` | Collapse |
| `fa-expand` | `Maximize2` | Expand |
| `fa-angle-right` | `ChevronRight` | Nav arrow |
| `fa-angle-down` | `ChevronDown` | Accordion |
| `fa-clock` | `Clock` | Time |

### Lucide Usage Pattern
```svelte
<script>
    import { Settings, Search, MapPin } from '@lucide/svelte';
</script>

<!-- Decorative icon with adjacent label -->
<Settings size="1em" class="shrink-0" aria-hidden="true" />

<!-- Icon-only button — MUST have aria-label -->
<button aria-label="Settings" class="btn btn-sm preset-tonal-surface">
    <Settings size="1.1em" />
</button>
```

---

## 7. Typography

### Standard Hierarchy
```html
<!-- Page title -->
<h1 class="text-3xl sm:text-4xl font-black tracking-tight">Title</h1>

<!-- Section heading -->
<h2 class="text-xl font-bold">Section</h2>

<!-- Card/item heading -->
<h3 class="text-lg font-semibold">Item</h3>

<!-- Label / eyebrow -->
<span class="text-xs font-bold uppercase tracking-wide opacity-40">Label</span>

<!-- Muted secondary text -->
<span class="text-sm opacity-60">Secondary info</span>

<!-- Hint / placeholder text -->
<span class="text-xs opacity-40 italic">Hint</span>
```

### Rule: Opacity Over Fixed Colors for Muted Text
```html
<!-- ✅ Theme-aware muted text -->
<span class="text-sm opacity-60">Note</span>

<!-- ❌ Fixed muted text — breaks in dark mode -->
<span class="text-sm text-gray-500">Note</span>
```

> **Exception:** `text-gray-*` is acceptable in components that intentionally use plain Tailwind grayscale for neutrality (e.g., Journals list cards), as long as `dark:text-gray-*` counterpart is always included.

---

## 8. Card & Layout Patterns

See `documentation/AE__UI_Component_Patterns.md` for the full pattern reference.

Key standard patterns:
- **List item card:** `border border-gray-200 dark:border-gray-700 border-l-4 border-l-primary-500/40` with hover intensification
- **Content card:** `rounded-lg border border-surface-200-800 bg-surface-50-900 px-4 py-3`
- **Glow accent:** `absolute -inset-1 bg-linear-to-r from-primary-500 to-secondary-500 rounded-2xl blur opacity-25 dark:opacity-40 group-hover:opacity-60 transition duration-1000 group-hover:duration-200 pointer-events-none`
- **Empty state:** `preset-tonal-warning p-6 rounded-xl` centered, with icon + heading + description

---

## 9. Accessibility Rules

- **Never remove focus rings.** `focus:ring-0` on text inputs fails WCAG 2.1 AA. Use `focus:ring-2 focus:ring-primary-500` instead.
- **Icon-only buttons must have `aria-label`.** No exceptions.
- **Decorative icons must have `aria-hidden="true"`.** This applies to ALL FontAwesome `<span class="fas ...">` elements too.
- **Color is not the only status indicator.** Pair color with text or icon shape.
- **Form labels must be explicit.** Use `<label for="...">` or `aria-label`.

---

## 10. Module-by-Module Status

### Core / App Shell

| Item | Status | Notes |
|---|---|---|
| Root layout banners (offline, expired) | ✅ Done | `bg-orange-600/90` → `preset-tonal-warning` (2026-03-16) |
| `e_app_sys_bar.svelte` | ✅ Modern | Best-practice reference component |
| `e_app_theme.svelte` | 🟡 Legacy | Redundant with sys_bar theme section; keep but no new work |
| `core/+layout.svelte` | ✅ Done | `variant-*` → `preset-*` (2026-03-16) |
| `core/+page.svelte` | ✅ Good | Excellent card grid template |
| All `/core/` files (21 files) | ✅ Done | `variant-*` → `preset-*`, FA → Lucide (2026-03-16) |

### Journals

| Item | Status | Notes |
|---|---|---|
| Overall | ✅ Canonical reference | Use as template for all new work |
| `ae_comp__journal_obj_li.svelte` | ✅ Excellent | Card pattern, icon sizing, hover states |
| `ae_comp__journal_entry_obj_li.svelte` | ✅ Done | `bg-slate-*` → `bg-gray-*`; hardcoded HSL → Tailwind tokens (2026-03-16) |
| `ae_comp__journal_entry_header.svelte` | ✅ Done | `focus:ring-0` restored to `focus:ring-2` (2026-03-16) |

### Events — General

| Item | Status | Notes |
|---|---|---|
| `events/+page.svelte` | ✅ Done | FA → Lucide; `variant-ghost-surface` → `preset-outlined-surface` (2026-03-16) |
| `events/+layout.svelte` | ✅ Done | FA → Lucide (spinners, arrows) (2026-03-16) |
| `events/ae_comp__events_menu_nav.svelte` | ✅ Done | FA → Lucide (2026-03-16) |
| `events/[id]/+page.svelte` | ✅ Done | FA → Lucide; `variant-*` → `preset-*` (2026-03-16) |
| `events/ae_comp__event_file_obj_tbl.svelte` | ✅ Done | FA → Lucide (2026-03-16) |
| `events/ae_comp__event_presentation_obj_li.svelte` | ✅ Done | FA → Lucide (2026-03-16) |
| Lucide inline flow | ✅ Done | Global `svg.lucide { display: inline }` rule in `app.css` (2026-03-16) |

### Events — Pres Mgmt

| Item | Status | Notes |
| --- | --- | --- |
| All 24 pres_mgmt files | ✅ Done | FA → Lucide; `variant-*` → `preset-*` (2026-03-16) |
| Card styling for session/presenter lists | 🔒 Phase 3 | Deferred to post-April 2026 |

### Events — Launcher ⚠️ Live Production

| Item | Status | Notes |
| --- | --- | --- |
| FA → Lucide | ✅ Done | All FA spans were already in HTML comments — launcher is clean (verified 2026-03-16) |
| `variant-*` | ✅ Done | The `variant-soft-secondary` at line 329 is inside a comment block — no live variants remain |
| Card styling / UX polish | 🔒 Phase 3 | Deferred to post-April 2026 conference |

### Events — Badges

| Item | Status | Notes |
| --- | --- | --- |
| FA → Lucide | ✅ Done | All badge files migrated (2026-03-16) |
| `badge_upload_form.svelte` | ✅ Done | `variant-*` → `preset-*` (2026-03-16) |
| `badge_template_form.svelte` | ✅ Done | `variant-*` → `preset-*` (2026-03-16) |
| `code_to_html` | ✅ Refactored | FA HTML string dict → `code_to_icon` Lucide component map (2026-03-16) |

### Events — Leads

| Item | Status | Notes |
| --- | --- | --- |
| FA → Lucide | ✅ Done | All leads files migrated (2026-03-16) |
| `ae_comp__exhibit_signin.svelte` | ✅ Done | `variant-*` → `preset-*` (2026-03-16) |
| `ae_comp__lead_qr_scanner.svelte` | ✅ Done | `variant-*` → `preset-*` (2026-03-16) |
| `ae_tab__add.svelte` | ✅ Done | `variant-*` → `preset-*` (2026-03-16) |

### IDAA ⚠️ Privacy-Critical

| Item | Status | Notes |
| --- | --- | --- |
| `(idaa)/+page.svelte` | ✅ Modern | Semantic tokens, good access gate |
| FA CDN | ✅ Scoped | Moved from `app.html` → `idaa/+layout.svelte` `<svelte:head>` (2026-03-16) |
| Archives, BB, Recovery Meetings | 🔒 Deferred | Full style review deferred to Phase 3 |
| **All IDAA FA → Lucide** | 🔒 Last priority | Review only after non-IDAA modules are complete |

---

## 11. Issues Ranked by Priority

| # | Severity | Issue | Location | Phase |
|---|---|---|---|---|
| 1 | 🔴 A11y | `focus:ring-0` removes focus indicator on journal name input | `ae_comp__journal_entry_header.svelte:108` | 1 |
| 2 | 🔴 Maintenance | No global dark mode form fix — per-component patches scattered | `e_app_sys_bar.svelte` lines 693–707; others | 1 |
| 3 | 🟡 Consistency | FontAwesome icons throughout events module | 61 event files | 1–2 |
| 4 | 🟡 Consistency | `variant-*` buttons used instead of `preset-*` | Events, Badges, Leads routes | 1–2 |
| 5 | 🟡 Theme | Hardcoded `bg-orange-600/90` on root layout offline banner | `+layout.svelte` | 2 |
| 6 | 🟡 Theme | Hardcoded HSL colors on journal entry eye icon | `ae_comp__journal_entry_obj_li.svelte` | 2 |
| 7 | 🟢 Consistency | `bg-slate-*` used in journal entry instead of `bg-gray-*` | `ae_comp__journal_entry_obj_li.svelte` | 2 |
| 8 | 🟢 Polish | Pres Mgmt pages lack card styling (bare `<ul>` lists) | `pres_mgmt/+page.svelte` and sub-pages | 3 |
| 9 | 🟢 Polish | Root layout banner uses direct `font-semibold text-white` instead of preset | `+layout.svelte` | 2 |

---

## 12. Implementation Plan

### Phase 1: Quick Wins (current)

**Step 1 — Global form dark mode utility** ✅ Target: `src/app.css`

Add a global utility so Skeleton `.input`, `.select`, `.textarea` classes render correctly in dark mode. This eliminates all per-component `<style>` patches.

**Step 2 — FontAwesome → Lucide in events nav/layout files**

Scope: Non-Launcher, non-IDAA files only. Priority order:
1. `src/routes/events/ae_comp__events_menu_nav.svelte` — top-level navigation
2. `src/routes/events/+layout.svelte` — spinner and sort icons

**Step 3 — Standardize `variant-*` → `preset-*` in events**

Scope: `+page.svelte`, `settings/+page.svelte`, `sign_in_out.svelte`
Skip: Launcher files (frozen), IDAA files (deferred)

---

### Phase 2: Consolidation

- Replace hardcoded banner color in root layout (`bg-orange-600/90` → `preset-tonal-warning`)
- Fix journal entry eye icon hardcoded HSL colors
- Fix `bg-slate-*` inconsistency in journal entry
- Migrate `variant-*` in remaining events files: Pres Mgmt, Badges, Leads
- Remove per-component `<style>` dark mode patches (now covered by global utility)
- Add responsive typography to events hub and pres mgmt pages

---

### Phase 3: Module Refactors (post-April 2026 conference)

- Events Launcher: FontAwesome → Lucide, `variant-*` → `preset-*`
- Events Pres Mgmt: Card styling for session/presenter lists
- IDAA: Full style review (Archives, BB, Recovery Meetings)
- Create `.prose-journal` utility in app.css to centralize markdown prose overrides

---

## 13. Files to Modify (Phase 1)

| File | Change |
|---|---|
| `src/app.css` | Add global `.dark` form element utility |
| `src/routes/events/ae_comp__events_menu_nav.svelte` | Replace `fas fa-*` with Lucide imports |
| `src/routes/events/+layout.svelte` | Replace `fas fa-sync-alt fa-spin` and arrow icons with Lucide |
| `src/routes/events/+page.svelte` | Replace `variant-ghost-surface` → `preset-outlined-surface` |
| `src/routes/events/[event_id]/settings/+page.svelte` | Replace `variant-filled-secondary/primary` → `preset-*` |
| `src/routes/events/[event_id]/sign_in_out.svelte` | Replace `variant-soft-warning` → `preset-tonal-warning` |

---

## 14. Testing Notes

- Run `npx svelte-check` after every file change
- Test dark mode toggle after form utility added — confirm inputs render correctly in dark
- Test light mode — confirm no regressions
- Events nav: verify all Lucide icons render at correct size and with correct meaning
- Launcher: do not touch — verify no unintended changes via `git diff`
- IDAA: do not touch — verify no unintended changes via `git diff`

---

## 15. What We Are NOT Changing (Phase 1)

- Events Launcher files — frozen until post-April 2026 conference
- All IDAA files — deferred to last phase
- Root layout banner hardcoded color — Phase 2
- Journal entry HSL eye icon colors — Phase 2
- Pres Mgmt card styling — Phase 3
