1import{r as a,j as l,C as h,d,f as c,h as v}from"./three-DGSc4TtV.js";const g=-.28,m=-1.3,p=1.75,b=1.15,w=.65,C=.5,T=[{colorT:.5,rOff:0,halfW:.11,tailAng:.55,alpha:.75,seed:3.1},{colorT:.28,rOff:.1,halfW:.09,tailAng:.62,alpha:.6,seed:9.7},{colorT:.75,rOff:-.1,halfW:.09,tailAng:.48,alpha:.65,seed:5.4},{colorT:.06,rOff:.2,halfW:.075,tailAng:.72,alpha:.5,seed:12.9},{colorT:.95,rOff:-.2,halfW:.065,tailAng:.42,alpha:.55,seed:7.3}],t=e=>e.toFixed(3),x=T.map(e=>`acc = strip(acc, r, ang, foldT, t, ${t(e.colorT)}, ${t(e.rOff)}, ${t(e.halfW)}, ${t(e.tailAng)}, ${t(e.alpha)}, ${t(e.seed)});`).join(` 2 `),A=` 3 varying vec2 vUv; 4 5 void main() { 6 vUv = uv; 7 gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0); 8 } 9`,E=` 10 uniform float uTime; 11 uniform float uOpacity; 12 uniform float uAspect; 13 uniform vec3 uColorA; 14 uniform vec3 uColorB; 15 uniform vec3 uColorC; 16 uniform vec3 uColorD; 17 uniform vec3 uColorE; 18 19 varying vec2 vUv; 20 21 // Five stops blended in sequence, so the hue travels across the band â one 22 // continuous sweep through the accent family. 23 vec3 ramp(float t) { 24 t = clamp(t, 0.0, 1.0); 25 if (t < 0.25) return mix(uColorA, uColorB, t / 0.25); 26 if (t < 0.50) return mix(uColorB, uColorC, (t - 0.25) / 0.25); 27 if (t < 0.75) return mix(uColorC, uColorD, (t - 0.50) / 0.25); 28 return mix(uColorD, uColorE, (t - 0.75) / 0.25); 29 } 30 31 float hash(float n) { 32 return fract(sin(n) * 43758.5453123); 33 } 34 35 // 1D value noise: the streak texture only ever needs variation across one 36 // coordinate at a time, so nothing heavier is worth its cost here. 37 float vnoise(float x) { 38 float i = floor(x); 39 float fr = fract(x); 40 float u = fr * fr * (3.0 - 2.0 * fr); 41 return mix(hash(i), hash(i + 1.0), u); 42 } 43 44 // Front-to-back "over" compositing, premultiplied. 45 vec4 over(vec4 acc, vec3 rgb, float a) { 46 float w = (1.0 - acc.a) * a; 47 return vec4(acc.rgb + rgb * w, acc.a + w); 48 } 49 50 vec4 strip( 51 vec4 acc, float r, float ang, float foldT, float t, 52 float colorT, float rOff, float halfW, float tailAng, float amax, float seed 53 ) { 54 // Centreline radius: the shared arc, the strip's own offset â pulled 55 // inward at the fold so the strips gather â and a slow breathing sag. 56 float centre = ${t(p)} + rOff * (1.0 - 0.35 * foldT) 57 + 0.05 * sin(ang * 2.6 - t * 0.6 + seed); 58 // Strips thicken a little through the fold, like cloth seen edge-on. 59 float w = halfW * (1.0 + 0.35 * foldT); 60 float v = (r - centre) / w; 61 if (abs(v) >= 1.0) return acc; 62 63 // Soft airbrush profile â the strips have no hard edge, their overlaps do 64 // the drawing. 65 float env = 1.0 - smoothstep(0.2, 1.0, abs(v)); 66 67 // Streaks running along the strip. Lines of constant q follow the arc, so 68 // they are the brush fibres; the waver bends them slightly against the 69 // flow so they read painted rather than ruled. 70 float q = v * 20.0 + seed * 19.0; 71 q += 2.0 * vnoise(ang * 1.6 + seed * 4.7) - 1.0; 72 float n = 0.65 * vnoise(q * 0.5) + 0.35 * vnoise(q * 1.7 + seed); 73 float fib = 0.5 + 0.5 * sin(q * 2.4); 74 75 // A faint brightness wave sliding left-to-right along the drape â the 76 // only fast motion, and barely-there on purpose. 77 float flow = 0.92 + 0.08 * sin(ang * 4.0 + t * 1.4 + q * 0.12); 78 79 // The tail fades out on the way down the fall, before the frame edge. 80 float tail = smoothstep(tailAng, tailAng + 0.4, ang); 81 82 float a = amax * env * (0.45 + 0.55 * n) * (0.88 + 0.12 * fib) * tail * flow; 83 84 // Colour drifts a little across the width and along the run, so each 85 // strip shades into its neighbours instead of printing flat. 86 vec3 rgb = ramp(colorT + 0.10 * v + 0.06 * sin(ang * 1.2 + seed - t * 0.25)); 87 // Pale streaks toward each strip's crown: the silk sheen, strongest in 88 // the fold where the cloth turns through the light â and on the light 89 // theme what keeps the band from clogging into solid colour. 90 rgb = mix(rgb, vec3(1.0), (0.20 + 0.25 * foldT) * env * env * n); 91 92 return over(acc, rgb, a); 93 } 94 95 void main() { 96 vec2 p = vUv - 0.5; 97 p.x *= uAspect; 98 99 vec2 pivot = vec2(uAspect * ${t(g)}, ${t(m)}); 100 vec2 d = p - pivot; 101 float r = length(d); 102 float ang = atan(d.y, d.x); 103 float foldT = 1.0 - smoothstep(${t(w)}, ${t(b)}, ang); 104 float t = uTime; 105 106 vec4 acc = vec4(0.0); 107 ${x} 108 109 if (acc.a < 0.004) discard; 110 111 vec3 rgb = acc.rgb / acc.a; 112 // A hair of dither: the profiles are wide and soft, which bands visibly 113 // on 8-bit output without it. 114 rgb += (hash(dot(gl_FragCoord.xy, vec2(0.754, 0.569))) - 0.5) / 25
1145.0; 115 116 gl_FragColor = vec4(rgb, acc.a * uOpacity); 117 } 118`,y={a:"#bae6fd",b:"#38bdf8",c:"#22d3ee",d:"#0891b2",e:"#2dd4bf",opacity:.95},O={a:"#0ea5e9",b:"#22d3ee",c:"#06b6d4",d:"#0e7490",e:"#14b8a6",opacity:.8};function S({palette:e,reduceMotion:f}){const{viewport:n}=d(),s=a.useRef(null),u=a.useRef(0),o=a.useMemo(()=>({uTime:{value:0},uOpacity:{value:e.opacity},uAspect:{value:1},uColorA:{value:new c(e.a)},uColorB:{value:new c(e.b)},uColorC:{value:new c(e.c)},uColorD:{value:new c(e.d)},uColorE:{value:new c(e.e)}}),[]);return a.useEffect(()=>{o.uColorA.value.set(e.a),o.uColorB.value.set(e.b),o.uColorC.value.set(e.c),o.uColorD.value.set(e.d),o.uColorE.value.set(e.e),o.uOpacity.value=e.opacity},[e,o]),v((i,r)=>{s.current&&(s.current.uniforms.uAspect.value=n.width/n.height,!f&&(u.current+=r*C,s.current.uniforms.uTime.value=u.current))}),l.jsxs("mesh",{children:[l.jsx("planeGeometry",{args:[n.width,n.height,1,1]}),l.jsx("shaderMaterial",{ref:s,uniforms:o,vertexShader:A,fragmentShader:E,transparent:!0,depthWrite:!1,toneMapped:!1})]})}function R({className:e}){const[f,n]=a.useState(()=>document.documentElement.classList.contains("dark")),[s,u]=a.useState(()=>window.matchMedia("(prefers-reduced-motion: reduce)").matches);a.useEffect(()=>{const i=()=>n(document.documentElement.classList.contains("dark")),r=new MutationObserver(i);return r.observe(document.documentElement,{attributes:!0,attributeFilter:["class"]}),()=>r.disconnect()},[]),a.useEffect(()=>{const i=window.matchMedia("(prefers-reduced-motion: reduce)"),r=()=>u(i.matches);return i.addEventListener("change",r),()=>i.removeEventListener("change",r)},[]);const o=f?O:y;return l.jsx("div",{className:e,"aria-hidden":"true",children:l.jsx(h,{dpr:[1,1.5],gl:{antialias:!0,alpha:!0},style:{background:"transparent"},children:l.jsx(S,{palette:o,reduceMotion:s})})})}export{R as SilkRibbon};
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.