- watch_ticket.php GET now returns watcher list (up to 6 users) for avatar group
- TicketView: watcher avatar group rendered next to WATCH button, refreshes on toggle
- Rewrite renderDependencies/renderDependents to use TDS lt-kv-grid/lt-badge/lt-btn classes
- renderDependencies: show lt-alert--warning blocker banner when blocked_by has open tickets
- Fix ALL hardcoded ?v=20260327 asset version strings in CreateTicketView + all admin views
- base.css: fix .lt-nav-dropdown-menu hardcoded background → var(--bg-overlay)
- base.css: add light-theme overrides for nav dropdown menu (background, links, hover)
- ticket.css: add .lt-avatar-group and .lt-avatar--overflow styles for watcher display
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
P1-A: Fix CSP - add fonts.googleapis.com to style-src, fonts.gstatic.com to font-src
P1-B: CSRF token rotation - add rotateToken() to CsrfMiddleware; bootstrap.php rotates
after successful validation and stores in $GLOBALS['_new_csrf_token']; add
apiRespond() helper to append token to responses; lt.api interceptor in
layout_footer.php auto-updates window.CSRF_TOKEN from responses
P1-C: Styled 403/404 error views with TDS layout instead of raw text; index.php now
uses requireAdmin() helper eliminating 7 duplicated guard blocks (P3-D)
P2-A: Remove duplicate JS-generated keyboard help modal from keyboard-shortcuts.js;
'?' key now routes to static #lt-keys-help modal in footer
P2-B: Asset versioning driven by config ASSET_VERSION key; base.css and base.js get
?v= cache-busting in layout_header.php
P2-C: Add data-theme="dark" to <html> tag to prevent FOUC on light-mode users
P2-E: Escape status value in dashboard.js hover preview class attribute via lt.escHtml()
P2-F: Replace bespoke showLoadingOverlay() with lt-spinner / lt-loading-text from
base.css; add .lt-loading-overlay wrapper CSS to dashboard.css
P2-G: Add keyboard-shortcuts.js to all 7 admin views so J/K nav and ? help work
P3-A: APP_NAME, APP_SUBTITLE, APP_VERSION driven from config.php; layout header/footer
use config values instead of hardcoded strings
P3-G: Replace custom initTableSorting() with lt.sortTable.init() which manages aria-sort
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Full application redesign using Terminal Design System v1.2 (lt-* class
system). Introduces shared layout_header/footer partials, upgrades
base.css/base.js to TDS v1.2, and rewrites all views (Dashboard, Ticket,
CreateTicket, and all 7 admin views) with lt-frame, lt-table, lt-modal,
lt-stats-grid, lt-kv-grid, and data-action event delegation patterns.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Remove collapsible ASCII banner from dashboard (was cluttering the UI)
- Show ASCII banner in the boot overlay on first session visit, above
the boot messages, with a 400ms pause before messages begin
- Add scroll fade indicator (green-tinted gradient edges) to .table-wrapper
so users can see when the table is horizontally scrollable
- Fix null guards for tab switcher in ticket.js (tabEl, activeBtn)
- Fix Reset → RESET uppercase in AuditLogView and UserActivityView
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
CSS fixes:
- Fix [ ] brackets appearing below button text by replacing display:inline-flex
with display:inline-block + white-space:nowrap on .btn — removes cross-browser
flex pseudo-element inconsistency as root cause
- Remove conflicting .btn::before ripple block (position:absolute was overriding
bracket content positioning)
- Remove overflow:hidden from .btn which was clipping bracket content
- Fix body::after duplicate rule causing GPU layer blink (second position:fixed
rule re-created compositor layer, overriding display:none suppression)
- Replace all transition:all with scoped property transitions in dashboard.css,
ticket.css, base.css (prevents full CSS property evaluation on every hover)
- Convert pulse-warning/pulse-critical keyframes from box-shadow to opacity
animation (GPU-composited, eliminates CPU repaints at 60fps)
- Fix mobile *::before/*::after blanket content:none rule — now targets only
decorative frame glyphs, preserving button brackets and status indicators
- Remove --terminal-green-dim override that broke .lt-btn hover backgrounds
JS fixes:
- Fix all lt.lt.toast.* double-prefix instances in dashboard.js
- Add null guard before .appendChild() on bulkAssignUser select
- Replace all remaining emoji with terminal bracket notation (dashboard.js,
ticket.js, markdown.js)
- Migrate all toast.*() shim calls to lt.toast.* across all JS files
View fixes:
- Remove hardcoded [ ] brackets from .btn buttons (CSS now adds them)
- Replace all emoji with terminal bracket notation in all views and admin views
- Add missing CSP nonces to AuditLogView.php and UserActivityView.php script tags
- Bump CSS version strings to ?v=20260319b for cache busting
Security fixes:
- update_ticket.php: add authorization check (non-admins can only edit their own
or assigned tickets)
- add_comment.php: validate and cast ticket_id to integer with 400 response
- clone_ticket.php: fix unconditional session_start(), add ticket ID validation,
add internal ticket access check
- bulk_operation.php: add HTTP 401/403 status codes on auth failures
- upload_attachment.php: fix missing $conn arg in AttachmentModel constructor
- assign_ticket.php: add ticket existence check and permission verification
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
/web_template/ path was being intercepted by the auth proxy at
t.lotusguild.org returning HTML instead of the actual files. Moving
base.js and base.css into /assets/js/ and /assets/css/ where static
assets are already served correctly. Updated all 10 view files and
deploy.sh accordingly.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>