Commit Graph

36 Commits

Author SHA1 Message Date
jared 19d6a2883c docs: add new-app guide and EJS layout skeleton
Lint / JS (eslint) (push) Successful in 13s
README.md:
- Add 'Starting a New App' section with step-by-step instructions:
  nginx alias setup, which skeleton to copy, how to define nav for
  each framework, app.css pattern, lt.init() call
- Update File Structure section: remove app-specific labels from
  framework skeletons (was 'PHP / Tinker Tickets' etc.), add
  layout.ejs to the node/ listing

node/layout.ejs:
- New EJS base layout skeleton matching the PHP/Python equivalents:
  generic nav via navLinks locals, lt-* class names throughout,
  CSP nonce on all script tags, pageStyles/pageScripts arrays,
  CURRENT_USER + CSRF_TOKEN globals injected at runtime

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-18 14:00:01 -04:00
jared 75c57092f8 fix: make layout templates generic — remove app-specific nav and config
Lint / JS (eslint) (push) Successful in 10s
php/layout.php: nav is now data-driven via $navLinks array (supports
  top-level links, dropdowns, adminOnly flag); removed tinker_tickets
  hardcoded nav items; moved APP_CONFIG note to comment
python/base.html: nav driven by nav_links list from context; removed
  gandalf-specific routes (links_page, inspector, suppressions_page);
  removed APP_CONFIG.ticketWebUrl from shared script block; added
  nav_links format documentation in header comment

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-18 13:53:29 -04:00
jared f61705afb8 docs: add Authelia portal integration guide
Lint / JS (eslint) (push) Successful in 12s
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-14 16:30:39 -04:00
jared 140a57a029 docs: add CI lint badge to README
Lint / JS (eslint) (push) Has been cancelled
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-14 16:28:23 -04:00
jared f9445ed5ae ci: add ESLint workflow
Lint / JS (eslint) (push) Has been cancelled
- .gitea/workflows/lint.yml: lint base.js and node/ directory
- .eslintrc.json: browser + node environment, CommonJS
- .gitignore: ignore node_modules/ and .env
- package.json + package-lock.json: eslint@8 dev dependency

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-14 16:25:53 -04:00
jared 044adb3a18 Fix nav dropdown dismissing when cursor moves into menu
top:calc(100%+4px) left a 4px dead zone between the trigger and
menu that broke :hover continuity. Changed to top:100% with
padding-top:6px + margin-top:-2px so the hoverable area is
contiguous. Updated ::before decorative line to top:6px to match.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-12 00:43:33 -04:00
jared 842190d225 fix: light theme override for lt-nav-dropdown-menu
Menu had hardcoded dark background (rgba(6,12,20,0.98)) with no light
theme rule, leaving it black regardless of theme toggle.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-04 11:59:57 -04:00
jared a807944b50 feat: implement RECOMMENDED_ADDITIONS — cursor, scanlines, radar, display-field, VT323
- --font-crt: 'VT323' token added to :root; VT323 added to Google Fonts link
- .lt-cursor / .lt-cursor--cyan/orange/red — blinking block cursor via CSS ::after
- .lt-scanlines — opt-in CRT horizontal scanline overlay on body/container (light-mode suppressed)
- .lt-radar / --sm / --lg / --green — radar sweep loading indicator as lt-spinner alternative
- .lt-display-field — readable non-editable field variant (distinct from :disabled opacity:0.45)
- base.html demos: radar variants in loading row, display-field in forms, cursor+VT323 in tags section

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-01 16:50:46 -04:00
jared 1b7e57d9f5 Add gotchas section: disabled/readonly display patterns
Documents the opacity:0.45 behavior on :disabled and [readonly] elements
and the correct workarounds for display-only contexts (edit-mode toggle
selects, copy inputs, pre-wrap description areas).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-31 19:43:49 -04:00
jared 083a918729 docs: add LDAP avatar integration guide to README
Documents the lldap service account setup, avatar endpoint pattern,
CSS photo-over-initials approach, and HTML template used in tinker_tickets.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-28 21:04:57 -04:00
jared de30ff13e6 fix: add in-memory _bootFired flag to runBoot as primary dedup guard
sessionStorage alone could be bypassed in hash-URL edge cases. A module-scoped
_bootFired flag blocks any second runBoot call within the same JS context
regardless of sessionStorage state, then sessionStorage handles cross-reload
suppression. Also restores boot call in private init() to preserve original
dual-path structure.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-27 14:52:31 -04:00
jared 32f7b49f98 fix: remove boot call from private init() to prevent hash-URL double-boot
Private init() and lt.init() both called runBoot(), creating two code paths.
With base.html# URLs the sessionStorage guard could be bypassed causing every
boot line to appear twice. Boot is now exclusively triggered by lt.init() or
lt.boot.run(), which already has its own _ltInitialized guard.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-27 14:46:34 -04:00
jared 80011e6de5 docs: update README for LotusGuild Terminal Design System v1.2
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-27 14:32:58 -04:00
jared d651cfbe2c audit pass 15: type=button on JS createElement and innerHTML buttons
- Toast close button: set closeEl.type = 'button' on createElement
- Combobox tag remove button: add type="button" to innerHTML string

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-27 14:24:10 -04:00
jared bdf3ad085f audit pass 14: type=button on JS-generated button HTML strings
Add type="button" to all buttons created via innerHTML in JS:
- Lightbox close/prev/next buttons (3 instances)
- Pagination prev/page/ellipsis/next buttons (7 instances)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-27 14:22:11 -04:00
jared 5caaf38e9a audit pass 13: context menu arrow key navigation
Add ArrowUp/ArrowDown/Home/End keyboard navigation between context
menu items per WAI-ARIA menu widget specification. Focus wraps at
top and bottom boundaries.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-27 14:18:17 -04:00
jared 7630da8abd fix: boot sequence lines appearing twice
Two init paths both called runBoot() before sessionStorage was set
(the key was only written on completion, ~1.1s later):
- Private init() at DOMContentLoaded → runBoot()
- lt.init() HTML call on DOMContentLoaded → ltInit() → runBoot()

Both found no session key and started simultaneous setInterval loops
on the same <pre>, each appending the same message → every line twice.

Fix: set the sessionStorage key immediately at the start of runBoot()
so any concurrent second call exits early.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-27 14:12:05 -04:00
jared 45b968b77d audit pass 12: type=button, focus restore, :focus-visible on links
HTML:
- Add type="button" to all remaining buttons (nav drawer close, menu
  btn, theme toggle, notif bell, right drawer close, tab buttons,
  sidebar toggle, alert close x4, code copy, tab bar buttons x4,
  detail panel open, modal close x2, keyboard shortcuts close)
- Add aria-label="Search commands" to command palette input
- Notification panel close(true): restore focus to bell on Escape
- Generic dropdowns: add Escape key handler with trigger focus restore

CSS:
- Add a:focus-visible global focus ring
- Add .lt-nav-dropdown-menu li a:focus-visible
- Add .lt-markdown a:focus-visible
- Fix dead .lt-typeahead-option selector → .lt-typeahead-item with
  :hover, .is-focused, :focus-visible for light theme

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-27 13:49:23 -04:00
jared ca2d6d225e audit pass 10-11: type=button, XSS escaping, focus/ARIA fixes
HTML:
- Add type="button" to all buttons outside forms (22 instances)
- Add aria-label="Add comment" to unlabelled textarea#td-comment

JS:
- Escape alt text and link text in markdown renderer with escHtml()
  to prevent XSS in image alt/link content
- Fix nested modal focus: only restore trigger focus when no other
  modal is still open; add document.contains guard

CSS:
- Add .lt-nav-link:focus-visible focus ring (was missing entirely)
- Fix .lt-typeahead-option (dead selector) → .lt-typeahead-item with
  :hover, .is-focused, and :focus-visible for light theme

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-26 20:46:31 -04:00
jared 8b54efef61 audit pass 9: XSS fix, focus management, ARIA labels, and :focus-visible gaps
JS:
- Lightbox: remove keydown listener on close (memory leak fix)
- Lightbox: restore focus to trigger on close
- Right drawer: fix aria-hidden="false" anti-pattern to removeAttribute
- Markdown renderer: block javascript:/data: protocol URIs in link and
  image replacements to prevent XSS
- Sidebar submenus: add aria-expanded tracking on toggle; hide decorative
  chevron from screen readers; initialize aria-expanded on mount

CSS:
- Add :focus-visible to .lt-sidebar-toggle (interactive button)
- Add :focus-visible to .lt-dropzone (focusable container)
- Fix .lt-stat-card:focus-visible outline-offset to -2px (clip-path clips it)
- Add light theme override for .lt-nav-drawer-link:focus-visible
- Adjust .lt-split-divider:focus-visible outline-offset to 3px

HTML:
- Range input: update aria-valuenow dynamically on input event
- Combobox label: add for="demo-combobox-input" association
- Typeahead label: add for="demo-typeahead-input" association
- Dropzone file input: add aria-label
- Notification items: add descriptive aria-label to all 4 items;
  add aria-hidden="true" to decorative dot spans
- Mark all read button: add type="button" to prevent accidental form submit

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-26 20:16:12 -04:00
jared e8c1197613 audit pass 8: keyboard accessibility and table semantics
CSS:
- Fix light theme input/select/textarea :focus -> :focus-visible

HTML:
- Worker metrics table: convert label <td> to <th scope="row"> for screen readers
- Add aria-label to worker metrics table
- Sticky table: add scope="col" to all column headers
- Keyboard shortcuts modal table: add scope="col" to headers
- Kanban cards: remove tabindex="0" from role="article" (non-interactive)
- Advanced filter: ensure all 3 label/select pairs have for/id associations

JS:
- Lightbox: fix keydown listener leak by storing bound reference for removeEventListener
- Lightbox: save/restore trigger focus on open/close
- Sortable table: add tabindex="0" and Enter/Space keydown handler on sortable <th>
- Split pane: add tabindex="0", role="separator", aria-label, and arrow/Home/End
  keyboard resize support on divider (5% steps)
- Form validation: handle <select multiple> required check via selectedOptions.length

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-26 20:09:29 -04:00
jared b84d71dd7a audit pass 7: ARIA, focus management, and label fixes
CSS:
- Add :focus-visible to sortable th, breadcrumb links, list links, cmd-item,
  combobox-option, typeahead-item, sidebar-sub-link, split-divider, stat-card
- Fix .lt-skip-link:focus to also include :focus-visible for spec compliance

JS:
- Mobile nav: add focus trap (_trapFocus), save/restore trigger focus, fix
  aria-hidden="false" to removeAttribute pattern, add document.contains guard
- Combobox: add aria-activedescendant on _moveFocus; add unique IDs to options;
  clear aria-activedescendant on close; wrap querySelectorAll in Array.from
- Typeahead: add aria-activedescendant on _moveFocus; add unique IDs to items;
  add aria-busy during async search; clear aria-activedescendant on select;
  wrap querySelectorAll in Array.from
- Command palette: add unique IDs to items; set/clear aria-activedescendant
  on move and mouseenter; clear on close
- Lightbox: add document.contains guard on focus setTimeout
- Stats filter: add Enter/Space keyboard handler for role="button" cards

HTML:
- Stat cards: add role="button" tabindex="0" aria-label (interactive divs)
- Advanced filter selects: add id/for associations to all 3 label+select pairs
- Accordion SVG icons: add aria-hidden="true" (decorative)
- Range input: add aria-label, aria-valuemin/max/now
- Wizard form controls: add id/for to all 4 label+input/select pairs

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-26 20:02:15 -04:00
jared d08007cdd7 audit pass 6: accessibility, ARIA, and keyboard fixes
- JS: fix checkbox/radio required validation using .checked not .value
- JS: guard _cpTrigger.focus() with document.contains() check
- JS: add arrow/Home/End key navigation to tab groups (WCAG 2.1)
- JS: clamp context menu left edge with Math.max(8, ...) to prevent off-screen
- JS: fix wizard _show() to removeAttribute aria-hidden on active step
- HTML: add role="region" + aria-label to notification panel
- HTML: convert Assigned To span+div to label+select with for/id association
- HTML: add role="article" tabindex="0" aria-label to all kanban cards
- HTML: remove aria-hidden="false" anti-pattern from wizard active step
- CSS/HTML/JS: replace aria-hidden="false" show-hook with :not([aria-hidden])
  so open state is represented by absent attribute rather than false value

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-26 19:51:21 -04:00
jared fdcadad23b fix: accessibility & quality audit pass 4+5
CSS:
- Add :active/:focus-visible to .lt-modal-close, .lt-drawer-right-close,
  .lt-notif-panel-clear, .lt-file-item-remove
- Add :focus-visible to .lt-accordion-header, .lt-tag-remove,
  .lt-combobox-tag-remove
- Add .lt-cmd-input-wrap:focus-within focus indicator (outline:none compensation)
- Add will-change: stroke-dashoffset to .lt-gauge-fill
- Add range slider :focus-visible thumb ring
- Fix .tok-cmt hardcoded #5c8c6a → var(--color-tok-cmt) w/ light-mode override
- Add .lt-skip-link component (visible on focus)
- Fix .lt-filter-group fieldset UA border reset

JS:
- Fix infinite scroll: store throttled handler ref so removeEventListener works
- Fix right drawer: remove close-button listeners in _rdClose (were never removed)
- Fix right drawer: add Tab focus trap (matches modal behaviour)
- Fix _cmdPaletteClose: restore focus to element that opened the palette
- Fix initSortTable: set aria-sort="ascending"/"descending"/"none" on th elements
- Fix switchTab: set aria-selected="true"/"false" on .lt-tab[data-tab] buttons
- Fix copy button timeout: guard with document.contains() before DOM mutation
- Fix combobox: add role=combobox, aria-expanded, aria-controls, role=listbox;
  toggle aria-expanded on open/close

HTML:
- Add skip nav link + id="main-content" on <main>
- Primary tab nav: add role=tablist, role=tab, aria-selected, aria-controls,
  id attrs; tab panels get role=tabpanel + aria-labelledby
- Tab bar demo: same ARIA wiring + aria-controls + role/labelledby on panels
- Sidebar filters: convert div+span to fieldset+legend for proper grouping
- Table sort headers: add aria-sort="none" (JS updates on click)
- Accordion: add aria-controls on headers, IDs on bodies
- Wizard: add aria-current="step" on active step indicator
- Table th: scope="col" on all column headers
- Row checkboxes: aria-label per ticket ID
- Worker metrics table: add <tbody>
- Progress bars: role=progressbar + aria-valuenow/min/max + aria-label
- Export + keyboard shortcuts modals: role=dialog, aria-modal, aria-labelledby

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-26 18:22:53 -04:00
jared 8585993602 merge: v1.1 feature branch → main
Merges all v1.1 work:
- 26 new components (theme toggle, right drawer, context menu, combobox,
  typeahead, split pane, wizard, sortable, lightbox, infinite scroll,
  countdown/stopwatch, markdown, auth, WebSocket, offline banner,
  avatar, timeline, skeleton variants, empty state, notification badge,
  chart containers, sidebar submenus, cookie utils, toast progress)
- Full mobile/responsive audit (50+ fixes, 8-breakpoint system)
- Complete light mode rebuild (professional, all components covered)
- lt.init() master initializer
- Bug fixes: duplicate function decls, clipboard crash, toast infinite
  recursion, kanban drag-and-drop, pagination module, notification
  dropdown, bulk actions dropdown, ticket detail editable form
- Cross-tab theme sync, color-scheme meta, WCAG table caption

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-26 00:12:24 -04:00
jared d5dc96178f feat: final production polish — light mode rebuild, lt.init(), cross-tab theme
Light mode — complete rebuild (section 51):
- Full token override for every surface, component, and state
- Desaturated accents: orange #c44e00, cyan #0062b8, green #006d35 etc.
- Glows replaced with subtle drop-shadow rings (no neon on white)
- Covers: toasts, modals, dropdowns, notification panel, context menu,
  right drawer, combobox, typeahead, wizard, timeline, pagination, tabs,
  badges, tables, code blocks, skeleton, avatar, sortable, markdown,
  scrollbars, buttons, nav drawer, WS status — nothing missed
- Dot-grid: neutral gray (was incorrect blue tint)
- Toast background uses var(--bg-overlay) instead of hardcoded dark rgba

Theme system improvements:
- _applyTheme now sets document.documentElement.style.colorScheme
- theme-color meta tag syncs on toggle (browser chrome follows theme)
- Cross-tab sync via storage event (toggle in one tab updates others)

lt.init() master initializer:
- Single call wires accordion, tooltip, alerts, clipboard, sidebar,
  submenus, and boot sequence
- Replaces 6+ individual .init() calls in user code
- demo HTML updated to use lt.init({ bootName: 'MY APP' })

Accessibility:
- Ticket table: add <caption class="lt-sr-only"> for WCAG compliance
- Table gets aria-label attribute

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-26 00:12:04 -04:00
jared 1d8d274fdd feat: comprehensive mobile/responsive audit fixes
Touch targets:
- All .lt-btn-sm, .lt-menu-btn, .lt-page-btn, .lt-dropdown-trigger,
  .lt-notif-bell-btn now 44px minimum on pointer:coarse devices

Font size floors:
- Nothing below 0.72rem on XS; nav drawer, cmd palette, stats, timeline,
  dropdown items, notification timestamps all bumped to readable sizes

Notification panel:
- width: min(300px,92vw) prevents overflow on 320px screens
- max-height: min(280px,calc(80vh-110px)) for landscape safety
- title: 2-line clamp instead of single-line truncate
- Header/time font sizes increased to 0.75rem/0.7rem

Dropdown panels:
- Advanced filter: clamp(200px,60vw,260px) instead of fixed 240px
- All dropdowns: max-width:90vw + proper alignment on SM/XS
- Dropdown items: 0.78-0.8rem, 36px min-height

Toolbar:
- toolbar-left/right now flex-wrap on SM+XS; search expands full-width
- Result count hidden on XS (.lt-hide-xs) to uncramp narrow toolbars

Drawer:
- Right drawer goes full-width (100vw) on SM with border-top
- Status/Priority 2-col form grid collapses to 1-col (.lt-drawer-form-grid)

Table card mode:
- Breakpoint corrected from rogue 640px → 767px (system breakpoint)
- Row min-height 36px, font bumped to 0.78rem

Kanban:
- Keeps 2-col at SM and XS (was collapsing to 1-col, confusing semantics)

Grids:
- Chart demo, sortable demo: auto-fit minmax so they reflow naturally
- Countdown stat grid: auto-fit minmax(160px,1fr) instead of fixed 3-col
- Grid gap reduced to var(--space-sm) at XS

Split pane:
- Demo height: clamp(160px,30vh,240px) instead of fixed 200px
- Stacks vertically on SM with horizontal divider

Modals:
- max-width: 640px cap prevents 4K-wide modals; overridden on SM/XS

Header:
- Brand title truncated at max-width:110px on XS
- WS status indicator hidden on XS to free header space
- Admin badge hidden on XS
- Safe-area insets applied to header-right and toast container

Landscape phone:
- Modal max-height respects viewport; notif list shrinks

Breakpoint consistency:
- Removed rogue 640px breakpoint; all queries use 479/767/1023/1279px system

Section 78 added with all targeted overrides.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-25 23:51:21 -04:00
jared 6ee9760168 fix: toast crash, notification dropdown, ticket detail editable, toolbar dropdowns
- Fix duplicate function showToast declaration causing infinite recursion
  (showToast declared twice → function hoisting → _origShowToast === self)
  Progress bar now inlined directly into _displayToast; Module 47 removed
- Notification bell now opens a proper dropdown panel with unread items,
  per-item click-to-read, "Mark all read", close on outside click/Esc
- Ticket detail drawer now has real editable fields (title, status,
  priority, assignee, description textarea, comment box) instead of
  read-only KV pairs; Save Changes and Post Comment buttons functional
- Advanced ▾ filter dropdown: status/priority/assignee selects + Apply/Reset
- Bulk Actions dropdown: Close/Reassign/Export/Delete with toast feedback
- Generic .lt-dropdown-trigger toggle system (works for any future dropdown)
- Add CSS sections 76 (notification panel) and 77 (dropdown widget + .lt-textarea)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-25 23:36:29 -04:00
jared 3847513594 fix: resolve DOMContentLoaded crash + wire kanban/pagination
- Fix lt.clipboard.init() → initCopyButtons() (crashed init handler
  before context menu, split pane, lightbox, theme btn could register)
- Add lt.pagination module (Module 55) with ellipsis rendering,
  prev/next, onChange callback; wire demo-pagination nav
- Upgrade lt.sortable for cross-list group dragging (shared module-level
  drag state enables kanban card movement between columns)
- Wire kanban columns (open/pending/inprogress/closed) to lt.sortable
  with group:'kanban' for drag-and-drop between columns

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-25 23:19:49 -04:00
jared 0c2e136cae Fix: resolve JS SyntaxErrors that crashed entire window.lt namespace
Root cause: two SyntaxErrors prevented the IIFE from completing,
meaning window.lt was never created and all features were broken.

Fixes applied:
1. CRITICAL: Renamed auth's apiFetch redeclaration → _apiFetchAuth
   (duplicate function declaration in strict-mode IIFE = SyntaxError)
2. CRITICAL: Renamed toast queue vars (_toastQueue/_toastActive already
   declared by original showToast in outer scope = SyntaxError)
   Replaced heavy queue wrapper with lightweight progress-bar injector
3. timer.countdown: classList.add(urgentClass) throws on space-separated
   class string — split/filter/forEach now used
4. contextMenu: _ctxItems declared as [] but used as string-keyed object
   — changed to {}
5. Split pane divider: background was border-dim (7% opacity, invisible)
   — raised to border-color (16%), added ::before hit-area expansion,
   hover state uses accent-cyan for clear visual feedback
6. Light theme: html background-image was hardcoded cyan rgba, didn't
   update with data-theme — added explicit html[data-theme="light"] rule
7. Light theme: .lt-header background was hardcoded rgba(3,5,8,0.96)
   — added explicit light-mode override

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-25 23:04:24 -04:00
jared 6ad4cb2354 v1.1: Complete remaining 8 feature modules + 7 CSS component sections
JS modules added:
- lt.sidebarSubmenus — nested nav groups with expand/collapse, auto-opens active
- lt.infiniteScroll  — IntersectionObserver-based (scroll fallback), loading indicator
- lt.wizard          — multi-step form with indicators, validation hook, getData()
- lt.sortable        — HTML5 drag-to-reorder lists with placeholder ghost + bus event
- lt.timer           — countdown (urgent threshold + onExpire) + stopwatch (pause/reset)
- lt.lightbox        — full-screen image viewer, prev/next, ESC, caption, loop
- lt.auth            — JWT token management: setToken, refresh (auto + manual),
                       401 retry, onExpire hook, patches lt.api with Bearer header
- lt.markdown        — micro-renderer (no deps); auto-delegates to window.marked /
                       markdownit if present; renders headings/bold/italic/code/
                       links/lists/blockquotes/tables/HR

CSS sections added (69–75):
- Infinite scroll sentinel + loading indicator
- Wizard step indicators (connectors, active/complete/error states, nav footer)
- Sortable item dragging + placeholder ghost
- Countdown/timer display + urgency blink animation
- Image lightbox overlay (close/prev/next controls, caption, counter)
- Sidebar submenu groups (chevron, expand/collapse, active sub-link)
- Markdown output styling (.lt-markdown — all block elements themed)

HTML demos for all 8 new components added and wired

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-25 22:42:16 -04:00
jared 0eb91f1937 v1.1: Add 10 new feature modules + 18 CSS component sections
JS modules added:
- lt.theme    — dark/light toggle, OS preference sync, localStorage persist
- lt.notif    — notification badge (set/inc/clear) on any element
- lt.rightDrawer — right-side detail panel with focus trap + return focus
- lt.contextMenu — right-click custom menu, keyboard nav, danger variant
- lt.offline  — navigator.onLine banner + event hooks
- lt.ws       — WebSocket manager with exponential backoff reconnect
- lt.combobox — multi-select with search, tag chips, keyboard nav
- lt.typeahead — async/sync autocomplete with match highlighting
- lt.cookie   — get/set/del with SameSite/Secure helpers
- lt.splitPane — pointer-events resizable split pane (horizontal/vertical)
- Toast queue: max-stack, progress bar drain animation, auto-drain

CSS sections added (51–68):
- Light theme (html[data-theme="light"]) with full variable overrides
- Theme toggle button (.lt-theme-btn)
- Skeleton loader variants (card, row, text, title, avatar, btn, badge)
- Empty state component (.lt-empty-state, --sm variant)
- Nav notification badge (.lt-notif-wrap / .lt-notif-badge)
- Right-side drawer (.lt-drawer-right + overlay)
- Sticky table header (.lt-table-sticky-wrap)
- Multi-select combobox (.lt-combobox, tags, dropdown)
- Context menu (.lt-context-menu, divider, label, danger)
- Offline banner (.lt-offline-banner)
- Timeline / activity feed (.lt-timeline, color variants)
- Avatar + avatar group + status ring (.lt-avatar)
- Split pane (.lt-split, .lt-split-divider with pointer drag)
- Chart container (.lt-chart-wrap, legend, axis, loading state)
- Toast queue stack + progress drain bar
- Autocomplete / typeahead (.lt-typeahead-dropdown, match highlight)
- WebSocket status indicator (.lt-ws-status, data-state variants)
- Print enhancements (extended @media print rules)

HTML demo sections for all new components added to base.html

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-25 22:29:55 -04:00
jared db67f0c92b v1.2 → v1.3: responsive overhaul, mobile nav, accessibility & bug fixes
- 8-breakpoint responsive system (xs→4k) replacing 3-breakpoint stub
- Off-canvas mobile nav drawer with swipe gestures and focus trap
- iOS-safe scroll lock for modals (position:fixed pattern + ref count)
- Modal focus trap with Tab cycling and return-focus to trigger
- Z-index stack overhaul: modal > nav drawer, toast above scanlines
- Fixed --border-dim CSS variable undefined across all v1.2 components
- Fixed badge absolute positioning clipping in Component Reference
- Fixed accordion CSS class mismatch (open → is-open)
- Fixed command palette selector/class mismatches
- Select dark mode: color-scheme:dark + option background
- 4K scaling: rem-based overrides for all hardcoded px elements
- Safe area insets for iPhone notch/home bar (viewport-fit:cover)
- Touch targets: 44px min on all interactive elements (pointer:coarse)
- Disabled glitch/pulse animations on coarse/hover:none devices
- Table responsive card mode with data-label attributes
- viewport.is() validation, debounce caching, 350ms orientation debounce
- initMobileNav() guard prevents duplicate listener registration
- cmd palette: input.select() on open, consistent scroll lock

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-25 18:47:26 -04:00
jared d7eb20cb3c Remove aesthetic_diff.md — convergence complete across all three apps
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-14 21:49:18 -04:00
jared 997450aaf1 Fix boot sequence alignment, rate limiter memory leak, and docs gaps
- base.js: Fix boot sequence title centering — old formula was off by 1
  char for odd-length app names (PULSE, GANDALF). Remove unused `bar`
  variable. New logic computes left/right padding independently to
  handle both even and odd title lengths correctly.
- node/middleware.js: Prune expired rate-limit entries from Map when
  size exceeds 5000 to prevent unbounded memory growth. Also use
  req.socket?.remoteAddress as fallback for req.ip.
- README.md: Document lt.beep() in the JS API section. Clarify Quick
  Start to distinguish core files from platform-specific helpers.
  Note that tableNav.init() and sortTable.init() require explicit calls.
- aesthetic_diff.md: Correct §8 toast icon format — base.js uses
  bracketed symbols [✓][✗][!][i], not >> prefix as previously stated.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-14 21:27:31 -04:00
jared 66538f9ad8 Initial commit: LotusGuild Terminal Design System v1.0
Unified CSS, JavaScript utilities, HTML template, and framework skeleton
files for Tinker Tickets (PHP), PULSE (Node.js), and GANDALF (Flask).

Includes aesthetic_diff.md documenting every divergence between the three
apps with prioritised recommendations for convergence.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-14 21:08:57 -04:00