Adds the falling-glyph "digital rain" effect the operator asked for as a dimmed background on the home hub. - index.html: a decorative full-viewport <canvas id="matrix-rain"> (aria-hidden, pointer-events:none) as the first body child. - home.css: fixes it behind the content (z-index:-1, inset:0) at low opacity (0.16) so the menu tiles stay legible — the "dimmed bg". - home.js: startMatrixRain() drives the classic stepped digital rain. Glyph + fade-trail colours are RESOLVED FROM THE STYLIX PALETTE at runtime (--green glyphs, --bg trail; resolved via a probe element since getComputedStyle returns custom props unresolved), so a theme swap re-colours it rather than hardcoding matrix-green. Stepped via a 55ms interval, paused while the tab is hidden, and skipped entirely under prefers-reduced-motion. CSS/JS only, home page only.
90 lines
2.4 KiB
CSS
90 lines
2.4 KiB
CSS
/* H0M3 — the menu-hub page. Minimal portal styling: a banner
|
|
+ a responsive grid of link tiles. Colours come from theme.css (the
|
|
shared palette); base typography from common.css. When the shared
|
|
page-chrome component lands (a later refactor step) the banner + tile
|
|
styling can fold into it. */
|
|
|
|
body.home-shell {
|
|
/* Full-bleed body; the 1.5em side gutter lives on the inner
|
|
`.page-content` wrapper (common.css) so the server-warnings banner
|
|
spans full width. `padding-bottom` keeps breathing room at the foot. */
|
|
margin: 0;
|
|
padding-bottom: 2em;
|
|
min-height: 100vh;
|
|
}
|
|
|
|
/* Matrix-rain backdrop (driven by home.js). Fixed, full-viewport, dimmed,
|
|
and behind every other element (z-index below the auto-stacked content).
|
|
Decorative only — pointer-events off so it never intercepts clicks. The
|
|
low opacity keeps the menu tiles legible over it; glyph + fade colours
|
|
are themed from the stylix palette in JS. */
|
|
#matrix-rain {
|
|
position: fixed;
|
|
inset: 0;
|
|
width: 100%;
|
|
height: 100%;
|
|
z-index: -1;
|
|
opacity: 0.16;
|
|
pointer-events: none;
|
|
}
|
|
|
|
.home-header {
|
|
text-align: center;
|
|
padding: 1.5em 0 0.5em;
|
|
}
|
|
.home-header .banner {
|
|
font-size: 1.05em;
|
|
}
|
|
|
|
.home-main {
|
|
max-width: 60em;
|
|
margin: 1.5em auto 0;
|
|
}
|
|
|
|
.home-menu {
|
|
display: grid;
|
|
grid-template-columns: repeat(auto-fit, minmax(16em, 1fr));
|
|
gap: 1em;
|
|
}
|
|
|
|
.home-tile {
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: 0.35em;
|
|
padding: 1.1em 1.2em;
|
|
border: 1px solid var(--purple-dim);
|
|
border-radius: 6px;
|
|
background: color-mix(in srgb, var(--bg-elev) 55%, transparent);
|
|
text-decoration: none;
|
|
color: var(--fg);
|
|
transition: color 0.15s ease, background 0.15s ease, border-color 0.15s ease,
|
|
box-shadow 0.15s ease;
|
|
}
|
|
.home-tile:hover {
|
|
border-color: var(--purple);
|
|
background: color-mix(in srgb, var(--purple) 6%, transparent);
|
|
box-shadow: 0 -2px 14px -6px color-mix(in srgb, var(--purple) 50%, transparent);
|
|
}
|
|
|
|
/* Icon + label share the top row of each tile; the description sits
|
|
below. The icon is decorative (aria-hidden) — the label carries the
|
|
accessible name. */
|
|
.home-tile-head {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 0.55em;
|
|
}
|
|
.home-tile-icon {
|
|
font-size: 1.25em;
|
|
line-height: 1;
|
|
flex: none;
|
|
}
|
|
.home-tile-label {
|
|
font-weight: bold;
|
|
letter-spacing: 0.08em;
|
|
color: var(--purple);
|
|
}
|
|
.home-tile-desc {
|
|
font-size: 0.85em;
|
|
color: var(--muted);
|
|
}
|