1/** 2 * divider_halo.js â DOM measurement + brand color lerp for the 3 * sky-shader wordmark halo. (File name is historical: it originally 4 * also tracked the .hero-divider bar, removed along with the Coming 5 * Soon badge.) 6 * 7 * Each frame, reads .hero-wordmark's bounding rect (in CSS pixels), 8 * converts to gl_FragCoord-space (bottom-left origin, devicePixelRatio 9 * scaled), and publishes the halo state to window._wordmarkHaloState 10 * for SKY_FS to consume. 11 * 12 * Why this lives in the sky shader instead of CSS: 13 * The CSS radial-gradient that previously painted the glow had no 14 * dither â at 8-bit RGB, a smooth goldâtransparent radial falloff 15 * produces visible concentric bands. SKY_FS already applies TPDF 16 * dither at ±1/255 amplitude on every fragment, so anything composited 17 * into the sky color before that pass gets free band suppression. The 18 * CSS ::after rule is gone; this is the single source of truth. 19 * 20 * Color: the existing brand pair (gold #F2A900 / slate #1e3a5f), lerped 21 * by --day-mix via brand_mix.js. We read --day-mix directly from 22 * documentElement rather than re-deriving it from zenithLum, so the 23 * halo color tracks the wordmark color exactly. (If the wordmark 24 * crossfade rule ever changes, we don't have to re-implement it here.) 25 * 26 */ 27(function () { 28 'use strict'; 29 30 // sRGB-linear of the brand pair (computed once; matches the CSS hex 31 // values). The shader does its own dither in sRGB, so we hand it sRGB 32 // values too â interpolation between similar-saturation warm/cool 33 // pairs in sRGB is acceptable here since the halo strength is low and 34 // the difference vs oklab interp is sub-perceptual at peak intensity 35 // ~0.1. 36 var GOLD_R = 0xF2 / 255; 37 var GOLD_G = 0xA9 / 255; 38 var GOLD_B = 0x00 / 255; 39 var SLATE_R = 0x1e / 255; 40 var SLATE_G = 0x3a / 255; 41 var SLATE_B = 0x5f / 255; 42 43 // Peak intensity. The wordmark is a large area, so a low intensity 44 // keeps the halo ambient rather than washing the surrounding sky into 45 // a gold haze. 46 var WORDMARK_STRENGTH = 0.12; 47 48 // Wordmark footprint multipliers applied to the measured rect. 49 // The half-radius is text_dim à factor; the smoothstep(0, 0.75) 50 // falloff means the halo "bright zone" (where contribution > 50% 51 // of peak) extends to ~37.5% of half-radius. To get the bright zone 52 // to span the entire text width, half_radius needs to be ~text_width 53 // / 0.375 â 2.7 à text_half_width â so factor ~2.7+ widthwise. We 54 // round up to 3.0 to give bleed past the leading-S and trailing-s, 55 // so the halo reads as ambient under the whole word rather than a 56 // spotlight on the middle. 57 // Height is more constrained: the bounding rect is roughly the font 58 // line-box (1.05em), so factor 2.0 gives the halo a soft vertical 59 // bleed equal to about one text height past the top and bottom. 60 var WORDMARK_W_FACTOR = 1.0; 61 var WORDMARK_H_FACTOR = 1.0; 62 // The wordmark bounding rect spans the full line-box including the 63 // tall script-font ascenders on S/l/t/k. The visual mass of the word 64 // sits in the lowercase x-height band below the rect's geometric 65 // center, so we shift the halo center downward by ~15% of rect 66 // height to land on the lowercase midpoint. 67 var WORDMARK_Y_OFFSET_FACTOR = 0.10; 68 69 var wordmark = null; 70 var canvas = null; 71 var root = document.documentElement; 72 73 function ensureWordmark() { 74 if (wordmark && wordmark.isConnected) return wordmark; 75 // First .hero-wordmark is the gold (night) layer in document flow â 76 // that's the one with the real bounding box. The day duplicate is 77 // absolute-positioned and shares the same screen footprint. 78 wordmark = document.querySelector('.hero-wordmark'); 79 return wordmark; 80 } 81 function ensureCanvas() { 82 if (canvas && canvas.isConnected) return canvas; 83 canvas = document.querySelector('canvas'); 84 return canvas; 85 } 86 87 function buildHaloState(rect, halfWCss, halfHCss, peakStrength, dpr, 88 heroFade, r, g, b, yOffsetCss) { 89 if (!rect || rect.width < 1 || rect.height < 1) return null; 90 var cssCenterX = rect.left + rect.width * 0.5; 91 var cssCenterY = rect.top + rect.height * 0.5 + (yOffsetCss || 0); 92 return { 93 cx: cssCenterX * dpr,
94 cy: (window.innerHeight - cssCenterY) * dpr, 95 rx: halfWCss * dpr, 96 ry: halfHCss * dpr, 97 strength: peakStrength * heroFade, 98 r: r, g: g, b: b 99 }; 100 } 101 102 function tick() { 103 // Derive the effective DPR from the actual canvas dimensions vs the 104 // CSS viewport. stars_gl.js caps DPR at 2 (MAX_DPR) for performance; 105 // using window.devicePixelRatio directly would put us out of sync 106 // with the renderer on 3x phones. 107 var cv = ensureCanvas(); 108 var dpr = (cv && window.innerWidth > 0) ? (cv.width / window.innerWidth) : 1; 109 110 // Brand color lerp from --day-mix (set by brand_mix.js). Default 0 111 // (full gold) if the variable isn't set yet. 112 var dayMixStr = root.style.getPropertyValue('--day-mix'); 113 var dayMix = dayMixStr ? parseFloat(dayMixStr) : 0; 114 if (!(dayMix >= 0 && dayMix <= 1)) dayMix = 0; 115 var r = GOLD_R + (SLATE_R - GOLD_R) * dayMix; 116 var g = GOLD_G + (SLATE_G - GOLD_G) * dayMix; 117 var b = GOLD_B + (SLATE_B - GOLD_B) * dayMix; 118 119 // Tie halo opacity to the hero-content fade. constellations.js drops 120 // .hero-content's opacity during the constellation showcase; the halos 121 // belong to the hero visually and should disappear with it. The global 122 // is the same value the JS animation writes to the DOM, so the halos 123 // and the rest of the hero crossfade in lockstep. 124 var heroFade = (typeof window._heroOverlayFade === 'number') 125 ? window._heroOverlayFade : 1; 126 // The halo is painted by the sky shader, so CSS hiding the hero 127 // (page-overlay navigation) can't hide it â it would glow through 128 // the translucent content cards. Kill it explicitly while a content 129 // page is open. 130 if (window._pageOverlayOpen) heroFade = 0; 131 132 // Wordmark â footprint scales with the wordmark's measured rect so 133 // the halo grows/shrinks with the responsive font-size clamp. 134 var wEl = ensureWordmark(); 135 var wRect = wEl ? wEl.getBoundingClientRect() : null; 136 if (wRect && wRect.width >= 1 && wRect.height >= 1) { 137 window._wordmarkHaloState = buildHaloState( 138 wRect, 139 wRect.width * WORDMARK_W_FACTOR, 140 wRect.height * WORDMARK_H_FACTOR, 141 WORDMARK_STRENGTH, 142 dpr, heroFade, r, g, b, 143 wRect.height * WORDMARK_Y_OFFSET_FACTOR 144 ); 145 } else { 146 window._wordmarkHaloState = null; 147 } 148 149 requestAnimationFrame(tick); 150 } 151 152 requestAnimationFrame(tick); 153})();
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.