stage-31 polish: featured hero — full-bleed animated grid cycling colors

The hero is now layered:
  base   — radial accent + dark gradient (truly full-width, min 240px /
           up to 320px tall, no aspect-ratio cap)
  grid   — full-bleed CSS grid (38px cells), line color cycles through
           cyan → red → gold → green → violet over 18s, plus a slow
           grid-drift so the lattice subtly slides; a glowing column
           sweeps left-to-right across the hero every 12s for depth
  particles — the existing case-specific SVG sits on top at lower
           opacity (mix-blend-mode: screen) so the per-case identity
           is preserved as a constellation glittering over the grid
  overlay — title + Open-case CTA pinned to the bottom

Severity just nudges the grid opacity (CRITICAL/HIGH get a bit denser);
the color cycle stays on for all severities. Honors prefers-reduced-motion.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
m17hr1l
2026-05-25 19:32:27 +02:00
parent 3f1f7cc420
commit 977c3670f3
2 changed files with 63 additions and 6 deletions

View File

@@ -881,8 +881,62 @@ body.wide .net-grid { grid-template-columns: repeat(auto-fill, minmax(320px, 1fr
.featured:hover { transform: translateY(-1px); box-shadow: 0 10px 36px rgba(30,200,255,0.18); } .featured:hover { transform: translateY(-1px); box-shadow: 0 10px 36px rgba(30,200,255,0.18); }
.featured-link { display: block; color: inherit; text-decoration: none; position: relative; } .featured-link { display: block; color: inherit; text-decoration: none; position: relative; }
.featured-link:hover { text-decoration: none; } .featured-link:hover { text-decoration: none; }
.featured-hero { position: relative; aspect-ratio: 880 / 220; max-height: 240px; overflow: hidden; } .featured-hero {
.featured-hero svg { width: 100%; height: 100%; display: block; } position: relative; width: 100%;
min-height: 240px; height: clamp(220px, 28vw, 320px);
overflow: hidden;
background:
radial-gradient(900px 480px at 80% 50%, rgba(30,200,255,0.20), transparent 65%),
linear-gradient(180deg, #0f1115, #1c2230);
}
.featured-hero > * { position: absolute; inset: 0; }
/* Animated full-bleed grid — line color cycles through severity-ish hues. */
.featured-grid {
color: var(--accent);
background-image:
linear-gradient(currentColor 1px, transparent 1px),
linear-gradient(90deg, currentColor 1px, transparent 1px);
background-size: 38px 38px;
background-position: -1px -1px;
opacity: 0.22;
animation: hero-hue-cycle 18s ease-in-out infinite, hero-grid-drift 22s linear infinite;
will-change: color, background-position;
}
.featured-grid::after {
/* a soft glowing column that sweeps across the hero */
content: ""; position: absolute; inset: 0;
background: radial-gradient(220px 100% at 0% 50%, currentColor 0%, transparent 65%);
opacity: 0.55; mix-blend-mode: screen;
animation: hero-sweep 12s ease-in-out infinite alternate;
}
@keyframes hero-hue-cycle {
0%, 100% { color: #1ec8ff; } /* cyan */
18% { color: #f87171; } /* red */
36% { color: #fbbf24; } /* gold */
54% { color: #4ade80; } /* green */
72% { color: #a78bfa; } /* violet */
}
@keyframes hero-grid-drift {
from { background-position: -1px -1px; }
to { background-position: 37px 37px; }
}
@keyframes hero-sweep {
0% { transform: translateX(-20%); }
100% { transform: translateX(120%); }
}
/* case-specific particles layered on top of the grid */
.featured-particles { opacity: 0.55; mix-blend-mode: screen; pointer-events: none; }
.featured-particles svg { width: 100%; height: 100%; display: block; }
/* Severity nudges the cycle's intensity but doesn't stop the cycle. */
.featured.sev-critical .featured-grid { opacity: 0.30; }
.featured.sev-high .featured-grid { opacity: 0.28; }
@media (prefers-reduced-motion: reduce) {
.featured-grid, .featured-grid::after { animation: none; }
}
.featured-overlay { .featured-overlay {
position: absolute; left: 0; right: 0; bottom: 0; position: absolute; left: 0; right: 0; bottom: 0;
padding: 18px 22px 18px; padding: 18px 22px 18px;

View File

@@ -52,10 +52,13 @@
</div> </div>
</header> </header>
<a class="featured sev-{{ featured.classification.severity.value }}" href="/cases/{{ featured.case_id }}"> <a class="featured sev-{{ featured.classification.severity.value }}" href="/cases/{{ featured.case_id }}">
<div class="featured-hero">{{ featured_hero|safe }}</div> <div class="featured-hero">
<div class="featured-overlay"> <div class="featured-grid" aria-hidden="true"></div>
<h3 class="featured-title">{{ featured.summary }}</h3> <div class="featured-particles" aria-hidden="true">{{ featured_hero|safe }}</div>
<div class="featured-cta">Open case <span class="featured-arrow"></span></div> <div class="featured-overlay">
<h3 class="featured-title">{{ featured.summary }}</h3>
<div class="featured-cta">Open case <span class="featured-arrow"></span></div>
</div>
</div> </div>
</a> </a>
</section> </section>