# LotusGuild Aesthetic Diff — Convergence Guide Cross-app analysis of every divergence between Tinker Tickets (PHP), PULSE (Node.js), and GANDALF (Flask) that prevents a unified aesthetic. Each section lists the current state in each app, then the **target state** from the unified design system (`web_template/base.css`). --- ## 1. CSS Custom Property Names The biggest source of divergence. Gandalf uses entirely different variable names. | Property | Tinker Tickets | PULSE | GANDALF | **Target** | |---|---|---|---|---| | Main background | `--bg-primary: #0a0a0a` | `--bg-primary: #0a0a0a` | `--bg: #0a0a0a` | `--bg-primary` | | Surface | `--bg-secondary: #1a1a1a` | `--bg-secondary: #1a1a1a` | `--bg2: #1a1a1a` | `--bg-secondary` | | Raised surface | `--bg-tertiary: #2a2a2a` | `--bg-tertiary: #2a2a2a` | `--bg3: #2a2a2a` | `--bg-tertiary` | | Primary green | `--terminal-green: #00ff41` | `--terminal-green: #00ff41` | `--green: #00ff41` | `--terminal-green` | | Green tint | `--terminal-green-dim` | `--terminal-green-dim` | `--green-dim: rgba(0,255,65,.15)` | `--terminal-green-dim` | | Amber | `--terminal-amber: #ffb000` | `--terminal-amber: #ffb000` | `--amber: #ffb000` | `--terminal-amber` | | Amber tint | `--terminal-amber-dim` | `--terminal-amber-dim` | `--amber-dim` | `--terminal-amber-dim` | | Cyan | `--terminal-cyan: #00ffff` | `--terminal-cyan: #00ffff` | `--cyan: #00ffff` | `--terminal-cyan` | | Red | `--terminal-red: #ff4444` | `--terminal-red: #ff4444` | `--red: #ff4444` | `--terminal-red` | | Body text | `--text-primary` | `--text-primary` | `--text` | `--text-primary` | | Dim text | `--text-secondary` | `--text-secondary` | `--text-dim` | `--text-secondary` | | Muted text | `--text-muted: #00bb33` | `--text-muted: #008822` | `--text-muted: #00bb33` | `--text-muted: #00bb33` | | Border | `--border-color` | `--border-color` | `--border: rgba(0,255,65,.35)` | `--border-color` | | Glow (green) | `--glow-green` | `--glow-green` | `--glow` | `--glow-green` | | Glow (amber) | `--glow-amber` | `--glow-amber` | `--glow-amber` | `--glow-amber` ✓ | | Font | `--font-mono` | `--font-mono` | `--font` | `--font-mono` | ### Fix for GANDALF (`style.css`) Add these aliases at the top of `:root` (keeps existing rules working): ```css :root { /* Aliases to match unified naming */ --bg-primary: var(--bg); --bg-secondary: var(--bg2); --bg-tertiary: var(--bg3); --terminal-green: var(--green); --terminal-green-dim:var(--green-dim); --terminal-amber: var(--amber); --terminal-amber-dim:var(--amber-dim); --terminal-cyan: var(--cyan); --terminal-red: var(--red); --text-primary: var(--text); --text-secondary: var(--text-dim); --border-color: var(--border); --glow-green: var(--glow); --font-mono: var(--font); --text-muted: #00bb33; /* override GANDALF's #008822 — too dark */ } ``` Then migrate GANDALF's new code to use unified names. Remove aliases on next major refactor. --- ## 2. Border Width & Style | Context | Tinker Tickets | PULSE | GANDALF | **Target** | |---|---|---|---|---| | Standard card / panel | `2px solid` | `2px solid` | `1px solid` | `2px solid` | | Modal | `3px double` | `3px double` | `1px solid` | `3px double` | | Table outer | `2px solid` | — | none | `2px solid` | | Input fields | `2px solid` | `2px solid` | `1px solid` | `2px solid` | | Button | `2px solid` | `2px solid` | `1px solid` (`.btn-sm`) | `2px solid` | **Change required in GANDALF:** Increase `.modal`, `.host-card`, `.data-table`, `.form-group input/select`, `.btn-sm` border widths from `1px` to `2px`. The `1px` borders make elements look fragile compared to the other apps. ```css /* GANDALF style.css — search & replace */ .modal { border: 1px solid → border: 3px double } .host-card { border: 1px solid → border: 2px solid } .form-group input, .form-group select { border: 1px solid → border: 2px solid } .btn-sm { border: 1px solid → border: 2px solid } ``` --- ## 3. Button Pattern | Aspect | Tinker Tickets | PULSE | GANDALF | **Target** | |---|---|---|---|---| | Bracket decoration | `[ text ]` via `::before`/`::after` | `[ text ]` via `::before`/`::after` | `> text` (primary only), no brackets on most buttons | `[ text ]` via `::before`/`::after` | | Hover transform | `translateY(-2px)` | `translateY(-2px)` | none | `translateY(-2px)` | | Hover animation | `pulse-glow-box 1.5s infinite` | none | none | none (lift is sufficient) | | Padding (standard) | `10px 20px` | `12px 24px` | `6px 14px` (`.btn`) | `10px 20px` | | Padding (small) | `5px 10px` | `6px 12px` | `2px 8px` | `5px 10px` | | Font size | `0.9rem` | `1em` | `0.72em–0.8em` | `0.9rem` | | Text transform | uppercase | uppercase | uppercase | uppercase | **Change required in GANDALF:** Add `::before`/`::after` bracket decorations to all `.btn`, `.btn-primary`, `.btn-secondary`, `.btn-danger` classes. Add `translateY(-2px)` hover transform. Increase padding. ```css /* GANDALF — add to existing .btn rules */ .btn::before { content: '[ '; } .btn::after { content: ' ]'; } .btn:hover { transform: translateY(-2px); } /* Adjust .btn-primary::before to '> ' instead of '[ ' for visual differentiation */ .btn-primary::before { content: '> '; } ``` --- ## 4. Glow Definition Consistency | App | Green glow | Amber glow | |---|---|---| | Tinker Tickets | `0 0 5px #00ff41, 0 0 10px #00ff41, 0 0 15px #00ff41` (3-layer solid) | `0 0 5px #ffb000, 0 0 10px #ffb000, 0 0 15px #ffb000` | | PULSE | Identical to Tinker Tickets | Identical | | GANDALF | `0 0 5px #00ff41, 0 0 10px rgba(0,255,65,.4)` (2-layer, rgba 2nd) | `0 0 5px #ffb000, 0 0 10px rgba(255,176,0,.4)` | GANDALF's 2-layer glow is slightly softer. Both look fine, but they appear different on the same screen if pages are compared side-by-side. **Change required in GANDALF:** Update glow definitions to match the 3-layer solid stack: ```css /* GANDALF style.css */ :root { --glow: 0 0 5px #00ff41, 0 0 10px #00ff41, 0 0 15px #00ff41; --glow-xl: 0 0 8px #00ff41, 0 0 16px #00ff41, 0 0 24px #00ff41, 0 0 32px rgba(0,255,65,.5); --glow-amber: 0 0 5px #ffb000, 0 0 10px #ffb000, 0 0 15px #ffb000; } ``` --- ## 5. Section Header Pattern | App | Syntax | Example | |---|---|---| | Tinker Tickets | `╠═══ TITLE ═══╣` | Symmetric, double-bar bookends | | PULSE | `═══ TITLE ═══` (via h3::before/after) | No `╠` character | | GANDALF | `╠══ TITLE` (one-sided) | Only left bookend, no right | **Change required in PULSE and GANDALF:** Standardise to `╠═══ TITLE ═══╣`. PULSE (`index.html`, all `h3::before`/`h3::after`): ```css /* PULSE: update h3 pseudo-elements */ h3::before { content: '╠═══ '; color: var(--terminal-green); } h3::after { content: ' ═══╣'; color: var(--terminal-green); } ``` GANDALF (`style.css`, `.section-title`): ```css /* GANDALF: add right bookend */ .section-title::after { content: ' ═══╣'; color: var(--green); } ``` --- ## 6. Modal Border Style | App | Border | Box shadow | |---|---|---| | Tinker Tickets | `3px double var(--terminal-green)` | none | | PULSE | `3px double var(--terminal-green)` | `0 0 30px rgba(0,255,65,.3)` | | GANDALF | `1px solid var(--green)` | `0 0 30px rgba(0,255,65,.18)` | **Change required in GANDALF:** Upgrade to `3px double` and add PULSE-style glow: ```css .modal { border: 3px double var(--green); box-shadow: 0 0 30px rgba(0, 255, 65, 0.2), 0 8px 40px rgba(0,0,0,0.8); } ``` --- ## 7. Modal Corner Characters | App | Top corners | Notes | |---|---|---| | Tinker Tickets | `╔ ╗` (double-line) | Matches `3px double` border | | PULSE | `╔ ╗` (double-line) | Matches `3px double` border | | GANDALF | `┌ ┐` (single-line) | Doesn't match — should be `╔ ╗` for modals | **Change required in GANDALF:** ```css .modal::before { content: '╔'; } .modal::after { content: '╗'; } ``` --- ## 8. Toast Position & Animation | Aspect | Tinker Tickets | PULSE | GANDALF | **Target** | |---|---|---|---|---| | Position | `bottom: 1rem; right: 1rem` | `top: 80px; right: 20px` | `bottom: 20px; right: 20px` | `bottom: 1rem; right: 1rem` | | Slide direction | from bottom | from top | from right | from right (`translateX(30px)`) | | Animation duration | `0.3s ease` | `0.3s ease-out` | `0.15s ease` | `0.2s ease-out` | | Auto-dismiss | 3500ms | 3000ms | 3500ms | `3500ms` | | Icon format | `>> ` prefix | `✓/✗/ℹ` prefix (inline style) | `>> ` prefix | `[✓]` `[✗]` `[!]` `[i]` in `.lt-toast-icon` | | Queue system | Yes (serialised) | No (stacks) | No (stacks) | Yes (serialised) | **Change required in PULSE:** Move toast position to `bottom: 20px; right: 20px`. Replace inline-style `showTerminalNotification()` with `lt.toast.*` calls. The icon format in `base.js` uses bracketed symbols: `[✓]`, `[✗]`, `[!]`, `[i]` — matches the terminal aesthetic better than bare unicode symbols. **Change required in GANDALF:** Already close — update animation to `slide-in-right` instead of `slide-in` (which slides from left in GANDALF's current implementation). Replace `showToast()` calls with `lt.toast.*` calls. --- ## 9. Table Cell Borders | App | Approach | |---|---| | Tinker Tickets | `border: 1px solid var(--border-color)` on every `