SectionBanner.astro (2454B)
1 --- 2 import SignalField from './SignalField.astro'; 3 4 interface Stat { 5 label: string; 6 value: string | number; 7 /** Paint the value in the banner's accent — one per banner, the number 8 * worth reading first. */ 9 accent?: boolean; 10 } 11 12 interface Props { 13 /** Mono lockup before the rule, e.g. `03 ^: ACTIVE DIRECTORY`. */ 14 n: string; 15 label: string; 16 title: string; 17 blurb?: string; 18 stats?: Stat[]; 19 accent?: 'iris' | 'foam' | 'love' | 'gold' | 'rose' | 'pine'; 20 } 21 const { n, label, title, blurb, stats = [], accent = 'foam' } = Astro.props; 22 23 --- 24 <header class="banner plate bleed signal-hero" style={`--acc: var(--${accent});`}> 25 <SignalField /> 26 <span class="banner__scrim" aria-hidden="true"></span> 27 <span class="grain grain--local" aria-hidden="true"></span> 28 <!-- CRT film over the signal field — the body row is already z-index 2, 29 so the type stays above the scanlines. --> 30 <span class="scanlines" aria-hidden="true"></span> 31 32 <div class="wrap banner__body"> 33 <div> 34 <p class="eyebrow" style={`--acc: var(--${accent});`}> 35 <span class="eyebrow__n">{n}</span> 36 <span class="eyebrow__mark">^:</span> 37 <span>{label}</span> 38 <span class="eyebrow__rule" aria-hidden="true"></span> 39 </p> 40 <h1 class="banner__title" data-unscramble={title}>{title}</h1> 41 {blurb && <p class="banner__blurb">{blurb}</p>} 42 </div> 43 44 {stats.length > 0 && ( 45 <dl class="banner__ledger"> 46 {stats.map((s) => ( 47 <div class={`banner__row${s.accent ? ' banner__row--acc' : ''}`}> 48 <dt>{s.label}</dt> 49 <dd><b>{s.value}</b></dd> 50 </div> 51 ))} 52 </dl> 53 )} 54 </div> 55 </header> 56 57 <style> 58 /* ---- Cyberdeck chrome for the banner ----------------------------------- 59 Hairline frame + CRT film over the dark plate. The plate pins the night 60 palette (`.plate`), so `--rule`/`--rule-hi` below resolve to the night 61 hairlines in both modes — the frame belongs to the plate, not the page. */ 62 .banner { border-top: 1px solid var(--rule); } 63 /* Kept faint: the signal field and the grain already texture the plate, 64 and the title has to win every layer stack it sits in. */ 65 .banner > .scanlines { opacity: 0.45; } 66 /* The ledger is terminal furniture — JetBrains Mono, same as the segbar. */ 67 .banner__ledger { 68 font-family: var(--font-term, 'JetBrains Mono', 'IBM Plex Mono', ui-monospace, monospace); 69 } 70 </style>