PageSourceSearch

https://motion.dev/assets/BrandAsciiCanvas-DtI2KjJH.js

js motion.dev collected 2026-09-24 17:12:05 UTC 21,610 bytes, 407 lines download raw bytes

1import{r as w,j as de}from"./chunk-6CSD65Y2-C0TiM0T8.js";import{a as E,c as _e,b as J}from"./brand-palette-CrTJb4HX.js";import{u as Ne}from"./use-in-view-9xR4HxK7.js";import{u as Be}from"./use-reduced-motion-_rAsVjG9.js";import{f as oe,c as fe}from"./frame-BT3eX1Ww.js";const k=40,F=24,K=4,ve=k*F*K,Ye=48,Xe=1e3/60,X=.16;function De(){return{read:new Float32Array(ve),write:new Float32Array(ve)}}function O(r,a,c){return Math.min(c,Math.max(a,r))}function Ue(r,a){return Math.min(1,Math.hypot(r,a)*Ye)}function b(r,a,c,f){const m=O(a,0,k-1),v=O(c,0,F-1),l=Math.floor(m),n=Math.floor(v),g=Math.min(k-1,l+1),e=Math.min(F-1,n+1),t=m-l,x=v-n,N=r[(n*k+l)*K+f],P=r[(n*k+g)*K+f],R=r[(e*k+l)*K+f],L=r[(e*k+g)*K+f],C=N+(P-N)*t,I=R+(L-R)*t;return C+(I-C)*x}function We(r,a,c,f,m,v){const l=O(a,0,1)*(k-1),n=O(c,0,1)*(F-1),g=O(v,0,1),e=1.2+g*1.25,t=Math.ceil(e*2),x=Math.max(0,Math.floor(l)-t),N=Math.min(k-1,Math.ceil(l)+t),P=Math.max(0,Math.floor(n)-t),R=Math.min(F-1,Math.ceil(n)+t),L=e*e;for(let C=P;C<=R;C++)for(let I=x;I<=N;I++){const T=I-l,D=C-n,y=Math.exp(-(T*T+D*D)/(L*.72));if(y<.01)continue;const p=(C*k+I)*K;r.read[p]=O(r.read[p]+f*y*.48,-X,X),r.read[p+1]=O(r.read[p+1]+m*y*.48,-X,X),r.read[p+2]=Math.min(1.2,r.read[p+2]+y*g*.72)}}function Ve(r,a,c,f,m,v,l,n){const g=Math.hypot((f-a)*k,(m-c)*F),e=Math.max(1,Math.ceil(g*.75));for(let t=1;t<=e;t++){const x=t/e;We(r,a+(f-a)*x,c+(m-c)*x,v,l,n)}}function ze(r,a){const c=O(a/Xe,0,4),f=Math.pow(.935,c),m=Math.pow(.985,c),v=Math.min(.08,c*.08),l=c*.62,n=r.read,g=r.write;for(let e=0;e<F;e++)for(let t=0;t<k;t++){const x=(e*k+t)*K,N=n[x],P=n[x+1],R=t-N*k*l,L=e-P*F*l,C=b(n,R,L,0),I=b(n,R,L,1),T=b(n,R,L,2),D=(b(n,t-1,e,0)+b(n,t+1,e,0)+b(n,t,e-1,0)+b(n,t,e+1,0))*.25,y=(b(n,t-1,e,1)+b(n,t+1,e,1)+b(n,t,e-1,1)+b(n,t,e+1,1))*.25,p=(b(n,t-1,e,2)+b(n,t+1,e,2)+b(n,t,e-1,2)+b(n,t,e+1,2))*.25;g[x]=O((C+(D-C)*v)*f,-X,X),g[x+1]=O((I+(y-I)*v)*f,-X,X),g[x+2]=Math.max(0,T+(p-T)*v*.65)*m,g[x+3]=0}r.read=g,r.write=n}function qe(r){r.read.fill(0),r.write.fill(0)}const Ge=18,pe=.8,he=9,le=64,Pe=32,Le=le*Pe;let ue=null;function He(r){return ue||(ue=r.requestAdapter().then(a=>(a==null?void 0:a.requestDevice())??null).catch(()=>(ue=null,null))),ue}const A={durationMs:2600,wordmarkWindow:.52,fieldStart:.5,wordRows:6,wordStagger:.12,wipeDuration:.52,rowStagger:.008,noise:.08,feather:.08},H={velocityBlend:.68,maxVelocity:.14,dampingPerFrame:.975,referenceFrameMs:1e3/60};function u(r){return`vec3f(${r.join(", ")})`}function Ke(r){const a=new Float32Array(Le);if(!r)return{data:a,width:0,height:0};const c=r.split(`
2`).slice(0,Pe);let f=0;return c.forEach((m,v)=>{f=Math.max(f,Math.min(m.length,le));for(let l=0;l<Math.min(m.length,le);l++)m[l]==="#"&&(a[v*le+l]=1)}),{data:a,width:f,height:c.length}}const je=`
3struct Uniforms {
4  viewport: vec4f,
5  controls: vec4f,
6  edgeTreatment: vec4f,
7  pointer: vec4f,
8  maskPlacement: vec4f,
9  maskColour: vec4f,
10}
11
12@group(0) @binding(0) var<uniform> uniforms: Uniforms;
13@group(0) @binding(1) var<storage, read> pointerFlow: array<vec4f>;
14@group(0) @binding(2) var<storage, read> glyphMaskData: array<f32>;
15
16const FLOW_COLUMNS: i32 = ${k};
17const FLOW_ROWS: i32 = ${F};
18const MASK_COLUMNS: i32 = ${le};
19
20fn flowCell(x: i32, y: i32) -> vec4f {
21  let safeX = clamp(x, 0, FLOW_COLUMNS - 1);
22  let safeY = clamp(y, 0, FLOW_ROWS - 1);
23  return pointerFlow[u32(safeY * FLOW_COLUMNS + safeX)];
24}
25
26fn samplePointerFlow(uv: vec2f) -> vec4f {
27  let coordinate = clamp(uv, vec2f(0.0), vec2f(1.0))
28    * vec2f(f32(FLOW_COLUMNS - 1), f32(FLOW_ROWS - 1));
29  let lower = vec2i(floor(coordinate));
30  let upper = min(lower + vec2i(1), vec2i(FLOW_COLUMNS - 1, FLOW_ROWS - 1));
31  let blend = fract(coordinate);
32  let top = mix(
33    flowCell(lower.x, lower.y),
34    flowCell(upper.x, lower.y),
35    blend.x
36  );
37  let bottom = mix(
38    flowCell(lower.x, upper.y),
39    flowCell(upper.x, upper.y),
40    blend.x
41  );
42  return mix(top, bottom, blend.y);
43}
44
45fn field(uv: vec2f, time: f32) -> f32 {
46  let aspect = uniforms.viewport.x / max(uniforms.viewport.y, 1.0);
47  var p = vec2f((uv.x - 0.56) * aspect, uv.y - 0.52);
48  let warpAmount = uniforms.controls.z;
49  let warp = vec2f(
50    sin(p.y * 5.2 + time * 0.34 + uniforms.viewport.w) * 0.13,
51    sin(p.x * 4.1 - time * 0.27) * 0.1
52  ) * warpAmount;
53  p += warp;
54
55  let foldA = sin(p.x * 7.0 + p.y * 3.1 + time * 0.42);
56  let foldB = cos(p.y * 8.2 - p.x * 2.7 - time * 0.31);
57  let ribbon = abs(p.y + foldA * 0.16 + foldB * 0.07);
58  let body = 1.0 - smoothstep(0.18, 0.72, length(p * vec2f(0.84, 1.12)));
59  let wave = 1.0 - smoothstep(0.06, 0.42, ribbon);
60  let lobe = 1.0 - smoothstep(
61    0.16,
62    0.68,
63    length(p - vec2f(0.3 + sin(time * 0.21) * 0.07, -0.08))
64  );
65
66  return clamp(max(body * 0.82 + wave * 0.48, lobe * 0.72), 0.0, 1.0);
67}
68
69fn gradient3(t: f32, start: vec3f, middle: vec3f, end: vec3f) -> vec3f {
70  if (t < 0.5) {
71    return mix(start, middle, t * 2.0);
72  }
73  return mix(middle, end, (t - 0.5) * 2.0);
74}
75
76fn palette(t: f32, paletteIndex: f32) -> vec3f {
77  let lemon = ${u(E[0].rgb)};
78  let rind = ${u(E[1].rgb)};
79  let blueberry = ${u(E[2].rgb)};
80  let blackcurrant = ${u(E[3].rgb)};
81  let dragonfruit = ${u(E[4].rgb)};
82  let watermelon = ${u(E[5].rgb)};
83  let tangerine = ${u(_e.rgb)};
84  let paper = ${u(J.paper.rgb)};
85  let ink = ${u(J.ink.rgb)};
86  let uiPaper = ${u(J.uiPaper.rgb)};
87  let preset = i32(round(paletteIndex));
88
89  if (preset == 1) {
90    return gradient3(t, lemon, mix(lemon, paper, 0.28), rind);
91  }
92  if (preset == 2) {
93    return gradient3(t, lemon, rind, mix(rind, blueberry, 0.28));
94  }
95  if (preset == 3) {
96    return gradient3(t, rind, blueberry, blackcurrant);
97  }
98  if (preset == 4) {
99    return gradient3(t, blueberry, blackcurrant, dragonfruit);
100  }
101  if (preset == 5) {
102    return gradient3(t, lemon, dragonfruit, watermelon);
103  }
104  if (preset == 6) {
105    return gradient3(t, rind, mix(rind, ink, 0.72), watermelon);
106  }
107  if (preset == 7) {
108    return gradient3(t, uiPaper, mix(uiPaper, blueberry, 0.2), blueberry);
109  }
110  if (preset == 8) {
111    return gradient3(t, mix(dragonfruit, blackcurrant, 0.3), dragonfruit, mix(dragonfruit, paper, 0.24));
112  }
113  if (preset == ${he}) {
114    return gradient3(t, ink, mix(ink, paper, 0.09), mix(ink, paper, 0.24));
115  }
116  if (preset == 10) {
117    return gradient3(t, mix(tangerine, lemon, 0.35), tangerine, mix(tangerine, watermelon, 0.4));
118  }
119  if (t < 0.2) {
120    return mix(lemon, rind, t / 0.2);
121  }
122  if (t < 0.4) {
123    return mix(rind, blueberry, (t - 0.2) / 0.2);
124  }
125  if (t < 0.6) {
126    return mix(blueberry, blackcurrant, (t - 0.4) / 0.2);
127  }
128  if (t < 0.8) {
129    return mix(blackcurrant, dragonfruit, (t - 0.6) / 0.2);
130  }
131  return mix(dragonfruit, watermelon, (t - 0.8) / 0.2);
132}
133
134fn paletteSolid(paletteIndex: f32) -> vec3f {
135  let preset = i32(round(paletteIndex));
136  if (preset == 2 || preset == 6) {
137    return ${u(E[1].rgb)};
138  }
139  if (preset == 3) {
140    return ${u(E[2].rgb)};
141  }
142  if (preset == 4) {
143    return ${u(E[3].rgb)};
144  }
145  if (preset == 5) {
146    return ${u(E[5].rgb)};
147  }
148  if (preset == 7) {
149    return ${u(J.uiPaper.rgb)};
150  }
151  if (preset == 8) {
152    return ${u(E[4].rgb)};
153  }
154  if (preset == ${he}) {
155    return mix(
156      ${u(J.ink.rgb)},
157      ${u(J.paper.rgb)},
158      0.12
159    );
160  }
161  if (preset == 10) {
162    return ${u(_e.rgb)};
163  }
164  return ${u(E[0].rgb)};
165}
166
167fn pointerHead(uv: vec2f) -> f32 {
168  let velocity = uniforms.pointer.zw;
169  let movement = length(velocity);
170  let sizeSpeed = clamp(movement * 10.0, 0.0, 1.0);
171  let movementVisibility = smoothstep(0.002, 0.006, movement);
172  if (
173    uniforms.pointer.x < 0.0 || uniforms.pointer.x > 1.0
174      || uniforms.pointer.y < 0.0 || uniforms.pointer.y > 1.0
175  ) {
176    return 0.0;
177  }
178
179  let aspect = uniforms.viewport.x / max(uniforms.viewport.y, 1.0);
180  let relative = (uv - uniforms.pointer.xy) * vec2f(aspect, 1.0);
181  let headRadius = (0.035 + sizeSpeed * 0.035) * 0.75;
182  let head = 1.0 - smoothstep(headRadius, headRadius * 1.7, length(relative));
183  return head * movementVisibility;
184}
185
186fn lineMask(p: vec2f, halfLength: f32, width: f32) -> f32 {
187  let body = 1.0 - smoothstep(width, width + 0.08, abs(p.y));
188  let ends = 1.0 - smoothstep(halfLength, halfLength + 0.08, abs(p.x));
189  return body * ends;
190}
191
192fn hashGlyph(local: vec2f) -> f32 {
193  let vertical = max(
194    lineMask(vec2f(local.y, local.x - 0.25), 0.72, 0.075),
195    lineMask(vec2f(local.y, local.x + 0.25), 0.72, 0.075)
196  );
197  let horizontal = max(
198    lineMask(vec2f(local.x, local.y - 0.24), 0.68, 0.075),
199    lineMask(vec2f(local.x, local.y + 0.24), 0.68, 0.075)
200  );
201  return max(vertical, horizontal);
202}
203
204fn glyphMaskValue(cell: vec2f) -> f32 {
205  if (uniforms.maskColour.w < 0.5) {
206    return 0.0;
207  }
208
209  let local = vec2i(cell) - vec2i(round(uniforms.maskPlacement.xy));
210  let width = i32(round(uniforms.maskPlacement.z));
211  let height = i32(round(uniforms.maskPlacement.w));
212  if (local.x < 0 || local.y < 0 || local.x >= width || local.y >= height) {
213    return 0.0;
214  }
215
216  return glyphMaskData[u32(local.y * MASK_COLUMNS + local.x)];
217}
218
219fn glyphMaskReveal(cell: vec2f, revealTime: f32, noise: f32) -> f32 {
220  if (uniforms.maskColour.w < 0.5) {
221    return 0.0;
222  }
223
224  let local = vec2i(cell) - vec2i(round(uniforms.maskPlacement.xy));
225  let width = i32(round(uniforms.maskPlacement.z));
226  let height = i32(round(uniforms.maskPlacement.w));
227  if (local.x < 0 || local.y < 0 || local.x >= width || local.y >= height) {
228    return 0.0;
229  }
230
231  let wordmarkTime = clamp(
232    revealTime / ${A.wordmarkWindow},
233    0.0,
234    1.0
235  );
236  let wordIndex = floor(f32(local.y) / ${A.wordRows}.0);
237  let rowIndex = f32(local.y % ${A.wordRows});
238  let columnProgress = (f32(local.x) + 0.5) / max(f32(width), 1.0);
239  let threshold = wordIndex * ${A.wordStagger}
240    + columnProgress * ${A.wipeDuration}
241    + rowIndex * ${A.rowStagger}
242    + (noise - 0.5) * ${A.noise};
243  return smoothstep(
244    -${A.feather},
245    ${A.feather},
246    wordmarkTime - threshold
247  );
248}
249
250fn glyph(local: vec2f, tangent: vec2f, value: f32, edge: f32) -> f32 {
251  let normal = vec2f(-tangent.y, tangent.x);
252  let p = vec2f(dot(local, tangent), dot(local, normal));
253  let dotMark = 1.0 - smoothstep(0.12, 0.22, length(local));
254  let contour = lineMask(p, 0.72, 0.08);
255  let crossMark = max(
256    lineMask(local, 0.56, 0.075),
257    lineMask(vec2f(local.y, local.x), 0.48, 0.075)
258  );
259  let doubleMark = max(
260    lineMask(p + vec2f(0.0, 0.22), 0.64, 0.065),
261    lineMask(p - vec2f(0.0, 0.22), 0.64, 0.065)
262  );
263  let corner = max(
264    lineMask(vec2f(local.x + 0.18, local.y - 0.28), 0.45, 0.07),
265    lineMask(vec2f(local.y + 0.25, local.x + 0.25), 0.34, 0.07)
266  );
267
268  if (edge > 0.06) {
269    return contour;
270  }
271  if (value < 0.22) {
272    return dotMark;
273  }
274  if (value < 0.46) {
275    return corner;
276  }
277  if (value < 0.72) {
278    return crossMark;
279  }
280  return doubleMark;
281}
282
283@vertex
284fn vertexMain(@builtin(vertex_index) index: u32) -> @builtin(position) vec4f {
285  var positions = array<vec2f, 3>(
286    vec2f(-1.0, -1.0),
287    vec2f(3.0, -1.0),
288    vec2f(-1.0, 3.0)
289  );
290  return vec4f(positions[index], 0.0, 1.0);
291}
292
293@fragment
294fn fragmentMain(@builtin(position) position: vec4f) -> @location(0) vec4f {
295  let cellHeight = uniforms.controls.x;
296  let cellSize = vec2f(cellHeight * 0.6667, cellHeight);
297  let cell = floor(position.xy / cellSize);
298  let cellCenter = (cell + 0.5) * cellSize;
299  let uv = cellCenter / uniforms.viewport.xy;
300  let local = fract(position.xy / cellSize) * 2.0 - 1.0;
301  let time = uniforms.viewport.z;
302  let flow = samplePointerFlow(uv);
303  let flowStrength = clamp(flow.z, 0.0, 1.0);
304  let head = pointerHead(uv);
305  let swish = clamp(max(flowStrength * 1.05, head * 0.9), 0.0, 1.0);
306  let flowSpeed = length(flow.xy);
307  let pointerDirection = normalize(uniforms.pointer.zw + vec2f(0.00001, 0.0));
308  let flowDirection = normalize(flow.xy + vec2f(0.00001, 0.0));
309  let swishDirection = normalize(
310    mix(pointerDirection, flowDirection, smoothstep(0.002, 0.025, flowSpeed))
311      + vec2f(0.00001, 0.0)
312  );
313  let sampleUv = uv
314    - flow.xy * flowStrength * 0.26
315    - pointerDirection * head * 0.015;
316  let value = field(sampleUv, time);
317  let sampleStep = cellSize / uniforms.viewport.xy;
318  let dx = field(sampleUv + vec2f(sampleStep.x, 0.0), time)
319    - field(sampleUv - vec2f(sampleStep.x, 0.0), time);
320  let dy = field(sampleUv + vec2f(0.0, sampleStep.y), time)
321    - field(sampleUv - vec2f(0.0, sampleStep.y), time);
322  let edge = length(vec2f(dx, dy));
323  let fieldGradient = vec2f(dx, dy);
324  let interiorNormal = normalize(fieldGradient + vec2f(0.0001, 0.0));
325  let tangent = vec2f(-interiorNormal.y, interiorNormal.x);
326  let glyphTangent = normalize(
327    mix(tangent, swishDirection, smoothstep(0.04, 0.52, swish) * 0.42)
328      + vec2f(0.0001, 0.0)
329  );
330
331  let drift = sin(uv.y * 5.0 + time * 0.12) * 0.08;
332  let paletteIndex = uniforms.edgeTreatment.z;
333  let colour = palette(clamp(uv.x + drift, 0.0, 1.0), paletteIndex);
334  let contrast = max(uniforms.controls.w, 0.1);
335  let sourceAlpha = smoothstep(0.04, 0.42 / contrast, value) * 0.9;
336  let solidColour = paletteSolid(paletteIndex);
337  let mappedColour = mix(solidColour, colour, sourceAlpha);
338  let cellNoise = fract(
339    sin(dot(cell + vec2f(uniforms.viewport.w * 7.1, 0.0), vec2f(12.9898, 78.233)))
340      * 43758.5453
341  );
342  let revealTime = smoothstep(0.0, 1.0, uniforms.edgeTreatment.y);
343  var fieldRevealTime = revealTime;
344  if (uniforms.maskColour.w >= 0.5) {
345    fieldRevealTime = clamp(
346      (revealTime - ${A.fieldStart})
347        / ${1-A.fieldStart},
348      0.0,
349      1.0
350    );
351  }
352  let wavefront = fieldRevealTime * 1.78 - 0.34;
353  let cellThreshold = uv.x + (cellNoise - 0.5) * 0.14;
354  let reveal = smoothstep(-0.03, 0.42, wavefront - cellThreshold);
355  let glyphReveal = smoothstep(0.08, 0.9, reveal);
356  var result = mix(solidColour, mappedColour, reveal);
357  let pointerCut = clamp(flowStrength * 0.28 + head * 0.18, 0.0, 0.34);
358  result = mix(result, solidColour, pointerCut);
359
360  let reactiveValue = value;
361  let reactiveEdge = edge;
362  let glyphMask = glyph(local, glyphTangent, reactiveValue, reactiveEdge);
363  let wordmarkCell = glyphMaskValue(cell);
364  let wordmarkReveal = glyphMaskReveal(cell, revealTime, cellNoise);
365  let wordmarkInk = hashGlyph(local) * wordmarkCell * wordmarkReveal;
366  let visibility = smoothstep(
367    0.035,
368    0.18 / contrast,
369    reactiveValue + reactiveEdge * 1.8
370  );
371  let boundaryBand = smoothstep(0.035, 0.16, edge)
372    * (1.0 - smoothstep(0.68, 0.94, value));
373  let interiorSide = smoothstep(-0.42, 0.58, dot(local, interiorNormal));
374  let directionalLift = boundaryBand * interiorSide * uniforms.edgeTreatment.x;
375  var dormantInk = 0.015;
376  if (uniforms.maskColour.w >= 0.5) {
377    dormantInk = 0.0;
378  }
379  let whiteInk = glyphMask
380    * visibility
381    * (0.62 + edge * 2.8)
382    * contrast
383    * (1.0 + directionalLift * 0.45)
384    * mix(dormantInk, 1.0, glyphReveal);
385  let palettePreset = i32(round(paletteIndex));
386  var glyphInk = vec3f(1.0);
387  if (palettePreset == 7) {
388    glyphInk = vec3f(0.25, 0.46, 0.94);
389  }
390  let glyphColour = mix(
391    mappedColour,
392    glyphInk,
393    glyphReveal * (0.94 + directionalLift * 0.06)
394  );
395  result = mix(result, glyphColour, clamp(whiteInk, 0.0, 0.96));
396  if (palettePreset == ${he}) {
397    let monoAlpha = clamp(whiteInk, 0.0, 0.25);
398    let outputAlpha = monoAlpha * (1.0 - wordmarkInk) + wordmarkInk;
399    let outputColour = vec3f(monoAlpha) * (1.0 - wordmarkInk)
400      + uniforms.maskColour.rgb * wordmarkInk;
401    return vec4f(outputColour, outputAlpha);
402  }
403
404  result = mix(result, uniforms.maskColour.rgb, wordmarkInk);
405  return vec4f(result, 1.0);
406}
407`;function rt({className:r,label:a="Animated summer-fruit ASCII field",phase:c=0,speed:f=1,contrast:m=1,edgeEmphasis:v=.35,cellSize:l=Ge,paletteIndex:n=0,solidColour:g="var(--lab-yellow)",staticFrame:e=!1,pointerSwish:t=!0,renderWidth:x,renderHeight:N,glyphMask:P,glyphMaskColour:R=E[1].rgb,fitGlyphMask:L=!1,glyphMaskInset:C,deferUntilVisible:I=!1}){const T=w.useRef(null),D=w.useRef(null),y=Ne(T),p=!!Be(),ie=w.useRef(y),j=w.useRef(p),ge=w.useRef({cellSize:l,speed:f,warp:pe,contrast:m,edgeEmphasis:v,paletteIndex:n}),B=w.useRef(null),U=w.useRef({x:-2,y:-2,velocityX:0,velocityY:0,lastX:0,lastY:0,lastEventAt:0,lastFrameAt:0,flow:De()}),[we,W]=w.useState("loading"),[xe,V]=w.useState(!1),[ye,Oe]=w.useState(!I);w.useEffect(()=>{y&&Oe(!0)},[y]);const Te=s=>{if(!t||p||e||s.pointerType==="touch")return;const z=s.currentTarget.getBoundingClientRect(),h=Math.min(1,Math.max(0,(s.clientX-z.left)/z.width)),q=Math.min(1,Math.max(0,(s.clientY-z.top)/z.height)),o=U.current,Y=performance.now();if(o.lastEventAt>0){const ae=Math.min(50,Math.max(8,Y-o.lastEventAt)),ee=H.referenceFrameMs/ae,me=(h-o.lastX)*ee,d=(q-o.lastY)*ee,Q=H.velocityBlend;o.velocityX+=(me-o.velocityX)*Q,o.velocityY+=(d-o.velocityY)*Q,o.velocityX=Math.min(H.maxVelocity,Math.max(-.14,o.velocityX)),o.velocityY=Math.min(H.maxVelocity,Math.max(-.14,o.velocityY))}const M=Ue(o.velocityX,o.velocityY);o.lastEventAt>0&&M>.01&&Ve(o.flow,o.lastX,o.lastY,h,q,o.velocityX,o.velocityY,M),o.x=h,o.y=q,o.lastX=h,o.lastY=q,o.lastEventAt=Y},$e=()=>{const s=U.current;s.x=-2,s.y=-2,s.velocityX=0,s.velocityY=0,s.lastEventAt=0};return w.useEffect(()=>{ie.current=y},[y]),w.useEffect(()=>{j.current=p},[p]),w.useEffect(()=>{ge.current={cellSize:l,speed:f,warp:pe,contrast:m,edgeEmphasis:v,paletteIndex:n},ie.current&&B.current&&oe.render(()=>{var s;return(s=B.current)==null?void 0:s.call(B,{timestamp:performance.now()})})},[l,m,v,n,f]),w.useEffect(()=>{if(!ye)return;const s=T.current;if(!s)return;const z=navigator.gpu;if(!z){V(!1),W("static");return}const h=s,q=z;let o=!1,Y=null,M=null,ae=!1,ee=null;V(!1),W("loading");async function me(){try{const d=await He(q);if(o)return;if(!d){V(!1),W("static");return}const Q=h.getContext("webgpu");if(!Q){V(!1),W("static");return}
407const Me=q.getPreferredCanvasFormat();Q.configure({device:d,format:Me,alphaMode:"premultiplied"});const be=d.createShaderModule({code:je}),Z=Ke(P),ke=d.createRenderPipeline({layout:"auto",vertex:{module:be,entryPoint:"vertexMain"},fragment:{module:be,entryPoint:"fragmentMain",targets:[{format:Me}]},primitive:{topology:"triangle-list"}}),i=new Float32Array(24),Se=d.createBuffer({size:i.byteLength,usage:72}),Re=d.createBuffer({size:ve*Float32Array.BYTES_PER_ELEMENT,usage:136}),Ce=d.createBuffer({size:Le*Float32Array.BYTES_PER_ELEMENT,usage:136});d.queue.writeBuffer(Ce,0,Z.data);const Fe=d.createBindGroup({layout:ke.getBindGroupLayout(0),entries:[{binding:0,resource:{buffer:Se}},{binding:1,resource:{buffer:Re}},{binding:2,resource:{buffer:Ce}}]});let Ee=0,Ae=0,se=l;const Ie=()=>{var G;const $=h.getBoundingClientRect(),_=Math.min(window.devicePixelRatio||1,1.5),S=Math.max(1,Math.round($.width*_)),te=Math.max(1,Math.round($.height*_));(h.width!==S||h.height!==te)&&(h.width=S,h.height=te);const re=(G=D.current)==null?void 0:G.getBoundingClientRect(),ne=re?Math.max(0,re.left-$.left):0;se=L?Math.min(l,(h.width-ne*_*2)/Math.max(1,Z.width*.6667),h.height/Math.max(1,Z.height)):l;const ce=se*.6667;Ee=Math.round(ne*_/ce),Ae=Math.max(0,Math.floor((h.height/se-Z.height)/2))};M=({timestamp:$})=>{if(o||!ie.current)return;const _=ge.current,S=U.current,te=S.lastFrameAt?Math.min(64,Math.max(0,$-S.lastFrameAt)):H.referenceFrameMs,re=Math.pow(H.dampingPerFrame,te/H.referenceFrameMs);S.velocityX*=re,S.velocityY*=re,t&&!j.current&&!e&&ze(S.flow,te),S.lastFrameAt=$;let ne=1;!j.current&&!e&&(ee??(ee=$),ne=Math.min(1,Math.max(0,($-ee)/A.durationMs))),i[0]=h.width,i[1]=h.height,i[2]=j.current||e?c:$/1e3*_.speed,i[3]=c,i[4]=se,i[5]=_.speed,i[6]=_.warp,i[7]=_.contrast,i[8]=_.edgeEmphasis,i[9]=ne,i[10]=_.paletteIndex,i[11]=0,i[12]=S.x,i[13]=S.y,i[14]=t&&!j.current&&!e?S.velocityX:0,i[15]=t&&!j.current&&!e?S.velocityY:0,i[16]=Ee,i[17]=Ae,i[18]=Z.width,i[19]=Z.height,i[20]=R[0],i[21]=R[1],i[22]=R[2],i[23]=P?1:0,d.queue.writeBuffer(Se,0,i),d.queue.writeBuffer(Re,0,S.flow.read);const ce=d.createCommandEncoder(),G=ce.beginRenderPass({colorAttachments:[{view:Q.getCurrentTexture().createView(),clearValue:{r:.985,g:.81,b:.07,a:1},loadOp:"clear",storeOp:"store"}]});G.setPipeline(ke),G.setBindGroup(0,Fe),G.draw(3),G.end(),d.queue.submit([ce.finish()]),ae||(ae=!0,W("live"))},B.current=M,Ie(),M({timestamp:performance.now()}),Y=new ResizeObserver(()=>{oe.read(Ie),ie.current&&M&&oe.render(()=>M==null?void 0:M({timestamp:performance.now()}))}),Y.observe(h),V(!0),d.lost.then(()=>{o||(M&&fe(M),V(!1),W("static"))})}catch(d){console.error("Brand ASCII renderer failed to start",d),o||(V(!1),W("static"))}}return me(),()=>{o=!0,M&&fe(M),B.current===M&&(B.current=null),Y==null||Y.disconnect()}},[P,R,C,L,ye,l,c,t,e]),w.useEffect(()=>{const s=B.current;if(!(!xe||!s)){if(fe(s),!y){U.current.velocityX=0,U.current.velocityY=0,U.current.lastFrameAt=0,qe(U.current.flow);return}if(p||e){oe.render(()=>s({timestamp:0}));return}return oe.render(s,!0),()=>fe(s)}},[y,p,xe,e]),de.jsxs("div",{className:r,"data-ascii-status":we,"data-ascii-active":we==="live"&&y&&!p&&!e?"true":"false","data-ascii-reduced-motion":p?"true":"false","data-ascii-palette":n,"data-ascii-pointer-swish":t?"true":"false","data-ascii-static":e?"true":"false",role:a?"img":void 0,"aria-label":a||void 0,"aria-hidden":a?void 0:!0,onPointerMove:Te,onPointerLeave:$e,style:{"--ascii-cell-size":`${l}px`,"--ascii-contrast":m,"--ascii-warp":pe,"--ascii-solid":g,background:g},children:[de.jsx("canvas",{ref:T,className:"brand-ascii-canvas",width:x,height:N,"aria-hidden":"true"}),P?de.jsx("span",{ref:D,"aria-hidden":"true",style:{position:"absolute",insetBlockStart:0,insetInlineStart:C??0,width:0,height:0,visibility:"hidden",pointerEvents:"none"}}):null]})}export{he as A,rt as B,Ge as a,pe as b};

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.