7 Commits

Author SHA1 Message Date
jared ec92445a0f Force header clearance via inline style on main element
CSS cascade fixes were correct but browser was serving cached base.css.
Inline style cannot be cached separately and bypasses all cascade issues.
CSS variables still respect media query :root overrides so --header-height
resolves to the correct value (50px SM, 46px XS) at each breakpoint.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-01 17:52:22 -04:00
jared 0eab5d40e6 Restore .lt-main.lt-container combined selector — proper cascade fix
The TDS v1.2 sync removed the .lt-main.lt-container combined selector that
was already in the project's base.css. That selector has specificity (0,2,0)
vs single-class (0,1,0), so it always wins over .lt-container padding
shorthand at every breakpoint without needing per-breakpoint overrides.

Also restored flex:1, width:100%, min-width:0 on .lt-main that were dropped.
Removed the incorrect per-breakpoint .lt-main and #main-content hacks added
today which were the wrong approach to the same problem.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-01 17:49:00 -04:00
jared 3cfe46050b Fix header overlap with ID selector — unambiguous highest specificity
Use #main-content (specificity 1,0,0,0) to set padding-top at each breakpoint.
This cannot be overridden by any class-based rule regardless of cascade order,
permanently fixing the fixed header overlapping page content.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-01 17:45:14 -04:00
jared e71f35c041 Fix asset cache-busting — include base.css and base.js in ASSET_VERSION
Previously only dashboard/ticket assets were tracked, so changes to base.css
and base.js were never reflected in the cache-busting version string. Browsers
served stale cached copies, meaning the header padding-top fix never reached
users. Touch base files to bump mtime and force a cache miss immediately.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-01 17:43:18 -04:00
jared 6102985f92 Fix header overlap at all breakpoints — restore lt-main padding-top
Every media query that overrides .lt-container { padding } with a shorthand
was clobbering .lt-main { padding-top } because both selectors have equal
specificity and the container rule came later in the file. Added .lt-main
padding-top restores after each affected breakpoint (LG 1024-1279px, MD
768-1023px, 1920px+). The laptop range (LG) was the likely culprit on desktop.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-01 17:41:33 -04:00
jared e91709798b Fix header overlapping content at mobile breakpoints
In the SM (≤767px) and XS (≤479px) media queries, .lt-container { padding }
shorthand appeared after .lt-main { padding-top } with equal specificity,
causing the shorthand to clobber the header-clearance padding-top. Swap order
so .lt-main always wins.

Also remove redundant lt-scanlines div — body::before in base.css already
renders the scanline overlay globally.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-01 17:19:22 -04:00
jared 4150e1ced3 Fix lt-scanlines header overlap — move class off body to dedicated div
body::before and body::after are used for background grid/gradient effects.
Adding lt-scanlines to body caused ::after conflict (higher specificity) and
put the scanline overlay at z-index 9998, above the header at z-index 300.

Move lt-scanlines to a dedicated fixed div so pseudo-elements don't conflict
and the header remains fully visible.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-01 17:12:07 -04:00
3 changed files with 15 additions and 8 deletions
+10 -4
View File
@@ -350,6 +350,16 @@ hr {
.lt-main { .lt-main {
padding-top: calc(var(--header-height) + var(--space-lg)); padding-top: calc(var(--header-height) + var(--space-lg));
flex: 1;
width: 100%;
min-width: 0;
}
/* When both lt-main and lt-container are on the same element, the lt-container
shorthand `padding` overrides the lt-main `padding-top` in responsive breakpoints
(same cascade specificity, later rule wins). The combined selector has higher
specificity (0,2,0 vs 0,1,0) and always wins regardless of source order. */
.lt-main.lt-container {
padding-top: calc(var(--header-height) + var(--space-lg));
} }
.lt-layout { .lt-layout {
@@ -2042,8 +2052,6 @@ select option:checked {
/* ── SM — phones 480767px ── */ /* ── SM — phones 480767px ── */
@media (max-width: 767px) { @media (max-width: 767px) {
:root { --header-height: 50px; } :root { --header-height: 50px; }
.lt-main { padding-top: calc(50px + var(--space-md)); }
.lt-container { padding: var(--space-md); } .lt-container { padding: var(--space-md); }
.lt-header { padding: 0 var(--space-md); } .lt-header { padding: 0 var(--space-md); }
.lt-brand-subtitle { display: none; } .lt-brand-subtitle { display: none; }
@@ -2142,8 +2150,6 @@ select option:checked {
/* ── XS — tiny phones ≤ 479px ── */ /* ── XS — tiny phones ≤ 479px ── */
@media (max-width: 479px) { @media (max-width: 479px) {
:root { --header-height: 46px; } :root { --header-height: 46px; }
.lt-main { padding-top: calc(46px + var(--space-sm)); }
.lt-container { padding: var(--space-sm); } .lt-container { padding: var(--space-sm); }
.lt-stats-grid { grid-template-columns: 1fr 1fr; gap: var(--space-xs); } .lt-stats-grid { grid-template-columns: 1fr 1fr; gap: var(--space-xs); }
.lt-stat-card { padding: var(--space-xs) var(--space-sm); } .lt-stat-card { padding: var(--space-xs) var(--space-sm); }
+3 -1
View File
@@ -25,13 +25,15 @@ $GLOBALS['config'] = [
'APP_SUBTITLE' => $envVars['APP_SUBTITLE'] ?? 'LotusGuild Infrastructure', 'APP_SUBTITLE' => $envVars['APP_SUBTITLE'] ?? 'LotusGuild Infrastructure',
'APP_VERSION' => $envVars['APP_VERSION'] ?? '1.2', 'APP_VERSION' => $envVars['APP_VERSION'] ?? '1.2',
// Asset cache-busting version — auto-computed from dashboard.js/css mtime so // Asset cache-busting version — auto-computed from key asset mtimes so
// browsers always pick up changes on deploy. Override via ASSET_VERSION in .env. // browsers always pick up changes on deploy. Override via ASSET_VERSION in .env.
'ASSET_VERSION' => (function() use ($envVars) { 'ASSET_VERSION' => (function() use ($envVars) {
if (!empty($envVars['ASSET_VERSION'])) return $envVars['ASSET_VERSION']; if (!empty($envVars['ASSET_VERSION'])) return $envVars['ASSET_VERSION'];
$files = [ $files = [
__DIR__ . '/../assets/css/base.css',
__DIR__ . '/../assets/css/dashboard.css', __DIR__ . '/../assets/css/dashboard.css',
__DIR__ . '/../assets/css/ticket.css', __DIR__ . '/../assets/css/ticket.css',
__DIR__ . '/../assets/js/base.js',
__DIR__ . '/../assets/js/dashboard.js', __DIR__ . '/../assets/js/dashboard.js',
__DIR__ . '/../assets/js/ticket.js', __DIR__ . '/../assets/js/ticket.js',
]; ];
+2 -3
View File
@@ -55,8 +55,7 @@ $_lt_assetVer = $GLOBALS['config']['ASSET_VERSION'] ?? '20260329';
], JSON_UNESCAPED_UNICODE | JSON_HEX_TAG) ?>; ], JSON_UNESCAPED_UNICODE | JSON_HEX_TAG) ?>;
</script> </script>
</head> </head>
<body class="lt-scanlines"> <body>
<!-- SKIP LINK --> <!-- SKIP LINK -->
<a class="lt-skip-link" href="#main-content">Skip to main content</a> <a class="lt-skip-link" href="#main-content">Skip to main content</a>
@@ -182,4 +181,4 @@ $_lt_assetVer = $GLOBALS['config']['ASSET_VERSION'] ?? '20260329';
</header><!-- /.lt-header --> </header><!-- /.lt-header -->
<main class="lt-main lt-container" id="main-content"> <main class="lt-main lt-container" id="main-content" style="padding-top: calc(var(--header-height, 56px) + var(--space-lg, 1.5rem))">