/* Yellow Stone Traders & General Supplies — footer background
 * A vanilla-JS port of the React Bits "Prism" component (https://reactbits.dev),
 * rendered with the ogl WebGL micro-library instead of React. Draws a slowly
 * rotating gold/amber raymarched prism behind the footer content.
 * Skipped on small screens and prefers-reduced-motion (see style.css).
 *
 * Loaded as a CLASSIC script (no type="module") on purpose: browsers block
 * module scripts from loading over file:// (opening the HTML file directly,
 * e.g. by double-clicking it) with a CORS error, even though nothing here
 * needs that. ogl is instead pulled in with a dynamic import() from inside
 * a plain async function, which works the same over file://, http:// and
 * https://.
 */
(function () {
  var el = document.getElementById('footerPrism');
  if (!el) return;
  if (window.matchMedia('(max-width: 700px)').matches) return;
  if (window.matchMedia('(prefers-reduced-motion: reduce)').matches) return;
  if (!window.WebGLRenderingContext) return;

  function initPrism(container, ogl, opts) {
    var Renderer = ogl.Renderer, Triangle = ogl.Triangle, Program = ogl.Program, Mesh = ogl.Mesh;
    opts = opts || {};
    var height = opts.height || 3.2;
    var baseWidth = opts.baseWidth || 5.5;
    var glow = opts.glow != null ? opts.glow : 0.9;
    var noise = opts.noise != null ? opts.noise : 0.35;
    var scale = opts.scale || 3.2;
    var hueShift = opts.hueShift || 0.08;
    var colorFrequency = opts.colorFrequency || 1;
    var bloom = opts.bloom != null ? opts.bloom : 1;
    var timeScale = opts.timeScale != null ? opts.timeScale : 0.35;
    var offset = opts.offset || { x: 0, y: 0 };

    var H = Math.max(0.001, height);
    var BASE_HALF = Math.max(0.001, baseWidth) * 0.5;
    var GLOW = Math.max(0.0, glow);
    var NOISE = Math.max(0.0, noise);
    var offX = offset.x || 0;
    var offY = offset.y || 0;
    var SCALE = Math.max(0.001, scale);
    var HUE = hueShift || 0;
    var CFREQ = Math.max(0.0, colorFrequency || 1);
    var BLOOM = Math.max(0.0, bloom || 1);
    var TS = Math.max(0, timeScale || 1);

    var dpr = Math.min(2, window.devicePixelRatio || 1);
    var renderer = new Renderer({ dpr: dpr, alpha: true, antialias: false });
    var gl = renderer.gl;
    gl.disable(gl.DEPTH_TEST);
    gl.disable(gl.CULL_FACE);
    gl.disable(gl.BLEND);

    Object.assign(gl.canvas.style, {
      position: 'absolute', inset: '0', width: '100%', height: '100%', display: 'block'
    });
    container.appendChild(gl.canvas);

  var vertex = 'attribute vec2 position;\n' +
    'void main(){ gl_Position = vec4(position, 0.0, 1.0); }';

  var fragment = [
    'precision highp float;',
    'uniform vec2  iResolution;',
    'uniform float iTime;',
    'uniform mat3  uRot;',
    'uniform float uGlow;',
    'uniform vec2  uOffsetPx;',
    'uniform float uNoise;',
    'uniform float uSaturation;',
    'uniform float uHueShift;',
    'uniform float uColorFreq;',
    'uniform float uBloom;',
    'uniform float uCenterShift;',
    'uniform float uInvBaseHalf;',
    'uniform float uInvHeight;',
    'uniform float uMinAxis;',
    'uniform float uPxScale;',
    'uniform float uTimeScale;',
    'vec4 tanh4(vec4 x){ vec4 e2x = exp(2.0*x); return (e2x - 1.0) / (e2x + 1.0); }',
    'float rand(vec2 co){ return fract(sin(dot(co, vec2(12.9898, 78.233))) * 43758.5453123); }',
    'float sdOctaAnisoInv(vec3 p){',
    '  vec3 q = vec3(abs(p.x) * uInvBaseHalf, abs(p.y) * uInvHeight, abs(p.z) * uInvBaseHalf);',
    '  float m = q.x + q.y + q.z - 1.0;',
    '  return m * uMinAxis * 0.5773502691896258;',
    '}',
    'float sdPyramidUpInv(vec3 p){ float oct = sdOctaAnisoInv(p); return max(oct, -p.y); }',
    'mat3 hueRotation(float a){',
    '  float c = cos(a), s = sin(a);',
    '  mat3 W = mat3(0.299,0.587,0.114, 0.299,0.587,0.114, 0.299,0.587,0.114);',
    '  mat3 U = mat3(0.701,-0.587,-0.114, -0.299,0.413,-0.114, -0.300,-0.588,0.886);',
    '  mat3 V = mat3(0.168,-0.331,0.500, 0.328,0.035,-0.500, -0.497,0.296,0.201);',
    '  return W + U * c + V * s;',
    '}',
    'void main(){',
    '  vec2 f = (gl_FragCoord.xy - 0.5 * iResolution.xy - uOffsetPx) * uPxScale;',
    '  float z = 5.0; float d = 0.0; vec3 p; vec4 o = vec4(0.0);',
    '  float centerShift = uCenterShift; float cf = uColorFreq;',
    '  float t = iTime * uTimeScale;',
    '  float c0 = cos(t), c1 = cos(t + 33.0), c2 = cos(t + 11.0);',
    '  mat2 wob = mat2(c0, c1, c2, c0);',
    '  for (int i = 0; i < 100; i++) {',
    '    p = vec3(f, z);',
    '    p.xz = p.xz * wob;',
    '    p = uRot * p;',
    '    vec3 q = p; q.y += centerShift;',
    '    d = 0.1 + 0.2 * abs(sdPyramidUpInv(q));',
    '    z -= d;',
    '    o += (sin((p.y + z) * cf + vec4(0.0, 1.0, 2.0, 3.0)) + 1.0) / d;',
    '  }',
    '  o = tanh4(o * o * (uGlow * uBloom) / 1e5);',
    '  vec3 col = o.rgb;',
    '  float n = rand(gl_FragCoord.xy + vec2(iTime));',
    '  col += (n - 0.5) * uNoise;',
    '  col = clamp(col, 0.0, 1.0);',
    '  float L = dot(col, vec3(0.2126, 0.7152, 0.0722));',
    '  col = clamp(mix(vec3(L), col, uSaturation), 0.0, 1.0);',
    '  if (abs(uHueShift) > 0.0001) { col = clamp(hueRotation(uHueShift) * col, 0.0, 1.0); }',
    '  gl_FragColor = vec4(col, o.a);',
    '}'
  ].join('\n');

  var geometry = new Triangle(gl);
  var iResBuf = new Float32Array(2);
  var offsetPxBuf = new Float32Array(2);

  var program = new Program(gl, {
    vertex: vertex,
    fragment: fragment,
    uniforms: {
      iResolution: { value: iResBuf },
      iTime: { value: 0 },
      uRot: { value: new Float32Array([1, 0, 0, 0, 1, 0, 0, 0, 1]) },
      uGlow: { value: GLOW },
      uOffsetPx: { value: offsetPxBuf },
      uNoise: { value: NOISE },
      uSaturation: { value: 1.5 },
      uHueShift: { value: HUE },
      uColorFreq: { value: CFREQ },
      uBloom: { value: BLOOM },
      uCenterShift: { value: H * 0.25 },
      uInvBaseHalf: { value: 1 / BASE_HALF },
      uInvHeight: { value: 1 / H },
      uMinAxis: { value: Math.min(BASE_HALF, H) },
      uPxScale: { value: 1 / ((gl.drawingBufferHeight || 1) * 0.1 * SCALE) },
      uTimeScale: { value: TS }
    }
  });
  var mesh = new Mesh(gl, { geometry: geometry, program: program });

  function resize() {
    var w = container.clientWidth || 1;
    var h = container.clientHeight || 1;
    renderer.setSize(w, h);
    iResBuf[0] = gl.drawingBufferWidth;
    iResBuf[1] = gl.drawingBufferHeight;
    offsetPxBuf[0] = offX * dpr;
    offsetPxBuf[1] = offY * dpr;
    program.uniforms.uPxScale.value = 1 / ((gl.drawingBufferHeight || 1) * 0.1 * SCALE);
  }
  var ro = new ResizeObserver(resize);
  ro.observe(container);
  resize();

  var rotBuf = new Float32Array(9);
  function setMat3FromEuler(yawY, pitchX, rollZ, out) {
    var cy = Math.cos(yawY), sy = Math.sin(yawY);
    var cx = Math.cos(pitchX), sx = Math.sin(pitchX);
    var cz = Math.cos(rollZ), sz = Math.sin(rollZ);
    out[0] = cy * cz + sy * sx * sz; out[1] = cx * sz; out[2] = -sy * cz + cy * sx * sz;
    out[3] = -cy * sz + sy * sx * cz; out[4] = cx * cz; out[5] = sy * sz + cy * sx * cz;
    out[6] = sy * cx; out[7] = -sx; out[8] = cy * cx;
    return out;
  }

  var rnd = Math.random;
  var wX = 0.3 + rnd() * 0.6, wY = 0.2 + rnd() * 0.7, wZ = 0.1 + rnd() * 0.5;
  var phX = rnd() * Math.PI * 2, phZ = rnd() * Math.PI * 2;

  var raf = 0;
  var t0 = performance.now();

  function render(t) {
    var time = (t - t0) * 0.001;
    program.uniforms.iTime.value = time;
    var tScaled = time * TS;
    var yaw = tScaled * wY;
    var pitch = Math.sin(tScaled * wX + phX) * 0.6;
    var roll = Math.sin(tScaled * wZ + phZ) * 0.5;
    program.uniforms.uRot.value = setMat3FromEuler(yaw, pitch, roll, rotBuf);
    renderer.render({ scene: mesh });
    raf = requestAnimationFrame(render);
  }

  function start() { if (!raf) raf = requestAnimationFrame(render); }
  function stop() { if (raf) { cancelAnimationFrame(raf); raf = 0; } }

  var io = new IntersectionObserver(function (entries) {
    var vis = entries.some(function (e) { return e.isIntersecting; });
    if (vis) start(); else stop();
  });
  io.observe(container);
  start();
}

  import('https://cdn.jsdelivr.net/npm/ogl@1.0.9/src/index.js').then(function (ogl) {
    initPrism(el, ogl, {
      height: 3.0,
      baseWidth: 6.5,
      scale: 3.4,
      glow: 0.8,
      noise: 0.3,
      hueShift: 0.06,
      bloom: 0.9,
      timeScale: 0.3,
      offset: { x: 0, y: 40 }
    });
  }).catch(function (err) {
    // CDN unreachable, blocked, or WebGL unavailable — fail silently,
    // the footer looks fine without the effect.
    console.warn('Prism footer background did not load:', err);
  });
})();
