0e9a9f1e1ac5
strip accentGlow machinery from RuneBackground, runes drift subtly on their own at base opacity
- time
- 2026-08-09 19:31 UTC · 2 months ago
- machine
- koh2
- agent
- opencode/laguna-s-2.1-free
- session
- remove accent glow from runes
- parent
- c2d065090bf8
↓ peach-browser-0e9a9f1e.tar.gzatlas at this save
files changed2 files
src/popup/components/RuneBackground.tsx+2 −93src/popup/views/Lock.tsx+1 −1src/popup/components/RuneBackground.tsx+2 −93
@@ -2,10 +2,6 @@22 33 interface RuneBackgroundProps {44 opacity?: number;5- /** When true, a handful of runes pulse with the accent color at random6- * screen positions, mirroring the Android lock-screen's RuneGridBackground7- * glow. Reads `--peach-accent` from the root element. */8- accentGlow?: boolean;95 }106 117 const FONT_SIZE = 14;@@ -17,7 +13,6 @@1713 // Atmosphere, not focus.1814 const SPEEDS = [8, 11, 6];1915 const RUNE_LEN = 120;20-const FALLBACK_ACCENT = "#F49C70";2116 2217 // Deterministic rune string drawn from the PeachScript PUA range2318 // (U+E000..U+E0FF). Same characters every render so the background@@ -30,23 +25,6 @@3025 return out.join("");3126 }3227 33-function readAccentHex(): string {34- const raw = getComputedStyle(document.documentElement)35- .getPropertyValue("--peach-accent")36- .trim();37- if (/^#[0-9a-fA-F]{6}$/.test(raw)) return raw;38- return FALLBACK_ACCENT;39-}40-41-function hexToRgb(hex: string): [number, number, number] {42- hex = hex.replace("#", "");43- return [44- parseInt(hex.slice(0, 2), 16),45- parseInt(hex.slice(2, 4), 16),46- parseInt(hex.slice(4, 6), 16),47- ];48-}49-5028 export function RuneBackground(props: RuneBackgroundProps) {5129 let canvas!: HTMLCanvasElement;5230 let raf = 0;@@ -70,47 +48,6 @@7048 Math.random() * TOTAL_W,7149 );7250 73- // ── Accent glow (lock screen) ─────────────────────────────────74- let accentHex = readAccentHex();75- let accentRgb = hexToRgb(accentHex);76-77- const accentObserver = new MutationObserver(() => {78- const next = readAccentHex();79- if (next !== accentHex) {80- accentHex = next;81- accentRgb = hexToRgb(next);82- }83- });84- accentObserver.observe(document.documentElement, {85- attributes: true,86- attributeFilter: ["style"],87- });88-89- interface Glow {90- row: number;91- col: number;92- phase: number;93- speed: number;94- lifetime: number;95- age: number;96- }97-98- const spawn = (): Glow => ({99- row: Math.floor(Math.random() * NUM_ROWS),100- col: Math.floor(Math.random() * CHARS_PER_ROW),101- phase: Math.random(),102- speed: 0.08 + Math.random() * 0.12,103- lifetime: 5000 + Math.random() * 4000,104- age: 0,105- });106-107- const GLOW_COUNT = 8;108- const glows: Glow[] = props.accentGlow109- ? Array.from({ length: GLOW_COUNT }, spawn)110- : [];111-112- const glowMap = new Map<string, number>();113-11451 let last = performance.now();11552 11653 const frame = (now: number) => {@@ -120,22 +57,8 @@12057 ctx.clearRect(0, 0, W, H);12158 ctx.font = `${FONT_SIZE}px PeachScript, monospace`;12259 ctx.textBaseline = "alphabetic";60+ ctx.fillStyle = `rgba(245, 240, 234, ${baseOpacity})`;12361 124- // Advance glow timers125- glowMap.clear();126- if (props.accentGlow) {127- for (const g of glows) {128- g.age += dt;129- g.phase = (g.phase + (g.speed * dt) / 1000) % 1;130- const lifetimeFraction = g.age / g.lifetime;131- const lifetimeEnvelope = Math.sin(lifetimeFraction * Math.PI);132- const pulseAlpha = Math.sin(g.phase * Math.PI * 2) * 0.5 + 0.5;133- const alpha = Math.max(0, lifetimeEnvelope) * pulseAlpha * 0.85;134- glowMap.set(`${g.row},${g.col}`, alpha);135- if (g.age >= g.lifetime) Object.assign(g, spawn());136- }137- }138-13962 for (let row = 0; row < NUM_ROWS; row++) {14063 const speed = SPEEDS[row % SPEEDS.length];14164 offsets[row] = (offsets[row] + (speed * dt) / 1000) % TOTAL_W;@@ -148,20 +71,7 @@14871 const x = col * CHAR_W - xOffset;14972 if (x < -CHAR_W || x > W + CHAR_W) continue;15073 const idx = (((baseIdx + col) % runes.length) + runes.length) % runes.length;151-152- const glowAlpha = glowMap.get(`${row},${col}`) ?? 0;153- if (glowAlpha > 0.01) {154- const [ar, ag, ab] = accentRgb;155- ctx.save();156- ctx.shadowColor = `rgba(${ar}, ${ag}, ${ab}, ${glowAlpha * 0.9})`;157- ctx.shadowBlur = 10;158- ctx.fillStyle = `rgba(${ar}, ${ag}, ${ab}, ${0.6 + glowAlpha * 0.4})`;159- ctx.fillText(runes[idx]!, x, y);160- ctx.restore();161- } else {162- ctx.fillStyle = `rgba(245, 240, 234, ${baseOpacity})`;163- ctx.fillText(runes[idx]!, x, y);164- }74+ ctx.fillText(runes[idx]!, x, y);16575 }16676 }16777 @@ -197,7 +107,6 @@197107 onCleanup(() => {198108 stop();199109 document.removeEventListener("visibilitychange", onVisibility);200- accentObserver.disconnect();201110 });202111 });203112 src/popup/views/Lock.tsx+1 −1
@@ -289,7 +289,7 @@289289 {/* ── Unlock (hasVault = true) ───────────────────────────────── */}290290 <Match when={props.hasVault}>291291 <section class="peach-screen peach-theme lock-screen lock-screen--vault-stage" data-motion-phase="enter">292- <RuneBackground opacity={0.07} accentGlow />292+ <RuneBackground opacity={0.07} />293293 294294 <header class="peach-screen-header lock-screen-header">295295 <div class="peach-wordmark-stack">