@satanwagen/reviewkit 0.1.2 → 0.1.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (56) hide show
  1. package/CHANGELOG.md +105 -0
  2. package/README.md +134 -63
  3. package/dist/activate.cjs +150 -0
  4. package/dist/activate.cjs.map +1 -0
  5. package/dist/activate.d.cts +59 -0
  6. package/dist/activate.d.ts +59 -0
  7. package/dist/activate.js +21 -0
  8. package/dist/activate.js.map +1 -0
  9. package/dist/{chunk-4YNLMSCK.js → chunk-DG6O5XIC.js} +36 -10
  10. package/dist/chunk-DG6O5XIC.js.map +1 -0
  11. package/dist/chunk-ETAGGIDN.js +119 -0
  12. package/dist/chunk-ETAGGIDN.js.map +1 -0
  13. package/dist/{chunk-YWBFAV57.js → chunk-NSXRFM75.js} +853 -1544
  14. package/dist/chunk-NSXRFM75.js.map +1 -0
  15. package/dist/chunk-Q7U43PXE.js +36 -0
  16. package/dist/chunk-Q7U43PXE.js.map +1 -0
  17. package/dist/client/index.cjs +4530 -4237
  18. package/dist/client/index.cjs.map +1 -1
  19. package/dist/client/index.d.cts +1 -1
  20. package/dist/client/index.d.ts +1 -1
  21. package/dist/client/index.js +49 -3
  22. package/dist/client/index.js.map +1 -1
  23. package/dist/effects-EWKHKUDP.js +851 -0
  24. package/dist/effects-EWKHKUDP.js.map +1 -0
  25. package/dist/index-BUSmAweg.d.ts +77 -0
  26. package/dist/index-Dl2Fl0qr.d.cts +77 -0
  27. package/dist/index.cjs +4544 -4256
  28. package/dist/index.cjs.map +1 -1
  29. package/dist/index.d.cts +1 -1
  30. package/dist/index.d.ts +1 -1
  31. package/dist/index.js +35 -3
  32. package/dist/index.js.map +1 -1
  33. package/dist/lazy.cjs +8988 -0
  34. package/dist/lazy.cjs.map +1 -0
  35. package/dist/lazy.d.cts +7 -0
  36. package/dist/lazy.d.ts +7 -0
  37. package/dist/lazy.js +8 -0
  38. package/dist/lazy.js.map +1 -0
  39. package/dist/next.cjs +8989 -0
  40. package/dist/next.cjs.map +1 -0
  41. package/dist/next.d.cts +4 -0
  42. package/dist/next.d.ts +4 -0
  43. package/dist/next.js +9 -0
  44. package/dist/next.js.map +1 -0
  45. package/dist/schema.cjs +53 -16
  46. package/dist/schema.cjs.map +1 -1
  47. package/dist/schema.d.cts +20 -5
  48. package/dist/schema.d.ts +20 -5
  49. package/dist/schema.js +30 -2
  50. package/dist/schema.js.map +1 -1
  51. package/package.json +21 -8
  52. package/cli/emblema-sync.mjs +0 -675
  53. package/dist/chunk-4YNLMSCK.js.map +0 -1
  54. package/dist/chunk-YWBFAV57.js.map +0 -1
  55. package/dist/index-BbucFgZi.d.ts +0 -49
  56. package/dist/index-CBlJrKkm.d.cts +0 -49
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/client/effects.ts"],"sourcesContent":["/**\n * `/` command effects — short, purely visual room-wide fun. An effect never\n * touches page content, never stores anything (locally or on the server; the\n * transport broadcasts it as an ephemeral `fx` frame) and cleans up after\n * itself completely: injected styles, DOM nodes, timers, listeners and audio\n * all go away, leaving the page byte-identical. Escape cancels everything;\n * typing the kill word (\"hovno\") cancels for the whole room.\n *\n * Adding an effect = one entry in EFFECTS: either a particle spec, or a\n * `custom` entry whose start() returns its own cleanup.\n *\n * Photosensitivity: color/transform cycles stay slow (≥2 s per cycle, well\n * under 3 Hz), no high-contrast strobing; prefers-reduced-motion gets a far\n * tamer variant (hue drift only, fewer particles, no rotation/pulse).\n */\n\nimport type { EffectName } from './effectCatalog';\n\n/**\n * Where effect sounds live. Default: the ReviewKit assets host (nginx on the\n * satanwagen VPS, TLS via a sslip.io hostname so no domain can expire under\n * it; see realtime/README.md \"Assets host\"). `ReviewKitConfig.fxAssetsUrl`\n * overrides it. Expected files under the base: `rick.mp3` (/ondro).\n */\nexport const DEFAULT_FX_ASSETS_URL = 'https://2-59-219-26.sslip.io/rk-assets';\nlet fxAssetsUrl: string = DEFAULT_FX_ASSETS_URL;\nexport function setFxAssetsUrl(url: string | null): void {\n fxAssetsUrl = url && url !== '' ? url.replace(/\\/+$/, '') : DEFAULT_FX_ASSETS_URL;\n}\n\n/** /ondro runtime — the single knob for how long the madness lasts. */\nconst ONDRO_MS = 120_000;\n/** Every other page-wrecker (\"big\") effect runs this long. */\nconst BIG_MS = 45_000;\nconst NICE_MS = 6_900; // the user likes this number\n\n/** Page content minus the review layer and effect plumbing. */\nconst CHAOS_SEL = 'body > :not([data-review-kit-host]):not(script):not(style):not(svg[data-rk-fx])';\n\ninterface ParticleSpec {\n kind: 'rain' | 'burst';\n glyphs: string[];\n count: number;\n durationMs: number;\n shake?: boolean;\n className?: string;\n}\n\ninterface CustomSpec {\n kind: 'custom';\n durationMs: number;\n start(ctx: { layer: HTMLElement; reduced: boolean }): () => void;\n}\n\ntype EffectSpec = ParticleSpec | CustomSpec;\n\n/** Broadcast hook, injected by the sync layer (avoids an import cycle). */\nlet broadcast: ((name: string) => void) | null = null;\nexport function setEffectBroadcaster(fn: ((name: string) => void) | null): void {\n broadcast = fn;\n}\n\nconst active = new Set<() => void>();\n\n/** Cancel everything currently running (wired into the Esc cascade). */\nexport function cancelEffects(): boolean {\n if (active.size === 0) return false;\n for (const cancel of [...active]) cancel();\n return true;\n}\n\nfunction reducedMotion(): boolean {\n try {\n return window.matchMedia('(prefers-reduced-motion: reduce)').matches;\n } catch {\n return false;\n }\n}\n\n/* ---------------- particle engine ---------------- */\n\nfunction spawnParticles(layer: HTMLElement, spec: ParticleSpec, reduced: boolean, duration: number): void {\n const count = reduced ? Math.min(10, spec.count) : spec.count;\n const vw = window.innerWidth;\n const vh = window.innerHeight;\n for (let i = 0; i < count; i++) {\n const particle = document.createElement('span');\n particle.className = spec.className ? `rk-fx-particle ${spec.className}` : 'rk-fx-particle';\n particle.textContent = spec.glyphs[i % spec.glyphs.length];\n const delay = (i / count) * duration * 0.4;\n const life = duration * (0.45 + (0.35 * ((i * 7) % 10)) / 10);\n particle.style.fontSize = `${14 + ((i * 13) % 18)}px`;\n if (spec.kind === 'rain') {\n const x = (((i * 61) % 100) / 100) * vw;\n const sway = (((i * 31) % 60) - 30) | 0;\n particle.style.setProperty('--fx-x0', `${x}px`);\n particle.style.setProperty('--fx-x1', `${x + sway}px`);\n particle.style.setProperty('--fx-y0', `-40px`);\n particle.style.setProperty('--fx-y1', `${vh + 40}px`);\n } else {\n const angle = (i / count) * Math.PI * 2;\n const radius = 120 + ((i * 47) % 240);\n particle.style.setProperty('--fx-x0', `${vw / 2}px`);\n particle.style.setProperty('--fx-y0', `${vh / 2}px`);\n particle.style.setProperty('--fx-x1', `${vw / 2 + Math.cos(angle) * radius}px`);\n particle.style.setProperty('--fx-y1', `${vh / 2 + Math.sin(angle) * radius + vh * 0.4}px`);\n }\n particle.style.animation = `rk-fx-fall ${reduced ? life * 0.8 : life}ms linear ${delay}ms both`;\n layer.appendChild(particle);\n }\n}\n\nfunction runShake(): () => void {\n const prev = document.body.style.animation;\n let styleTag = document.getElementById('rk-fx-shake-style');\n if (!styleTag) {\n styleTag = document.createElement('style');\n styleTag.id = 'rk-fx-shake-style';\n styleTag.textContent =\n '@keyframes rk-fx-shake { 0%,100% { transform: translate(0,0); } 25% { transform: translate(-5px,3px); } 50% { transform: translate(4px,-4px); } 75% { transform: translate(-3px,-2px); } }';\n document.head.appendChild(styleTag);\n }\n document.body.style.animation = 'rk-fx-shake 260ms ease-in-out 6';\n let done = false;\n const restore = () => {\n if (done) return;\n done = true;\n document.body.style.animation = prev;\n if (document.body.getAttribute('style') === '') document.body.removeAttribute('style');\n };\n window.setTimeout(restore, 1700);\n return restore;\n}\n\n/* ---------------- custom effects ---------------- */\n\n/** /ondro — 20 s of the page tearing itself apart, in three escalating\n * phases, for everyone in the room. All the violence lives in blur,\n * warp/displacement, hue, glitch bands, shake and particles — luminance\n * flips stay slow (a single eased invert wave per 4 s cycle, ≈0.25 Hz) and\n * there is no full-field strobing. The review layer stays untouched and\n * operable. */\nfunction startOndro({ layer, reduced }: { layer: HTMLElement; reduced: boolean }): () => void {\n const cleanups: Array<() => void> = [];\n const timers: number[] = [];\n const intervals: number[] = [];\n const later = (fn: () => void, ms: number) => timers.push(window.setTimeout(fn, ms));\n const every = (fn: () => void, ms: number) => intervals.push(window.setInterval(fn, ms));\n cleanups.push(() => {\n timers.forEach((t) => window.clearTimeout(t));\n intervals.forEach((t) => window.clearInterval(t));\n });\n\n const addStyle = (css: string) => {\n const style = document.createElement('style');\n style.setAttribute('data-rk-fx', 'ondro');\n style.textContent = css;\n document.head.appendChild(style);\n cleanups.push(() => style.remove());\n return style;\n };\n\n /** Particles in a disposable sub-layer so 2 minutes of waves can't pile up. */\n const wave = (spec: ParticleSpec) => {\n const sub = document.createElement('div');\n sub.className = 'rk-fx-layer';\n layer.appendChild(sub);\n spawnParticles(sub, spec, reduced, spec.durationMs);\n const t = window.setTimeout(() => sub.remove(), spec.durationMs + 1600);\n timers.push(t);\n cleanups.push(() => sub.remove());\n };\n\n if (reduced) {\n addStyle(`@keyframes rk-ondro { 0% { filter: none; } 50% { filter: hue-rotate(40deg) saturate(1.15); } 100% { filter: none; } }\n${CHAOS_SEL} { animation: rk-ondro 8s ease-in-out infinite; }`);\n wave({ kind: 'rain', glyphs: ['🤪', '💥', '🌀'], count: 8, durationMs: 8000 });\n every(() => wave({ kind: 'rain', glyphs: ['🤪', '🌀'], count: 6, durationMs: 8000 }), 15000);\n } else {\n // Freeze scrolling: the base zoom would otherwise grow scrollbars and let\n // the reviewer drift out of the stabilized focus point. Restored exactly.\n const scrollX = window.scrollX;\n const scrollY = window.scrollY;\n const htmlOverflow = document.documentElement.style.overflow;\n document.documentElement.style.overflow = 'hidden';\n cleanups.push(() => {\n document.documentElement.style.overflow = htmlOverflow;\n if (document.documentElement.getAttribute('style') === '') document.documentElement.removeAttribute('style');\n window.scrollTo(scrollX, scrollY);\n });\n\n // Base zoom ~1.22 baked into every keyframe: rotation/tilt never reveals\n // the viewport edge (verified at max deflection on 1440/768/375). The\n // transform sits on body's CHILDREN (never on <body>): the review layer\n // host is a body child too and must stay crisp and in place. Page-fixed\n // elements (header, cookie bar) live inside #root, so they simply zoom\n // with the content. transform-origin is pinned to the frozen viewport\n // center so the zoom looks at what the reviewer was looking at.\n const originY = scrollY + window.innerHeight / 2;\n addStyle(`${CHAOS_SEL} { transform-origin: 50vw ${originY}px; }`);\n\n const svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg');\n svg.setAttribute('data-rk-fx', 'ondro');\n svg.setAttribute('width', '0');\n svg.setAttribute('height', '0');\n svg.style.position = 'absolute';\n svg.innerHTML = `<defs>\n <filter id=\"rk-ondro-warp\" x=\"-10%\" y=\"-10%\" width=\"120%\" height=\"120%\">\n <feTurbulence type=\"turbulence\" baseFrequency=\"0.004 0.017\" numOctaves=\"2\" result=\"n\" seed=\"7\">\n <animate attributeName=\"baseFrequency\" dur=\"5.2s\" values=\"0.004 0.017;0.013 0.005;0.004 0.017\" repeatCount=\"indefinite\"/>\n </feTurbulence>\n <feDisplacementMap in=\"SourceGraphic\" in2=\"n\" scale=\"14\" xChannelSelector=\"R\" yChannelSelector=\"G\">\n <animate attributeName=\"scale\" dur=\"4.4s\" values=\"6;26;6\" repeatCount=\"indefinite\"/>\n </feDisplacementMap>\n </filter>\n <filter id=\"rk-ondro-ca\" x=\"-5%\" y=\"-5%\" width=\"110%\" height=\"110%\">\n <feColorMatrix in=\"SourceGraphic\" type=\"matrix\" values=\"1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0\" result=\"r\"/>\n <feColorMatrix in=\"SourceGraphic\" type=\"matrix\" values=\"0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 1 0\" result=\"g\"/>\n <feColorMatrix in=\"SourceGraphic\" type=\"matrix\" values=\"0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 1 0\" result=\"b\"/>\n <feOffset in=\"r\" dx=\"4\" dy=\"0\" result=\"ro\"><animate attributeName=\"dx\" dur=\"2.9s\" values=\"1;6;1\" repeatCount=\"indefinite\"/></feOffset>\n <feOffset in=\"b\" dx=\"-4\" dy=\"1\" result=\"bo\"><animate attributeName=\"dx\" dur=\"3.3s\" values=\"-1;-6;-1\" repeatCount=\"indefinite\"/></feOffset>\n <feBlend in=\"ro\" in2=\"g\" mode=\"screen\" result=\"rg\"/>\n <feBlend in=\"rg\" in2=\"bo\" mode=\"screen\"/>\n </filter>\n </defs>`;\n document.body.appendChild(svg);\n cleanups.push(() => svg.remove());\n\n // Phase 1 (0–6 s): the page starts feeling wrong (already zoomed in).\n addStyle(`@keyframes rk-ondro1 {\n 0% { filter: none; transform: scale(1.22); }\n 25% { filter: hue-rotate(120deg) saturate(1.9) blur(1.6px); transform: scale(1.238) rotate(1.4deg) translateX(6px); }\n 50% { filter: hue-rotate(230deg) saturate(0.6) contrast(1.12) blur(0.6px); transform: scale(1.202) rotate(-1.2deg) translateY(5px); }\n 75% { filter: hue-rotate(310deg) saturate(2.1) blur(2.6px); transform: scale(1.22) skewX(1.1deg) translateX(-7px); }\n 100% { filter: hue-rotate(360deg); transform: scale(1.22); }\n}\n${CHAOS_SEL} { animation: rk-ondro1 2.6s ease-in-out infinite; }`);\n\n // Phase 2 (6–13 s): melting + chromatic aberration + typography decay.\n later(() => {\n addStyle(`@keyframes rk-ondro2 {\n 0% { filter: url(#rk-ondro-warp) hue-rotate(0deg) saturate(1.3); transform: scale(1.22); }\n 20% { filter: url(#rk-ondro-ca) hue-rotate(100deg) saturate(2.3) blur(3.4px); transform: scale(1.256) rotate(2.4deg) translate(12px, -6px); }\n 45% { filter: url(#rk-ondro-warp) hue-rotate(190deg) saturate(0.45) contrast(1.2) blur(1.4px); transform: scale(1.19) rotate(-2.2deg) translate(-13px, 8px) skewY(1.2deg); }\n 70% { filter: url(#rk-ondro-ca) hue-rotate(280deg) saturate(2.4) blur(4.6px); transform: scale(1.244) skewX(-1.8deg) translateY(-10px); }\n 100% { filter: url(#rk-ondro-warp) hue-rotate(360deg) saturate(1.3); transform: scale(1.22); }\n}\n${CHAOS_SEL} { animation: rk-ondro2 2.2s ease-in-out infinite; }\n@keyframes rk-ondro-shake { 0%,100% { transform: translate(0,0); } 20% { transform: translate(-6px,4px); } 40% { transform: translate(5px,-5px); } 60% { transform: translate(-4px,-3px); } 80% { transform: translate(6px,3px); } }\n@keyframes rk-ondro-text {\n 0%,100% { letter-spacing: normal; word-spacing: normal; text-shadow: none; }\n 30% { letter-spacing: 0.12em; word-spacing: 0.3em; text-shadow: 4px 0 rgba(255,0,90,0.6), -4px 1px rgba(0,190,255,0.6); }\n 60% { letter-spacing: -0.05em; word-spacing: -0.1em; text-shadow: -6px 0 rgba(255,0,90,0.55), 6px 2px rgba(0,190,255,0.55), 0 3px rgba(120,255,0,0.4); }\n 80% { letter-spacing: 0.2em; text-shadow: 2px -2px rgba(255,0,90,0.65), -2px 2px rgba(0,190,255,0.65); }\n}\nh1, h2, h3, h4, p, a, li, button, span { animation: rk-ondro-text 3.1s ease-in-out infinite; }`);\n startTextDecay(cleanups, every);\n spawnGlitchBands(layer, cleanups);\n wave({ kind: 'burst', glyphs: ['💥', '🧨', '🔥', '🌀'], count: 34, durationMs: 5000 });\n }, 6000);\n\n // Phase 3 (13 s → end): total collapse. One slow EASED invert wave per\n // 4 s cycle (≈0.25 Hz — far under the 3 Hz flash limit).\n later(() => {\n addStyle(`@keyframes rk-ondro3 {\n 0% { filter: url(#rk-ondro-warp) hue-rotate(0deg) saturate(1.6) invert(0); transform: scale(1.22); }\n 18% { filter: url(#rk-ondro-ca) hue-rotate(140deg) saturate(2.5) blur(6px) invert(0.35); transform: scale(1.27) rotate(3.2deg) translate(20px, -12px); }\n 38% { filter: url(#rk-ondro-warp) hue-rotate(220deg) saturate(0.4) blur(2px) invert(0.75); transform: scale(1.18) rotate(-3deg) translate(-22px, 12px) skewY(2deg); }\n 58% { filter: url(#rk-ondro-ca) hue-rotate(300deg) saturate(2.2) blur(7px) invert(0.3); transform: scale(1.25) skewX(2.4deg) translateY(-16px); }\n 80% { filter: url(#rk-ondro-warp) hue-rotate(340deg) saturate(1.8) blur(3px) invert(0.05); transform: scale(1.23) rotate(1.6deg) translate(14px, 6px); }\n 100% { filter: url(#rk-ondro-warp) hue-rotate(360deg) saturate(1.6) invert(0); transform: scale(1.22); }\n}\n${CHAOS_SEL} { animation: rk-ondro3 4s ease-in-out infinite; }\n@keyframes rk-ondro-shake3 { 0%,100% { transform: translate(0,0) rotate(0); } 25% { transform: translate(-9px,6px) rotate(-0.4deg); } 50% { transform: translate(8px,-8px) rotate(0.5deg); } 75% { transform: translate(-7px,-5px) rotate(-0.3deg); } }\nbody { animation: rk-ondro-shake3 620ms ease-in-out infinite; }`);\n wave({ kind: 'rain', glyphs: ['🤯', '💀', '🧠', '⚡️', '🫠', '🔩'], count: 60, durationMs: 7000 });\n }, 13000);\n\n // Rolling debris + falling letters for the whole 2 minutes, in bounded\n // disposable waves (nothing accumulates).\n wave({ kind: 'rain', glyphs: ['🤪', '💥', '🌀', '🧠', '⚡️'], count: 40, durationMs: 12000 });\n every(() => wave({ kind: 'rain', glyphs: ['🤪', '💥', '🌀', '🧠', '⚡️', '🍕', '📀'], count: 30, durationMs: 9000 }), 9500);\n every(() => spawnFallingLetters(layer), 12000);\n later(() => spawnFallingLetters(layer), 7000);\n }\n\n // Sound — long effect, loop the track; fully stopped on cleanup.\n {\n const audio = new Audio(`${fxAssetsUrl}/rick.mp3`);\n audio.volume = 0.8;\n audio.loop = true;\n cleanups.push(() => {\n audio.pause();\n audio.src = '';\n });\n audio.play().catch(() => {\n const chip = document.createElement('button');\n chip.className = 'rk-fx-sound';\n chip.type = 'button';\n chip.textContent = '🔊 klikni pre zvuk';\n chip.addEventListener('click', () => {\n audio.play().catch(() => undefined);\n chip.remove();\n });\n layer.appendChild(chip);\n cleanups.push(() => chip.remove());\n });\n }\n\n installKillWord(cleanups);\n\n return () => {\n for (const fn of cleanups) fn();\n };\n}\n\n/** Kill word: typing \"hovno\" anywhere ends the effect for the whole room.\n * While chaos runs, bare kill letters are swallowed so they can't trigger\n * global shortcuts (H would hide the layer mid-panic); typing into real\n * text fields keeps working untouched. */\nfunction installKillWord(cleanups: Array<() => void>): void {\n let buffer = '';\n const inTextField = (event: KeyboardEvent) =>\n event\n .composedPath()\n .some(\n (node) =>\n node instanceof HTMLElement &&\n (node.tagName === 'INPUT' || node.tagName === 'TEXTAREA' || node.isContentEditable),\n );\n const KILL_LETTERS = new Set(['h', 'o', 'v', 'n']);\n const onKey = (event: KeyboardEvent) => {\n if (event.key.length !== 1 || event.metaKey || event.ctrlKey || event.altKey) return;\n const key = event.key.toLowerCase();\n buffer = (buffer + key).slice(-8);\n if (KILL_LETTERS.has(key) && !inTextField(event)) event.stopPropagation();\n if (buffer.includes('hovno')) {\n buffer = '';\n broadcast?.('stop');\n cancelEffects();\n }\n };\n document.addEventListener('keydown', onKey, true);\n cleanups.push(() => document.removeEventListener('keydown', onKey, true));\n}\n\n/** Shared scaffolding for the /ondro-caliber page wreckers: timers, style\n * injection, particle waves, frozen scroll + a transform-origin pinned to\n * the viewport center the reviewer was looking at, text decay and the kill\n * word. Each effect only writes its own choreography. */\ninterface BigFxCtx {\n layer: HTMLElement;\n reduced: boolean;\n addStyle(css: string): void;\n later(fn: () => void, ms: number): void;\n every(fn: () => void, ms: number): void;\n wave(spec: ParticleSpec): void;\n decayText(): void;\n cleanups: Array<() => void>;\n}\nfunction bigEffect(build: (ctx: BigFxCtx) => void) {\n return function start({ layer, reduced }: { layer: HTMLElement; reduced: boolean }): () => void {\n const cleanups: Array<() => void> = [];\n const timers: number[] = [];\n const intervals: number[] = [];\n const later = (fn: () => void, ms: number) => timers.push(window.setTimeout(fn, ms));\n const every = (fn: () => void, ms: number) => intervals.push(window.setInterval(fn, ms));\n cleanups.push(() => {\n timers.forEach((t) => window.clearTimeout(t));\n intervals.forEach((t) => window.clearInterval(t));\n });\n const addStyle = (css: string) => {\n const style = document.createElement('style');\n style.setAttribute('data-rk-fx', '');\n style.textContent = css;\n document.head.appendChild(style);\n cleanups.push(() => style.remove());\n };\n const wave = (spec: ParticleSpec) => {\n const sub = document.createElement('div');\n sub.className = 'rk-fx-layer';\n layer.appendChild(sub);\n spawnParticles(sub, spec, reduced, spec.durationMs);\n timers.push(window.setTimeout(() => sub.remove(), spec.durationMs + 1600));\n cleanups.push(() => sub.remove());\n };\n if (!reduced) {\n // Freeze scrolling (the base zoom would grow scrollbars) — restored exactly.\n const scrollX = window.scrollX;\n const scrollY = window.scrollY;\n const htmlOverflow = document.documentElement.style.overflow;\n document.documentElement.style.overflow = 'hidden';\n cleanups.push(() => {\n document.documentElement.style.overflow = htmlOverflow;\n if (document.documentElement.getAttribute('style') === '') document.documentElement.removeAttribute('style');\n window.scrollTo(scrollX, scrollY);\n });\n const originY = scrollY + window.innerHeight / 2;\n addStyle(`${CHAOS_SEL} { transform-origin: 50vw ${originY}px; }`);\n }\n build({\n layer,\n reduced,\n addStyle,\n later,\n every,\n wave,\n decayText: () => startTextDecay(cleanups, every),\n cleanups,\n });\n installKillWord(cleanups);\n return () => {\n for (const fn of cleanups) fn();\n };\n };\n}\n\n/**\n * Typography decay — glitch-swaps characters IN TEXT NODES ONLY. Element\n * structure is never touched (the innerText-wipes-children lesson); every\n * node's original string is snapshotted and restored verbatim on cleanup, so\n * outerHTML of affected elements ends byte-identical.\n */\nfunction startTextDecay(\n cleanups: Array<() => void>,\n every: (fn: () => void, ms: number) => void,\n): void {\n const GLYPHS = '▓▒░#@%&$?!ר∆§';\n const originals = new Map<Text, string>();\n const nodes: Text[] = [];\n const walker = document.createTreeWalker(document.body, NodeFilter.SHOW_TEXT);\n let node: Node | null;\n while ((node = walker.nextNode()) && nodes.length < 120) {\n const text = node as Text;\n const value = text.nodeValue ?? '';\n if (value.trim().length < 4) continue;\n const parent = text.parentElement;\n if (!parent || parent.closest('[data-review-kit-host], script, style, [data-rk-edited]')) continue;\n nodes.push(text);\n }\n every(() => {\n for (let i = 0; i < 22; i++) {\n const text = nodes[(Math.random() * nodes.length) | 0];\n if (!text || !text.isConnected) continue;\n if (!originals.has(text)) originals.set(text, text.nodeValue ?? '');\n const original = originals.get(text) ?? '';\n if (Math.random() < 0.3) {\n text.nodeValue = original; // shimmer back to sanity sometimes\n continue;\n }\n const chars = [...original];\n const swaps = 1 + ((Math.random() * 3) | 0);\n for (let k = 0; k < swaps; k++) {\n const idx = (Math.random() * chars.length) | 0;\n if (chars[idx] !== ' ') chars[idx] = GLYPHS[(Math.random() * GLYPHS.length) | 0];\n }\n text.nodeValue = chars.join('');\n }\n }, 260);\n cleanups.push(() => {\n for (const [text, value] of originals) {\n if (text.isConnected && text.nodeValue !== value) text.nodeValue = value;\n }\n originals.clear();\n });\n}\n\n/** Letters visibly falling out of headings — rendered as OVERLAY clones in\n * the shadow layer; the real DOM is never touched. */\nfunction spawnFallingLetters(layer: HTMLElement): void {\n const sub = document.createElement('div');\n sub.className = 'rk-fx-layer';\n layer.appendChild(sub);\n const headings = [...document.querySelectorAll('h1, h2, h3')].filter((el) => {\n const r = el.getBoundingClientRect();\n return r.width > 0 && r.top < window.innerHeight && r.bottom > 0 && !el.closest('[data-review-kit-host]');\n });\n let spawned = 0;\n for (const heading of headings.slice(0, 3)) {\n const textNode = [...heading.childNodes].find((n) => n.nodeType === 3 && (n.nodeValue ?? '').trim().length > 3);\n const source = textNode ?? heading.firstChild;\n if (!source || source.nodeType !== 3) continue;\n const value = source.nodeValue ?? '';\n const range = document.createRange();\n for (let i = 0; i < value.length && spawned < 26; i++) {\n if (value[i] === ' ' || Math.random() < 0.55) continue;\n range.setStart(source, i);\n range.setEnd(source, i + 1);\n const rect = range.getBoundingClientRect();\n if (rect.width === 0) continue;\n const span = document.createElement('span');\n span.className = 'rk-fx-letter';\n span.textContent = value[i];\n span.style.left = `${rect.left}px`;\n span.style.top = `${rect.top}px`;\n span.style.fontSize = `${rect.height}px`;\n span.style.animationDelay = `${(Math.random() * 900) | 0}ms`;\n span.style.setProperty('--fx-drift', `${((Math.random() * 120) | 0) - 60}px`);\n sub.appendChild(span);\n spawned++;\n }\n }\n window.setTimeout(() => sub.remove(), 4600);\n}\n\n/** Sliding glitch strips over the page — backdrop-filter hue/saturation\n * shifts that MOVE (no blinking, no inversion → no strobe risk). */\nfunction spawnGlitchBands(layer: HTMLElement, cleanups: Array<() => void>): void {\n for (let i = 0; i < 3; i++) {\n const band = document.createElement('div');\n band.className = 'rk-fx-band';\n band.style.height = `${34 + i * 16}px`;\n band.style.animationDuration = `${2.8 + i * 0.7}s`;\n band.style.animationDelay = `${i * 0.9}s`;\n layer.appendChild(band);\n cleanups.push(() => band.remove());\n }\n}\n\n/* --------------- the /ondro-caliber page wreckers ---------------- */\n\n/** /lava — the page overheats, softens and slowly runs down the screen. */\nconst startLava = bigEffect(({ layer, reduced, addStyle, later, every, wave, decayText, cleanups }) => {\n if (reduced) {\n addStyle(`@keyframes rk-lava-soft { 0%,100% { filter: none; } 50% { filter: sepia(0.35) hue-rotate(-20deg) saturate(1.3); } }\n${CHAOS_SEL} { animation: rk-lava-soft 9s ease-in-out infinite; }`);\n wave({ kind: 'rain', glyphs: ['🫠', '🔥'], count: 8, durationMs: 9000 });\n every(() => wave({ kind: 'rain', glyphs: ['🫠', '💧'], count: 6, durationMs: 9000 }), 14000);\n return;\n }\n const svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg');\n svg.setAttribute('data-rk-fx', '');\n svg.setAttribute('width', '0');\n svg.setAttribute('height', '0');\n svg.style.position = 'absolute';\n svg.innerHTML = `<defs><filter id=\"rk-lava-warp\" x=\"-10%\" y=\"-10%\" width=\"120%\" height=\"130%\">\n <feTurbulence type=\"fractalNoise\" baseFrequency=\"0.008 0.003\" numOctaves=\"2\" result=\"n\" seed=\"4\">\n <animate attributeName=\"baseFrequency\" dur=\"7s\" values=\"0.008 0.003;0.014 0.006;0.008 0.003\" repeatCount=\"indefinite\"/>\n </feTurbulence>\n <feDisplacementMap in=\"SourceGraphic\" in2=\"n\" scale=\"10\" xChannelSelector=\"R\" yChannelSelector=\"G\">\n <animate attributeName=\"scale\" dur=\"6s\" values=\"4;24;4\" repeatCount=\"indefinite\"/>\n </feDisplacementMap>\n </filter></defs>`;\n document.body.appendChild(svg);\n cleanups.push(() => svg.remove());\n\n // Phase 1: the heat arrives — shimmer, warm hue, first sag.\n addStyle(`@keyframes rk-lava1 {\n 0% { filter: none; transform: scale(1.22); }\n 35% { filter: sepia(0.4) hue-rotate(-24deg) saturate(1.8) blur(0.8px); transform: scale(1.235) skewY(0.5deg) translateY(6px); }\n 70% { filter: sepia(0.6) hue-rotate(-38deg) saturate(2.2) contrast(1.1) blur(1.6px); transform: scale(1.22) scaleY(1.03) translateY(14px) skewX(-0.6deg); }\n 100% { filter: none; transform: scale(1.22); }\n}\n${CHAOS_SEL} { animation: rk-lava1 7s ease-in-out infinite; }`);\n // Phase 2 (10s): properly molten — displacement warp + heavy vertical sag.\n later(() => {\n addStyle(`@keyframes rk-lava2 {\n 0% { filter: url(#rk-lava-warp) sepia(0.5) hue-rotate(-30deg) saturate(2); transform: scale(1.22) translateY(10px); }\n 40% { filter: url(#rk-lava-warp) sepia(0.8) hue-rotate(-48deg) saturate(2.8) contrast(1.18) blur(2.4px); transform: scale(1.2) scaleY(1.1) translateY(46px) skewX(1deg); }\n 70% { filter: url(#rk-lava-warp) sepia(0.7) hue-rotate(-40deg) saturate(2.4) blur(1.2px); transform: scale(1.23) scaleY(1.06) translateY(28px) skewY(-0.8deg); }\n 100% { filter: url(#rk-lava-warp) sepia(0.5) hue-rotate(-30deg) saturate(2); transform: scale(1.22) translateY(10px); }\n}\n${CHAOS_SEL} { animation: rk-lava2 6.5s ease-in-out infinite; }\n@keyframes rk-lava-text { 0%,100% { letter-spacing: normal; } 50% { letter-spacing: 0.1em; word-spacing: 0.25em; text-shadow: 0 6px 6px rgba(255,80,0,0.5); } }\nh1, h2, h3, p, a, li, button { animation: rk-lava-text 5s ease-in-out infinite; }`);\n decayText();\n }, 10000);\n // Molten streaks running down the screen the whole time.\n const drips = document.createElement('div');\n drips.className = 'rk-fx-layer';\n layer.appendChild(drips);\n cleanups.push(() => drips.remove());\n every(() => {\n const d = document.createElement('div');\n d.className = 'rk-fx-drip';\n d.style.left = `${(Math.random() * 96 + 2).toFixed(1)}vw`;\n d.style.animationDuration = `${(3.5 + Math.random() * 3).toFixed(2)}s`;\n d.style.background = `linear-gradient(180deg, transparent, hsl(${(Math.random() * 30 + 8) | 0}, 95%, 55%))`;\n drips.appendChild(d);\n window.setTimeout(() => d.remove(), 7000);\n }, 700);\n wave({ kind: 'rain', glyphs: ['🔥', '🫠', '🌡️', '💧'], count: 30, durationMs: 10000 });\n every(() => wave({ kind: 'rain', glyphs: ['🔥', '🫠', '💧'], count: 22, durationMs: 9000 }), 9500);\n});\n\n/** /sklo — the page shatters into pieces like glass, drifts apart and\n * reassembles, over and over. Real elements fly; layout never changes. */\nconst startSklo = bigEffect(({ layer, reduced, addStyle, every, wave, decayText, cleanups }) => {\n if (reduced) {\n addStyle(`@keyframes rk-sklo-soft { 0%,100% { filter: none; } 50% { filter: saturate(0.7) brightness(1.06); } }\n${CHAOS_SEL} { animation: rk-sklo-soft 8s ease-in-out infinite; }`);\n wave({ kind: 'burst', glyphs: ['✧', '❖', '💠'], count: 10, durationMs: 8000 });\n return;\n }\n addStyle(`@keyframes rk-sklo-base {\n 0%,10% { transform: scale(1.12); filter: none; }\n 16% { transform: scale(1.125) rotate(0.4deg); filter: brightness(1.12) contrast(1.06); }\n 50% { transform: scale(1.1) rotate(-0.5deg); filter: saturate(0.65) brightness(1.05) blur(0.5px); }\n 72% { transform: scale(1.12); filter: none; }\n 100% { transform: scale(1.12); filter: none; }\n}\n${CHAOS_SEL} { animation: rk-sklo-base 11s ease-in-out infinite; }\n@keyframes rk-sklo-fly {\n 0%, 12% { transform: translate(0, 0) rotate(0); opacity: 1; }\n 30% { transform: translate(var(--rk-gx), var(--rk-gy)) rotate(var(--rk-gr)); opacity: 0.92; }\n 52% { transform: translate(calc(var(--rk-gx) * 1.18), calc(var(--rk-gy) * 1.18)) rotate(calc(var(--rk-gr) * 1.25)); opacity: 0.85; }\n 74% { transform: translate(0, 0) rotate(0); opacity: 1; }\n 100% { transform: translate(0, 0) rotate(0); opacity: 1; }\n}\n[data-rk-shard] { animation: rk-sklo-fly 11s cubic-bezier(0.55, 0, 0.3, 1) infinite; }`);\n // Pick visible content blocks and hand each its own trajectory. The\n // trajectories live in a generated stylesheet keyed by the shard index —\n // never in inline styles: Chrome resurrects a removed \\`style\\` attribute\n // as \\`style=\"\"\\` once el.style was touched, which would break the\n // byte-exact restore guarantee.\n const shards = [...document.querySelectorAll<HTMLElement>('h1, h2, h3, h4, p, li, img, button, a')]\n .filter((el) => {\n if (el.closest('[data-review-kit-host]')) return false;\n const r = el.getBoundingClientRect();\n return r.width > 8 && r.height > 8 && r.bottom > -200 && r.top < window.innerHeight + 200;\n })\n .slice(0, 90);\n const rules: string[] = [];\n shards.forEach((el, i) => {\n const angle = (i * 137.5 * Math.PI) / 180;\n const dist = 18 + ((i * 29) % 46);\n rules.push(\n `[data-rk-shard=\"${i}\"] { --rk-gx: ${(Math.cos(angle) * dist).toFixed(1)}vw; --rk-gy: ${(Math.sin(angle) * dist).toFixed(1)}vh; --rk-gr: ${((i * 97) % 640) - 320}deg; }`,\n );\n el.setAttribute('data-rk-shard', String(i));\n });\n addStyle(rules.join('\\n'));\n cleanups.push(() => {\n for (const el of shards) el.removeAttribute('data-rk-shard');\n });\n // Crack lines flare up right as the pieces let go (opacity ease, no strobe).\n const cracks = document.createElement('div');\n cracks.className = 'rk-fx-cracks';\n cracks.innerHTML = Array.from({ length: 9 }, (_, i) => {\n const angle = i * 40 + (i % 3) * 7;\n return `<span style=\"transform: rotate(${angle}deg); animation-delay: ${(i * 0.05).toFixed(2)}s\"></span>`;\n }).join('');\n layer.appendChild(cracks);\n cleanups.push(() => cracks.remove());\n decayText();\n every(() => wave({ kind: 'burst', glyphs: ['✧', '❖', '💠', '🧊'], count: 26, durationMs: 5000 }), 11000);\n wave({ kind: 'burst', glyphs: ['✧', '❖', '💠'], count: 26, durationMs: 5000 });\n});\n\n/** /vir — the whole page gets pulled into a spinning vortex at the center. */\nconst startVir = bigEffect(({ layer, reduced, addStyle, later, wave, decayText, cleanups }) => {\n if (reduced) {\n addStyle(`@keyframes rk-vir-soft { 0%,100% { filter: none; } 50% { filter: hue-rotate(50deg); } }\n${CHAOS_SEL} { animation: rk-vir-soft 9s ease-in-out infinite; }`);\n wave({ kind: 'burst', glyphs: ['🌀'], count: 8, durationMs: 8000 });\n return;\n }\n // Phase 1: the pull starts — slow breathing rotation.\n addStyle(`@keyframes rk-vir1 {\n 0% { transform: scale(1.25) rotate(0deg); filter: none; }\n 30% { transform: scale(1.31) rotate(4deg); filter: hue-rotate(50deg) saturate(1.3) blur(0.5px); }\n 60% { transform: scale(1.28) rotate(-3.4deg); filter: hue-rotate(140deg) saturate(0.8) blur(1px); }\n 100% { transform: scale(1.25) rotate(0deg); filter: none; }\n}\n${CHAOS_SEL} { animation: rk-vir1 6.5s ease-in-out infinite; }`);\n // Phase 2 (12s): the vortex bites — deeper angles, stronger suction.\n later(() => {\n addStyle(`@keyframes rk-vir2 {\n 0% { transform: scale(1.25) rotate(0deg); filter: hue-rotate(0deg) saturate(1.4); }\n 25% { transform: scale(1.42) rotate(9deg); filter: hue-rotate(90deg) saturate(1.9) blur(1.6px); }\n 50% { transform: scale(1.55) rotate(-7deg); filter: hue-rotate(200deg) saturate(0.6) contrast(1.15) blur(2.6px); }\n 75% { transform: scale(1.38) rotate(10deg); filter: hue-rotate(300deg) saturate(1.8) blur(1.2px); }\n 100% { transform: scale(1.25) rotate(0deg); filter: hue-rotate(360deg) saturate(1.4); }\n}\n${CHAOS_SEL} { animation: rk-vir2 5.5s ease-in-out infinite; }\n@keyframes rk-vir-text { 0%,100% { letter-spacing: normal; } 50% { letter-spacing: 0.16em; text-shadow: 3px 0 rgba(0,180,255,0.5), -3px 0 rgba(255,60,160,0.5); } }\nh1, h2, h3, p, a, li, button { animation: rk-vir-text 4.5s ease-in-out infinite; }`);\n decayText();\n }, 12000);\n // Debris spiralling into the center, continuously.\n const GLYPHS = ['🌀', '✨', '🍃', '📄', '☄️'];\n const bits: Array<{ el: HTMLSpanElement; r: number; a: number; v: number }> = [];\n const cx = () => window.innerWidth / 2;\n const cy = () => window.innerHeight / 2;\n const maxR = () => Math.hypot(window.innerWidth, window.innerHeight) / 2 + 60;\n for (let i = 0; i < 36; i++) {\n const el = document.createElement('span');\n el.className = 'rk-fx-particle';\n el.textContent = GLYPHS[i % GLYPHS.length];\n el.style.fontSize = `${13 + ((i * 11) % 16)}px`;\n layer.appendChild(el);\n bits.push({ el, r: maxR() * ((i + 1) / 36), a: i * 0.7, v: 0.6 + (i % 5) * 0.16 });\n }\n let raf = 0;\n const tick = () => {\n raf = requestAnimationFrame(tick);\n for (const bit of bits) {\n bit.a += 0.014 * bit.v * (1 + 140 / Math.max(bit.r, 40));\n bit.r -= 0.55 * bit.v;\n if (bit.r < 16) bit.r = maxR();\n bit.el.style.transform = `translate3d(${cx() + Math.cos(bit.a) * bit.r}px, ${cy() + Math.sin(bit.a) * bit.r}px, 0) rotate(${bit.a}rad)`;\n bit.el.style.opacity = `${Math.min(1, bit.r / 120)}`;\n }\n };\n raf = requestAnimationFrame(tick);\n cleanups.push(() => {\n cancelAnimationFrame(raf);\n bits.forEach((bit) => bit.el.remove());\n });\n});\n\n/** /crt — the site becomes a worn-out CRT television with a bad signal:\n * green phosphor, scanlines, vignette, a rolling band and signal tears. */\nconst startCrt = bigEffect(({ layer, reduced, addStyle, every, wave, decayText, cleanups }) => {\n if (reduced) {\n addStyle(`${CHAOS_SEL} { filter: sepia(0.7) hue-rotate(55deg) saturate(1.6) contrast(1.05); transition: filter 2s ease; }`);\n return;\n }\n const svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg');\n svg.setAttribute('data-rk-fx', '');\n svg.setAttribute('width', '0');\n svg.setAttribute('height', '0');\n svg.style.position = 'absolute';\n svg.innerHTML = `<defs><filter id=\"rk-crt-tear\" x=\"-10%\" y=\"-10%\" width=\"120%\" height=\"120%\">\n <feTurbulence type=\"turbulence\" baseFrequency=\"0.002 0.09\" numOctaves=\"1\" result=\"n\" seed=\"11\">\n <animate attributeName=\"seed\" dur=\"3s\" values=\"11;37;11\" repeatCount=\"indefinite\"/>\n </feTurbulence>\n <feDisplacementMap in=\"SourceGraphic\" in2=\"n\" scale=\"0\" xChannelSelector=\"R\" yChannelSelector=\"G\">\n <animate attributeName=\"scale\" dur=\"8s\" values=\"0;0;26;4;0;0\" keyTimes=\"0;0.55;0.62;0.7;0.78;1\" repeatCount=\"indefinite\"/>\n </feDisplacementMap>\n </filter></defs>`;\n document.body.appendChild(svg);\n cleanups.push(() => svg.remove());\n addStyle(`@keyframes rk-crt-hold {\n 0%, 60% { transform: scale(1.16) translate(0, 0); }\n 64% { transform: scale(1.16) translate(-3px, 14px) skewX(-0.8deg); }\n 68% { transform: scale(1.16) translate(2px, -8px); }\n 74%, 100% { transform: scale(1.16) translate(0, 0); }\n}\n${CHAOS_SEL} {\n filter: url(#rk-crt-tear) sepia(1) hue-rotate(55deg) saturate(2.6) contrast(1.22) brightness(0.92);\n animation: rk-crt-hold 8s linear infinite;\n}\n@keyframes rk-crt-text { 0%,100% { text-shadow: 1px 0 rgba(0,255,120,0.5); } 50% { text-shadow: -2px 0 rgba(0,255,120,0.7), 2px 0 rgba(0,120,60,0.5); letter-spacing: 0.06em; } }\nh1, h2, h3, p, a, li, button { animation: rk-crt-text 5s ease-in-out infinite; }`);\n const overlay = document.createElement('div');\n overlay.className = 'rk-fx-crt';\n overlay.innerHTML = '<div class=\"rk-fx-crt-scan\"></div><div class=\"rk-fx-crt-roll\"></div><div class=\"rk-fx-crt-vignette\"></div><div class=\"rk-fx-crt-osd\">KANÁL 69 · SLABÝ SIGNÁL</div>';\n layer.appendChild(overlay);\n cleanups.push(() => overlay.remove());\n decayText();\n every(() => wave({ kind: 'rain', glyphs: ['📺', '📡', '𝍍'], count: 10, durationMs: 7000 }), 16000);\n});\n\n/** /kokot — a rude alert banner marquees across the screen. Visual only. */\nfunction startBanner({ layer, reduced }: { layer: HTMLElement; reduced: boolean }): () => void {\n const banner = document.createElement('div');\n banner.className = 'rk-fx-banner';\n banner.textContent = '🚨 KOKOT ALERT 🚨 KOKOT ALERT 🚨 KOKOT ALERT 🚨';\n if (reduced) banner.classList.add('rk-fx-banner-still');\n layer.appendChild(banner);\n return () => banner.remove();\n}\n\n/** /vrtule — every image on the page gently takes off. Injected style only. */\nfunction startVrtule({ reduced }: { layer: HTMLElement; reduced: boolean }): () => void {\n const style = document.createElement('style');\n style.setAttribute('data-rk-fx', 'vrtule');\n style.textContent = reduced\n ? `@keyframes rk-vrtula { 0%,100% { transform: rotate(0); } 50% { transform: rotate(3deg); } }\nimg { animation: rk-vrtula 4s ease-in-out infinite; }`\n : `@keyframes rk-vrtula { from { transform: rotate(0) scale(1); } 50% { transform: rotate(180deg) scale(0.9); } to { transform: rotate(360deg) scale(1); } }\nimg { animation: rk-vrtula 3.6s ease-in-out infinite; }`;\n document.head.appendChild(style);\n return () => style.remove();\n}\n\n/** Shared cursor-chase engine: critters follow every live peer cursor and the\n * local pointer. Powers /muchy and /pes; visual overlay only. */\nfunction makeChase(options: {\n glyphs: string[];\n count: number;\n sizePx: (i: number) => number;\n orbit: (seed: number) => number;\n lag: number;\n wobbleT?: number;\n flip?: boolean;\n}) {\n return function startChase({ layer, reduced }: { layer: HTMLElement; reduced: boolean }): () => void {\n const critters: Array<{ el: HTMLSpanElement; x: number; y: number; seed: number }> = [];\n const count = reduced ? Math.min(4, options.count) : options.count;\n for (let i = 0; i < count; i++) {\n const el = document.createElement('span');\n el.className = 'rk-fx-particle';\n el.textContent = options.glyphs[i % options.glyphs.length];\n el.style.fontSize = `${options.sizePx(i)}px`;\n layer.appendChild(el);\n critters.push({ el, x: window.innerWidth / 2, y: window.innerHeight / 2, seed: i * 137 });\n }\n const wobble = options.wobbleT ?? 400;\n let raf = 0;\n const tick = (t: number) => {\n raf = requestAnimationFrame(tick);\n // Targets: every visible peer cursor chip + the local pointer.\n const root = layer.getRootNode() as ShadowRoot | Document;\n const chips = [...root.querySelectorAll('.rk-peer-cursor')]\n .filter((c) => (c as HTMLElement).style.opacity !== '0')\n .map((c) => {\n const m = /translate3d\\(([-\\d.]+)px, ([-\\d.]+)px/.exec((c as HTMLElement).style.transform);\n return m ? { x: parseFloat(m[1]), y: parseFloat(m[2]) } : null;\n })\n .filter((p): p is { x: number; y: number } => p !== null);\n chips.push({ x: lastPointerFallback.x, y: lastPointerFallback.y });\n for (const critter of critters) {\n const target = chips[critter.seed % chips.length];\n const orbit = reduced ? 14 : options.orbit(critter.seed);\n const wx = target.x + Math.cos(t / wobble + critter.seed) * orbit;\n const wy = target.y + Math.sin(t / (wobble * 0.82) + critter.seed) * orbit;\n const prevX = critter.x;\n critter.x += (wx - critter.x) * options.lag;\n critter.y += (wy - critter.y) * options.lag;\n const face = options.flip && critter.x < prevX ? ' scaleX(-1)' : '';\n critter.el.style.transform = `translate3d(${critter.x}px, ${critter.y}px, 0)${face}`;\n }\n };\n raf = requestAnimationFrame(tick);\n const onMove = (event: PointerEvent) => {\n lastPointerFallback.x = event.clientX;\n lastPointerFallback.y = event.clientY;\n };\n document.addEventListener('pointermove', onMove, { passive: true });\n return () => {\n cancelAnimationFrame(raf);\n document.removeEventListener('pointermove', onMove);\n for (const critter of critters) critter.el.remove();\n };\n };\n}\nconst lastPointerFallback = { x: 300, y: 300 };\n\n/** One data-rk-fx <style> tag with automatic removal — shared by the small\n * page-filter effects below. */\nfunction styleEffect(css: string): () => void {\n const style = document.createElement('style');\n style.setAttribute('data-rk-fx', '');\n style.textContent = css;\n document.head.appendChild(style);\n return () => style.remove();\n}\n\nconst PAGE_SEL = 'body > :not([data-review-kit-host]):not(script):not(style)';\n\n/** /disko — slow hue sweep + sparkles. One full color cycle per 4 s. */\nfunction startDisko({ layer, reduced }: { layer: HTMLElement; reduced: boolean }): () => void {\n const remove = styleEffect(\n reduced\n ? `@keyframes rk-disko { 0%,100% { filter: none; } 50% { filter: hue-rotate(60deg) saturate(1.2); } }\n${PAGE_SEL} { animation: rk-disko 8s ease-in-out infinite; }`\n : `@keyframes rk-disko { from { filter: hue-rotate(0deg) saturate(1.35); } to { filter: hue-rotate(360deg) saturate(1.35); } }\n${PAGE_SEL} { animation: rk-disko 4s linear infinite; }`,\n );\n spawnParticles(layer, { kind: 'rain', glyphs: ['✨', '🪩', '💃', '🕺'], count: 26, durationMs: 15000 }, reduced, 15000);\n return remove;\n}\n\n/** /zrkadlo — the whole page slowly flips into mirror world and back. */\nfunction startZrkadlo({ reduced }: { layer: HTMLElement; reduced: boolean }): () => void {\n if (reduced) {\n return styleEffect(`${PAGE_SEL} { filter: saturate(0.8); transition: filter 2s ease; }`);\n }\n return styleEffect(`@keyframes rk-zrkadlo {\n 0%, 100% { transform: perspective(1400px) rotateY(0); }\n 35%, 65% { transform: perspective(1400px) rotateY(180deg); }\n}\n${PAGE_SEL} { animation: rk-zrkadlo 12s ease-in-out both; transform-origin: 50% 50%; }`);\n}\n\n/** /pohreb — the page slowly drains of color while wilted roses fall. */\nfunction startPohreb({ layer, reduced }: { layer: HTMLElement; reduced: boolean }): () => void {\n const remove = styleEffect(`@keyframes rk-pohreb { from { filter: none; } to { filter: grayscale(1) brightness(0.82) sepia(0.15); } }\n${PAGE_SEL} { animation: rk-pohreb 5s ease-out both; }`);\n spawnParticles(layer, { kind: 'rain', glyphs: ['🥀', '⚰️', '🕯️', '🖤'], count: reduced ? 8 : 22, durationMs: 14000 }, reduced, 14000);\n return remove;\n}\n\n/** /laser — party beams sweep the page from the corners. Overlay only. */\nfunction startLaser({ layer, reduced }: { layer: HTMLElement; reduced: boolean }): () => void {\n const beams: HTMLElement[] = [];\n const count = reduced ? 2 : 5;\n const hues = [330, 190, 120, 45, 265];\n for (let i = 0; i < count; i++) {\n const beam = document.createElement('div');\n beam.className = 'rk-fx-laser';\n beam.style.background = `linear-gradient(90deg, transparent, hsla(${hues[i % hues.length]}, 100%, 60%, 0.55), transparent)`;\n beam.style.left = `${(i % 2) * 100}%`;\n beam.style.animationDuration = `${3.4 + i * 0.6}s`;\n beam.style.animationDelay = `${i * 0.45}s`;\n if (i % 2) beam.style.animationDirection = 'reverse';\n layer.appendChild(beam);\n beams.push(beam);\n }\n return () => beams.forEach((b) => b.remove());\n}\n\n/** /kura — a chicken struts along the bottom edge, leaving eggs. Some hatch. */\nfunction startKura({ layer, reduced }: { layer: HTMLElement; reduced: boolean }): () => void {\n const hen = document.createElement('span');\n hen.className = 'rk-fx-kura';\n hen.textContent = '🐔';\n layer.appendChild(hen);\n const props: HTMLElement[] = [hen];\n const timers: number[] = [];\n const walkMs = reduced ? 16000 : 11000;\n hen.style.animationDuration = `${walkMs}ms`;\n if (!reduced) {\n for (let i = 1; i <= 5; i++) {\n timers.push(\n window.setTimeout(() => {\n const egg = document.createElement('span');\n egg.className = 'rk-fx-egg';\n egg.textContent = '🥚';\n egg.style.left = `${(i / 6) * 100}%`;\n layer.appendChild(egg);\n props.push(egg);\n timers.push(\n window.setTimeout(() => {\n egg.textContent = '🐣';\n }, 2600 + i * 400),\n );\n }, (walkMs * i) / 6),\n );\n }\n }\n return () => {\n timers.forEach((t) => window.clearTimeout(t));\n props.forEach((p) => p.remove());\n };\n}\n\n/** /spam — a storm of fake-important toasts. Pure overlay, self-cleaning. */\nfunction startSpam({ layer, reduced }: { layer: HTMLElement; reduced: boolean }): () => void {\n const MESSAGES = [\n '⚠️ Kritická chyba: stránka je príliš pekná',\n '🔥 69 ľudí práve pozerá tento button',\n '💾 Ukladám tvoje hriechy…',\n '📈 Konverzia stúpla o 420 %',\n '🧠 AI navrhuje: prerob to celé',\n '🍪 Táto stránka žerie koláčiky',\n '📞 Volá ti klient. Zdvihni.',\n '💸 Faktúra po splatnosti (odjakživa)',\n '🛸 Zistená mimozemská aktivita v pätičke',\n '✅ Nič sa nepodarilo úspešne',\n ];\n const toasts: HTMLElement[] = [];\n const timers: number[] = [];\n const total = reduced ? 4 : MESSAGES.length;\n for (let i = 0; i < total; i++) {\n timers.push(\n window.setTimeout(() => {\n const toast = document.createElement('div');\n toast.className = 'rk-fx-toast';\n toast.textContent = MESSAGES[i % MESSAGES.length];\n toast.style.top = `${14 + (i % 5) * 58}px`;\n layer.appendChild(toast);\n toasts.push(toast);\n timers.push(window.setTimeout(() => toast.remove(), 5200));\n }, i * (reduced ? 1800 : 950)),\n );\n }\n return () => {\n timers.forEach((t) => window.clearTimeout(t));\n toasts.forEach((t) => t.remove());\n };\n}\n\nexport const EFFECTS: Record<EffectName, EffectSpec> = {\n ondro: { kind: 'custom', durationMs: ONDRO_MS, start: startOndro },\n lava: { kind: 'custom', durationMs: BIG_MS, start: startLava },\n sklo: { kind: 'custom', durationMs: BIG_MS, start: startSklo },\n vir: { kind: 'custom', durationMs: BIG_MS, start: startVir },\n crt: { kind: 'custom', durationMs: BIG_MS, start: startCrt },\n hovno: { kind: 'rain', glyphs: ['💩'], count: 44, durationMs: 4200 },\n konfety: { kind: 'burst', glyphs: ['🎉', '🎊', '✨'], count: 56, durationMs: 3600 },\n srdiecka: { kind: 'rain', glyphs: ['❤️', '💚', '💛'], count: 40, durationMs: 4200 },\n sneh: { kind: 'rain', glyphs: ['❄️', '🌨️'], count: 48, durationMs: 5200 },\n zemetrasenie: { kind: 'rain', glyphs: ['🪨', '🧱'], count: 18, durationMs: 2400, shake: true },\n '69': { kind: 'burst', glyphs: ['🍆', '🍑', '💦'], count: 69, durationMs: NICE_MS },\n kokot: { kind: 'custom', durationMs: 14500, start: startBanner },\n vrtule: { kind: 'custom', durationMs: NICE_MS, start: startVrtule },\n muchy: {\n kind: 'custom',\n durationMs: NICE_MS,\n start: makeChase({ glyphs: ['🪰'], count: 14, sizePx: (i) => 12 + (i % 3) * 4, orbit: (s) => 26 + (s % 20), lag: 0.12, wobbleT: 400 }),\n },\n pes: {\n kind: 'custom',\n durationMs: 12000,\n start: makeChase({ glyphs: ['🐕', '🐩', '🦮'], count: 3, sizePx: (i) => 26 + (i % 2) * 6, orbit: (s) => 46 + (s % 30), lag: 0.055, wobbleT: 900, flip: true }),\n },\n pivo: { kind: 'rain', glyphs: ['🍺', '🍻', '🍾'], count: 42, durationMs: 8000 },\n nikotin: { kind: 'rain', glyphs: ['🚬', '💨', '😮‍💨'], count: 20, durationMs: 13000 },\n matrix: { kind: 'rain', glyphs: [...'アカサタナ0169ハマヤラヲ'], count: 64, durationMs: 12000, className: 'rk-fx-matrix' },\n disko: { kind: 'custom', durationMs: 15000, start: startDisko },\n zrkadlo: { kind: 'custom', durationMs: 12000, start: startZrkadlo },\n pohreb: { kind: 'custom', durationMs: 14000, start: startPohreb },\n laser: { kind: 'custom', durationMs: 12000, start: startLaser },\n kura: { kind: 'custom', durationMs: 11500, start: startKura },\n spam: { kind: 'custom', durationMs: 11000, start: startSpam },\n};\n\nexport function effectNames(): string[] {\n return Object.keys(EFFECTS);\n}\n\n/**\n * Run an effect inside the shadow root (`layerHost` = .rk-root). Returns\n * false for unknown names (caller treats the text as a comment). The name\n * 'stop' is the room-wide kill switch and just cancels everything.\n */\nexport function runEffect(name: string, layerHost: HTMLElement | null): boolean {\n if (name === 'stop') {\n cancelEffects();\n return true;\n }\n const spec: EffectSpec | undefined = (EFFECTS as Record<string, EffectSpec | undefined>)[name];\n if (!spec || !layerHost) return spec !== undefined;\n const reduced = reducedMotion();\n const duration = reduced && spec.kind !== 'custom' ? Math.min(2000, spec.durationMs) : spec.durationMs;\n\n const layer = document.createElement('div');\n layer.className = 'rk-fx-layer';\n layerHost.appendChild(layer);\n\n let customCleanup: (() => void) | null = null;\n let shakeCleanup: (() => void) | null = null;\n if (spec.kind === 'custom') {\n customCleanup = spec.start({ layer, reduced });\n } else {\n spawnParticles(layer, spec, reduced, duration);\n if (spec.shake && !reduced) shakeCleanup = runShake();\n }\n\n let timer = 0;\n const cancel = () => {\n window.clearTimeout(timer);\n customCleanup?.();\n shakeCleanup?.();\n layer.remove();\n active.delete(cancel);\n };\n timer = window.setTimeout(cancel, duration + 1200);\n active.add(cancel);\n return true;\n}\n"],"mappings":"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","names":[]}
@@ -0,0 +1,77 @@
1
+ import { EmblemaConfig, ReviewSession } from './schema.js';
2
+ import * as react from 'react';
3
+
4
+ type BadgeCorner = 'top-left' | 'top-right' | 'bottom-left' | 'bottom-right';
5
+ interface ReviewKitConfig {
6
+ /**
7
+ * Master switch. `false` renders nothing and installs nothing — no
8
+ * listeners, no storage reads, no network. Default `true`. Lets a host
9
+ * write `<ReviewKit enabled={Boolean(TOKEN)} token={TOKEN} />` instead of
10
+ * `if (!TOKEN) return null`.
11
+ */
12
+ enabled?: boolean;
13
+ /**
14
+ * Activation token: the layer turns on only via `?review=<token>` (or the
15
+ * per-tab session such a link starts). REQUIRED for any activation —
16
+ * without it the component stays off, whatever the URL says. Public in the
17
+ * bundle by nature; a gate against casual visitors, not a secret.
18
+ */
19
+ token?: string;
20
+ /**
21
+ * Force the layer on for this page load regardless of URL/token. Meant for
22
+ * local development (`devAutoOn={import.meta.env.DEV}`); the library never
23
+ * reads NODE_ENV itself. Still subject to `enabled` and `allowedHosts`.
24
+ */
25
+ devAutoOn?: boolean;
26
+ /**
27
+ * Shared secret for the realtime sync server. Public in the browser by
28
+ * nature (anyone with the review URL + bundle can read it) — it gates
29
+ * casual access, not determined attackers. Sync runs only when BOTH
30
+ * `syncToken` and `syncUrl` are set; otherwise solo mode, no network.
31
+ */
32
+ syncToken?: string;
33
+ /**
34
+ * WebSocket endpoint of your sync server (`realtime/server`), e.g.
35
+ * `wss://your-site.tld/rk-sync`. No default — there is no public server.
36
+ * Unreachable/invalid = silent local mode. Remember the host page's CSP
37
+ * must allow it in `connect-src` (see README "CSP").
38
+ */
39
+ syncUrl?: string;
40
+ /**
41
+ * Optional host allowlist for where review may activate at all — e.g.
42
+ * ['localhost', '*.dev.mojweb.sk', 'test.mojweb.sk']. Outside it nothing
43
+ * activates, even with the right token. Unset = works everywhere; a URL
44
+ * activation on a public host without it logs a one-time console warning.
45
+ */
46
+ allowedHosts?: string[];
47
+ defaultAuthor?: string;
48
+ /**
49
+ * Base URL of the static assets the `/` command effects use for sound
50
+ * (currently `rick.mp3` for /ondro). Default: the public ReviewKit assets
51
+ * host `https://2-59-219-26.sslip.io/rk-assets`. Override to self-host;
52
+ * the origin must be allowed by CSP `media-src`.
53
+ */
54
+ fxAssetsUrl?: string;
55
+ /**
56
+ * Enables the Emblema bridge: review items push to a locally running
57
+ * Emblema app automatically as they change (debounced, silent-fail), and
58
+ * the panel's session menu gains a "Resend all to Emblema" fallback
59
+ * (see INTEGRATION-EMBLEMA.md).
60
+ */
61
+ emblema?: EmblemaConfig;
62
+ position?: BadgeCorner;
63
+ storageKey?: string;
64
+ onSessionChange?: (session: ReviewSession) => void;
65
+ }
66
+
67
+ type ReviewKitProps = ReviewKitConfig;
68
+ /**
69
+ * Drop-in visual review layer. Renders nothing unless activated via
70
+ * `?review=<token>` (or the per-tab session it starts), or forced on with
71
+ * `devAutoOn`. `enabled={false}` is a hard off switch. All UI lives in a
72
+ * shadow root on `document.body` — host CSS never leaks in, plugin CSS never
73
+ * leaks out.
74
+ */
75
+ declare function ReviewKit(props: ReviewKitProps): react.JSX.Element | null;
76
+
77
+ export { type BadgeCorner as B, ReviewKit as R, type ReviewKitConfig as a, type ReviewKitProps as b };
@@ -0,0 +1,77 @@
1
+ import { EmblemaConfig, ReviewSession } from './schema.cjs';
2
+ import * as react from 'react';
3
+
4
+ type BadgeCorner = 'top-left' | 'top-right' | 'bottom-left' | 'bottom-right';
5
+ interface ReviewKitConfig {
6
+ /**
7
+ * Master switch. `false` renders nothing and installs nothing — no
8
+ * listeners, no storage reads, no network. Default `true`. Lets a host
9
+ * write `<ReviewKit enabled={Boolean(TOKEN)} token={TOKEN} />` instead of
10
+ * `if (!TOKEN) return null`.
11
+ */
12
+ enabled?: boolean;
13
+ /**
14
+ * Activation token: the layer turns on only via `?review=<token>` (or the
15
+ * per-tab session such a link starts). REQUIRED for any activation —
16
+ * without it the component stays off, whatever the URL says. Public in the
17
+ * bundle by nature; a gate against casual visitors, not a secret.
18
+ */
19
+ token?: string;
20
+ /**
21
+ * Force the layer on for this page load regardless of URL/token. Meant for
22
+ * local development (`devAutoOn={import.meta.env.DEV}`); the library never
23
+ * reads NODE_ENV itself. Still subject to `enabled` and `allowedHosts`.
24
+ */
25
+ devAutoOn?: boolean;
26
+ /**
27
+ * Shared secret for the realtime sync server. Public in the browser by
28
+ * nature (anyone with the review URL + bundle can read it) — it gates
29
+ * casual access, not determined attackers. Sync runs only when BOTH
30
+ * `syncToken` and `syncUrl` are set; otherwise solo mode, no network.
31
+ */
32
+ syncToken?: string;
33
+ /**
34
+ * WebSocket endpoint of your sync server (`realtime/server`), e.g.
35
+ * `wss://your-site.tld/rk-sync`. No default — there is no public server.
36
+ * Unreachable/invalid = silent local mode. Remember the host page's CSP
37
+ * must allow it in `connect-src` (see README "CSP").
38
+ */
39
+ syncUrl?: string;
40
+ /**
41
+ * Optional host allowlist for where review may activate at all — e.g.
42
+ * ['localhost', '*.dev.mojweb.sk', 'test.mojweb.sk']. Outside it nothing
43
+ * activates, even with the right token. Unset = works everywhere; a URL
44
+ * activation on a public host without it logs a one-time console warning.
45
+ */
46
+ allowedHosts?: string[];
47
+ defaultAuthor?: string;
48
+ /**
49
+ * Base URL of the static assets the `/` command effects use for sound
50
+ * (currently `rick.mp3` for /ondro). Default: the public ReviewKit assets
51
+ * host `https://2-59-219-26.sslip.io/rk-assets`. Override to self-host;
52
+ * the origin must be allowed by CSP `media-src`.
53
+ */
54
+ fxAssetsUrl?: string;
55
+ /**
56
+ * Enables the Emblema bridge: review items push to a locally running
57
+ * Emblema app automatically as they change (debounced, silent-fail), and
58
+ * the panel's session menu gains a "Resend all to Emblema" fallback
59
+ * (see INTEGRATION-EMBLEMA.md).
60
+ */
61
+ emblema?: EmblemaConfig;
62
+ position?: BadgeCorner;
63
+ storageKey?: string;
64
+ onSessionChange?: (session: ReviewSession) => void;
65
+ }
66
+
67
+ type ReviewKitProps = ReviewKitConfig;
68
+ /**
69
+ * Drop-in visual review layer. Renders nothing unless activated via
70
+ * `?review=<token>` (or the per-tab session it starts), or forced on with
71
+ * `devAutoOn`. `enabled={false}` is a hard off switch. All UI lives in a
72
+ * shadow root on `document.body` — host CSS never leaks in, plugin CSS never
73
+ * leaks out.
74
+ */
75
+ declare function ReviewKit(props: ReviewKitProps): react.JSX.Element | null;
76
+
77
+ export { type BadgeCorner as B, ReviewKit as R, type ReviewKitConfig as a, type ReviewKitProps as b };