domma-cms 0.107.0 → 0.107.1

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.
@@ -1,9 +1,9 @@
1
1
  /*!
2
- * Domma Tools CSS v0.51.4
2
+ * Domma Tools CSS v0.51.5
3
3
  * Dynamic Object Manipulation & Modeling API
4
4
  * (c) 2026 Darryl Waterhouse & DCBW-IT
5
- * Built: 2026-09-30T15:11:39.929Z
6
- * Commit: 86dbba4
5
+ * Built: 2026-10-01T08:33:07.263Z
6
+ * Commit: 094a9d3
7
7
  */
8
8
 
9
9
  /*!
@@ -1,9 +1,9 @@
1
1
  /*!
2
- * Domma Tools v0.51.4
2
+ * Domma Tools v0.51.5
3
3
  * Developer tools: Theme Roller & Page Roller
4
4
  * (c) 2026 Darryl Waterhouse & DCBW-IT
5
- * Built: 2026-09-30T15:11:28.566Z
6
- * Commit: 86dbba4
5
+ * Built: 2026-10-01T08:32:52.270Z
6
+ * Commit: 094a9d3
7
7
  *
8
8
  * Requires: domma.min.js
9
9
  */
@@ -1 +1 @@
1
- export const EFFECTS=[{name:"reveal",label:"Reveal",category:"Entrance",description:"Scroll-triggered entrance animation when the element enters the viewport.",attrs:[{name:"animation",label:"Animation",type:"select",default:"fade",options:[["fade","Fade"],["slide-up","Slide up"],["slide-down","Slide down"],["zoom","Zoom"],["flip","Flip"]]},{name:"duration",label:"Duration (ms)",type:"number",default:600},{name:"delay",label:"Delay (ms)",type:"number",default:0},{name:"threshold",label:"Threshold",type:"number",default:.1,step:.05,min:0,max:1},{name:"once",label:"Animate once",type:"checkbox",default:!0}],hosts:["card","box","hero","banner","col"],previewable:!0},{name:"breathe",label:"Breathe",category:"Animation",description:"Continuous gentle scaling - makes elements feel alive.",attrs:[{name:"amplitude",label:"Amplitude (px)",type:"number",default:8},{name:"duration",label:"Duration (ms)",type:"number",default:3e3}],hosts:["card","box","hero","col","button"],previewable:!0},{name:"pulse",label:"Pulse",category:"Animation",description:"A repeating scale pulse - stronger than breathe.",attrs:[{name:"scale",label:"Scale",type:"number",default:1.05,step:.01},{name:"duration",label:"Duration (ms)",type:"number",default:1e3}],hosts:["card","box","hero","banner","button"],previewable:!0},{name:"shake",label:"Shake",category:"Animation",description:"One-shot horizontal or vertical shake.",attrs:[{name:"intensity",label:"Intensity (px)",type:"number",default:5},{name:"duration",label:"Duration (ms)",type:"number",default:500},{name:"direction",label:"Direction",type:"select",default:"horizontal",options:[["horizontal","Horizontal"],["vertical","Vertical"]]}],hosts:["card","box","banner","button"],previewable:!0},{name:"animate",label:"CSS Animate",category:"Animation",description:"Applies a Domma CSS animation utility class - no JavaScript.",attrs:[{name:"type",label:"Type",type:"select",default:"fade-in-up",options:[["fade-in","fade-in"],["fade-in-up","fade-in-up"],["fade-in-down","fade-in-down"],["fade-in-left","fade-in-left"],["fade-in-right","fade-in-right"],["slide-in-up","slide-in-up"],["slide-in-down","slide-in-down"],["zoom-in","zoom-in"],["zoom-out","zoom-out"],["bounce","bounce"],["pulse","pulse"],["shake","shake"],["spin","spin"],["flip","flip"]]},{name:"duration",label:"Duration",type:"select",default:"normal",options:[["fast","fast"],["normal","normal"],["slow","slow"],["slower","slower"]]},{name:"delay",label:"Delay (ms)",type:"number",default:0},{name:"repeat",label:"Repeat",type:"select",default:"once",options:[["once","Once"],["infinite","Infinite"]]}],hosts:["card","box","hero","banner","col","button"],previewable:!0},{name:"scribe",label:"Scribe (typewriter)",category:"Text",description:"Types text character by character. Simple mode only - for the action-script composer use Insert \u2192 Scribe.",attrs:[{name:"speed",label:"Speed (ms/char)",type:"number",default:50},{name:"cursor",label:"Show cursor",type:"checkbox",default:!0},{name:"loop",label:"Loop",type:"checkbox",default:!1}],hosts:[],previewable:!0},{name:"scramble",label:"Scramble",category:"Text",description:"Reveals text through a character-scramble animation.",attrs:[{name:"speed",label:"Speed (ms/char)",type:"number",default:50},{name:"loop",label:"Loop",type:"checkbox",default:!1}],hosts:[],previewable:!0},{name:"counter",label:"Counter",category:"Text",description:"Animates a number from a starting value to a target. Self-closing shortcode.",attrs:[{name:"to",label:"To",type:"number",default:100},{name:"from",label:"From",type:"number",default:0},{name:"duration",label:"Duration (ms)",type:"number",default:2e3},{name:"prefix",label:"Prefix",type:"text",default:""},{name:"suffix",label:"Suffix",type:"text",default:""},{name:"decimals",label:"Decimal places",type:"number",default:0},{name:"separator",label:"Thousand separator",type:"text",default:""}],hosts:[],previewable:!0,selfClosing:!0},{name:"ripple",label:"Ripple",category:"Visual",description:"Click-triggered ripple effect on the element.",attrs:[{name:"colour",label:"Colour",type:"colour",default:"#7c6af7"},{name:"duration",label:"Duration (ms)",type:"number",default:600},{name:"opacity",label:"Opacity",type:"number",default:.3,step:.05,min:0,max:1}],hosts:["card","box","col","button"],previewable:!0},{name:"twinkle",label:"Twinkle",category:"Visual",description:"Generates animated particle effects inside the element.",attrs:[{name:"count",label:"Particle count",type:"number",default:80},{name:"shape",label:"Shape",type:"select",default:"star",options:[["star","Star"],["circle","Circle"],["square","Square"]]},{name:"colour",label:"Colour",type:"colour",default:"#ffffff"},{name:"min-size",label:"Min size (px)",type:"number",default:2},{name:"max-size",label:"Max size (px)",type:"number",default:6}],hosts:["card","box","hero"],previewable:!0},{name:"ambient",label:"Ambient background",category:"Visual",description:"Applies an animated CSS background class to the element.",attrs:[{name:"type",label:"Type",type:"select",default:"float-blobs",options:[["float-blobs","Float blobs"],["float-orbs","Float orbs"],["float-particles","Float particles"],["rotate-glow","Rotate glow"],["rotate-dual","Rotate dual"],["rotate-spotlight","Rotate spotlight"],["wave","Wave"],["ripple","Ripple"],["aurora","Aurora"]]},{name:"speed",label:"Speed",type:"select",default:"normal",options:[["slow","Slow"],["normal","Normal"],["fast","Fast"]]},{name:"intensity",label:"Intensity",type:"select",default:"subtle",options:[["subtle","Subtle"],["intense","Intense"]]}],hosts:["card","box","hero","banner"],previewable:!0},{name:"firework",label:"Firework",category:"Celebrations",description:"CSS-only firework particle. Self-closing or wrapping form.",attrs:[{name:"type",label:"Type",type:"select",default:"burst",options:[["burst","Burst"],["sparkle","Sparkle"],["trail","Trail"]]},{name:"colour",label:"Colour theme",type:"select",default:"rainbow",options:[["rainbow","Rainbow"],["primary","Primary"],["info","Info"],["success","Success"],["warning","Warning"],["danger","Danger"]]},{name:"size",label:"Size",type:"select",default:"md",options:[["sm","Small"],["md","Medium"],["lg","Large"]]},{name:"continuous",label:"Continuous",type:"checkbox",default:!1},{name:"hover",label:"On hover only",type:"checkbox",default:!1}],hosts:[],previewable:!0},{name:"fireworks",label:"Fireworks show",category:"Celebrations",description:"A container with multiple firework particles inside.",attrs:[],hosts:[],previewable:!1},{name:"celebrate",label:"Celebrate",category:"Celebrations",description:"Canvas-based seasonal particle system. Runs full-page on the published site.",attrs:[{name:"theme",label:"Theme",type:"select",default:"auto",options:[["auto","Auto (date-detected)"],["christmas","Christmas"],["halloween","Halloween"],["valentines","Valentines"],["guy-fawkes","Guy Fawkes"],["st-patricks","St Patrick's"],["st-davids","St David's"],["st-georges","St George's"],["st-andrews","St Andrew's"]]},{name:"intensity",label:"Intensity",type:"select",default:"medium",options:[["light","Light"],["medium","Medium"],["heavy","Heavy"]]},{name:"snow-only",label:"Snow only (Christmas)",type:"checkbox",default:!1,hint:"Just the falling snow - every Christmas decoration off."},{name:"trees",label:"Christmas: trees",type:"select",default:"",options:[["","Shown"],["off","Off"]]},{name:"wreaths",label:"Christmas: wreaths",type:"select",default:"",options:[["","Shown"],["off","Off"]]},{name:"northstars",label:"Christmas: North Star",type:"select",default:"",options:[["","Shown"],["off","Off"]]},{name:"snowmen",label:"Christmas: snowmen",type:"select",default:"",options:[["","Shown"],["off","Off"]]},{name:"sleigh",label:"Christmas: Santa's sleigh",type:"select",default:"",options:[["","Shown"],["off","Off"]]},{name:"elf",label:"Christmas: elf",type:"select",default:"",options:[["","Shown"],["off","Off"]]},{name:"train",label:"Christmas: train",type:"select",default:"",options:[["","Shown"],["off","Off"]]},{name:"firework",label:"Christmas: fireworks",type:"select",default:"",options:[["","Shown"],["off","Off"]]},{name:"robin",label:"Christmas: robin",type:"select",default:"",options:[["","Shown"],["off","Off"]]},{name:"peeing-elf",label:"Peeing elf (opt-in)",type:"checkbox",default:!1,hint:"A clothed rear-view gag. Off by default; Snow only keeps it off."},{name:"thieving-elf",label:"Thieving elf (opt-in)",type:"checkbox",default:!1,hint:"Runs to a tree, takes a present and escapes. Needs a visible tree."}],hosts:[],previewable:!1,selfClosing:!0},{name:"christmas",label:"Christmas",category:"Celebrations",description:"Christmas on the published site: snow, trees, wreaths, snowmen, Santa's sleigh and more. Snow only for just the snow.",attrs:[{name:"intensity",label:"Intensity",type:"select",default:"medium",options:[["light","Light"],["medium","Medium"],["heavy","Heavy"]]},{name:"snow-only",label:"Snow only",type:"checkbox",default:!1,hint:"Just the falling snow - every decoration off."},{name:"trees",label:"trees",type:"select",default:"",options:[["","Shown"],["off","Off"]]},{name:"wreaths",label:"wreaths",type:"select",default:"",options:[["","Shown"],["off","Off"]]},{name:"northstars",label:"North Star",type:"select",default:"",options:[["","Shown"],["off","Off"]]},{name:"snowmen",label:"snowmen",type:"select",default:"",options:[["","Shown"],["off","Off"]]},{name:"sleigh",label:"Santa's sleigh",type:"select",default:"",options:[["","Shown"],["off","Off"]]},{name:"elf",label:"elf",type:"select",default:"",options:[["","Shown"],["off","Off"]]},{name:"train",label:"train",type:"select",default:"",options:[["","Shown"],["off","Off"]]},{name:"firework",label:"fireworks",type:"select",default:"",options:[["","Shown"],["off","Off"]]},{name:"robin",label:"robin",type:"select",default:"",options:[["","Shown"],["off","Off"]]},{name:"peeing-elf",label:"Peeing elf (opt-in)",type:"checkbox",default:!1,hint:"A clothed rear-view gag. Off by default; Snow only keeps it off."},{name:"thieving-elf",label:"Thieving elf (opt-in)",type:"checkbox",default:!1,hint:"Runs to a tree, takes a present and escapes. Needs a visible tree."}],hosts:[],previewable:!1,selfClosing:!0},{name:"ticker-tape",label:"Ticker tape",category:"Celebrations",description:"Coloured rectangular strips fall from the top, sway, rotate, and fade. Inserted self-closing (full-page); hand-write the wrapping form for container-scoped.",attrs:[{name:"palette",label:"Palette",type:"select",default:"theme",options:[["theme","Theme"],["rainbow","Rainbow"],["gold","Gold"],["silver","Silver"],["festive","Festive"],["pastel","Pastel"],["mono","Mono"]]},{name:"density",label:"Density",type:"number",default:50},{name:"speed",label:"Speed multiplier",type:"number",default:1,step:.1},{name:"sway",label:"Sway (px)",type:"number",default:60},{name:"burst",label:"Burst mode (one-shot)",type:"checkbox",default:!1},{name:"burst-count",label:"Burst count",type:"number",default:150}],hosts:["hero"],previewable:!0,selfClosing:!0},{name:"butterflies",label:"Butterflies",category:"Celebrations",description:"Procedurally drawn butterflies wander and rise with flapping wings. Self-closing for full-page; wrapping form for container-scoped.",attrs:[{name:"palette",label:"Palette",type:"select",default:"meadow",options:[["meadow","Meadow"],["theme","Theme"],["rainbow","Rainbow"],["pastel","Pastel"],["festive","Festive"],["gold","Gold"],["silver","Silver"],["mono","Mono"],["sunset","Sunset"],["ocean","Ocean"],["forest","Forest"],["bridal","Bridal"],["firefly","Firefly"]]},{name:"density",label:"Density",type:"number",default:18},{name:"speed",label:"Speed multiplier",type:"number",default:1,step:.1},{name:"wander",label:"Wander",type:"number",default:1,step:.1,hint:"Steering erraticness"},{name:"rise-speed",label:"Rise speed",type:"number",default:.4,step:.1,hint:"Upward drift bias"},{name:"flap-speed",label:"Flap speed",type:"number",default:1,step:.1},{name:"min-size",label:"Min wingspan (px)",type:"number",default:14},{name:"max-size",label:"Max wingspan (px)",type:"number",default:26},{name:"two-tone",label:"Two-tone wings",type:"checkbox",default:!0},{name:"burst",label:"Burst mode (one-shot)",type:"checkbox",default:!1},{name:"burst-count",label:"Burst count",type:"number",default:40}],hosts:["hero"],previewable:!0},{name:"strobe",label:"Strobe lighting",category:"Celebrations",description:"Light beams sweep from the corners and brighten where they cross - club, concert, or searchlight moods. Self-closing for full-page; wrapping form for container-scoped.",attrs:[{name:"preset",label:"Preset",type:"select",default:"club",options:[["club","Club"],["concert","Concert"],["police","Police"],["searchlight","Searchlight"],["scanner","Scanner"],["mood","Mood"]],hint:"Other fields override the preset when changed"},{name:"motion",label:"Motion",type:"select",default:"sweep",options:[["sweep","Sweep (fan back and forth)"],["rotate","Rotate (full circle)"]]},{name:"speed",label:"Speed multiplier",type:"number",default:1,step:.1},{name:"sweep-arc",label:"Sweep arc (deg)",type:"number",default:100},{name:"beam-width",label:"Beam width (deg)",type:"number",default:16},{name:"intensity",label:"Intensity",type:"number",default:.7,step:.05,min:0,max:1},{name:"flicker",label:"Flicker",type:"checkbox",default:!0},{name:"hz",label:"Flicker rate (Hz)",type:"number",default:10,hint:"Rates above 5 flashes/sec can trigger photosensitive seizures"},{name:"colours",label:"Colours",type:"text",default:"",placeholder:"#ffffff, #38bdf8",hint:"Comma-separated hex colours - overrides the preset palette"},{name:"duration",label:"Auto-stop (ms)",type:"number",default:"",hint:"Stop after this many ms - blank runs forever"}],hosts:["hero"],previewable:!0}];export function getEffect(t){return EFFECTS.find(e=>e.name===t)||null}export function effectsByCategory(){return["Entrance","Animation","Text","Visual","Celebrations"].map(e=>({category:e,effects:EFFECTS.filter(a=>a.category===e)}))}export function effectsInjectableInto(t){return EFFECTS.filter(e=>e.hosts.includes(t))}
1
+ import{CELEBRATION_THEMES as i,traitAttribute as f}from"../../../public/js/celebrations/trait-data.mjs";export{i as CELEBRATION_THEMES};export const EFFECTS=[{name:"reveal",label:"Reveal",category:"Entrance",description:"Scroll-triggered entrance animation when the element enters the viewport.",attrs:[{name:"animation",label:"Animation",type:"select",default:"fade",options:[["fade","Fade"],["slide-up","Slide up"],["slide-down","Slide down"],["zoom","Zoom"],["flip","Flip"]]},{name:"duration",label:"Duration (ms)",type:"number",default:600},{name:"delay",label:"Delay (ms)",type:"number",default:0},{name:"threshold",label:"Threshold",type:"number",default:.1,step:.05,min:0,max:1},{name:"once",label:"Animate once",type:"checkbox",default:!0}],hosts:["card","box","hero","banner","col"],previewable:!0},{name:"breathe",label:"Breathe",category:"Animation",description:"Continuous gentle scaling - makes elements feel alive.",attrs:[{name:"amplitude",label:"Amplitude (px)",type:"number",default:8},{name:"duration",label:"Duration (ms)",type:"number",default:3e3}],hosts:["card","box","hero","col","button"],previewable:!0},{name:"pulse",label:"Pulse",category:"Animation",description:"A repeating scale pulse - stronger than breathe.",attrs:[{name:"scale",label:"Scale",type:"number",default:1.05,step:.01},{name:"duration",label:"Duration (ms)",type:"number",default:1e3}],hosts:["card","box","hero","banner","button"],previewable:!0},{name:"shake",label:"Shake",category:"Animation",description:"One-shot horizontal or vertical shake.",attrs:[{name:"intensity",label:"Intensity (px)",type:"number",default:5},{name:"duration",label:"Duration (ms)",type:"number",default:500},{name:"direction",label:"Direction",type:"select",default:"horizontal",options:[["horizontal","Horizontal"],["vertical","Vertical"]]}],hosts:["card","box","banner","button"],previewable:!0},{name:"animate",label:"CSS Animate",category:"Animation",description:"Applies a Domma CSS animation utility class - no JavaScript.",attrs:[{name:"type",label:"Type",type:"select",default:"fade-in-up",options:[["fade-in","fade-in"],["fade-in-up","fade-in-up"],["fade-in-down","fade-in-down"],["fade-in-left","fade-in-left"],["fade-in-right","fade-in-right"],["slide-in-up","slide-in-up"],["slide-in-down","slide-in-down"],["zoom-in","zoom-in"],["zoom-out","zoom-out"],["bounce","bounce"],["pulse","pulse"],["shake","shake"],["spin","spin"],["flip","flip"]]},{name:"duration",label:"Duration",type:"select",default:"normal",options:[["fast","fast"],["normal","normal"],["slow","slow"],["slower","slower"]]},{name:"delay",label:"Delay (ms)",type:"number",default:0},{name:"repeat",label:"Repeat",type:"select",default:"once",options:[["once","Once"],["infinite","Infinite"]]}],hosts:["card","box","hero","banner","col","button"],previewable:!0},{name:"scribe",label:"Scribe (typewriter)",category:"Text",description:"Types text character by character. Simple mode only - for the action-script composer use Insert \u2192 Scribe.",attrs:[{name:"speed",label:"Speed (ms/char)",type:"number",default:50},{name:"cursor",label:"Show cursor",type:"checkbox",default:!0},{name:"loop",label:"Loop",type:"checkbox",default:!1}],hosts:[],previewable:!0},{name:"scramble",label:"Scramble",category:"Text",description:"Reveals text through a character-scramble animation.",attrs:[{name:"speed",label:"Speed (ms/char)",type:"number",default:50},{name:"loop",label:"Loop",type:"checkbox",default:!1}],hosts:[],previewable:!0},{name:"counter",label:"Counter",category:"Text",description:"Animates a number from a starting value to a target. Self-closing shortcode.",attrs:[{name:"to",label:"To",type:"number",default:100},{name:"from",label:"From",type:"number",default:0},{name:"duration",label:"Duration (ms)",type:"number",default:2e3},{name:"prefix",label:"Prefix",type:"text",default:""},{name:"suffix",label:"Suffix",type:"text",default:""},{name:"decimals",label:"Decimal places",type:"number",default:0},{name:"separator",label:"Thousand separator",type:"text",default:""}],hosts:[],previewable:!0,selfClosing:!0},{name:"ripple",label:"Ripple",category:"Visual",description:"Click-triggered ripple effect on the element.",attrs:[{name:"colour",label:"Colour",type:"colour",default:"#7c6af7"},{name:"duration",label:"Duration (ms)",type:"number",default:600},{name:"opacity",label:"Opacity",type:"number",default:.3,step:.05,min:0,max:1}],hosts:["card","box","col","button"],previewable:!0},{name:"twinkle",label:"Twinkle",category:"Visual",description:"Generates animated particle effects inside the element.",attrs:[{name:"count",label:"Particle count",type:"number",default:80},{name:"shape",label:"Shape",type:"select",default:"star",options:[["star","Star"],["circle","Circle"],["square","Square"]]},{name:"colour",label:"Colour",type:"colour",default:"#ffffff"},{name:"min-size",label:"Min size (px)",type:"number",default:2},{name:"max-size",label:"Max size (px)",type:"number",default:6}],hosts:["card","box","hero"],previewable:!0},{name:"ambient",label:"Ambient background",category:"Visual",description:"Applies an animated CSS background class to the element.",attrs:[{name:"type",label:"Type",type:"select",default:"float-blobs",options:[["float-blobs","Float blobs"],["float-orbs","Float orbs"],["float-particles","Float particles"],["rotate-glow","Rotate glow"],["rotate-dual","Rotate dual"],["rotate-spotlight","Rotate spotlight"],["wave","Wave"],["ripple","Ripple"],["aurora","Aurora"]]},{name:"speed",label:"Speed",type:"select",default:"normal",options:[["slow","Slow"],["normal","Normal"],["fast","Fast"]]},{name:"intensity",label:"Intensity",type:"select",default:"subtle",options:[["subtle","Subtle"],["intense","Intense"]]}],hosts:["card","box","hero","banner"],previewable:!0},{name:"firework",label:"Firework",category:"Celebrations",description:"CSS-only firework particle. Self-closing or wrapping form.",attrs:[{name:"type",label:"Type",type:"select",default:"burst",options:[["burst","Burst"],["sparkle","Sparkle"],["trail","Trail"]]},{name:"colour",label:"Colour theme",type:"select",default:"rainbow",options:[["rainbow","Rainbow"],["primary","Primary"],["info","Info"],["success","Success"],["warning","Warning"],["danger","Danger"]]},{name:"size",label:"Size",type:"select",default:"md",options:[["sm","Small"],["md","Medium"],["lg","Large"]]},{name:"continuous",label:"Continuous",type:"checkbox",default:!1},{name:"hover",label:"On hover only",type:"checkbox",default:!1}],hosts:[],previewable:!0},{name:"fireworks",label:"Fireworks show",category:"Celebrations",description:"A container with multiple firework particles inside.",attrs:[],hosts:[],previewable:!1},{name:"celebrate",label:"Celebrate",category:"Celebrations",description:"Canvas-based seasonal particle system. Runs full-page on the published site.",attrs:[{name:"theme",label:"Theme",type:"select",default:"auto",options:[["auto","Auto (date-detected)"],["christmas","Christmas"],["halloween","Halloween"],["valentines","Valentines"],["guy-fawkes","Guy Fawkes"],["st-patricks","St Patrick's"],["st-davids","St David's"],["st-georges","St George's"],["st-andrews","St Andrew's"]]},{name:"intensity",label:"Intensity",type:"select",default:"medium",options:[["light","Light"],["medium","Medium"],["heavy","Heavy"]]},{name:"snow-only",label:"Snow only (Christmas)",type:"checkbox",default:!1,hint:"Just the falling snow - every Christmas decoration off."},{name:"trees",label:"Christmas: trees",type:"select",default:"",options:[["","Shown"],["off","Off"]]},{name:"wreaths",label:"Christmas: wreaths",type:"select",default:"",options:[["","Shown"],["off","Off"]]},{name:"northstars",label:"Christmas: North Star",type:"select",default:"",options:[["","Shown"],["off","Off"]]},{name:"snowmen",label:"Christmas: snowmen",type:"select",default:"",options:[["","Shown"],["off","Off"]]},{name:"sleigh",label:"Christmas: Santa's sleigh",type:"select",default:"",options:[["","Shown"],["off","Off"]]},{name:"elf",label:"Christmas: elf",type:"select",default:"",options:[["","Shown"],["off","Off"]]},{name:"train",label:"Christmas: train",type:"select",default:"",options:[["","Shown"],["off","Off"]]},{name:"firework",label:"Christmas: fireworks",type:"select",default:"",options:[["","Shown"],["off","Off"]]},{name:"robin",label:"Christmas: robin",type:"select",default:"",options:[["","Shown"],["off","Off"]]},{name:"peeing-elf",label:"Peeing elf (opt-in)",type:"checkbox",default:!1,hint:"A clothed rear-view gag. Off by default; Snow only keeps it off."},{name:"thieving-elf",label:"Thieving elf (opt-in)",type:"checkbox",default:!1,hint:"Runs to a tree, takes a present and escapes. Needs a visible tree."}],hosts:[],previewable:!1,selfClosing:!0},{name:"christmas",label:"Christmas",category:"Celebrations",description:"Christmas on the published site: snow, trees, wreaths, snowmen, Santa's sleigh and more. Snow only for just the snow.",attrs:[{name:"intensity",label:"Intensity",type:"select",default:"medium",options:[["light","Light"],["medium","Medium"],["heavy","Heavy"]]},{name:"snow-only",label:"Snow only",type:"checkbox",default:!1,hint:"Just the falling snow - every decoration off."},{name:"trees",label:"trees",type:"select",default:"",options:[["","Shown"],["off","Off"]]},{name:"wreaths",label:"wreaths",type:"select",default:"",options:[["","Shown"],["off","Off"]]},{name:"northstars",label:"North Star",type:"select",default:"",options:[["","Shown"],["off","Off"]]},{name:"snowmen",label:"snowmen",type:"select",default:"",options:[["","Shown"],["off","Off"]]},{name:"sleigh",label:"Santa's sleigh",type:"select",default:"",options:[["","Shown"],["off","Off"]]},{name:"elf",label:"elf",type:"select",default:"",options:[["","Shown"],["off","Off"]]},{name:"train",label:"train",type:"select",default:"",options:[["","Shown"],["off","Off"]]},{name:"firework",label:"fireworks",type:"select",default:"",options:[["","Shown"],["off","Off"]]},{name:"robin",label:"robin",type:"select",default:"",options:[["","Shown"],["off","Off"]]},{name:"peeing-elf",label:"Peeing elf (opt-in)",type:"checkbox",default:!1,hint:"A clothed rear-view gag. Off by default; Snow only keeps it off."},{name:"thieving-elf",label:"Thieving elf (opt-in)",type:"checkbox",default:!1,hint:"Runs to a tree, takes a present and escapes. Needs a visible tree."}],hosts:[],previewable:!1,selfClosing:!0},{name:"ticker-tape",label:"Ticker tape",category:"Celebrations",description:"Coloured rectangular strips fall from the top, sway, rotate, and fade. Inserted self-closing (full-page); hand-write the wrapping form for container-scoped.",attrs:[{name:"palette",label:"Palette",type:"select",default:"theme",options:[["theme","Theme"],["rainbow","Rainbow"],["gold","Gold"],["silver","Silver"],["festive","Festive"],["pastel","Pastel"],["mono","Mono"]]},{name:"density",label:"Density",type:"number",default:50},{name:"speed",label:"Speed multiplier",type:"number",default:1,step:.1},{name:"sway",label:"Sway (px)",type:"number",default:60},{name:"burst",label:"Burst mode (one-shot)",type:"checkbox",default:!1},{name:"burst-count",label:"Burst count",type:"number",default:150}],hosts:["hero"],previewable:!0,selfClosing:!0},{name:"butterflies",label:"Butterflies",category:"Celebrations",description:"Procedurally drawn butterflies wander and rise with flapping wings. Self-closing for full-page; wrapping form for container-scoped.",attrs:[{name:"palette",label:"Palette",type:"select",default:"meadow",options:[["meadow","Meadow"],["theme","Theme"],["rainbow","Rainbow"],["pastel","Pastel"],["festive","Festive"],["gold","Gold"],["silver","Silver"],["mono","Mono"],["sunset","Sunset"],["ocean","Ocean"],["forest","Forest"],["bridal","Bridal"],["firefly","Firefly"]]},{name:"density",label:"Density",type:"number",default:18},{name:"speed",label:"Speed multiplier",type:"number",default:1,step:.1},{name:"wander",label:"Wander",type:"number",default:1,step:.1,hint:"Steering erraticness"},{name:"rise-speed",label:"Rise speed",type:"number",default:.4,step:.1,hint:"Upward drift bias"},{name:"flap-speed",label:"Flap speed",type:"number",default:1,step:.1},{name:"min-size",label:"Min wingspan (px)",type:"number",default:14},{name:"max-size",label:"Max wingspan (px)",type:"number",default:26},{name:"two-tone",label:"Two-tone wings",type:"checkbox",default:!0},{name:"burst",label:"Burst mode (one-shot)",type:"checkbox",default:!1},{name:"burst-count",label:"Burst count",type:"number",default:40}],hosts:["hero"],previewable:!0},{name:"strobe",label:"Strobe lighting",category:"Celebrations",description:"Light beams sweep from the corners and brighten where they cross - club, concert, or searchlight moods. Self-closing for full-page; wrapping form for container-scoped.",attrs:[{name:"preset",label:"Preset",type:"select",default:"club",options:[["club","Club"],["concert","Concert"],["police","Police"],["searchlight","Searchlight"],["scanner","Scanner"],["mood","Mood"]],hint:"Other fields override the preset when changed"},{name:"motion",label:"Motion",type:"select",default:"sweep",options:[["sweep","Sweep (fan back and forth)"],["rotate","Rotate (full circle)"]]},{name:"speed",label:"Speed multiplier",type:"number",default:1,step:.1},{name:"sweep-arc",label:"Sweep arc (deg)",type:"number",default:100},{name:"beam-width",label:"Beam width (deg)",type:"number",default:16},{name:"intensity",label:"Intensity",type:"number",default:.7,step:.05,min:0,max:1},{name:"flicker",label:"Flicker",type:"checkbox",default:!0},{name:"hz",label:"Flicker rate (Hz)",type:"number",default:10,hint:"Rates above 5 flashes/sec can trigger photosensitive seizures"},{name:"colours",label:"Colours",type:"text",default:"",placeholder:"#ffffff, #38bdf8",hint:"Comma-separated hex colours - overrides the preset palette"},{name:"duration",label:"Auto-stop (ms)",type:"number",default:"",hint:"Stop after this many ms - blank runs forever"}],hosts:["hero"],previewable:!0}];export function getEffect(e){return EFFECTS.find(t=>t.name===e)||null}export function effectsByCategory(){return["Entrance","Animation","Text","Visual","Celebrations"].map(t=>({category:t,effects:EFFECTS.filter(l=>l.category===t)}))}export function effectsInjectableInto(e){return EFFECTS.filter(t=>t.hosts.includes(e))}const n=EFFECTS.find(e=>e.name==="celebrate");for(const e of n.attrs.slice(2))e.themes=["christmas"];n.attrs.push({name:"falling-only",label:"Falling particles only",type:"checkbox",default:!1});const r=new Map(n.attrs.map(e=>[e.name,e]));for(const[e,t]of Object.entries(i))if(e!=="christmas")for(const[l,o]of Object.entries(t.traits)){const s=f(l);let a=r.get(s);a||(a={name:s,label:o.label,type:"select",default:"",options:[["","Shown"],["off","Off"]],themes:[]},r.set(s,a)),a.themes.includes(e)||a.themes.push(e),a.themes.length>1&&(a.label=a.label.replace(/^Christmas: /,""))}for(const e of r.values())n.attrs.includes(e)||n.attrs.push(e);export function getEffectAttrs(e,t={}){if(e.name!=="celebrate")return e.attrs||[];const l=t.theme||"auto";return e.attrs.filter(o=>!o.themes||l==="auto"||o.themes.includes(l))}
@@ -1,3 +1,3 @@
1
- import{EFFECTS as _,effectsByCategory as z,effectsInjectableInto as A,getEffect as u}from"./effect-defs.js";import{insertAtCursor as R,replaceRange as x}from"./markdown-toolbar.js";let g=null;function j(e,t,r=14){e.textContent="";const o=document.createElement("span");return o.setAttribute("data-icon",t),o.setAttribute("data-icon-size",String(r)),o.style.cssText="display:inline-flex;align-items:center;vertical-align:middle;",e.appendChild(o),I.scan(e),e}function L(e,t,r,o=14){return j(e,t,o),e.appendChild(document.createTextNode(" "+r)),e}export const EffectsBuilder={open(e){if(g)return;const t={textarea:e,activeEffect:S.get("effects-builder-last")||"reveal",scope:"standalone",host:null,editing:null,fieldValues:{}};if(t.host=F(e),t.host&&A(t.host.name).map(c=>c.name).includes(t.activeEffect)&&!(t.activeEffect in t.host.attrs)&&(t.scope="inject"),t.editing=q(e),t.editing){t.activeEffect=t.editing.name,t.scope="standalone";const a=u(t.editing.name);for(const c of a.attrs)if(c.name in t.editing.attrs){const s=t.editing.attrs[c.name];c.type==="number"?t.fieldValues[c.name]=Number(s):c.type==="checkbox"?t.fieldValues[c.name]=s==="true":t.fieldValues[c.name]=s}}const r=E.slideover({title:"Effects",size:"lg",position:"right",onClose:()=>{g=null}}),o=O(t,r);r.element.appendChild(o),r.open(),I.scan(o),g={state:t,slideover:r}},close(){g&&(g.slideover.close(),g=null)}};function O(e,t){const r=document.createElement("div");r.style.cssText="display:grid;grid-template-columns:170px 1fr;height:100%;min-height:520px;";const o=document.createElement("div");o.className="effects-rail",o.style.cssText="background:var(--dm-background-alt,#15152a);border-right:1px solid var(--dm-border,#2a2a40);padding:.5rem .35rem;font-size:.8rem;overflow-y:auto;";const a=document.createElement("div");a.className="effects-pane",a.style.cssText="padding:1rem;display:flex;flex-direction:column;gap:.75rem;overflow-y:auto;";function c(){H(a,e,t)}return b(o,e,c),c(),r.appendChild(o),r.appendChild(a),r}function b(e,t,r){e.replaceChildren();for(const o of z()){const a=document.createElement("div");a.style.cssText="color:var(--dm-text-muted,#888);text-transform:uppercase;font-size:.65rem;letter-spacing:.05em;margin:.4rem .35rem .25rem;",a.textContent=o.category,e.appendChild(a);for(const c of o.effects){const s=document.createElement("button");s.type="button",s.dataset.effect=c.name,s.style.cssText="display:block;width:100%;text-align:left;padding:.3rem .5rem;border:none;background:transparent;color:var(--dm-text,#ddd);border-radius:3px;font-size:.8rem;cursor:pointer;margin-bottom:.1rem;",s.textContent=c.label,c.name===t.activeEffect&&(s.style.background="var(--dm-primary,#4338ca)",s.style.color="var(--dm-primary-text,#fff)"),s.addEventListener("click",()=>{t.activeEffect=c.name,S.set("effects-builder-last",c.name),t.fieldValues={},b(e,t,r),r()}),e.appendChild(s)}}}function V(e,t){if(e.type==="select"){const o=document.createElement("select");o.style.cssText="width:100%;padding:.35rem .5rem;background:var(--dm-input-bg,#1a1a1a);border:1px solid var(--dm-border,#333);border-radius:3px;color:var(--dm-text,#eee);font-size:.85rem;";for(const[a,c]of e.options){const s=document.createElement("option");s.value=a,s.textContent=c,o.appendChild(s)}return o.value=t??e.default??"",o}if(e.type==="checkbox"){const o=document.createElement("input");return o.type="checkbox",o.checked=t??e.default??!1,o}const r=document.createElement("input");return r.type=e.type==="number"?"number":e.type==="colour"?"color":"text",r.value=t??e.default??"",e.placeholder&&(r.placeholder=e.placeholder),e.type==="number"&&(e.min!=null&&(r.min=e.min),e.max!=null&&(r.max=e.max),e.step!=null&&(r.step=e.step)),r.style.cssText="width:100%;padding:.35rem .5rem;background:var(--dm-input-bg,#1a1a1a);border:1px solid var(--dm-border,#333);border-radius:3px;color:var(--dm-text,#eee);font-size:.85rem;",r}function v(e,t){return t.type==="checkbox"?e.checked:t.type==="number"?e.value===""?"":Number(e.value):e.value}function N(e,t,r){const o=u(t.activeEffect);if(e.replaceChildren(),o.attrs.length===0){const c=document.createElement("div");c.style.cssText="color:var(--dm-text-muted,#888);font-size:.8rem;font-style:italic;",c.textContent="This effect takes no parameters.",e.appendChild(c);return}const a=document.createElement("div");a.style.cssText="display:grid;grid-template-columns:1fr 1fr;gap:.6rem .7rem;";for(const c of o.attrs){const s=document.createElement("div"),d=document.createElement("label");d.style.cssText="display:block;color:var(--dm-text-muted,#888);font-size:.7rem;text-transform:uppercase;letter-spacing:.05em;margin-bottom:.2rem;",d.textContent=c.label,s.appendChild(d);const i=V(c,t.fieldValues[c.name]);if(i.addEventListener("input",()=>{t.fieldValues[c.name]=v(i,c),r()}),i.addEventListener("change",()=>{t.fieldValues[c.name]=v(i,c),r()}),s.appendChild(i),c.hint){const n=document.createElement("div");n.style.cssText="color:var(--dm-text-muted,#666);font-size:.7rem;margin-top:.15rem;",n.textContent=c.hint,s.appendChild(n)}a.appendChild(s)}e.appendChild(a)}function y(e){const t={},r=/(\w[\w-]*)(?:\s*=\s*"([^"]*)"|\s*=\s*'([^']*)'|\s*=\s*(\S+))?/g;for(const o of e.matchAll(r)){const a=o[1],c=o[2]??o[3]??o[4]??"";t[a]=c}return t}const B=_.filter(e=>!e.selfClosing).map(e=>e.name);function q(e){const t=e.value,r=e.selectionStart;for(const o of B){const a=new RegExp(`\\[${o}([^\\]]*)\\]`,"g"),c=new RegExp(`\\[/${o}\\]`,"g"),s=[];for(const n of t.matchAll(a)){if(n.index>=r)break;s.push({type:"open",start:n.index,end:n.index+n[0].length,attrStr:n[1]})}for(const n of t.matchAll(c)){if(n.index>=r)break;s.push({type:"close",start:n.index,end:n.index+n[0].length})}s.sort((n,l)=>n.start-l.start);let d=0,i=null;for(const n of s)n.type==="open"?(d++,i=n):(d--,d<0&&(d=0,i=null));if(d>0&&i){const n=new RegExp(`\\[/${o}\\]`,"g"),l=t.slice(r),m=l.match(n);if(m){const f=r+l.indexOf(m[0]);return{name:o,blockStart:i.start,blockEnd:f+m[0].length,openTagEnd:i.end,attrs:y(i.attrStr)}}}}return null}const P=["card","box","hero","banner","col","button"];function F(e){const t=e.value,r=e.selectionStart;for(const o of P){const a=new RegExp(`\\[${o}([^\\]]*)\\]`,"g"),c=new RegExp(`\\[/${o}\\]`,"g"),s=[];for(const n of t.matchAll(a)){if(n.index>=r)break;s.push({type:"open",start:n.index,end:n.index+n[0].length,attrStr:n[1]})}for(const n of t.matchAll(c)){if(n.index>=r)break;s.push({type:"close",start:n.index,end:n.index+n[0].length})}s.sort((n,l)=>n.start-l.start);let d=0,i=null;for(const n of s)n.type==="open"?(d++,i=n):(d--,d<0&&(d=0,i=null));if(d>0&&i){const n=new RegExp(`\\[/${o}\\]`,"g"),l=t.slice(r),m=l.match(n);if(m){const f=r+l.indexOf(m[0]);return{name:o,openTagStart:i.start,openTagEnd:i.end,closeTagStart:f,closeTagEnd:f+m[0].length,attrs:y(i.attrStr)}}}}return null}function C(e,t){const r=[];for(const o of t.attrs){const a=e.fieldValues[o.name];a===void 0||a===""||a===null||a!==o.default&&(o.type==="checkbox"?r.push(`${o.name}="${a?"true":"false"}"`):r.push(`${o.name}="${String(a).replace(/"/g,"&quot;")}"`))}return r.join(" ")}function k(e){const t=u(e.activeEffect),r=C(e,t),o=r?" ":"";if(e.scope==="inject"&&e.host){const a=e.host.attrs,c=t.name,s=[];for(const d of Object.keys(a)){if(d===c||d.startsWith(c+"-"))continue;const i=a[d];s.push(i===""?d:`${d}="${String(i).replace(/"/g,"&quot;")}"`)}s.push(c);for(const d of t.attrs){const i=e.fieldValues[d.name];if(i===void 0||i===""||i===null||i===d.default)continue;const n=d.type==="checkbox"?i?"true":"false":String(i).replace(/"/g,"&quot;");s.push(`${c}-${d.name}="${n}"`)}return`[${e.host.name} ${s.join(" ")}]\u2026[/${e.host.name}]`}return t.selfClosing?`[${t.name}${o}${r} /]`:`[${t.name}${o}${r}]
1
+ import{EFFECTS as A,effectsByCategory as V,effectsInjectableInto as R,getEffect as u,getEffectAttrs as g}from"./effect-defs.js";import{insertAtCursor as j,replaceRange as v}from"./markdown-toolbar.js";let h=null;function L(e,t,n=14){e.textContent="";const r=document.createElement("span");return r.setAttribute("data-icon",t),r.setAttribute("data-icon-size",String(n)),r.style.cssText="display:inline-flex;align-items:center;vertical-align:middle;",e.appendChild(r),I.scan(e),e}function O(e,t,n,r=14){return L(e,t,r),e.appendChild(document.createTextNode(" "+n)),e}export const EffectsBuilder={open(e){if(h)return;const t={textarea:e,activeEffect:S.get("effects-builder-last")||"reveal",scope:"standalone",host:null,editing:null,fieldValues:{}};if(t.host=D(e),t.host&&R(t.host.name).map(c=>c.name).includes(t.activeEffect)&&!(t.activeEffect in t.host.attrs)&&(t.scope="inject"),t.editing=P(e),t.editing){t.activeEffect=t.editing.name,t.scope="standalone";const i=u(t.editing.name);for(const c of g(i,t.fieldValues))if(c.name in t.editing.attrs){const s=t.editing.attrs[c.name];c.type==="number"?t.fieldValues[c.name]=Number(s):c.type==="checkbox"?t.fieldValues[c.name]=s==="true":t.fieldValues[c.name]=s}}const n=E.slideover({title:"Effects",size:"lg",position:"right",onClose:()=>{h=null}}),r=N(t,n);n.element.appendChild(r),n.open(),I.scan(r),h={state:t,slideover:n}},close(){h&&(h.slideover.close(),h=null)}};function N(e,t){const n=document.createElement("div");n.style.cssText="display:grid;grid-template-columns:170px 1fr;height:100%;min-height:520px;";const r=document.createElement("div");r.className="effects-rail",r.style.cssText="background:var(--dm-background-alt,#15152a);border-right:1px solid var(--dm-border,#2a2a40);padding:.5rem .35rem;font-size:.8rem;overflow-y:auto;";const i=document.createElement("div");i.className="effects-pane",i.style.cssText="padding:1rem;display:flex;flex-direction:column;gap:.75rem;overflow-y:auto;";function c(){K(i,e,t)}return y(r,e,c),c(),n.appendChild(r),n.appendChild(i),n}function y(e,t,n){e.replaceChildren();for(const r of V()){const i=document.createElement("div");i.style.cssText="color:var(--dm-text-muted,#888);text-transform:uppercase;font-size:.65rem;letter-spacing:.05em;margin:.4rem .35rem .25rem;",i.textContent=r.category,e.appendChild(i);for(const c of r.effects){const s=document.createElement("button");s.type="button",s.dataset.effect=c.name,s.style.cssText="display:block;width:100%;text-align:left;padding:.3rem .5rem;border:none;background:transparent;color:var(--dm-text,#ddd);border-radius:3px;font-size:.8rem;cursor:pointer;margin-bottom:.1rem;",s.textContent=c.label,c.name===t.activeEffect&&(s.style.background="var(--dm-primary,#4338ca)",s.style.color="var(--dm-primary-text,#fff)"),s.addEventListener("click",()=>{t.activeEffect=c.name,S.set("effects-builder-last",c.name),t.fieldValues={},y(e,t,n),n()}),e.appendChild(s)}}}function B(e,t){if(e.type==="select"){const r=document.createElement("select");r.style.cssText="width:100%;padding:.35rem .5rem;background:var(--dm-input-bg,#1a1a1a);border:1px solid var(--dm-border,#333);border-radius:3px;color:var(--dm-text,#eee);font-size:.85rem;";for(const[i,c]of e.options){const s=document.createElement("option");s.value=i,s.textContent=c,r.appendChild(s)}return r.value=t??e.default??"",r}if(e.type==="checkbox"){const r=document.createElement("input");return r.type="checkbox",r.checked=t??e.default??!1,r}const n=document.createElement("input");return n.type=e.type==="number"?"number":e.type==="colour"?"color":"text",n.value=t??e.default??"",e.placeholder&&(n.placeholder=e.placeholder),e.type==="number"&&(e.min!=null&&(n.min=e.min),e.max!=null&&(n.max=e.max),e.step!=null&&(n.step=e.step)),n.style.cssText="width:100%;padding:.35rem .5rem;background:var(--dm-input-bg,#1a1a1a);border:1px solid var(--dm-border,#333);border-radius:3px;color:var(--dm-text,#eee);font-size:.85rem;",n}function C(e,t){return t.type==="checkbox"?e.checked:t.type==="number"?e.value===""?"":Number(e.value):e.value}function x(e,t,n){const r=u(t.activeEffect);if(e.replaceChildren(),r.attrs.length===0){const c=document.createElement("div");c.style.cssText="color:var(--dm-text-muted,#888);font-size:.8rem;font-style:italic;",c.textContent="This effect takes no parameters.",e.appendChild(c);return}const i=document.createElement("div");i.style.cssText="display:grid;grid-template-columns:1fr 1fr;gap:.6rem .7rem;";for(const c of g(r,t.fieldValues)){const s=document.createElement("div"),l=document.createElement("label");l.style.cssText="display:block;color:var(--dm-text-muted,#888);font-size:.7rem;text-transform:uppercase;letter-spacing:.05em;margin-bottom:.2rem;",l.textContent=c.label,s.appendChild(l);const d=B(c,t.fieldValues[c.name]);if(d.addEventListener("input",()=>{t.fieldValues[c.name]=C(d,c),n(),c.name==="theme"&&x(e,t,n)}),d.addEventListener("change",()=>{t.fieldValues[c.name]=C(d,c),n(),c.name==="theme"&&x(e,t,n)}),s.appendChild(d),c.hint){const o=document.createElement("div");o.style.cssText="color:var(--dm-text-muted,#666);font-size:.7rem;margin-top:.15rem;",o.textContent=c.hint,s.appendChild(o)}i.appendChild(s)}e.appendChild(i)}function k(e){const t={},n=/(\w[\w-]*)(?:\s*=\s*"([^"]*)"|\s*=\s*'([^']*)'|\s*=\s*(\S+))?/g;for(const r of e.matchAll(n)){const i=r[1],c=r[2]??r[3]??r[4]??"";t[i]=c}return t}const q=A.filter(e=>!e.selfClosing).map(e=>e.name);function P(e){const t=e.value,n=e.selectionStart;for(const r of q){const i=new RegExp(`\\[${r}([^\\]]*)\\]`,"g"),c=new RegExp(`\\[/${r}\\]`,"g"),s=[];for(const o of t.matchAll(i)){if(o.index>=n)break;s.push({type:"open",start:o.index,end:o.index+o[0].length,attrStr:o[1]})}for(const o of t.matchAll(c)){if(o.index>=n)break;s.push({type:"close",start:o.index,end:o.index+o[0].length})}s.sort((o,a)=>o.start-a.start);let l=0,d=null;for(const o of s)o.type==="open"?(l++,d=o):(l--,l<0&&(l=0,d=null));if(l>0&&d){const o=new RegExp(`\\[/${r}\\]`,"g"),a=t.slice(n),m=a.match(o);if(m){const f=n+a.indexOf(m[0]);return{name:r,blockStart:d.start,blockEnd:f+m[0].length,openTagEnd:d.end,attrs:k(d.attrStr)}}}}return null}const F=["card","box","hero","banner","col","button"];function D(e){const t=e.value,n=e.selectionStart;for(const r of F){const i=new RegExp(`\\[${r}([^\\]]*)\\]`,"g"),c=new RegExp(`\\[/${r}\\]`,"g"),s=[];for(const o of t.matchAll(i)){if(o.index>=n)break;s.push({type:"open",start:o.index,end:o.index+o[0].length,attrStr:o[1]})}for(const o of t.matchAll(c)){if(o.index>=n)break;s.push({type:"close",start:o.index,end:o.index+o[0].length})}s.sort((o,a)=>o.start-a.start);let l=0,d=null;for(const o of s)o.type==="open"?(l++,d=o):(l--,l<0&&(l=0,d=null));if(l>0&&d){const o=new RegExp(`\\[/${r}\\]`,"g"),a=t.slice(n),m=a.match(o);if(m){const f=n+a.indexOf(m[0]);return{name:r,openTagStart:d.start,openTagEnd:d.end,closeTagStart:f,closeTagEnd:f+m[0].length,attrs:k(d.attrStr)}}}}return null}function T(e,t){const n=[];for(const r of g(t,e.fieldValues)){const i=e.fieldValues[r.name];i===void 0||i===""||i===null||i!==r.default&&(r.type==="checkbox"?n.push(`${r.name}="${i?"true":"false"}"`):n.push(`${r.name}="${String(i).replace(/"/g,"&quot;")}"`))}return n.join(" ")}function $(e){const t=u(e.activeEffect),n=T(e,t),r=n?" ":"";if(e.scope==="inject"&&e.host){const i=e.host.attrs,c=t.name,s=[];for(const l of Object.keys(i)){if(l===c||l.startsWith(c+"-"))continue;const d=i[l];s.push(d===""?l:`${l}="${String(d).replace(/"/g,"&quot;")}"`)}s.push(c);for(const l of g(t,e.fieldValues)){const d=e.fieldValues[l.name];if(d===void 0||d===""||d===null||d===l.default)continue;const o=l.type==="checkbox"?d?"true":"false":String(d).replace(/"/g,"&quot;");s.push(`${c}-${l.name}="${o}"`)}return`[${e.host.name} ${s.join(" ")}]\u2026[/${e.host.name}]`}return t.selfClosing?`[${t.name}${r}${n} /]`:`[${t.name}${r}${n}]
2
2
  Content
3
- [/${t.name}]`}function T(e,t){e.replaceChildren();const r=document.createElement("div");r.style.cssText="color:var(--dm-text-muted,#888);font-size:.7rem;text-transform:uppercase;letter-spacing:.05em;margin-bottom:.25rem;",r.textContent="Shortcode (live)",e.appendChild(r);const o=document.createElement("pre");o.style.cssText="background:var(--dm-code-bg,#000);border:1px solid var(--dm-border,#333);padding:.5rem .65rem;border-radius:3px;font-family:var(--dm-font-mono,monospace);font-size:.75rem;color:var(--dm-code-text,#7c6af7);line-height:1.5;white-space:pre-wrap;word-break:break-all;margin:0;",o.textContent=k(t),e.appendChild(o)}function D(e,t,r){if(e.replaceChildren(),t.editing)return;const o=u(t.activeEffect),a=t.host&&o.hosts.includes(t.host.name),c=document.createElement("div");c.style.cssText="background:var(--dm-background-alt,#15152a);border:1px solid var(--dm-border,#2a2a40);border-radius:4px;padding:.5rem .6rem;";const s=document.createElement("div");if(s.style.cssText="color:var(--dm-text-muted,#888);text-transform:uppercase;font-size:.65rem;letter-spacing:.05em;margin-bottom:.3rem;",s.textContent="Apply as",c.appendChild(s),!a){const n=document.createElement("div");n.style.cssText="color:var(--dm-text-muted,#888);font-size:.75rem;font-style:italic;",t.host?n.textContent=`Inserted as a standalone block (${o.label} cannot be injected into [${t.host.name}]).`:n.textContent="Inserted as a standalone block.",c.appendChild(n),e.appendChild(c),t.scope="standalone";return}const d=document.createElement("div");d.style.cssText="display:flex;gap:.3rem;";function i(n,l){const m=document.createElement("button");return m.type="button",m.style.cssText="flex:1;padding:.35rem;border:1px solid var(--dm-border,#333);border-radius:3px;font-size:.75rem;font-weight:600;cursor:pointer;",t.scope===n?(m.style.background="var(--dm-primary,#4338ca)",m.style.color="var(--dm-primary-text,#fff)",m.style.borderColor="var(--dm-primary,#4338ca)"):(m.style.background="transparent",m.style.color="var(--dm-text-muted,#bbb)"),m.textContent=l,m.addEventListener("click",()=>{t.scope=n,r()}),m}d.appendChild(i("standalone","Standalone block")),d.appendChild(i("inject",`Inject into [${t.host.name}]`)),c.appendChild(d),e.appendChild(c)}let h=0;function $(e){return e.replace(/-([a-z])/g,(t,r)=>r.toUpperCase())}function w(e,t){e.replaceChildren();const r=u(t.activeEffect),o=document.createElement("div");o.style.cssText="display:flex;justify-content:space-between;align-items:center;margin-bottom:.25rem;";const a=document.createElement("div");if(a.style.cssText="color:var(--dm-text-muted,#888);text-transform:uppercase;font-size:.65rem;letter-spacing:.05em;",a.textContent="Live preview",o.appendChild(a),!r.previewable){const i=document.createElement("div");i.style.cssText="background:var(--dm-background-alt,#15152a);border:1px solid var(--dm-border,#2a2a40);border-radius:4px;padding:.6rem;color:var(--dm-text-muted,#888);font-size:.8rem;font-style:italic;text-align:center;",i.textContent="Runs full-page on the published site - no inline preview.",e.appendChild(i);return}const c=document.createElement("button");c.type="button",c.style.cssText="background:transparent;border:1px solid var(--dm-border,#333);color:var(--dm-text-muted,#888);font-size:.65rem;padding:.15rem .4rem;border-radius:2px;cursor:pointer;",L(c,"refresh-cw","Replay",12),o.appendChild(c),e.appendChild(o);const s=document.createElement("div");s.style.cssText="background:var(--dm-background-alt,#1a1a2e);border:1px solid var(--dm-border,#2a2a40);border-radius:4px;padding:1rem;text-align:center;min-height:80px;position:relative;overflow:hidden;",e.appendChild(s);function d(){h++;const i=h;s.replaceChildren();const n=document.createElement("div");n.style.cssText="background:linear-gradient(135deg,#6366f1,#a855f7);color:#fff;padding:.6rem;border-radius:4px;font-size:.8rem;font-weight:600;",n.textContent="Sample content",s.appendChild(n);const l=window.Domma&&window.Domma.effects;if(!l)return;const m={};for(const f of r.attrs){const p=t.fieldValues[f.name];p===void 0||p===""||p===null||(m[$(f.name)]=p)}try{const f=l[$(r.name)];if(typeof f=="function"){if(i!==h)return;f(n,m)}}catch(f){console.warn("Effects preview failed:",f)}}c.addEventListener("click",d),d()}function H(e,t,r){const o=u(t.activeEffect);e.replaceChildren();const a=document.createElement("h3");a.style.cssText="margin:0;font-size:1rem;color:var(--dm-text,#eee);",a.textContent=o.label,e.appendChild(a);const c=document.createElement("p");c.style.cssText="margin:0;color:var(--dm-text-muted,#999);font-size:.8rem;line-height:1.4;",c.textContent=o.description,e.appendChild(c);const s=document.createElement("div");e.appendChild(s);const d=document.createElement("div");e.appendChild(d);const i=document.createElement("div");e.appendChild(i);const n=document.createElement("div");e.appendChild(n);function l(){D(s,t,l),N(d,t,()=>{T(i,t),w(n,t)}),T(i,t),w(n,t)}l();const m=document.createElement("div");m.style.cssText="display:flex;gap:.5rem;margin-top:auto;padding-top:.75rem;border-top:1px solid var(--dm-border,#2a2a40);";const f=document.createElement("button");f.type="button",f.className="btn btn-ghost",f.textContent="Cancel",f.addEventListener("click",()=>r.close()),m.appendChild(f);const p=document.createElement("button");p.type="button",p.className="btn btn-primary",p.style.flex="2",p.textContent=t.editing?"Update":"Insert effect",p.addEventListener("click",()=>K(t,r)),m.appendChild(p),e.appendChild(m)}function K(e,t){const r=e.textarea,o=k(e);if(e.editing){const a=u(e.editing.name),c=r.value,s=`[/${a.name}]`.length,d=e.editing.openTagEnd,i=e.editing.blockEnd-s,n=c.substring(d,i),l=C(e,a),m=l?" ":"",f=a.selfClosing?`[${a.name}${m}${l} /]`:`[${a.name}${m}${l}]${n}[/${a.name}]`;x(r,e.editing.blockStart,e.editing.blockEnd,f);const p=a.selfClosing?e.editing.blockStart+f.length:e.editing.blockStart+f.indexOf("]")+1;r.setSelectionRange(p,p),t.close();return}if(e.scope==="inject"&&e.host){const a=u(e.activeEffect),c=e.host.attrs,s=a.name,d=[];for(const n of Object.keys(c)){if(n===s||n.startsWith(s+"-"))continue;const l=c[n];d.push(l===""?n:`${n}="${String(l).replace(/"/g,"&quot;")}"`)}d.push(s);for(const n of a.attrs){const l=e.fieldValues[n.name];if(l===void 0||l===""||l===null||l===n.default)continue;const m=n.type==="checkbox"?l?"true":"false":String(l).replace(/"/g,"&quot;");d.push(`${s}-${n.name}="${m}"`)}const i=`[${e.host.name} ${d.join(" ")}]`;x(r,e.host.openTagStart,e.host.openTagEnd,i),t.close();return}R(r,o),t.close()}
3
+ [/${t.name}]`}function w(e,t){e.replaceChildren();const n=document.createElement("div");n.style.cssText="color:var(--dm-text-muted,#888);font-size:.7rem;text-transform:uppercase;letter-spacing:.05em;margin-bottom:.25rem;",n.textContent="Shortcode (live)",e.appendChild(n);const r=document.createElement("pre");r.style.cssText="background:var(--dm-code-bg,#000);border:1px solid var(--dm-border,#333);padding:.5rem .65rem;border-radius:3px;font-family:var(--dm-font-mono,monospace);font-size:.75rem;color:var(--dm-code-text,#7c6af7);line-height:1.5;white-space:pre-wrap;word-break:break-all;margin:0;",r.textContent=$(t),e.appendChild(r)}function H(e,t,n){if(e.replaceChildren(),t.editing)return;const r=u(t.activeEffect),i=t.host&&r.hosts.includes(t.host.name),c=document.createElement("div");c.style.cssText="background:var(--dm-background-alt,#15152a);border:1px solid var(--dm-border,#2a2a40);border-radius:4px;padding:.5rem .6rem;";const s=document.createElement("div");if(s.style.cssText="color:var(--dm-text-muted,#888);text-transform:uppercase;font-size:.65rem;letter-spacing:.05em;margin-bottom:.3rem;",s.textContent="Apply as",c.appendChild(s),!i){const o=document.createElement("div");o.style.cssText="color:var(--dm-text-muted,#888);font-size:.75rem;font-style:italic;",t.host?o.textContent=`Inserted as a standalone block (${r.label} cannot be injected into [${t.host.name}]).`:o.textContent="Inserted as a standalone block.",c.appendChild(o),e.appendChild(c),t.scope="standalone";return}const l=document.createElement("div");l.style.cssText="display:flex;gap:.3rem;";function d(o,a){const m=document.createElement("button");return m.type="button",m.style.cssText="flex:1;padding:.35rem;border:1px solid var(--dm-border,#333);border-radius:3px;font-size:.75rem;font-weight:600;cursor:pointer;",t.scope===o?(m.style.background="var(--dm-primary,#4338ca)",m.style.color="var(--dm-primary-text,#fff)",m.style.borderColor="var(--dm-primary,#4338ca)"):(m.style.background="transparent",m.style.color="var(--dm-text-muted,#bbb)"),m.textContent=a,m.addEventListener("click",()=>{t.scope=o,n()}),m}l.appendChild(d("standalone","Standalone block")),l.appendChild(d("inject",`Inject into [${t.host.name}]`)),c.appendChild(l),e.appendChild(c)}let b=0;function _(e){return e.replace(/-([a-z])/g,(t,n)=>n.toUpperCase())}function z(e,t){e.replaceChildren();const n=u(t.activeEffect),r=document.createElement("div");r.style.cssText="display:flex;justify-content:space-between;align-items:center;margin-bottom:.25rem;";const i=document.createElement("div");if(i.style.cssText="color:var(--dm-text-muted,#888);text-transform:uppercase;font-size:.65rem;letter-spacing:.05em;",i.textContent="Live preview",r.appendChild(i),!n.previewable){const d=document.createElement("div");d.style.cssText="background:var(--dm-background-alt,#15152a);border:1px solid var(--dm-border,#2a2a40);border-radius:4px;padding:.6rem;color:var(--dm-text-muted,#888);font-size:.8rem;font-style:italic;text-align:center;",d.textContent="Runs full-page on the published site - no inline preview.",e.appendChild(d);return}const c=document.createElement("button");c.type="button",c.style.cssText="background:transparent;border:1px solid var(--dm-border,#333);color:var(--dm-text-muted,#888);font-size:.65rem;padding:.15rem .4rem;border-radius:2px;cursor:pointer;",O(c,"refresh-cw","Replay",12),r.appendChild(c),e.appendChild(r);const s=document.createElement("div");s.style.cssText="background:var(--dm-background-alt,#1a1a2e);border:1px solid var(--dm-border,#2a2a40);border-radius:4px;padding:1rem;text-align:center;min-height:80px;position:relative;overflow:hidden;",e.appendChild(s);function l(){b++;const d=b;s.replaceChildren();const o=document.createElement("div");o.style.cssText="background:linear-gradient(135deg,#6366f1,#a855f7);color:#fff;padding:.6rem;border-radius:4px;font-size:.8rem;font-weight:600;",o.textContent="Sample content",s.appendChild(o);const a=window.Domma&&window.Domma.effects;if(!a)return;const m={};for(const f of g(n,t.fieldValues)){const p=t.fieldValues[f.name];p===void 0||p===""||p===null||(m[_(f.name)]=p)}try{const f=a[_(n.name)];if(typeof f=="function"){if(d!==b)return;f(o,m)}}catch(f){console.warn("Effects preview failed:",f)}}c.addEventListener("click",l),l()}function K(e,t,n){const r=u(t.activeEffect);e.replaceChildren();const i=document.createElement("h3");i.style.cssText="margin:0;font-size:1rem;color:var(--dm-text,#eee);",i.textContent=r.label,e.appendChild(i);const c=document.createElement("p");c.style.cssText="margin:0;color:var(--dm-text-muted,#999);font-size:.8rem;line-height:1.4;",c.textContent=r.description,e.appendChild(c);const s=document.createElement("div");e.appendChild(s);const l=document.createElement("div");e.appendChild(l);const d=document.createElement("div");e.appendChild(d);const o=document.createElement("div");e.appendChild(o);function a(){H(s,t,a),x(l,t,()=>{w(d,t),z(o,t)}),w(d,t),z(o,t)}a();const m=document.createElement("div");m.style.cssText="display:flex;gap:.5rem;margin-top:auto;padding-top:.75rem;border-top:1px solid var(--dm-border,#2a2a40);";const f=document.createElement("button");f.type="button",f.className="btn btn-ghost",f.textContent="Cancel",f.addEventListener("click",()=>n.close()),m.appendChild(f);const p=document.createElement("button");p.type="button",p.className="btn btn-primary",p.style.flex="2",p.textContent=t.editing?"Update":"Insert effect",p.addEventListener("click",()=>M(t,n)),m.appendChild(p),e.appendChild(m)}function M(e,t){const n=e.textarea,r=$(e);if(e.editing){const i=u(e.editing.name),c=n.value,s=`[/${i.name}]`.length,l=e.editing.openTagEnd,d=e.editing.blockEnd-s,o=c.substring(l,d),a=T(e,i),m=a?" ":"",f=i.selfClosing?`[${i.name}${m}${a} /]`:`[${i.name}${m}${a}]${o}[/${i.name}]`;v(n,e.editing.blockStart,e.editing.blockEnd,f);const p=i.selfClosing?e.editing.blockStart+f.length:e.editing.blockStart+f.indexOf("]")+1;n.setSelectionRange(p,p),t.close();return}if(e.scope==="inject"&&e.host){const i=u(e.activeEffect),c=e.host.attrs,s=i.name,l=[];for(const o of Object.keys(c)){if(o===s||o.startsWith(s+"-"))continue;const a=c[o];l.push(a===""?o:`${o}="${String(a).replace(/"/g,"&quot;")}"`)}l.push(s);for(const o of g(i,e.fieldValues)){const a=e.fieldValues[o.name];if(a===void 0||a===""||a===null||a===o.default)continue;const m=o.type==="checkbox"?a?"true":"false":String(a).replace(/"/g,"&quot;");l.push(`${s}-${o.name}="${m}"`)}const d=`[${e.host.name} ${l.join(" ")}]`;v(n,e.host.openTagStart,e.host.openTagEnd,d),t.close();return}j(n,r),t.close()}
@@ -1,3 +1,3 @@
1
- import{SHORTCODES as $}from"./shortcode-registry.js";import{EFFECTS as C}from"./effect-defs.js";import{boolState as V,boolValue as G,findEnclosingShortcode as M,setAttr as N,setAttrs as X,effectAttrKeys as q}from"./shortcode-tags.js";import{insertAtCursor as J}from"./markdown-toolbar.js";import{clearLookupCache as Q,lookupOptions as Z}from"./shortcode-lookups.js";import{insertMenuGroups as ee,insertShortcodeByName as te}from"./shortcode-insert.js";import{openShortcodeForm as R}from"./shortcode-form.js";function ne(e){return Z(e,c?.span?.attrs||{})}const oe=$.map(e=>({name:e.name,selfClosing:!!e.selfClosing})),se=new Map($.map(e=>[e.name,e])),ie=new Map(C.map(e=>[e.name,e])),ce=C.map(e=>({name:e.name,selfClosing:!!e.selfClosing})),z=[...oe,...ce],D=new Set(["card","box","hero","banner","col","button"]);let c=null;const P="position:fixed;z-index:10000;min-width:210px;max-height:70vh;overflow-y:auto;background:var(--dm-surface,#1c1c30);border:1px solid var(--dm-border,#2a2a40);border-radius:6px;box-shadow:var(--dm-shadow-lg);padding:.3rem;font-size:.83rem;color:var(--dm-text,#e5e5e5);",p="display:flex;align-items:center;gap:.5rem;width:100%;text-align:left;padding:.35rem .55rem;border:none;background:transparent;color:inherit;border-radius:4px;cursor:pointer;font-size:.83rem;",S="padding:.3rem .55rem;color:var(--dm-text-muted,#8a8a9a);font-size:.68rem;text-transform:uppercase;letter-spacing:.06em;",H="flex:1;min-width:0;padding:.2rem .4rem;background:var(--dm-input-bg,#12121e);border:1px solid var(--dm-border,#333);border-radius:3px;color:var(--dm-text,#eee);font-size:.8rem;",ae="height:1px;background:var(--dm-border,#2a2a40);margin:.3rem .2rem;";function m(e){return e.addEventListener("mouseenter",()=>{e.style.background="var(--dm-primary,#4338ca)",e.style.color="var(--dm-primary-text,#fff)"}),e.addEventListener("mouseleave",()=>{e.style.background="transparent",e.style.color="inherit"}),e}export function attachContextMenu(e){return typeof Domma>"u"||!Domma.elements?.contextMenu?(e.addEventListener("contextmenu",n=>{n.preventDefault(),f();const t=M(e,z);F(e,t,n.clientX,n.clientY)}),null):Domma.elements.contextMenu(e,{inherit:!1,cursor:!1,render:n=>{f();const t=M(e,z);F(e,t,n.x,n.y)}})}function f(){c&&(v(),c.root.remove(),document.removeEventListener("mousedown",W,!0),document.removeEventListener("keydown",j,!0),window.removeEventListener("scroll",Y,!0),c=null)}const W=e=>{c&&!c.root.contains(e.target)&&!(c.submenu&&c.submenu.contains(e.target))&&f()},Y=e=>{c&&!c.root.contains(e.target)&&!(c.submenu&&c.submenu.contains(e.target))&&f()},j=e=>{e.key==="Escape"&&f()};function F(e,n,t,o){Q();const s=document.createElement("div");s.className="dm-sc-menu",s.style.cssText=P,c={root:s,textarea:e,span:n,submenu:null};const i=n&&(se.get(n.name)||ie.get(n.name)),l=n&&D.has(n.name)?C.filter(r=>r.name in n.attrs):[];i&&re(s,i);for(const r of l)xe(s,r);(i||l.length)&&s.appendChild(le()),s.appendChild(y("Add effect\u2026",()=>be())),s.appendChild(y("Insert\u2026",()=>ye()));const a=e.selectionStart!==e.selectionEnd;(n||a)&&s.appendChild(y(a?"Wrap selection in\u2026":"Wrap in\u2026",()=>Ee())),document.body.appendChild(s),U(s,t,o),document.addEventListener("mousedown",W,!0),document.addEventListener("keydown",j,!0),window.addEventListener("scroll",Y,!0),window.I&&I.scan(s)}function le(){const e=document.createElement("div");return e.style.cssText=ae,e}function k(e){const n=document.createElement("div");return n.style.cssText=S,n.textContent=e,n}function re(e,n){e.appendChild(k(`${n.label} options`));const t=m(document.createElement("button"));t.type="button",t.style.cssText=p,t.innerHTML='<span data-icon="edit" data-icon-size="13" style="display:inline-flex;align-items:center;"></span>',t.appendChild(document.createTextNode(`Edit ${n.label}\u2026`)),t.addEventListener("click",()=>{const{textarea:o,span:s}=c;f(),R(o,n,{span:s})}),e.appendChild(t);for(const o of n.attrs||[])e.appendChild(O(o))}function O(e,n=e.name){const t=c.span.attrs[n];switch(e.type){case"checkbox":return de(e,n,V(t,e.default));case"select":return me(e,n,t);case"lookup":return he(e,n,t);case"colour":return pe(e,n,t);case"icon":return fe(e,n,t);default:return ue(e,n,t)}}function b(e,n){c.span=N(c.textarea,c.span,e,n)}function de(e,n,t){const o=m(document.createElement("label"));o.style.cssText=p;const s=document.createElement("input");return s.type="checkbox",s.checked=t,s.addEventListener("change",()=>b(n,G(e,s.checked))),o.appendChild(s),o.appendChild(document.createTextNode(e.label)),o}function ue(e,n,t){const o=document.createElement("div");o.style.cssText=p+"cursor:default;";const s=document.createElement("span");s.textContent=e.label,s.style.cssText="white-space:nowrap;color:var(--dm-text-muted,#9a9aac);";const i=document.createElement("input");i.type=e.type==="number"?"number":"text",i.value=t===!0||t==null?"":t,e.default!=null&&e.default!==""&&(i.placeholder=String(e.default)),i.style.cssText=H;let l=null;return i.addEventListener("input",()=>{clearTimeout(l),l=setTimeout(()=>b(n,i.value.trim()),180)}),i.addEventListener("mousedown",a=>a.stopPropagation()),o.appendChild(s),o.appendChild(i),o}function pe(e,n,t){const o=document.createElement("div");o.style.cssText=p+"cursor:default;";const s=document.createElement("span");s.textContent=e.label,s.style.flex="1";const i=document.createElement("input");return i.type="color",typeof t=="string"&&/^#/.test(t)?i.value=t:typeof e.default=="string"&&/^#/.test(e.default)&&(i.value=e.default),i.addEventListener("input",()=>b(n,i.value)),o.appendChild(s),o.appendChild(i),o}function me(e,n,t){const o=t==null||t===!0?e.default??"":t;return y(`${e.label}${o!==""?`: ${o}`:""}`,()=>{const s=g();for(const[i,l]of e.options||[]){const a=m(document.createElement("button"));a.type="button",a.style.cssText=p,a.textContent=l,i===o&&(a.style.fontWeight="700"),a.addEventListener("click",()=>{b(n,i),v()}),s.appendChild(a)}return s})}function fe(e,n,t){const o=t==null||t===!0?"":String(t),s=o?`${e.label}: ${o}`:e.label;return y(s,()=>{const i=g();i.style.width="232px";const l=document.createElement("input");l.type="text",l.placeholder="Search icons\u2026",l.style.cssText=H+"margin:6px;width:calc(100% - 12px);",l.addEventListener("mousedown",T=>T.stopPropagation()),i.appendChild(l);const a=m(document.createElement("button"));a.type="button",a.style.cssText=p,a.textContent="- none -",o||(a.style.fontWeight="700"),a.addEventListener("click",()=>{b(n,null),v()}),i.appendChild(a);const r=document.createElement("div");r.style.cssText="display:flex;flex-wrap:wrap;gap:2px;padding:4px 6px;max-height:220px;overflow-y:auto;",i.appendChild(r);const u=96,w=()=>{const T=typeof I<"u"&&typeof I.list=="function"?I.list():[],A=l.value.trim().toLowerCase(),_=A?T.filter(d=>d.toLowerCase().includes(A)):T;r.replaceChildren();for(const d of _.slice(0,u)){const x=m(document.createElement("button"));x.type="button",x.title=d,x.style.cssText="width:26px;height:26px;display:inline-flex;align-items:center;justify-content:center;background:none;border:1px solid transparent;border-radius:4px;cursor:pointer;color:inherit;",d===o&&(x.style.borderColor="var(--dm-primary,#5b8cff)");const L=document.createElement("span");L.setAttribute("data-icon",d),L.setAttribute("data-icon-size","15"),L.style.cssText="display:inline-flex;align-items:center;",x.appendChild(L),x.addEventListener("click",()=>{b(n,d),v()}),r.appendChild(x)}if(_.length>u){const d=document.createElement("div");d.style.cssText=S,d.textContent=`${_.length-u} more - refine search`,r.appendChild(d)}if(!_.length){const d=document.createElement("div");d.style.cssText=S,d.textContent="No icons match",r.appendChild(d)}window.I&&I.scan(r)};let h=null;return l.addEventListener("input",()=>{clearTimeout(h),h=setTimeout(w,120)}),w(),setTimeout(()=>l.focus(),0),i})}function he(e,n,t){const o=t==null||t===!0?e.default??"":t;return y(`${e.label}${o!==""?`: ${o}`:""}`,()=>{const s=g();s.style.minHeight="48px";const i=typeof E<"u"&&E.loader?E.loader(s,{type:"dots"}):null;return ne(e.source).then(l=>{if(i&&i.destroy(),!c||c.submenu!==s)return;if(s.style.minHeight="",!l.length){const u=document.createElement("div");u.style.cssText=S,u.textContent="Nothing found",s.appendChild(u)}const a=l.some(([u])=>u===o),r=[["","- none -"],...l];o!==""&&!a&&r.push([o,`${o} (missing)`]);for(const[u,w]of r){const h=m(document.createElement("button"));h.type="button",h.style.cssText=p,h.textContent=w,u===o&&(h.style.fontWeight="700"),h.addEventListener("click",()=>{b(n,u===""?null:u),v()}),s.appendChild(h)}}),s})}function xe(e,n){e.appendChild(k(`Effect: ${n.label}`));for(const o of n.attrs||[])e.appendChild(O(o,`${n.name}-${o.name}`));const t=m(document.createElement("button"));t.type="button",t.style.cssText=p,t.innerHTML='<span data-icon="trash" data-icon-size="13" style="display:inline-flex;align-items:center;"></span> Remove effect',t.addEventListener("click",()=>{const o={};for(const s of q(c.span.attrs,n.name))o[s]=null;X(c.textarea,c.span,o),f()}),e.appendChild(t)}function be(){const e=g(),n=c.span,t=n&&D.has(n.name)?n.name:null;for(const o of[...new Set(C.map(s=>s.category))]){const s=C.filter(i=>i.category===o);if(s.length){e.appendChild(k(o));for(const i of s){const l=t&&(i.hosts||[]).includes(t)&&!(i.name in n.attrs),a=m(document.createElement("button"));if(a.type="button",a.style.cssText=p+"justify-content:space-between;",a.appendChild(document.createTextNode(i.label)),l){const r=document.createElement("span");r.textContent=`inject \u2192 [${t}]`,r.style.cssText="opacity:.6;font-size:.7rem;",a.appendChild(r)}a.addEventListener("click",()=>{if(l)N(c.textarea,c.span,i.name,!0);else{const r=i.selfClosing?`[${i.name} /]`:`[${i.name}]
1
+ import{SHORTCODES as $}from"./shortcode-registry.js";import{EFFECTS as w,CELEBRATION_THEMES as J,getEffectAttrs as R}from"./effect-defs.js";import{boolState as Q,boolValue as Z,findEnclosingShortcode as z,setAttr as P,setAttrs as ee,effectAttrKeys as te}from"./shortcode-tags.js";import{insertAtCursor as D}from"./markdown-toolbar.js";import{clearLookupCache as ne,lookupOptions as oe}from"./shortcode-lookups.js";import{insertMenuGroups as se,insertShortcodeByName as ie}from"./shortcode-insert.js";import{openShortcodeForm as A}from"./shortcode-form.js";function ce(e){return oe(e,c?.span?.attrs||{})}const ae=$.map(e=>({name:e.name,selfClosing:!!e.selfClosing})),le=new Map($.map(e=>[e.name,e])),H=new Map(w.map(e=>[e.name,e])),re=w.map(e=>({name:e.name,selfClosing:!!e.selfClosing})),O=[...ae,...re],j=new Set(["card","box","hero","banner","col","button"]);let c=null;const W="position:fixed;z-index:10000;min-width:210px;max-height:70vh;overflow-y:auto;background:var(--dm-surface,#1c1c30);border:1px solid var(--dm-border,#2a2a40);border-radius:6px;box-shadow:var(--dm-shadow-lg);padding:.3rem;font-size:.83rem;color:var(--dm-text,#e5e5e5);",p="display:flex;align-items:center;gap:.5rem;width:100%;text-align:left;padding:.35rem .55rem;border:none;background:transparent;color:inherit;border-radius:4px;cursor:pointer;font-size:.83rem;",k="padding:.3rem .55rem;color:var(--dm-text-muted,#8a8a9a);font-size:.68rem;text-transform:uppercase;letter-spacing:.06em;",Y="flex:1;min-width:0;padding:.2rem .4rem;background:var(--dm-input-bg,#12121e);border:1px solid var(--dm-border,#333);border-radius:3px;color:var(--dm-text,#eee);font-size:.8rem;",de="height:1px;background:var(--dm-border,#2a2a40);margin:.3rem .2rem;";function f(e){return e.addEventListener("mouseenter",()=>{e.style.background="var(--dm-primary,#4338ca)",e.style.color="var(--dm-primary-text,#fff)"}),e.addEventListener("mouseleave",()=>{e.style.background="transparent",e.style.color="inherit"}),e}export function attachContextMenu(e){return typeof Domma>"u"||!Domma.elements?.contextMenu?(e.addEventListener("contextmenu",n=>{n.preventDefault(),m();const t=z(e,O);M(e,t,n.clientX,n.clientY)}),null):Domma.elements.contextMenu(e,{inherit:!1,cursor:!1,render:n=>{m();const t=z(e,O);M(e,t,n.x,n.y)}})}function m(){c&&(v(),c.root.remove(),document.removeEventListener("mousedown",B,!0),document.removeEventListener("keydown",K,!0),window.removeEventListener("scroll",F,!0),c=null)}const B=e=>{c&&!c.root.contains(e.target)&&!(c.submenu&&c.submenu.contains(e.target))&&m()},F=e=>{c&&!c.root.contains(e.target)&&!(c.submenu&&c.submenu.contains(e.target))&&m()},K=e=>{e.key==="Escape"&&m()};function M(e,n,t,o){ne();const s=document.createElement("div");s.className="dm-sc-menu",s.style.cssText=W,c={root:s,textarea:e,span:n,submenu:null};const i=n&&(le.get(n.name)||H.get(n.name)),l=n&&j.has(n.name)?w.filter(r=>r.name in n.attrs):[];i&&ue(s,i);for(const r of l)ye(s,r);(i||l.length)&&s.appendChild(U()),s.appendChild(y("Celebrations\u2026",()=>Ee())),s.appendChild(y("Add effect\u2026",()=>ge())),s.appendChild(y("Insert\u2026",()=>Ce()));const a=e.selectionStart!==e.selectionEnd;(n||a)&&s.appendChild(y(a?"Wrap selection in\u2026":"Wrap in\u2026",()=>ve())),document.body.appendChild(s),q(s,t,o),document.addEventListener("mousedown",B,!0),document.addEventListener("keydown",K,!0),window.addEventListener("scroll",F,!0),window.I&&I.scan(s)}function U(){const e=document.createElement("div");return e.style.cssText=de,e}function C(e){const n=document.createElement("div");return n.style.cssText=k,n.textContent=e,n}function ue(e,n){e.appendChild(C(`${n.label} options`));const t=f(document.createElement("button"));t.type="button",t.style.cssText=p,t.innerHTML='<span data-icon="edit" data-icon-size="13" style="display:inline-flex;align-items:center;"></span>',t.appendChild(document.createTextNode(`Edit ${n.label}\u2026`)),t.addEventListener("click",()=>{const{textarea:o,span:s}=c;m(),A(o,{...n,attrs:R(n,s.attrs)},{span:s})}),e.appendChild(t);for(const o of R(n,c.span.attrs))e.appendChild(V(o))}function V(e,n=e.name){const t=c.span.attrs[n];switch(e.type){case"checkbox":return pe(e,n,Q(t,e.default));case"select":return he(e,n,t);case"lookup":return xe(e,n,t);case"colour":return fe(e,n,t);case"icon":return be(e,n,t);default:return me(e,n,t)}}function x(e,n){if(c.span=P(c.textarea,c.span,e,n),e==="theme"){const{textarea:t,span:o,root:s}=c,i=s.getBoundingClientRect();m(),M(t,o,i.left,i.top)}}function pe(e,n,t){const o=f(document.createElement("label"));o.style.cssText=p;const s=document.createElement("input");return s.type="checkbox",s.checked=t,s.addEventListener("change",()=>x(n,Z(e,s.checked))),o.appendChild(s),o.appendChild(document.createTextNode(e.label)),o}function me(e,n,t){const o=document.createElement("div");o.style.cssText=p+"cursor:default;";const s=document.createElement("span");s.textContent=e.label,s.style.cssText="white-space:nowrap;color:var(--dm-text-muted,#9a9aac);";const i=document.createElement("input");i.type=e.type==="number"?"number":"text",i.value=t===!0||t==null?"":t,e.default!=null&&e.default!==""&&(i.placeholder=String(e.default)),i.style.cssText=Y;let l=null;return i.addEventListener("input",()=>{clearTimeout(l),l=setTimeout(()=>x(n,i.value.trim()),180)}),i.addEventListener("mousedown",a=>a.stopPropagation()),o.appendChild(s),o.appendChild(i),o}function fe(e,n,t){const o=document.createElement("div");o.style.cssText=p+"cursor:default;";const s=document.createElement("span");s.textContent=e.label,s.style.flex="1";const i=document.createElement("input");return i.type="color",typeof t=="string"&&/^#/.test(t)?i.value=t:typeof e.default=="string"&&/^#/.test(e.default)&&(i.value=e.default),i.addEventListener("input",()=>x(n,i.value)),o.appendChild(s),o.appendChild(i),o}function he(e,n,t){const o=t==null||t===!0?e.default??"":t;return y(`${e.label}${o!==""?`: ${o}`:""}`,()=>{const s=g();for(const[i,l]of e.options||[]){const a=f(document.createElement("button"));a.type="button",a.style.cssText=p,a.textContent=l,i===o&&(a.style.fontWeight="700"),a.addEventListener("click",()=>{x(n,i),v()}),s.appendChild(a)}return s})}function be(e,n,t){const o=t==null||t===!0?"":String(t),s=o?`${e.label}: ${o}`:e.label;return y(s,()=>{const i=g();i.style.width="232px";const l=document.createElement("input");l.type="text",l.placeholder="Search icons\u2026",l.style.cssText=Y+"margin:6px;width:calc(100% - 12px);",l.addEventListener("mousedown",L=>L.stopPropagation()),i.appendChild(l);const a=f(document.createElement("button"));a.type="button",a.style.cssText=p,a.textContent="- none -",o||(a.style.fontWeight="700"),a.addEventListener("click",()=>{x(n,null),v()}),i.appendChild(a);const r=document.createElement("div");r.style.cssText="display:flex;flex-wrap:wrap;gap:2px;padding:4px 6px;max-height:220px;overflow-y:auto;",i.appendChild(r);const u=96,T=()=>{const L=typeof I<"u"&&typeof I.list=="function"?I.list():[],N=l.value.trim().toLowerCase(),_=N?L.filter(d=>d.toLowerCase().includes(N)):L;r.replaceChildren();for(const d of _.slice(0,u)){const b=f(document.createElement("button"));b.type="button",b.title=d,b.style.cssText="width:26px;height:26px;display:inline-flex;align-items:center;justify-content:center;background:none;border:1px solid transparent;border-radius:4px;cursor:pointer;color:inherit;",d===o&&(b.style.borderColor="var(--dm-primary,#5b8cff)");const S=document.createElement("span");S.setAttribute("data-icon",d),S.setAttribute("data-icon-size","15"),S.style.cssText="display:inline-flex;align-items:center;",b.appendChild(S),b.addEventListener("click",()=>{x(n,d),v()}),r.appendChild(b)}if(_.length>u){const d=document.createElement("div");d.style.cssText=k,d.textContent=`${_.length-u} more - refine search`,r.appendChild(d)}if(!_.length){const d=document.createElement("div");d.style.cssText=k,d.textContent="No icons match",r.appendChild(d)}window.I&&I.scan(r)};let h=null;return l.addEventListener("input",()=>{clearTimeout(h),h=setTimeout(T,120)}),T(),setTimeout(()=>l.focus(),0),i})}function xe(e,n,t){const o=t==null||t===!0?e.default??"":t;return y(`${e.label}${o!==""?`: ${o}`:""}`,()=>{const s=g();s.style.minHeight="48px";const i=typeof E<"u"&&E.loader?E.loader(s,{type:"dots"}):null;return ce(e.source).then(l=>{if(i&&i.destroy(),!c||c.submenu!==s)return;if(s.style.minHeight="",!l.length){const u=document.createElement("div");u.style.cssText=k,u.textContent="Nothing found",s.appendChild(u)}const a=l.some(([u])=>u===o),r=[["","- none -"],...l];o!==""&&!a&&r.push([o,`${o} (missing)`]);for(const[u,T]of r){const h=f(document.createElement("button"));h.type="button",h.style.cssText=p,h.textContent=T,u===o&&(h.style.fontWeight="700"),h.addEventListener("click",()=>{x(n,u===""?null:u),v()}),s.appendChild(h)}}),s})}function ye(e,n){e.appendChild(C(`Effect: ${n.label}`));for(const o of n.attrs||[])e.appendChild(V(o,`${n.name}-${o.name}`));const t=f(document.createElement("button"));t.type="button",t.style.cssText=p,t.innerHTML='<span data-icon="trash" data-icon-size="13" style="display:inline-flex;align-items:center;"></span> Remove effect',t.addEventListener("click",()=>{const o={};for(const s of te(c.span.attrs,n.name))o[s]=null;ee(c.textarea,c.span,o),m()}),e.appendChild(t)}function Ee(){const e=g();e.appendChild(C("Seasonal themes"));for(const[n,t]of[["auto","Auto (date-detected)"],...Object.entries(J).map(([o,s])=>[o,s.label])]){const o=f(document.createElement("button"));o.type="button",o.style.cssText=p,o.textContent=t,o.addEventListener("click",()=>{D(c.textarea,`[celebrate theme="${n}" /]`),m()}),e.appendChild(o)}e.appendChild(U()),e.appendChild(C("Celebration effects"));for(const n of["butterflies","ticker-tape","firework","fireworks"]){const t=H.get(n),o=f(document.createElement("button"));o.type="button",o.style.cssText=p,o.textContent=t.label,o.addEventListener("click",()=>{const s=c.textarea;m(),A(s,t)}),e.appendChild(o)}return e}function ge(){const e=g(),n=c.span,t=n&&j.has(n.name)?n.name:null;for(const o of[...new Set(w.map(s=>s.category))]){const s=w.filter(i=>i.category===o);if(s.length){e.appendChild(C(o));for(const i of s){const l=t&&(i.hosts||[]).includes(t)&&!(i.name in n.attrs),a=f(document.createElement("button"));if(a.type="button",a.style.cssText=p+"justify-content:space-between;",a.appendChild(document.createTextNode(i.label)),l){const r=document.createElement("span");r.textContent=`inject \u2192 [${t}]`,r.style.cssText="opacity:.6;font-size:.7rem;",a.appendChild(r)}a.addEventListener("click",()=>{if(l)P(c.textarea,c.span,i.name,!0);else{const r=i.selfClosing?`[${i.name} /]`:`[${i.name}]
2
2
  Content
3
- [/${i.name}]`;J(c.textarea,r)}f()}),e.appendChild(a)}}}return e}function y(e,n){const t=m(document.createElement("button"));t.type="button",t.style.cssText=p+"justify-content:space-between;",t.appendChild(document.createTextNode(e));const o=document.createElement("span");return o.setAttribute("data-icon","chevron-right"),o.setAttribute("data-icon-size","12"),o.style.cssText="opacity:.6;display:inline-flex;align-items:center;flex-shrink:0;",t.appendChild(o),t.addEventListener("mouseenter",()=>B(t,n)),t.addEventListener("click",s=>{s.stopPropagation(),B(t,n)}),t}function g(){const e=document.createElement("div");return e.className="dm-sc-submenu",e.style.cssText=P,e}function B(e,n){v();const t=n();c.submenu=t,document.body.appendChild(t);const o=e.getBoundingClientRect();U(t,o.right+2,o.top,o.left-2),window.I&&I.scan(t)}function v(){c&&c.submenu&&(c.submenu.remove(),c.submenu=null)}function K(e){const n=m(document.createElement("button"));if(n.type="button",n.style.cssText=p,e.icon){const t=document.createElement("span");t.setAttribute("data-icon",e.icon),t.setAttribute("data-icon-size","14"),t.style.cssText="opacity:.75;display:inline-flex;align-items:center;flex-shrink:0;",n.appendChild(t)}return n.appendChild(document.createTextNode(e.label)),n}function ye(){const e=g();for(const{category:n,items:t}of ee()){e.appendChild(k(n));for(const o of t){const s=K(o);s.addEventListener("click",()=>{const i=c.textarea;f(),te(o.name,i)}),e.appendChild(s)}}return e}function Ee(){const e=g();for(const n of $.filter(t=>t.wrappable||t.container)){const t=K(n);t.addEventListener("click",()=>{const o=c.textarea;f(),R(o,n)}),e.appendChild(t)}return e}function U(e,n,t,o){e.style.left="0px",e.style.top="0px";const s=e.getBoundingClientRect();let i=n;n+s.width>window.innerWidth-8&&(i=o!=null?o-s.width:n-s.width);let l=t;t+s.height>window.innerHeight-8&&(l=Math.max(8,window.innerHeight-s.height-8)),e.style.left=`${Math.max(8,i)}px`,e.style.top=`${Math.max(8,l)}px`}
3
+ [/${i.name}]`;D(c.textarea,r)}m()}),e.appendChild(a)}}}return e}function y(e,n){const t=f(document.createElement("button"));t.type="button",t.style.cssText=p+"justify-content:space-between;",t.appendChild(document.createTextNode(e));const o=document.createElement("span");return o.setAttribute("data-icon","chevron-right"),o.setAttribute("data-icon-size","12"),o.style.cssText="opacity:.6;display:inline-flex;align-items:center;flex-shrink:0;",t.appendChild(o),t.addEventListener("mouseenter",()=>G(t,n)),t.addEventListener("click",s=>{s.stopPropagation(),G(t,n)}),t}function g(){const e=document.createElement("div");return e.className="dm-sc-submenu",e.style.cssText=W,e}function G(e,n){v();const t=n();c.submenu=t,document.body.appendChild(t);const o=e.getBoundingClientRect();q(t,o.right+2,o.top,o.left-2),window.I&&I.scan(t)}function v(){c&&c.submenu&&(c.submenu.remove(),c.submenu=null)}function X(e){const n=f(document.createElement("button"));if(n.type="button",n.style.cssText=p,e.icon){const t=document.createElement("span");t.setAttribute("data-icon",e.icon),t.setAttribute("data-icon-size","14"),t.style.cssText="opacity:.75;display:inline-flex;align-items:center;flex-shrink:0;",n.appendChild(t)}return n.appendChild(document.createTextNode(e.label)),n}function Ce(){const e=g();for(const{category:n,items:t}of se()){e.appendChild(C(n));for(const o of t){const s=X(o);s.addEventListener("click",()=>{const i=c.textarea;m(),ie(o.name,i)}),e.appendChild(s)}}return e}function ve(){const e=g();for(const n of $.filter(t=>t.wrappable||t.container)){const t=X(n);t.addEventListener("click",()=>{const o=c.textarea;m(),A(o,n)}),e.appendChild(t)}return e}function q(e,n,t,o){e.style.left="0px",e.style.top="0px";const s=e.getBoundingClientRect();let i=n;n+s.width>window.innerWidth-8&&(i=o!=null?o-s.width:n-s.width);let l=t;t+s.height>window.innerHeight-8&&(l=Math.max(8,window.innerHeight-s.height-8)),e.style.left=`${Math.max(8,i)}px`,e.style.top=`${Math.max(8,l)}px`}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "domma-cms",
3
- "version": "0.107.0",
3
+ "version": "0.107.1",
4
4
  "description": "File-based CMS powered by Domma and Fastify. Run npx domma-cms my-site to create a new project.",
5
5
  "type": "module",
6
6
  "main": "server/server.js",
@@ -84,7 +84,7 @@
84
84
  "@fastify/rate-limit": "^10.3.0",
85
85
  "@fastify/static": "9.1.1",
86
86
  "bcryptjs": "^3.0.3",
87
- "domma-js": "0.51.4",
87
+ "domma-js": "0.51.5",
88
88
  "dotenv": "^17.2.3",
89
89
  "fastify": "5.8.5",
90
90
  "gray-matter": "^4.0.3",
@@ -99,7 +99,20 @@ function sanitiseBody(html, options) {
99
99
  'border': [/^.*$/],
100
100
  'border-collapse': [/^.*$/],
101
101
  'width': [/^.*$/],
102
- 'max-width': [/^.*$/]
102
+ 'max-width': [/^.*$/],
103
+ // Marketing mail hides its inbox preview text ("preheader")
104
+ // with these. Strip them and keep its width:0, and the hidden
105
+ // text renders one letter per line under a tall run of
106
+ // invisible padding characters. None of them can position,
107
+ // load or overlay anything.
108
+ 'display': [/^(none|block|inline|inline-block|table|table-row|table-cell|list-item)$/i],
109
+ 'visibility': [/^(hidden|visible)$/i],
110
+ 'height': [/^.*$/],
111
+ 'max-height': [/^.*$/],
112
+ 'line-height': [/^.*$/],
113
+ 'overflow': [/^(hidden|visible)$/i],
114
+ 'opacity': [/^[0-9.]+$/],
115
+ 'vertical-align': [/^.*$/]
103
116
  }
104
117
  },
105
118
  allowedSchemes: ['http', 'https', 'mailto', 'tel'],
@@ -1 +1 @@
1
- var w=Object.defineProperty;var v=(f,e,i)=>e in f?w(f,e,{enumerable:!0,configurable:!0,writable:!0,value:i}):f[e]=i;var p=(f,e,i)=>v(f,typeof e!="symbol"?e+"":e,i);import{CanvasManager as M}from"./core/canvas.js";import{PhysicsEngine as P,updateMovingParticle as b,updateParticlePhysics as C}from"./core/physics.js";import{createParticle as z}from"./core/particles.js";const h=class h{static isDateInRange(e,i,s,o){const r=new Date,n=r.getMonth()+1,c=r.getDate();return s<e?n===e&&c>=i||n>e||n<e&&n<=s||n===s&&c<=o:(n>e||n===e&&c>=i)&&(n<s||n===s&&c<=o)}static getCurrentTheme(){for(const[e,i]of Object.entries(h.themes)){const[[s,o],[r,n]]=i.dates;if(h.isDateInRange(s,o,r,n))return e}return null}static isCelebrationSeason(){return h.getCurrentTheme()!==null}static getThemes(){return h.themes}constructor(e={}){this.options={theme:e.theme||"auto",intensity:e.intensity||"medium",enabled:e.enabled!==void 0?e.enabled:!0,zIndex:e.zIndex||999,overrides:e.overrides||{}},this.canvasManager=null,this.physicsEngine=null,this.themeModule=null,this.currentTheme=null,this.particles=[],this.specialParticles=[],this.animationFrame=null,this.lastTime=0,this.running=!1,this.initialized=!1}async init(){if(this.initialized){console.warn("[Celebrations] Already initialized");return}console.log("[Celebrations] Initializing...");let e=this.options.theme;if(e==="auto"&&(e=h.getCurrentTheme(),!e)){console.log("[Celebrations] No active celebration detected");return}if(!h.themes[e]){console.error(`[Celebrations] Unknown theme: ${e}`);return}this.currentTheme=e,console.log(`[Celebrations] Loading theme: ${e}`);try{const s=await import(h.themes[e].module);this.themeModule=s.default,console.log(`[Celebrations] Theme loaded: ${this.themeModule.displayName}`)}catch(i){console.error(`[Celebrations] Failed to load theme module: ${i.message}`);return}this.canvasManager=new M({canvasId:"celebrations-canvas",zIndex:this.options.zIndex}),this.canvasManager.create(),this.physicsEngine=new P({gustInterval:[5e3,15e3],gustStrength:[-2,2]}),window.addEventListener("resize",()=>{this.canvasManager.resize(),this.resetParticles()}),this.resetParticles(),this.initialized=!0,console.log("[Celebrations] Initialized successfully"),this.options.enabled&&this.start()}resetParticles(){const e=Object.assign({},this.themeModule.intensityConfig[this.options.intensity]),i=a=>String(a).toLowerCase().replace(/[^a-z0-9]/g,""),s=[...Object.keys(e),...this.themeModule.decorationKeys||[]],o=a=>s.find(l=>i(l)===i(a))||a,r=a=>["true","1","yes","on"].includes(String(a).toLowerCase()),n=this.themeModule.optInDecorations||{},c=Object.entries(this.options.overrides).some(([a,l])=>["snowonly","fallingonly"].includes(i(a))&&r(l));for(const a of Object.values(n))e[a.chance]=0;for(const[a,l]of Object.entries(this.options.overrides)){if((i(a)==="snowonly"||i(a)==="fallingonly")&&r(l)){for(const g of this.themeModule.decorationKeys||[])e[g]=0;continue}const y=Object.keys(n).find(g=>i(g)===i(a));if(y&&!c&&r(l)){const g=n[y];e[g.chance]=g.value}l==="off"&&(e[o(a)]=0)}this.config=e;const t=this.canvasManager.canvas.width,d=this.canvasManager.canvas.height;this.particles=[],this.specialParticles=[];const m=e.initialParticleRatio!==void 0?e.initialParticleRatio:1,u=Math.floor(e.count*m);if(this.themeModule.createFallingParticle)for(let a=0;a<u;a++){const l=this.themeModule.createFallingParticle(t,d,e);l.y=Math.random()*d,this.particles.push(l)}else for(let a=0;a<u;a++){const l=z(e,t,d);l.y=Math.random()*d,this.particles.push(l)}if(this.themeModule.createInitialDecorations){const a=this.themeModule.createInitialDecorations(t,d,e);this.specialParticles.push(...a),console.log(`[Celebrations] Created ${a.length} decorations`)}console.log(`[Celebrations] Created ${u}/${e.count} particles (${this.options.intensity}, ${Math.round(m*100)}% initial)`)}start(){if(!this.initialized){console.warn("[Celebrations] Cannot start - not initialized");return}if(this.running){console.warn("[Celebrations] Already running");return}console.log("[Celebrations] Starting animation"),this.running=!0,this.lastTime=performance.now(),this.animate()}pause(){this.running&&(console.log("[Celebrations] Pausing animation"),this.running=!1,this.animationFrame&&(cancelAnimationFrame(this.animationFrame),this.animationFrame=null))}resume(){this.running||this.start()}destroy(){console.log("[Celebrations] Destroying effect"),this.pause(),this.canvasManager&&this.canvasManager.canvas&&this.canvasManager.canvas.remove(),this.particles=[],this.specialParticles=[],this.canvasManager=null,this.physicsEngine=null,this.themeModule=null,this.initialized=!1}setIntensity(e){if(!["light","medium","heavy"].includes(e)){console.error(`[Celebrations] Invalid intensity: ${e}`);return}console.log(`[Celebrations] Changing intensity to: ${e}`),this.options.intensity=e,this.resetParticles()}async setTheme(e){console.log(`[Celebrations] Changing theme to: ${e}`);const i=this.running;this.pause(),await new Promise(s=>setTimeout(s,20)),this.initialized=!1,this.canvasManager&&this.canvasManager.clear(),this.particles=[],this.specialParticles=[],this.canvasManager&&this.canvasManager.clear(),this.options.theme=e,await this.init(),i&&this.start()}animate(){if(!this.running)return;const e=performance.now(),i=e-this.lastTime;this.lastTime=e,this.canvasManager.clear();const s=this.canvasManager.ctx,o=this.canvasManager.canvas.width,r=this.canvasManager.canvas.height,n=this.config;this.physicsEngine.updateWind(e);const c=this.physicsEngine.getWindForce();if(this.particles.length<n.count&&Math.random()<.05&&this.themeModule.createFallingParticle){const t=this.themeModule.createFallingParticle(o,r,n);(t.y===void 0||t.y<0)&&(t.y=-20),this.particles.push(t)}if(this.particles.forEach((t,d)=>{if(C(t,i,c),t.y>r+50&&(t.y=-20,t.x=Math.random()*o),t.x<-50&&(t.x=o+50),t.x>o+50&&(t.x=-50),this.themeModule.drawSnowflake&&t.type==="snowflake")this.themeModule.drawSnowflake(s,t);else if(this.themeModule["draw"+this.capitalizeFirst(t.type)]){const m="draw"+this.capitalizeFirst(t.type);this.themeModule[m](s,t,e)}else s.save(),s.globalAlpha=t.opacity,s.fillStyle=this.themeModule.colors?.primary||"#ffffff",s.beginPath(),s.arc(t.x,t.y,t.size,0,Math.PI*2),s.fill(),s.restore()}),this.themeModule.updateSpecialParticles&&this.themeModule.updateSpecialParticles(this.specialParticles,i,o,r),this.specialParticles=this.specialParticles.filter(t=>{if(!t.active)return!1;if(!t.static){b(t,i,e);const u=t.type==="train"?600:200;if(t.x<-u||t.x>o+u)return t.active=!1,!1}if(!isFinite(t.x)||!isFinite(t.y)||t.size&&!isFinite(t.size))return console.warn("[Celebrations] Invalid particle values, removing:",t.type),t.active=!1,!1;const m="draw"+this.capitalizeFirst(t.type);return this.themeModule[m]&&this.themeModule[m](s,t,e),!0}),this.themeModule.spawnSpecialParticle){const t=this.themeModule.spawnSpecialParticle(this.specialParticles,o,r,n);t&&this.specialParticles.push(t)}this.themeModule.drawGlobalEffects&&this.themeModule.drawGlobalEffects(s,e,o,r),this.animationFrame=requestAnimationFrame(()=>this.animate())}capitalizeFirst(e){if(!e)return"";const i=e.replace(/-([a-z])/g,(s,o)=>o.toUpperCase());return i.charAt(0).toUpperCase()+i.slice(1)}};p(h,"themes",{christmas:{module:"./themes/christmas.js?v=20260930-snowman",dates:[[12,1],[1,1]],displayName:"Christmas",emoji:"\u{1F384}"},halloween:{module:"./themes/halloween.js?v=20260930-snow",dates:[[10,26],[10,31]],displayName:"Halloween",emoji:"\u{1F383}"},valentines:{module:"./themes/valentines.js?v=20260930-snow",dates:[[2,9],[2,14]],displayName:"Valentine's Day",emoji:"\u{1F495}"},"guy-fawkes":{module:"./themes/guy-fawkes.js?v=20260930-snow",dates:[[11,1],[11,5]],displayName:"Guy Fawkes Night",emoji:"\u{1F386}"},"st-patricks":{module:"./themes/st-patricks.js?v=20260930-snow",dates:[[3,12],[3,17]],displayName:"St Patrick's Day",emoji:"\u2618\uFE0F"},"st-andrews":{module:"./themes/st-andrews.js?v=20260930-snow",dates:[[11,25],[11,30]],displayName:"St Andrew's Day",emoji:"\u{1F3F4}\u{E0067}\u{E0062}\u{E0073}\u{E0063}\u{E0074}\u{E007F}"},"st-davids":{module:"./themes/st-davids.js?v=20260930-snow",dates:[[2,24],[3,1]],displayName:"St David's Day",emoji:"\u{1F3F4}\u{E0067}\u{E0062}\u{E0077}\u{E006C}\u{E0073}\u{E007F}"},"st-georges":{module:"./themes/st-georges.js?v=20260930-snow",dates:[[4,18],[4,23]],displayName:"St George's Day",emoji:"\u{1F3F4}\u{E0067}\u{E0062}\u{E0065}\u{E006E}\u{E0067}\u{E007F}"}});export let CelebrationsEffect=h;export default CelebrationsEffect;
1
+ var w=Object.defineProperty;var b=(u,e,i)=>e in u?w(u,e,{enumerable:!0,configurable:!0,writable:!0,value:i}):u[e]=i;var v=(u,e,i)=>b(u,typeof e!="symbol"?e+"":e,i);import{resolveCelebrationTraits as M}from"./trait-data.mjs";import{CanvasManager as P}from"./core/canvas.js";import{PhysicsEngine as C,updateMovingParticle as z,updateParticlePhysics as j}from"./core/physics.js";import{createParticle as F}from"./core/particles.js";const c=class c{static isDateInRange(e,i,s,o){const r=new Date,n=r.getMonth()+1,d=r.getDate();return s<e?n===e&&d>=i||n>e||n<e&&n<=s||n===s&&d<=o:(n>e||n===e&&d>=i)&&(n<s||n===s&&d<=o)}static getCurrentTheme(){for(const[e,i]of Object.entries(c.themes)){const[[s,o],[r,n]]=i.dates;if(c.isDateInRange(s,o,r,n))return e}return null}static isCelebrationSeason(){return c.getCurrentTheme()!==null}static getThemes(){return c.themes}constructor(e={}){this.options={theme:e.theme||"auto",intensity:e.intensity||"medium",enabled:e.enabled!==void 0?e.enabled:!0,zIndex:e.zIndex||999,overrides:e.overrides||{}},this.canvasManager=null,this.physicsEngine=null,this.themeModule=null,this.currentTheme=null,this.particles=[],this.specialParticles=[],this.animationFrame=null,this.lastTime=0,this.running=!1,this.initialized=!1}async init(){if(this.initialized){console.warn("[Celebrations] Already initialized");return}console.log("[Celebrations] Initializing...");let e=this.options.theme;if(e==="auto"&&(e=c.getCurrentTheme(),!e)){console.log("[Celebrations] No active celebration detected");return}if(!c.themes[e]){console.error(`[Celebrations] Unknown theme: ${e}`);return}this.currentTheme=e,console.log(`[Celebrations] Loading theme: ${e}`);try{const s=await import(c.themes[e].module);this.themeModule=s.default,console.log(`[Celebrations] Theme loaded: ${this.themeModule.displayName}`)}catch(i){console.error(`[Celebrations] Failed to load theme module: ${i.message}`);return}this.canvasManager=new P({canvasId:"celebrations-canvas",zIndex:this.options.zIndex}),this.canvasManager.create(),this.physicsEngine=new C({gustInterval:[5e3,15e3],gustStrength:[-2,2]}),window.addEventListener("resize",()=>{this.canvasManager.resize(),this.resetParticles()}),this.resetParticles(),this.initialized=!0,console.log("[Celebrations] Initialized successfully"),this.options.enabled&&this.start()}isParticleEnabled(e){return!this.disabledTypes?.has(e.type)}resetParticles(){const e=Object.assign({},this.themeModule.intensityConfig[this.options.intensity]),i=a=>String(a).toLowerCase().replace(/[^a-z0-9]/g,""),s=[...Object.keys(e),...this.themeModule.decorationKeys||[]],o=a=>s.find(l=>i(l)===i(a))||a,r=a=>["true","1","yes","on"].includes(String(a).toLowerCase()),n=this.themeModule.optInDecorations||{},d=Object.entries(this.options.overrides).some(([a,l])=>["snowonly","fallingonly"].includes(i(a))&&r(l));for(const a of Object.values(n))e[a.chance]=0;for(const[a,l]of Object.entries(this.options.overrides)){if((i(a)==="snowonly"||i(a)==="fallingonly")&&r(l)){for(const m of this.themeModule.decorationKeys||[])e[m]=0;continue}const p=Object.keys(n).find(m=>i(m)===i(a));if(p&&!d&&r(l)){const m=n[p];e[m.chance]=m.value}l==="off"&&(e[o(a)]=0)}const t=M(this.themeModule.name,this.options.overrides);Object.assign(e,t.config),this.disabledTypes=t.disabledTypes,this.disabledGlobals=t.disabledGlobals,this.config=e;const f=this.canvasManager.canvas.width,h=this.canvasManager.canvas.height;this.particles=[],this.specialParticles=[];const g=e.initialParticleRatio!==void 0?e.initialParticleRatio:1,y=Math.floor(e.count*g);if(this.themeModule.createFallingParticle)for(let a=0;a<y;a++){const l=this.themeModule.createFallingParticle(f,h,e);l.y=Math.random()*h,this.isParticleEnabled(l)&&this.particles.push(l)}else for(let a=0;a<y;a++){const l=F(e,f,h);l.y=Math.random()*h,this.isParticleEnabled(l)&&this.particles.push(l)}if(this.themeModule.createInitialDecorations){const a=this.themeModule.createInitialDecorations(f,h,e);this.specialParticles.push(...a.filter(l=>this.isParticleEnabled(l))),console.log(`[Celebrations] Created ${a.length} decorations`)}console.log(`[Celebrations] Created ${y}/${e.count} particles (${this.options.intensity}, ${Math.round(g*100)}% initial)`)}start(){if(!this.initialized){console.warn("[Celebrations] Cannot start - not initialized");return}if(this.running){console.warn("[Celebrations] Already running");return}console.log("[Celebrations] Starting animation"),this.running=!0,this.lastTime=performance.now(),this.animate()}pause(){this.running&&(console.log("[Celebrations] Pausing animation"),this.running=!1,this.animationFrame&&(cancelAnimationFrame(this.animationFrame),this.animationFrame=null))}resume(){this.running||this.start()}destroy(){console.log("[Celebrations] Destroying effect"),this.pause(),this.canvasManager&&this.canvasManager.canvas&&this.canvasManager.canvas.remove(),this.particles=[],this.specialParticles=[],this.canvasManager=null,this.physicsEngine=null,this.themeModule=null,this.initialized=!1}setIntensity(e){if(!["light","medium","heavy"].includes(e)){console.error(`[Celebrations] Invalid intensity: ${e}`);return}console.log(`[Celebrations] Changing intensity to: ${e}`),this.options.intensity=e,this.resetParticles()}async setTheme(e){console.log(`[Celebrations] Changing theme to: ${e}`);const i=this.running;this.pause(),await new Promise(s=>setTimeout(s,20)),this.initialized=!1,this.canvasManager&&this.canvasManager.clear(),this.particles=[],this.specialParticles=[],this.canvasManager&&this.canvasManager.clear(),this.options.theme=e,await this.init(),i&&this.start()}animate(){if(!this.running)return;const e=performance.now(),i=e-this.lastTime;this.lastTime=e,this.canvasManager.clear();const s=this.canvasManager.ctx,o=this.canvasManager.canvas.width,r=this.canvasManager.canvas.height,n=this.config;this.physicsEngine.updateWind(e);const d=this.physicsEngine.getWindForce();if(this.particles.length<n.count&&Math.random()<.05&&this.themeModule.createFallingParticle){const t=this.themeModule.createFallingParticle(o,r,n);(t.y===void 0||t.y<0)&&(t.y=-20),this.isParticleEnabled(t)&&this.particles.push(t)}if(this.particles.forEach((t,f)=>{if(j(t,i,d),t.y>r+50&&(t.y=-20,t.x=Math.random()*o),t.x<-50&&(t.x=o+50),t.x>o+50&&(t.x=-50),this.themeModule.drawSnowflake&&t.type==="snowflake")this.themeModule.drawSnowflake(s,t);else if(this.themeModule["draw"+this.capitalizeFirst(t.type)]){const h="draw"+this.capitalizeFirst(t.type);this.themeModule[h](s,t,e)}else s.save(),s.globalAlpha=t.opacity,s.fillStyle=this.themeModule.colors?.primary||"#ffffff",s.beginPath(),s.arc(t.x,t.y,t.size,0,Math.PI*2),s.fill(),s.restore()}),this.themeModule.updateSpecialParticles&&this.themeModule.updateSpecialParticles(this.specialParticles,i,o,r),this.specialParticles=this.specialParticles.filter(t=>{if(!t.active||!this.isParticleEnabled(t))return!1;if(!t.static){z(t,i,e);const g=t.type==="train"?600:200;if(t.x<-g||t.x>o+g)return t.active=!1,!1}if(!isFinite(t.x)||!isFinite(t.y)||t.size&&!isFinite(t.size))return console.warn("[Celebrations] Invalid particle values, removing:",t.type),t.active=!1,!1;const h="draw"+this.capitalizeFirst(t.type);return this.themeModule[h]&&this.themeModule[h](s,t,e),!0}),this.themeModule.spawnSpecialParticle){const t=this.themeModule.spawnSpecialParticle(this.specialParticles,o,r,n);t&&this.isParticleEnabled(t)&&this.specialParticles.push(t)}this.themeModule.drawGlobalEffects&&!this.disabledGlobals?.has("lightning")&&this.themeModule.drawGlobalEffects(s,e,o,r),this.animationFrame=requestAnimationFrame(()=>this.animate())}capitalizeFirst(e){if(!e)return"";const i=e.replace(/-([a-z])/g,(s,o)=>o.toUpperCase());return i.charAt(0).toUpperCase()+i.slice(1)}};v(c,"themes",{christmas:{module:"./themes/christmas.js?v=20261001-options",dates:[[12,1],[1,1]],displayName:"Christmas",emoji:"\u{1F384}"},halloween:{module:"./themes/halloween.js?v=20260930-snow",dates:[[10,26],[10,31]],displayName:"Halloween",emoji:"\u{1F383}"},valentines:{module:"./themes/valentines.js?v=20260930-snow",dates:[[2,9],[2,14]],displayName:"Valentine's Day",emoji:"\u{1F495}"},"guy-fawkes":{module:"./themes/guy-fawkes.js?v=20260930-snow",dates:[[11,1],[11,5]],displayName:"Guy Fawkes Night",emoji:"\u{1F386}"},"st-patricks":{module:"./themes/st-patricks.js?v=20260930-snow",dates:[[3,12],[3,17]],displayName:"St Patrick's Day",emoji:"\u2618\uFE0F"},"st-andrews":{module:"./themes/st-andrews.js?v=20260930-snow",dates:[[11,25],[11,30]],displayName:"St Andrew's Day",emoji:"\u{1F3F4}\u{E0067}\u{E0062}\u{E0073}\u{E0063}\u{E0074}\u{E007F}"},"st-davids":{module:"./themes/st-davids.js?v=20260930-snow",dates:[[2,24],[3,1]],displayName:"St David's Day",emoji:"\u{1F3F4}\u{E0067}\u{E0062}\u{E0077}\u{E006C}\u{E0073}\u{E007F}"},"st-georges":{module:"./themes/st-georges.js?v=20260930-snow",dates:[[4,18],[4,23]],displayName:"St George's Day",emoji:"\u{1F3F4}\u{E0067}\u{E0062}\u{E0065}\u{E006E}\u{E0067}\u{E007F}"}});export let CelebrationsEffect=c;export default CelebrationsEffect;
@@ -0,0 +1 @@
1
+ export function drawIllustratedButterfly(o,e){if(![e.x,e.y,e.size].every(Number.isFinite)||e.size<=0)return;const u=.12+Math.abs(Math.sin(e.flapPhase||0))*.88;o.save(),o.translate(e.x,e.y),o.rotate((e.heading??-Math.PI/2)+Math.PI/2),o.scale(e.size/2.2,e.size/2.2),o.globalAlpha*=e.alpha??1,o.lineCap="round",o.lineJoin="round";const t=(r,a,i,d=.025)=>{o.beginPath();for(const[s,...n]of r)o[s](...n);a&&(o.fillStyle=a,o.fill()),i&&(o.strokeStyle=i,o.lineWidth=d,o.stroke())},l=(r,a,i,d,s)=>{o.beginPath(),o.ellipse(r,a,i,d,0,0,Math.PI*2),o.fillStyle=s,o.fill()};for(const r of[-1,1]){o.save(),o.scale(r*u,1);const a=o.createLinearGradient(0,0,1.1,-.8);a.addColorStop(0,"#504354"),a.addColorStop(.26,e.colourUpper||"#d891b4"),a.addColorStop(1,"#f5dabc");const i=o.createLinearGradient(0,0,.9,.7);i.addColorStop(0,"#63505d"),i.addColorStop(.35,e.colourLower||e.colourUpper||"#bd8fb3"),i.addColorStop(1,"#e8cbb6"),t([["moveTo",.045,-.04],["bezierCurveTo",.3,-.52,.73,-1.02,1.04,-.83],["bezierCurveTo",1.18,-.67,.91,-.13,.63,.03],["quadraticCurveTo",.32,.17,.045,-.04],["closePath"]],a,"#5b4a59",.035),t([["moveTo",.05,0],["bezierCurveTo",.52,-.05,.98,.2,.84,.54],["quadraticCurveTo",.74,.73,.52,.68],["quadraticCurveTo",.31,.87,.15,.54],["quadraticCurveTo",.03,.28,.05,0],["closePath"]],i,"#5b4a59",.035);for(const[d,s]of[[1.03,-.73],[.93,-.38],[.73,-.08],[.8,.37],[.61,.64],[.28,.67]])t([["moveTo",.08,0],["quadraticCurveTo",d*.53,s*.8,d,s]],null,"rgba(78,54,67,0.45)",.018);for(const[d,s,n]of[[.89,-.66,.04],[.87,-.47,.034],[.77,-.29,.03],[.69,.38,.035],[.55,.54,.03],[.35,.55,.028]])l(d,s,n,n*1.2,"#fff0d5");l(.48,-.33,.11,.14,"#69506c"),l(.48,-.33,.058,.075,"#e8c68f"),l(.45,.34,.085,.105,"rgba(90,65,86,0.65)"),o.restore()}l(0,.16,.052,.37,"#493f49"),l(0,-.12,.073,.15,"#5c4d56"),l(0,-.31,.072,.075,"#443a45");for(const r of[-1,1])t([["moveTo",r*.025,-.35],["quadraticCurveTo",r*.1,-.61,r*.2,-.56]],null,"#665362",.018),l(r*.2,-.56,.02,.025,"#d6b391");o.restore()}
@@ -0,0 +1 @@
1
+ import{path as l,ellipse as n,gradient as u,rect as s}from"./christmas-drawing.js";function f(o,r,i=!1){return![r.x,r.y,r.size].every(Number.isFinite)||r.size<=0?!1:(o.save(),o.translate(r.x,r.y),o.scale(r.size*(i&&r.vx<0?-1:1),r.size),o.rotate(r.rotation||0),o.globalAlpha*=r.opacity??1,o.lineCap="round",o.lineJoin="round",!0)}function d(o,r,i,e,a=e){n(o,r,i,e,a,"#20252c"),n(o,r-e*.25,i-a*.25,e*.25,a*.2,"#58616a")}export function drawGhost(o,r,i=r.time||0){if(!f(o,r))return;const e=Math.sin(i*.004)*.08;o.shadowColor="#a7c1c5",o.shadowBlur=5,l(o,[["moveTo",-.57,-.37],["bezierCurveTo",-.57,-1.22,.6,-1.2,.58,-.35],["quadraticCurveTo",.56,.08,.86,.4+e],["quadraticCurveTo",.56,.37,.48,.57],["quadraticCurveTo",.27,.4,.11,.65-e],["quadraticCurveTo",-.13,.41,-.32,.6],["quadraticCurveTo",-.44,.36,-.79,.44-e],["quadraticCurveTo",-.55,.05,-.57,-.37],["closePath"]],u(o,-1,.7,["#fff7df","#dfe9e8","#91aab8"])),o.shadowBlur=0;for(const a of[-1,1])l(o,[["moveTo",a*.37,-.05],["quadraticCurveTo",a*.29,.29,a*.39,.42]],null,"#a7bac2",.02);d(o,-.18,-.44,.065,.1),d(o,.2,-.47,.065,.1),n(o,.045,-.13,.07,.085,"#566779"),n(o,-.32,-.23,.09,.04,"rgba(218,155,151,0.28)"),o.restore()}export function drawBat(o,r,i=r.time||0){if(!f(o,r,!0))return;const e=Math.sin(i*.01)*.35;for(const a of[-1,1]){o.save(),o.scale(a,1),o.rotate(e),l(o,[["moveTo",.13,-.14],["quadraticCurveTo",.7,-.88,1.55,-.38],["quadraticCurveTo",1.06,-.26,1.27,.2],["quadraticCurveTo",.91,-.06,.75,.39],["quadraticCurveTo",.5,.1,.22,.52],["lineTo",.1,.18],["closePath"]],u(o,-.7,.6,["#7b657e","#3d364e","#202939"]),"#967f91",.018);for(const[T,v]of[[1.4,-.37],[1.22,.13],[.75,.31]])l(o,[["moveTo",.14,-.1],["quadraticCurveTo",T*.56,-.1,T,v]],null,"#8b7188",.015);o.restore()}n(o,0,.09,.22,.36,"#443a4b");for(const a of[-1,1])l(o,[["moveTo",a*.18,-.18],["lineTo",a*.21,-.62],["quadraticCurveTo",a*.02,-.46,a*.04,-.18]],"#514454");n(o,0,-.22,.23,.21,"#514454");for(const a of[-.085,.085])n(o,a,-.24,.035,.04,"#e8ba7a"),n(o,a,-.24,.013,.03,"#26303c");l(o,[["moveTo",-.06,-.06],["quadraticCurveTo",0,-.015,.06,-.06]],null,"#c4a5a1",.018),o.restore()}function b(o,r,i,e){if(f(o,r)){n(o,0,.8,1.1,.13,"rgba(10,15,27,0.25)");for(const a of[-1,1])for(const[T,v,m]of[[.56,.44,.68],[.29,.42,.76]])n(o,a*T,.06,v,m,u(o,-.75,.8,["#eab474","#c87942","#7d4136"])),l(o,[["moveTo",a*T,-.53],["quadraticCurveTo",a*(T+.12),-.25,a*(T+.07),.48]],null,"#f1be7d",.025);if(n(o,0,.05,.37,.76,u(o,-.75,.8,["#efb876","#d58a48","#98543a"])),l(o,[["moveTo",-.1,-.65],["quadraticCurveTo",-.17,-.94,.11,-1.02],["lineTo",.2,-.89],["quadraticCurveTo",.04,-.9,.06,-.65],["closePath"]],"#526953","#a6a077",.02),l(o,[["moveTo",.05,-.72],["bezierCurveTo",.41,-.99,.62,-.73,.42,-.66],["bezierCurveTo",.3,-.64,.3,-.83,.44,-.79]],null,"#718665",.025),e){o.shadowColor="#f1b960",o.shadowBlur=5+Math.sin(i*.006+(r.glowPhase||0))*2;const a=u(o,-.3,.55,["#fff0bc","#e7aa59"]);for(const T of[-1,1])l(o,[["moveTo",T*.12,-.19],["lineTo",T*.53,-.28],["quadraticCurveTo",T*.44,.04,T*.18,.02],["closePath"]],a,"#7c4935",.025);l(o,[["moveTo",-.52,.22],["lineTo",-.28,.29],["lineTo",-.24,.2],["lineTo",-.09,.32],["lineTo",.1,.25],["lineTo",.16,.35],["lineTo",.32,.26],["lineTo",.51,.19],["quadraticCurveTo",.21,.7,-.13,.5],["quadraticCurveTo",-.36,.48,-.52,.22],["closePath"]],a,"#7c4935",.025),o.shadowBlur=0}o.restore()}}export function drawPumpkin(o,r,i=r.time||0){b(o,r,i,!1)}export function drawJackOLantern(o,r,i=r.time||0){b(o,r,i,!0)}export function drawScarecrow(o,r,i=0){if(f(o,r)){o.rotate(Math.sin(i*.002+(r.swayPhase||0))*.025),s(o,-.055,.1,.11,1.85,.025,u(o,0,2,["#9b805c","#635042"]));for(const e of[-1,1]){o.save(),o.scale(e,1),l(o,[["moveTo",.31,-.01],["lineTo",1.06,.1],["lineTo",1,.38],["lineTo",.62,.3],["lineTo",.33,.5],["closePath"]],u(o,0,.5,["#8a9b88","#566e68"]),"#b1ab87",.018);for(let a=0;a<5;a++)l(o,[["moveTo",.99,.19+a*.025],["lineTo",1.2+a%2*.08,.13+a*.05]],null,"#d5b679",.02);l(o,[["moveTo",.62,.11],["lineTo",.6,.25]],null,"#c2b991",.012),o.restore()}l(o,[["moveTo",-.37,-.01],["quadraticCurveTo",-.51,.45,-.55,1.02],["lineTo",-.36,.92],["lineTo",-.2,1.12],["lineTo",.02,1.02],["lineTo",.24,1.13],["lineTo",.5,.97],["quadraticCurveTo",.47,.45,.35,-.01],["closePath"]],u(o,0,1.15,["#899782","#536960","#394e4c"]),"#a7a98b",.018);for(const e of[.27,.52,.78])d(o,.025,e,.028),l(o,[["moveTo",-.25,e],["lineTo",-.13,e+.1]],null,"#b2ad89",.012);s(o,.16,.48,.2,.22,.01,"#b28966","#d7b78c",.015);for(let e=0;e<7;e++)l(o,[["moveTo",-.37+e*.12,1],["lineTo",-.4+e*.12,1.2+e%2*.08]],null,"#d3b77d",.016);n(o,0,-.38,.35,.35,u(o,-.75,0,["#ddc8a0","#b99a71"]));for(const e of[-.12,.12])l(o,[["moveTo",e-.04,-.45],["lineTo",e+.04,-.37],["moveTo",e+.04,-.45],["lineTo",e-.04,-.37]],null,"#554b47",.026);l(o,[["moveTo",-.17,-.24],["quadraticCurveTo",0,-.13,.17,-.25]],null,"#655448",.02);for(let e=0;e<5;e++)l(o,[["moveTo",-.13+e*.06,-.25],["lineTo",-.14+e*.06,-.18]],null,"#655448",.018);l(o,[["moveTo",-.39,-.65],["lineTo",-.25,-1.16],["quadraticCurveTo",-.05,-1.24,.28,-1.12],["lineTo",.38,-.62],["closePath"]],u(o,-1.2,-.5,["#655655","#322f39"])),s(o,-.31,-.76,.66,.12,.02,"#ab725d"),n(o,0,-.61,.58,.09,"#3e3942"),l(o,[["moveTo",-.2,-.03],["lineTo",-.07,.12],["lineTo",.12,.05],["lineTo",.34,.41],["lineTo",.51,.32],["lineTo",.19,-.06],["closePath"]],"#b96858"),o.restore()}}export function drawHauntedHouse(o,r,i=0){if(f(o,r)){n(o,0,1.53,1.16,.13,"rgba(5,12,23,0.35)");for(const e of[-1,1]){o.save(),o.scale(e,1),o.rotate(e*.015),l(o,[["moveTo",.61,-.56],["lineTo",1.04,-.61],["lineTo",1.08,1.41],["lineTo",.56,1.41],["closePath"]],u(o,-.6,1.4,["#586172","#303d51","#19283c"]),"#71808a",.018),l(o,[["moveTo",.49,-.55],["lineTo",.77,-1.25],["lineTo",1.16,-.58],["closePath"]],"#303347","#879095",.02),l(o,[["moveTo",.77,-1.25],["lineTo",.77,-1.49]],null,"#97a1a5",.015);for(const a of[-.22,.27,.75])s(o,.72,a,.18,.25,.035,"#e8bb7d","#a58066",.02),l(o,[["moveTo",.81,a],["lineTo",.81,a+.25],["moveTo",.72,a+.13],["lineTo",.9,a+.13]],null,"#5f5c5c",.022);o.restore()}s(o,-.52,.11,1.09,1.32,.025,u(o,0,1.5,["#4a556a","#28384d"]),"#65737d",.018),s(o,.28,-.94,.12,.55,.01,"#475266"),l(o,[["moveTo",-.64,.16],["lineTo",-.12,-.73],["lineTo",.63,.14],["closePath"]],"#353b51","#849092",.02);for(let e=0;e<4;e++)l(o,[["moveTo",-.48+e*.11,.03-e*.17],["lineTo",.49-e*.15,.03-e*.17]],null,"#5e6271",.012);n(o,-.08,-.11,.12,.16,"#dcac73");for(const e of[-.32,.26])s(o,e,.35,.21,.31,.07,"#e8b980","#7f7972",.025),l(o,[["moveTo",e+.1,.35],["lineTo",e+.1,.66],["moveTo",e,.5],["lineTo",e+.21,.5]],null,"#575c65",.02),s(o,e-.035,.7,.28,.035,.01,"#8b9699");s(o,-.15,.86,.34,.54,.15,"#182739","#6f7e89",.025),n(o,.11,1.15,.018,.018,"#d6b582");for(const e of[1.43,1.49])s(o,-.27,e,.59,.055,.01,"#64707c");for(let e=0;e<12;e++){const a=(e<6?-1.15:.72)+e%6*.085;l(o,[["moveTo",a,1.5],["lineTo",a,1.15],["lineTo",a-.025,1.2],["moveTo",a,1.15],["lineTo",a+.025,1.2]],null,"#78868c",.012)}l(o,[["moveTo",-1.16,1.32],["lineTo",-.68,1.32],["moveTo",.73,1.32],["lineTo",1.17,1.32]],null,"#78868c",.018),o.save(),o.globalAlpha*=.3,l(o,[["moveTo",.34,-.94],["bezierCurveTo",.06,-1.23,.65,-1.42,.32+Math.sin(i*.001)*.07,-1.7]],null,"#a1b2bb",.045),o.restore(),o.restore()}}
@@ -1 +1 @@
1
- export default{name:"halloween",displayName:"Halloween",emoji:"\u{1F383}",intensityConfig:{light:{count:30,speedRange:[.3,1],sizeRange:[2,5],gravestones:3,jackOLanterns:2,spiders:2,scarecrows:1,twinklingStars:8},medium:{count:60,speedRange:[.5,1.5],sizeRange:[2,6],gravestones:5,jackOLanterns:4,spiders:4,scarecrows:2,twinklingStars:15},heavy:{count:100,speedRange:[.7,2],sizeRange:[3,8],gravestones:8,jackOLanterns:6,spiders:6,scarecrows:3,twinklingStars:25}},particles:["bat","ghost","pumpkin"],decorations:["gravestone","jack-o-lantern","haunted-house","cauldron","spider","scarecrow","twinkling-star"],colors:{primary:"#ff6600",secondary:"#1a1a2e",accent:"#8b0000",ghost:"#f0f0f0",purple:"#6a0dad"},lightningChance:5e-4,lightningDuration:200,lightningTimer:0,lightningActive:!1,lightningColor:"#fefefe",createBat(e,n,i){const s=Math.random();let o,a,l;s<.33?(o=i.sizeRange[0]+Math.random()*(i.sizeRange[1]-i.sizeRange[0])*1.5,a=i.speedRange[0]+Math.random()*(i.speedRange[1]-i.speedRange[0])*1.3,l=.9+Math.random()*.1):s<.66?(o=i.sizeRange[0]+Math.random()*(i.sizeRange[1]-i.sizeRange[0]),a=i.speedRange[0]+Math.random()*(i.speedRange[1]-i.sizeRange[0]),l=.6+Math.random()*.2):(o=i.sizeRange[0]+Math.random()*(i.sizeRange[1]-i.sizeRange[0])*.7,a=i.speedRange[0]+Math.random()*(i.sizeRange[1]-i.sizeRange[0])*.7,l=.4+Math.random()*.2);const t=Math.random()<.5;return{type:"bat",x:t?-20:e+20,y:Math.random()*n*.7,baseY:Math.random()*n*.7,vx:t?a*2:-a*2,vy:0,size:o,speed:a,opacity:l,waveAmplitude:10+Math.random()*20,waveFrequency:.002+Math.random()*.003,waveOffset:Math.random()*Math.PI*2,time:0,rotation:0,active:!0,depth:s}},createGhost(e,n,i){const s=Math.random();let o,a,l;return s<.33?(o=i.sizeRange[0]+Math.random()*(i.sizeRange[1]-i.sizeRange[0])*1.8,a=i.speedRange[0]+Math.random()*(i.speedRange[1]-i.sizeRange[0])*.5,l=.7+Math.random()*.2):s<.66?(o=i.sizeRange[0]+Math.random()*(i.sizeRange[1]-i.sizeRange[0])*1.2,a=i.speedRange[0]+Math.random()*(i.sizeRange[1]-i.sizeRange[0])*.5,l=.5+Math.random()*.15):(o=i.sizeRange[0]+Math.random()*(i.sizeRange[1]-i.sizeRange[0]),a=i.speedRange[0]+Math.random()*(i.sizeRange[1]-i.sizeRange[0])*.5,l=.3+Math.random()*.15),{type:"ghost",x:Math.random()*e,y:-50,size:o,speed:a,opacity:l,windOffset:Math.random()*Math.PI*2,windSpeed:.01+Math.random()*.02,rotation:0,rotationSpeed:(Math.random()-.5)*.005,time:Math.random()*1e3,active:!0,depth:s}},createPumpkin(e,n,i){return{type:"pumpkin",x:Math.random()*e,y:Math.random()*n,size:i.sizeRange[0]+Math.random()*(i.sizeRange[1]-i.sizeRange[0]),vx:(Math.random()-.5)*.2,speed:(i.speedRange[0]+Math.random()*(i.speedRange[1]-i.sizeRange[0]))*.2,opacity:.8+Math.random()*.2,rotation:Math.random()*Math.PI*2,rotationSpeed:(Math.random()-.5)*.008,windOffset:Math.random()*Math.PI*2,windSpeed:.008+Math.random()*.015,glowPhase:Math.random()*Math.PI*2,floatPhase:Math.random()*Math.PI*2,floatSpeed:.001+Math.random()*.002,active:!0}},createGravestone(e,n,i={}){const s=["rounded","cross","obelisk"];return{type:"gravestone",x:i.x!==void 0?i.x:Math.random()*e,y:i.y!==void 0?i.y:n-30-Math.random()*20,size:15+Math.random()*10,opacity:.7+Math.random()*.2,shape:s[Math.floor(Math.random()*s.length)],rotation:(Math.random()-.5)*.1,active:!0,static:!0}},createJackOLantern(e,n,i={}){const s=["happy","scary","wicked"];return{type:"jack-o-lantern",x:i.x!==void 0?i.x:Math.random()*e,y:i.y!==void 0?i.y:n-25-Math.random()*15,size:12+Math.random()*8,opacity:.9+Math.random()*.1,face:s[Math.floor(Math.random()*s.length)],glowPhase:Math.random()*Math.PI*2,active:!0,static:!0}},createSpider(e,n,i={}){return{type:"spider",x:i.x!==void 0?i.x:Math.random()*e,y:i.y!==void 0?i.y:Math.random()*n*.3,baseY:i.y!==void 0?i.y:Math.random()*n*.3,size:5+Math.random()*5,opacity:.8+Math.random()*.2,threadLength:30+Math.random()*50,swingPhase:Math.random()*Math.PI*2,swingAmplitude:20+Math.random()*30,swingSpeed:.001+Math.random()*.002,time:0,active:!0,static:!1}},createFallingParticle(e,n,i){return Math.random()<.7?this.createPumpkin(e,n,i):{type:"spider-small",x:Math.random()*e,y:-20,size:1+Math.random()*2,speed:i.speedRange[0]+Math.random()*(i.speedRange[1]-i.sizeRange[0])*.5,opacity:.6+Math.random()*.3,rotation:Math.random()*Math.PI*2,rotationSpeed:(Math.random()-.5)*.02,windOffset:Math.random()*Math.PI*2,windSpeed:.01+Math.random()*.02,active:!0}},createInitialDecorations(e,n,i){const s=[];s.push({type:"haunted-house",x:80,y:n-120,size:80,opacity:.85,active:!0,static:!0}),s.push({type:"moon",x:e-120,y:100,size:60,opacity:.9,glowPhase:0,active:!0,static:!0});const o=i.gravestones??5;for(let r=0;r<o;r++)s.push({type:"gravestone",x:e/(o+1)*(r+1)+(Math.random()-.5)*40,y:n-30-Math.random()*10,size:12+Math.random()*8,opacity:.7+Math.random()*.2,variant:Math.floor(Math.random()*3),active:!0,static:!0});const a=i.jackOLanterns??4;for(let r=0;r<a;r++)s.push({type:"jack-o-lantern",x:e/(a+1)*(r+1)+(Math.random()-.5)*30,y:n-15,size:10+Math.random()*6,opacity:.9,glowPhase:Math.random()*Math.PI*2,active:!0,static:!0});const l=i.spiders??4;for(let r=0;r<l;r++)s.push({type:"spider",x:e/(l+1)*(r+1),y:0,targetY:50+Math.random()*100,currentY:0,size:3+Math.random()*3,opacity:.8,swingPhase:Math.random()*Math.PI*2,swingAmplitude:20+Math.random()*30,swingSpeed:.02+Math.random()*.02,active:!0,static:!0});const t=i.scarecrows??2;for(let r=0;r<t;r++)s.push({type:"scarecrow",x:120+r/(t-1||1)*(e-240),y:n-60,size:30+Math.random()*10,opacity:.9,swayPhase:Math.random()*Math.PI*2,swaySpeed:.015+Math.random()*.015,glowPhase:Math.random()*Math.PI*2,glowSpeed:.02,active:!0,static:!0});const h=i.twinklingStars??15;for(let r=0;r<h;r++)s.push(this.createTwinklingStar(e,n));return s},createTwinklingStar(e,n){return{type:"twinkling-star",x:Math.random()*e,y:Math.random()*(n*.5),size:1+Math.random()*2.5,opacity:.5+Math.random()*.3,twinklePhase:Math.random()*Math.PI*2,twinkleSpeed:.004+Math.random()*.003,colorVariant:Math.floor(Math.random()*3),active:!0,static:!0}},drawLightning(e,n,i,s,o,a,l,t,h,r,M){if(a<1)return;const d=(n+s)/2,f=(i+o)/2,g=Math.atan2(o-i,s-n),m=g+Math.PI/2,T=(Math.random()-.5)*l,y=d+Math.cos(m)*T,P=f+Math.sin(m)*T,u=a-1,w=l*t,b=r*.8;if(e.strokeStyle=M,e.lineWidth=r,e.lineCap="round",e.lineJoin="round",e.beginPath(),e.moveTo(n,i),e.lineTo(y,P),e.lineTo(s,o),e.stroke(),u>0&&(this.drawLightning(e,n,i,y,P,u,w,t,h,b,M),this.drawLightning(e,y,P,s,o,u,w,t,h,b,M),Math.random()<h&&u>1)){const S=Math.random()*l*.5,v=(Math.random()-.5)*Math.PI/3,k=y+Math.cos(g+v)*S,p=P+Math.sin(g+v)*S;this.drawLightning(e,y,P,k,p,u-1,w*.5,t,h*.5,b*.6,M)}},spawnSpecialParticle(e,n,i){const s=Math.random(),o=this.intensityConfig.medium;if(s<.15)return this.createBat(n,i,o);if(s<.16){if(e.some(l=>l.type==="witch"))return null;const a=Math.random()<.5;return{type:"witch",x:a?-100:n+100,y:Math.random()*(i*.4)+50,baseY:Math.random()*(i*.4)+50,vx:a?3+Math.random()*2:-(3+Math.random()*2),size:15+Math.random()*8,opacity:.85,waveAmplitude:15+Math.random()*20,waveFrequency:.002+Math.random()*.002,waveOffset:Math.random()*Math.PI*2,time:0,active:!0,static:!1}}return s<.18?{type:"floating-pumpkin",x:Math.random()*n,y:-50,size:8+Math.random()*6,vx:(Math.random()-.5)*.5,vy:.3+Math.random()*.5,opacity:.9,rotation:Math.random()*Math.PI*2,rotationSpeed:(Math.random()-.5)*.01,glowPhase:Math.random()*Math.PI*2,windOffset:Math.random()*Math.PI*2,windSpeed:.015,active:!0}:s<.2102?e.some(a=>a.type==="haunted-house")?null:{type:"haunted-house",x:Math.random()*n*.6+n*.2,y:i-100,size:40+Math.random()*20,opacity:.8,windowFlicker:0,active:!0,static:!0}:s<.2105?e.some(a=>a.type==="cauldron")?null:{type:"cauldron",x:Math.random()*n*.6+n*.2,y:i-40,size:25+Math.random()*10,opacity:1,bubbles:[],smoke:[],time:0,active:!0,static:!0}:null},updateSpecialParticles(e,n,i,s){this.lightningActive?(this.lightningTimer+=n,this.lightningTimer>=this.lightningDuration&&(this.lightningActive=!1,this.lightningTimer=0)):Math.random()<this.lightningChance&&(this.lightningActive=!0,this.lightningTimer=0),e.forEach(o=>{switch(o.time!==void 0&&(o.time+=n),o.type){case"moon":break;case"witch":(o.vx>0&&o.x>i+100||o.vx<0&&o.x<-100)&&(o.active=!1);break;case"floating-pumpkin":o.y>s+50&&(o.active=!1);break;case"cauldron":o.time%100<20&&o.bubbles.push({x:(Math.random()-.5)*o.size*.5,y:o.size*.3+Math.random()*o.size*.2,size:o.size*(.05+Math.random()*.1),vy:-.5-Math.random()*.5,opacity:1,life:1,fadeRate:.01+Math.random()*.005}),o.bubbles=o.bubbles.filter(a=>(a.y+=a.vy,a.vy*=.98,a.opacity-=a.fadeRate,a.opacity>0&&a.y>-o.size)),o.time%200<30&&o.smoke.push({x:(Math.random()-.5)*o.size*.3,y:-o.size*.5+Math.random()*o.size*.1,size:o.size*(.2+Math.random()*.3),vx:(Math.random()-.5)*.1,vy:-.2-Math.random()*.2,opacity:.5,life:1,fadeRate:.005+Math.random()*.003}),o.smoke=o.smoke.filter(a=>(a.x+=a.vx,a.y+=a.vy,a.size*=1.02,a.opacity-=a.fadeRate,a.opacity>0));break}})},drawBat(e,n){const i=n.x,s=n.y,o=n.size,a=n.vx>0?1:-1,l=n.time;e.save(),e.globalAlpha=n.opacity,e.translate(i,s),a===-1&&e.scale(-1,1);const t=l*.01,h=Math.sin(t)*(Math.PI/4);e.fillStyle="#1a1a1a",e.beginPath(),e.ellipse(0,0,o*.4,o*.6,0,0,Math.PI*2),e.fill(),e.beginPath(),e.arc(o*.3,-o*.4,o*.35,0,Math.PI*2),e.fill(),e.beginPath(),e.moveTo(o*.1,-o*.7),e.lineTo(o*.25,-o*1.1),e.lineTo(o*.4,-o*.7),e.fill(),e.beginPath(),e.moveTo(o*.2,-o*.7),e.lineTo(o*.35,-o*1),e.lineTo(o*.5,-o*.7),e.fill(),e.fillStyle="#ff0000",e.beginPath(),e.arc(o*.2,-o*.45,o*.08,0,Math.PI*2),e.fill(),e.beginPath(),e.arc(o*.4,-o*.45,o*.08,0,Math.PI*2),e.fill(),e.fillStyle="rgba(255, 0, 0, 0.3)",e.beginPath(),e.arc(o*.2,-o*.45,o*.15,0,Math.PI*2),e.fill(),e.beginPath(),e.arc(o*.4,-o*.45,o*.15,0,Math.PI*2),e.fill(),e.fillStyle="#2a2a2a",e.strokeStyle="#1a1a1a",e.lineWidth=1,e.save(),e.translate(-o*.3,0),e.rotate(-h),e.beginPath(),e.moveTo(0,0),e.quadraticCurveTo(-o*.8,-o*.5,-o*1.2,0),e.quadraticCurveTo(-o*.9,o*.3,-o*.6,o*.4),e.quadraticCurveTo(-o*.3,o*.2,0,0),e.closePath(),e.fill(),e.stroke(),e.restore(),e.save(),e.translate(o*.3,0),e.rotate(h),e.beginPath(),e.moveTo(0,0),e.quadraticCurveTo(o*.8,-o*.5,o*1.2,0),e.quadraticCurveTo(o*.9,o*.3,o*.6,o*.4),e.quadraticCurveTo(o*.3,o*.2,0,0),e.closePath(),e.fill(),e.stroke(),e.restore(),e.restore()},drawGhost(e,n){const i=n.x,s=n.y,o=n.size,a=n.time;e.save(),e.globalAlpha=n.opacity,e.translate(i,s),e.fillStyle="#f0f0f0",e.shadowColor="rgba(240, 240, 240, 0.5)",e.shadowBlur=15,e.beginPath(),e.arc(0,-o*.5,o*.6,Math.PI,0);const l=5;for(let t=0;t<=l;t++){const h=-o*.6+t/l*o*1.2,r=Math.sin(a*.005+t)*o*.15;t===0?e.lineTo(h,r):e.quadraticCurveTo(h-o*.12,r-o*.1,h,r)}e.closePath(),e.fill(),e.shadowBlur=0,e.fillStyle="#000000",e.beginPath(),e.ellipse(-o*.2,-o*.6,o*.12,o*.18,-.2,0,Math.PI*2),e.fill(),e.beginPath(),e.ellipse(o*.2,-o*.6,o*.12,o*.18,.2,0,Math.PI*2),e.fill(),e.beginPath(),e.ellipse(0,-o*.3,o*.15,o*.2,0,0,Math.PI*2),e.fill(),e.restore()},drawPumpkin(e,n,i){const s=n.x,o=n.y,a=n.size;e.save(),e.globalAlpha=n.opacity,e.translate(s,o),e.rotate(n.rotation),e.fillStyle="#ff6600",e.strokeStyle="#cc5200",e.lineWidth=a*.08;const l=5;e.beginPath();for(let r=0;r<l;r++){const M=r/l*Math.PI*2-Math.PI/2,d=(r+1)/l*Math.PI*2-Math.PI/2,f=a*.9,g=a;r===0&&e.moveTo(Math.cos(M)*f,Math.sin(M)*g),e.quadraticCurveTo(Math.cos((M+d)/2)*f*.8,Math.sin((M+d)/2)*g*.8,Math.cos(d)*f,Math.sin(d)*g)}e.closePath(),e.fill(),e.stroke(),e.fillStyle="#8B4513",e.fillRect(-a*.2,-a*1.1,a*.4,a*.2);const t=(Math.sin(i*.002+n.glowPhase)+1)*.5;e.globalAlpha=n.opacity*t*.7;const h=e.createRadialGradient(0,0,0,0,0,a);h.addColorStop(0,"#ffaa00"),h.addColorStop(1,"rgba(255, 170, 0, 0)"),e.fillStyle=h,e.fillRect(-a,-a,a*2,a*2),e.restore()},drawGravestone(e,n){const i=n.x,s=n.y,o=n.size;e.save(),e.globalAlpha=n.opacity,e.translate(i,s),e.rotate(n.rotation),e.fillStyle="#555555",e.strokeStyle="#333333",e.lineWidth=1,n.shape==="rounded"?(e.beginPath(),e.moveTo(-o*.5,o*.8),e.lineTo(-o*.5,-o*.3),e.arc(0,-o*.3,o*.5,Math.PI,0),e.lineTo(o*.5,o*.8),e.closePath(),e.fill(),e.stroke()):n.shape==="cross"?(e.fillRect(-o*.15,-o,o*.3,o*1.8),e.fillRect(-o*.5,-o*.3,o,o*.3)):(e.beginPath(),e.moveTo(-o*.4,o*.8),e.lineTo(-o*.5,-o*.5),e.lineTo(0,-o),e.lineTo(o*.5,-o*.5),e.lineTo(o*.4,o*.8),e.closePath(),e.fill(),e.stroke()),e.fillStyle="rgba(0, 100, 0, 0.3)",e.fillRect(-o*.4,o*.5,o*.8,o*.3),e.fillStyle="#222222",e.font=`${o*.4}px serif`,e.textAlign="center",e.textBaseline="middle",e.fillText("RIP",0,0),e.restore()},drawJackOLantern(e,n,i){const s=n.x,o=n.y,a=n.size;e.save(),e.globalAlpha=n.opacity,e.translate(s,o),e.fillStyle="#ff8800",e.beginPath(),e.ellipse(0,0,a*1.2,a,0,0,Math.PI*2),e.fill(),e.strokeStyle="#cc6600",e.lineWidth=a*.08;for(let r=-2;r<=2;r++)e.beginPath(),e.moveTo(r*a*.35,-a*.8),e.quadraticCurveTo(r*a*.3,0,r*a*.35,a*.8),e.stroke();e.fillStyle="#8B4513",e.fillRect(-a*.2,-a*1.1,a*.4,a*.2);const l=.8+Math.sin(i*.02+n.glowPhase)*.2,t=.5+l*.5,h=e.createRadialGradient(0,0,0,0,0,a*1.5);h.addColorStop(0,`rgba(255, 255, 100, ${t})`),h.addColorStop(.5,`rgba(255, 200, 0, ${t*.7})`),h.addColorStop(1,"rgba(255, 150, 0, 0)"),e.fillStyle=h,e.fillRect(-a*1.5,-a*1.5,a*3,a*3),e.fillStyle="#000000",e.shadowColor=`rgba(255, 180, 0, ${l})`,e.shadowBlur=a*.5,e.beginPath(),e.moveTo(-a*.6,-a*.4),e.lineTo(-a*.2,-a*.3),e.lineTo(-a*.5,-a*.1),e.closePath(),e.fill(),e.beginPath(),e.moveTo(a*.6,-a*.4),e.lineTo(a*.2,-a*.3),e.lineTo(a*.5,-a*.1),e.closePath(),e.fill(),e.beginPath(),e.moveTo(-a*.7,a*.2),e.lineTo(-a*.5,a*.4),e.lineTo(-a*.3,a*.25),e.lineTo(0,a*.45),e.lineTo(a*.3,a*.25),e.lineTo(a*.5,a*.4),e.lineTo(a*.7,a*.2),e.lineTo(a*.5,a*.1),e.lineTo(0,a*.25),e.lineTo(-a*.5,a*.1),e.closePath(),e.fill(),e.shadowBlur=0,e.restore()},drawHauntedHouse(e,n,i){const s=n.x,o=n.y,a=n.size;e.save(),e.globalAlpha=n.opacity,e.translate(s,o);const l="#1a1a2e",t="#0a0a0a",h=.5+Math.random()*.5;e.fillStyle=l,e.strokeStyle=t,e.lineWidth=2,e.fillRect(-a*1.2,-a*1.4,a*.5,a*2);for(let r=0;r<3;r++)e.fillRect(-a*1.2+r*a*.2,-a*1.5,a*.12,a*.1);e.beginPath(),e.moveTo(-a*1.3,-a*1.5),e.lineTo(-a*.95,-a*2),e.lineTo(-a*.6,-a*1.5),e.closePath(),e.fill(),e.stroke(),e.fillRect(a*.7,-a*1.3,a*.5,a*1.9);for(let r=0;r<3;r++)e.fillRect(a*.7+r*a*.2,-a*1.4,a*.12,a*.1);e.beginPath(),e.moveTo(a*.6,-a*1.4),e.lineTo(a*.95,-a*1.9),e.lineTo(a*1.3,-a*1.4),e.closePath(),e.fill(),e.stroke(),e.fillRect(-a*.7,-a*.9,a*1.4,a*1.5),e.strokeRect(-a*.7,-a*.9,a*1.4,a*1.5);for(let r=0;r<7;r++)r%2===0&&e.fillRect(-a*.7+r*a*.2,-a*1,a*.2,a*.1);e.fillRect(-a*.8,-a*1.1,a*.3,a*.5),e.beginPath(),e.moveTo(-a*.85,-a*1.1),e.lineTo(-a*.65,-a*1.35),e.lineTo(-a*.45,-a*1.1),e.closePath(),e.fill(),e.fillRect(a*.5,-a*1.1,a*.3,a*.5),e.beginPath(),e.moveTo(a*.45,-a*1.1),e.lineTo(a*.65,-a*1.35),e.lineTo(a*.85,-a*1.1),e.closePath(),e.fill(),e.fillStyle=`rgba(255, 200, 100, ${h})`,e.shadowColor="#ffcc66",e.shadowBlur=10,e.fillRect(-a*1.05,-a*1.2,a*.2,a*.25),e.fillRect(-a*1.05,-a*.8,a*.2,a*.25),e.fillRect(-a*1.05,-a*.4,a*.2,a*.25),e.fillRect(a*.85,-a*1.1,a*.2,a*.25),e.fillRect(a*.85,-a*.7,a*.2,a*.25),e.fillRect(a*.85,-a*.3,a*.2,a*.25),e.fillRect(-a*.5,-a*.6,a*.25,a*.3),e.fillRect(-a*.1,-a*.6,a*.25,a*.3),e.fillRect(a*.3,-a*.6,a*.25,a*.3),e.fillRect(-a*.3,-a*.15,a*.25,a*.3),e.fillRect(a*.1,-a*.15,a*.25,a*.3),e.shadowBlur=0,e.fillStyle=t,e.beginPath(),e.arc(0,a*.3,a*.25,Math.PI,0,!0),e.lineTo(a*.25,a*.6),e.lineTo(-a*.25,a*.6),e.closePath(),e.fill(),e.strokeStyle="#333333",e.lineWidth=1.5;for(let r=-2;r<=2;r++)e.beginPath(),e.moveTo(r*a*.1,a*.3),e.lineTo(r*a*.1,a*.6),e.stroke();e.restore()},drawCauldron(e,n,i){const s=n.x,o=n.y,a=n.size;e.save(),e.translate(s,o),e.fillStyle="#222222",e.strokeStyle="#111111",e.lineWidth=2,e.beginPath(),e.arc(0,0,a*.8,0,Math.PI),e.lineTo(-a*.8,a*.5),e.quadraticCurveTo(0,a*.8,a*.8,a*.5),e.closePath(),e.fill(),e.stroke(),e.strokeStyle="#1a1a1a",e.lineWidth=3,[-a*.5,0,a*.5].forEach(l=>{e.beginPath(),e.moveTo(l,a*.5),e.lineTo(l,a*.9),e.stroke()}),e.fillStyle="#00ff00",e.shadowColor="#00ff00",e.shadowBlur=15,e.beginPath(),e.ellipse(0,0,a*.7,a*.3,0,0,Math.PI*2),e.fill(),e.shadowBlur=0,n.bubbles.forEach(l=>{e.globalAlpha=l.opacity,e.fillStyle="#88ff88",e.beginPath(),e.arc(l.x,l.y,l.size,0,Math.PI*2),e.fill()}),e.globalAlpha=1,n.smoke.forEach(l=>{e.globalAlpha=l.opacity,e.fillStyle="#aaaaaa",e.beginPath(),e.arc(l.x,l.y,l.size,0,Math.PI*2),e.fill()}),e.restore()},drawSpider(e,n,i){const s=n.x,o=n.y,a=n.size,l=Math.sin(i*n.swingSpeed+n.swingPhase)*n.swingAmplitude;e.save(),e.globalAlpha=n.opacity,e.strokeStyle="#cccccc",e.lineWidth=1,e.setLineDash([2,2]),e.beginPath(),e.moveTo(s,o),e.lineTo(s+l,o+n.threadLength),e.stroke(),e.setLineDash([]),e.translate(s+l,o+n.threadLength),e.fillStyle="#000000",e.beginPath(),e.ellipse(0,0,a*.5,a*.7,0,0,Math.PI*2),e.fill(),e.beginPath(),e.arc(0,-a*.5,a*.3,0,Math.PI*2),e.fill(),e.strokeStyle="#1a1a1a",e.lineWidth=a*.1;const t=Math.sin(i*.005)*.2;for(let h=0;h<4;h++){const r=h/4*Math.PI-Math.PI/2,M=a*1.5;e.beginPath(),e.moveTo(-a*.3,-a*.2+h*a*.2),e.quadraticCurveTo(-a-Math.sin(r+t)*a*.3,-a*.2+h*a*.2-a*.5,-a*1.2,-a*.2+h*a*.2),e.stroke(),e.beginPath(),e.moveTo(a*.3,-a*.2+h*a*.2),e.quadraticCurveTo(a+Math.sin(r+t)*a*.3,-a*.2+h*a*.2-a*.5,a*1.2,-a*.2+h*a*.2),e.stroke()}e.fillStyle="#ff0000";for(let h=0;h<4;h++)e.beginPath(),e.arc(-a*.15+h%2*a*.3,-a*.55+Math.floor(h/2)*a*.1,a*.05,0,Math.PI*2),e.fill();e.restore()},drawSpiderSmall(e,n){e.save(),e.globalAlpha=n.opacity,e.translate(n.x,n.y),e.rotate(n.rotation),e.fillStyle="#1a1a1a",e.beginPath(),e.arc(0,0,n.size,0,Math.PI*2),e.fill(),e.strokeStyle="#1a1a1a",e.lineWidth=n.size*.3;for(let i=0;i<4;i++){const s=i/4*Math.PI-Math.PI/2;e.beginPath(),e.moveTo(0,0),e.lineTo(Math.cos(s)*n.size*2,Math.sin(s)*n.size*2),e.stroke(),e.beginPath(),e.moveTo(0,0),e.lineTo(-Math.cos(s)*n.size*2,Math.sin(s)*n.size*2),e.stroke()}e.restore()},drawWitch(e,n,i){const s=n.x,o=n.y+Math.sin(i*n.waveFrequency+n.waveOffset)*n.waveAmplitude,a=n.size,l=n.vx>0?1:-1;e.save(),e.globalAlpha=n.opacity,e.translate(s,o),l===-1&&e.scale(-1,1),e.strokeStyle="#8B4513",e.lineWidth=a*.12,e.lineCap="round",e.beginPath(),e.moveTo(a*.2,a*.6),e.lineTo(-a*1.5,a*.6),e.stroke(),e.strokeStyle="#D2691E",e.lineWidth=a*.06;for(let t=0;t<8;t++){const h=Math.PI/3*(t/7-.5);e.beginPath(),e.moveTo(-a*1.5,a*.6),e.lineTo(-a*1.5+Math.cos(h)*a*.4,a*.6+Math.sin(h)*a*.4),e.stroke()}e.fillStyle="#1a1a1a",e.strokeStyle="#0a0a0a",e.lineWidth=1,e.beginPath(),e.moveTo(a*.2,a*.6),e.quadraticCurveTo(-a*.5,a*.4,-a*.8,a*.1),e.lineTo(-a*.7,-a*.3),e.quadraticCurveTo(-a*.3,-a*.5,0,-a*.6),e.lineTo(a*.3,-a*.4),e.lineTo(a*.3,a*.5),e.closePath(),e.fill(),e.stroke(),e.fillStyle="#8B9355",e.beginPath(),e.ellipse(a*.25,-a*.6,a*.3,a*.35,0,0,Math.PI*2),e.fill(),e.fillStyle="#7a8245",e.beginPath(),e.moveTo(a*.45,-a*.6),e.quadraticCurveTo(a*.7,-a*.65,a*.72,-a*.5),e.lineTo(a*.6,-a*.52),e.quadraticCurveTo(a*.58,-a*.58,a*.4,-a*.55),e.closePath(),e.fill(),e.fillStyle="#2C1810",e.beginPath(),e.moveTo(a*.05,-a*.85),e.lineTo(a*.4,-a*1.6),e.lineTo(a*.5,-a*.8),e.closePath(),e.fill(),e.beginPath(),e.ellipse(a*.25,-a*.85,a*.5,a*.12,0,0,Math.PI*2),e.fill(),e.fillStyle="#ff6600",e.shadowColor="#ff6600",e.shadowBlur=a*.3,e.beginPath(),e.arc(a*.35,-a*.65,a*.08,0,Math.PI*2),e.fill(),e.shadowBlur=0,e.fillStyle="#8B9355",e.beginPath(),e.arc(a*.1,a*.5,a*.12,0,Math.PI*2),e.fill(),e.beginPath(),e.arc(-a*.3,a*.55,a*.1,0,Math.PI*2),e.fill(),e.strokeStyle="#1a1a1a",e.lineWidth=a*.1,e.beginPath(),e.moveTo(a*.15,a*.6),e.lineTo(a*.1,a*1),e.stroke(),e.beginPath(),e.moveTo(a*.05,a*.6),e.lineTo(a*.2,a*.95),e.stroke(),e.restore()},drawFloatingPumpkin(e,n){const i=n.x,s=n.y,o=n.size;e.save(),e.globalAlpha=n.opacity,e.translate(i,s),e.rotate(n.rotation),e.fillStyle="#ff6600",e.strokeStyle="#cc5200",e.lineWidth=o*.1,e.beginPath(),e.ellipse(0,0,o,o*.9,0,0,Math.PI*2),e.fill(),e.stroke();for(let l=-2;l<=2;l++)e.beginPath(),e.moveTo(l*o*.25,-o*.8),e.quadraticCurveTo(l*o*.3,0,l*o*.25,o*.8),e.stroke();e.fillStyle="#228B22",e.beginPath(),e.moveTo(-o*.15,-o*.8),e.lineTo(-o*.1,-o*1.1),e.lineTo(o*.1,-o*1.1),e.lineTo(o*.15,-o*.8),e.closePath(),e.fill();const a=.5+Math.sin(n.glowPhase+Date.now()*.005)*.5;e.fillStyle=`rgba(255, 200, 0, ${a})`,e.beginPath(),e.moveTo(-o*.4,-o*.3),e.lineTo(-o*.2,-o*.1),e.lineTo(-o*.6,-o*.1),e.closePath(),e.fill(),e.beginPath(),e.moveTo(o*.4,-o*.3),e.lineTo(o*.6,-o*.1),e.lineTo(o*.2,-o*.1),e.closePath(),e.fill(),e.beginPath(),e.moveTo(-o*.5,o*.2);for(let l=-4;l<=4;l++)e.lineTo(l*o*.12,o*.2+(l%2===0?o*.15:0));e.lineTo(o*.5,o*.2),e.closePath(),e.fill(),e.restore()},drawMoon(e,n,i){const s=n.x,o=n.y,a=n.size;e.save(),e.globalAlpha=n.opacity,e.translate(s,o);const l=.8+Math.sin(i*.001+n.glowPhase)*.2,t=e.createRadialGradient(0,0,0,0,0,a*1.5);t.addColorStop(0,`rgba(255, 255, 220, ${l})`),t.addColorStop(.4,`rgba(255, 255, 200, ${l*.5})`),t.addColorStop(.7,`rgba(255, 220, 150, ${l*.2})`),t.addColorStop(1,"rgba(255, 200, 100, 0)"),e.fillStyle=t,e.fillRect(-a*1.5,-a*1.5,a*3,a*3),e.fillStyle="#ffffdc",e.shadowColor="#ffffaa",e.shadowBlur=a*.3,e.beginPath(),e.arc(0,0,a,0,Math.PI*2),e.fill(),e.shadowBlur=0,e.fillStyle="rgba(200, 200, 170, 0.4)",e.beginPath(),e.arc(-a*.3,-a*.2,a*.2,0,Math.PI*2),e.fill(),e.beginPath(),e.arc(a*.4,a*.1,a*.15,0,Math.PI*2),e.fill(),e.beginPath(),e.arc(a*.1,a*.4,a*.18,0,Math.PI*2),e.fill(),e.beginPath(),e.arc(-a*.2,a*.5,a*.12,0,Math.PI*2),e.fill(),e.restore()},drawScarecrow(e,n,i){const s=n.x,o=n.y,a=n.size,l=Math.sin(i*n.swaySpeed+n.swayPhase)*a*.12,t=Math.abs(Math.sin(i*n.swaySpeed*2+n.swayPhase))*a*.03;e.save(),e.globalAlpha=n.opacity,e.translate(s+l,o-t);const h=e.createLinearGradient(-a*.05,0,a*.05,0);if(h.addColorStop(0,"#5a4632"),h.addColorStop(.5,"#6b5644"),h.addColorStop(1,"#4a3622"),e.fillStyle=h,e.fillRect(-a*.05,0,a*.1,a*1.8),e.strokeStyle="#3a2612",e.lineWidth=1,e.strokeRect(-a*.05,0,a*.1,a*1.8),e.fillRect(-a*.8,a*.5,a*1.6,a*.08),e.strokeRect(-a*.8,a*.5,a*1.6,a*.08),e.fillStyle="#8B7355",e.strokeStyle="#654321",e.lineWidth=1.5,e.beginPath(),e.moveTo(-a*.4,a*.5),e.lineTo(-a*.45,a*1.2),e.lineTo(-a*.25,a*1.4),e.lineTo(a*.25,a*1.4),e.lineTo(a*.45,a*1.2),e.lineTo(a*.4,a*.5),e.closePath(),e.fill(),e.stroke(),e.fillStyle="#6b5c4d",e.fillRect(-a*.3,a*.7,a*.2,a*.15),e.fillRect(a*.1,a*1,a*.18,a*.2),e.fillStyle="#8B7355",e.strokeStyle="#654321",e.beginPath(),e.moveTo(-a*.8,a*.5),e.lineTo(-a*.75,a*.7),e.lineTo(-a*.85,a*.75),e.lineTo(-a*.9,a*.6),e.closePath(),e.fill(),e.stroke(),e.beginPath(),e.moveTo(a*.8,a*.5),e.lineTo(a*.75,a*.7),e.lineTo(a*.85,a*.75),e.lineTo(a*.9,a*.6),e.closePath(),e.fill(),e.stroke(),Math.random()<.6){const d=e.createRadialGradient(-a*.1,-a*.05,0,0,0,a*.35);d.addColorStop(0,"#ff8c00"),d.addColorStop(.7,"#ff6600"),d.addColorStop(1,"#cc5500"),e.fillStyle=d,e.beginPath(),e.ellipse(0,a*.2,a*.35,a*.3,0,0,Math.PI*2),e.fill(),e.strokeStyle="#8B4513",e.lineWidth=2,e.stroke(),e.strokeStyle="#cc5500",e.lineWidth=1;for(let f=-2;f<=2;f++)e.beginPath(),e.moveTo(f*a*.12,a*.05),e.quadraticCurveTo(f*a*.1,a*.2,f*a*.12,a*.45),e.stroke();e.fillStyle="#228B22",e.strokeStyle="#1a6b1a",e.fillRect(-a*.04,a*.02,a*.08,a*.1),e.strokeRect(-a*.04,a*.02,a*.08,a*.1)}else{e.fillStyle="#d2b48c",e.strokeStyle="#8b7355",e.lineWidth=2,e.beginPath(),e.ellipse(0,a*.2,a*.32,a*.28,0,0,Math.PI*2),e.fill(),e.stroke(),e.strokeStyle="#a0826d",e.lineWidth=.5;for(let d=-3;d<=3;d++)e.beginPath(),e.moveTo(d*a*.1,a*.05),e.lineTo(d*a*.1,a*.42),e.stroke()}const M=.6+Math.sin(i*n.glowSpeed+n.glowPhase)*.4;e.shadowColor="#ff0000",e.shadowBlur=a*.2,e.fillStyle=`rgba(255, 0, 0, ${M})`,e.beginPath(),e.moveTo(-a*.18,a*.15),e.lineTo(-a*.12,a*.2),e.lineTo(-a*.18,a*.25),e.closePath(),e.fill(),e.beginPath(),e.moveTo(a*.18,a*.15),e.lineTo(a*.12,a*.2),e.lineTo(a*.18,a*.25),e.closePath(),e.fill(),e.strokeStyle="#000000",e.lineWidth=a*.03,e.beginPath(),e.moveTo(-a*.2,a*.35);for(let d=-3;d<=3;d++){const f=d%2===0?0:a*.04;e.lineTo(d*a*.07,a*.35+f)}e.stroke(),e.shadowBlur=0,e.fillStyle="#2a2a2a",e.strokeStyle="#1a1a1a",e.lineWidth=2,e.beginPath(),e.ellipse(0,a*.05,a*.45,a*.08,0,0,Math.PI*2),e.fill(),e.stroke(),e.beginPath(),e.moveTo(-a*.2,a*.05),e.lineTo(-a*.15,-a*.2),e.lineTo(a*.15,-a*.2),e.lineTo(a*.2,a*.05),e.closePath(),e.fill(),e.stroke(),e.fillStyle="#8B4513",e.fillRect(-a*.2,a*.03,a*.4,a*.05),e.strokeStyle="#1a1a1a",e.lineWidth=1;for(let d=0;d<5;d++){const f=d/5*Math.PI*2,g=Math.cos(f)*a*.45,m=a*.05+Math.sin(f)*a*.08;e.beginPath(),e.moveTo(g,m),e.lineTo(g+Math.cos(f)*a*.08,m+Math.sin(f)*a*.08),e.stroke()}if(Math.random()<.3){const d=Math.random()<.5?-a*.6:a*.6;e.fillStyle="#000000",e.beginPath(),e.arc(d,a*.5,a*.08,0,Math.PI*2),e.fill(),e.fillStyle="#ffa500",e.beginPath(),e.moveTo(d+a*.08,a*.5),e.lineTo(d+a*.15,a*.5),e.lineTo(d+a*.1,a*.52),e.closePath(),e.fill()}e.restore()},drawTwinklingStar(e,n,i){const s=n.x,o=n.y,a=n.size,l=.4+Math.sin(i*n.twinkleSpeed+n.twinklePhase)*.6;let t,h;switch(n.colorVariant){case 0:t=`rgba(255, 255, 255, ${l})`,h=`rgba(255, 255, 255, ${l*.3})`;break;case 1:t=`rgba(200, 150, 255, ${l})`,h=`rgba(150, 100, 255, ${l*.3})`;break;case 2:t=`rgba(255, 180, 100, ${l})`,h=`rgba(255, 150, 50, ${l*.3})`;break}e.save(),e.translate(s,o),e.shadowColor=h,e.shadowBlur=a*4*l,e.fillStyle=t,e.beginPath();for(let r=0;r<4;r++){const M=r/4*Math.PI-Math.PI/2,d=Math.cos(M)*a,f=Math.sin(M)*a,g=M+Math.PI/4,m=Math.cos(g)*(a*.3),T=Math.sin(g)*(a*.3);r===0?e.moveTo(d,f):e.lineTo(d,f),e.lineTo(m,T)}e.closePath(),e.fill(),e.shadowBlur=a*2*l,e.beginPath(),e.arc(0,0,a*.3,0,Math.PI*2),e.fill(),e.restore()},drawGlobalEffects(e,n,i,s){if(this.lightningActive){e.save(),e.globalAlpha=.8+Math.sin(this.lightningTimer*.01)*.2,e.shadowColor=this.lightningColor,e.shadowBlur=20;const o=i*(.4+Math.random()*.2),a=0,l=i*Math.random(),t=s;this.drawLightning(e,o,a,l,t,5+Math.floor(Math.random()*3),50+Math.random()*50,.7,.3,3+Math.random()*2,this.lightningColor),e.restore()}}};
1
+ import{drawBat as b,drawGhost as R,drawPumpkin as I,drawJackOLantern as C,drawHauntedHouse as A,drawScarecrow as L}from"./halloween-drawing.js";export default{name:"halloween",displayName:"Halloween",emoji:"\u{1F383}",intensityConfig:{light:{count:30,speedRange:[.3,1],sizeRange:[2,5],gravestones:3,jackOLanterns:2,spiders:2,scarecrows:1,twinklingStars:8},medium:{count:60,speedRange:[.5,1.5],sizeRange:[2,6],gravestones:5,jackOLanterns:4,spiders:4,scarecrows:2,twinklingStars:15},heavy:{count:100,speedRange:[.7,2],sizeRange:[3,8],gravestones:8,jackOLanterns:6,spiders:6,scarecrows:3,twinklingStars:25}},particles:["bat","ghost","pumpkin"],decorations:["gravestone","jack-o-lantern","haunted-house","cauldron","spider","scarecrow","twinkling-star"],colors:{primary:"#ff6600",secondary:"#1a1a2e",accent:"#8b0000",ghost:"#f0f0f0",purple:"#6a0dad"},lightningChance:5e-4,lightningDuration:200,lightningTimer:0,lightningActive:!1,lightningColor:"#fefefe",createBat(e,t,o){const r=Math.random();let n,a,i;r<.33?(n=o.sizeRange[0]+Math.random()*(o.sizeRange[1]-o.sizeRange[0])*1.5,a=o.speedRange[0]+Math.random()*(o.speedRange[1]-o.speedRange[0])*1.3,i=.9+Math.random()*.1):r<.66?(n=o.sizeRange[0]+Math.random()*(o.sizeRange[1]-o.sizeRange[0]),a=o.speedRange[0]+Math.random()*(o.speedRange[1]-o.sizeRange[0]),i=.6+Math.random()*.2):(n=o.sizeRange[0]+Math.random()*(o.sizeRange[1]-o.sizeRange[0])*.7,a=o.speedRange[0]+Math.random()*(o.sizeRange[1]-o.sizeRange[0])*.7,i=.4+Math.random()*.2);const s=Math.random()<.5;return{type:"bat",x:s?-20:e+20,y:Math.random()*t*.7,baseY:Math.random()*t*.7,vx:s?a*2:-a*2,vy:0,size:n,speed:a,opacity:i,waveAmplitude:10+Math.random()*20,waveFrequency:.002+Math.random()*.003,waveOffset:Math.random()*Math.PI*2,time:0,rotation:0,active:!0,depth:r}},createGhost(e,t,o){const r=Math.random();let n,a,i;return r<.33?(n=o.sizeRange[0]+Math.random()*(o.sizeRange[1]-o.sizeRange[0])*1.8,a=o.speedRange[0]+Math.random()*(o.speedRange[1]-o.sizeRange[0])*.5,i=.7+Math.random()*.2):r<.66?(n=o.sizeRange[0]+Math.random()*(o.sizeRange[1]-o.sizeRange[0])*1.2,a=o.speedRange[0]+Math.random()*(o.sizeRange[1]-o.sizeRange[0])*.5,i=.5+Math.random()*.15):(n=o.sizeRange[0]+Math.random()*(o.sizeRange[1]-o.sizeRange[0]),a=o.speedRange[0]+Math.random()*(o.sizeRange[1]-o.sizeRange[0])*.5,i=.3+Math.random()*.15),{type:"ghost",x:Math.random()*e,y:-50,size:n,speed:a,opacity:i,windOffset:Math.random()*Math.PI*2,windSpeed:.01+Math.random()*.02,rotation:0,rotationSpeed:(Math.random()-.5)*.005,time:Math.random()*1e3,active:!0,depth:r}},createPumpkin(e,t,o){return{type:"pumpkin",x:Math.random()*e,y:Math.random()*t,size:o.sizeRange[0]+Math.random()*(o.sizeRange[1]-o.sizeRange[0]),vx:(Math.random()-.5)*.2,speed:(o.speedRange[0]+Math.random()*(o.speedRange[1]-o.sizeRange[0]))*.2,opacity:.8+Math.random()*.2,rotation:Math.random()*Math.PI*2,rotationSpeed:(Math.random()-.5)*.008,windOffset:Math.random()*Math.PI*2,windSpeed:.008+Math.random()*.015,glowPhase:Math.random()*Math.PI*2,floatPhase:Math.random()*Math.PI*2,floatSpeed:.001+Math.random()*.002,active:!0}},createGravestone(e,t,o={}){const r=["rounded","cross","obelisk"];return{type:"gravestone",x:o.x!==void 0?o.x:Math.random()*e,y:o.y!==void 0?o.y:t-30-Math.random()*20,size:15+Math.random()*10,opacity:.7+Math.random()*.2,shape:r[Math.floor(Math.random()*r.length)],rotation:(Math.random()-.5)*.1,active:!0,static:!0}},createJackOLantern(e,t,o={}){const r=["happy","scary","wicked"];return{type:"jack-o-lantern",x:o.x!==void 0?o.x:Math.random()*e,y:o.y!==void 0?o.y:t-25-Math.random()*15,size:12+Math.random()*8,opacity:.9+Math.random()*.1,face:r[Math.floor(Math.random()*r.length)],glowPhase:Math.random()*Math.PI*2,active:!0,static:!0}},createSpider(e,t,o={}){return{type:"spider",x:o.x!==void 0?o.x:Math.random()*e,y:o.y!==void 0?o.y:Math.random()*t*.3,baseY:o.y!==void 0?o.y:Math.random()*t*.3,size:5+Math.random()*5,opacity:.8+Math.random()*.2,threadLength:30+Math.random()*50,swingPhase:Math.random()*Math.PI*2,swingAmplitude:20+Math.random()*30,swingSpeed:.001+Math.random()*.002,time:0,active:!0,static:!1}},createFallingParticle(e,t,o){return Math.random()<.7?this.createPumpkin(e,t,o):{type:"spider-small",x:Math.random()*e,y:-20,size:1+Math.random()*2,speed:o.speedRange[0]+Math.random()*(o.speedRange[1]-o.sizeRange[0])*.5,opacity:.6+Math.random()*.3,rotation:Math.random()*Math.PI*2,rotationSpeed:(Math.random()-.5)*.02,windOffset:Math.random()*Math.PI*2,windSpeed:.01+Math.random()*.02,active:!0}},createInitialDecorations(e,t,o){const r=[];r.push({type:"haunted-house",x:80,y:t-120,size:80,opacity:.85,active:!0,static:!0}),r.push({type:"moon",x:e-120,y:100,size:60,opacity:.9,glowPhase:0,active:!0,static:!0});const n=o.gravestones??5;for(let l=0;l<n;l++)r.push({type:"gravestone",x:e/(n+1)*(l+1)+(Math.random()-.5)*40,y:t-30-Math.random()*10,size:12+Math.random()*8,opacity:.7+Math.random()*.2,variant:Math.floor(Math.random()*3),active:!0,static:!0});const a=o.jackOLanterns??4;for(let l=0;l<a;l++)r.push({type:"jack-o-lantern",x:e/(a+1)*(l+1)+(Math.random()-.5)*30,y:t-15,size:10+Math.random()*6,opacity:.9,glowPhase:Math.random()*Math.PI*2,active:!0,static:!0});const i=o.spiders??4;for(let l=0;l<i;l++)r.push({type:"spider",x:e/(i+1)*(l+1),y:0,targetY:50+Math.random()*100,currentY:0,size:3+Math.random()*3,opacity:.8,swingPhase:Math.random()*Math.PI*2,swingAmplitude:20+Math.random()*30,swingSpeed:.02+Math.random()*.02,active:!0,static:!0});const s=o.scarecrows??2;for(let l=0;l<s;l++)r.push({type:"scarecrow",x:120+l/(s-1||1)*(e-240),y:t-60,size:30+Math.random()*10,opacity:.9,swayPhase:Math.random()*Math.PI*2,swaySpeed:.015+Math.random()*.015,glowPhase:Math.random()*Math.PI*2,glowSpeed:.02,active:!0,static:!0});const h=o.twinklingStars??15;for(let l=0;l<h;l++)r.push(this.createTwinklingStar(e,t));return r},createTwinklingStar(e,t){return{type:"twinkling-star",x:Math.random()*e,y:Math.random()*(t*.5),size:1+Math.random()*2.5,opacity:.5+Math.random()*.3,twinklePhase:Math.random()*Math.PI*2,twinkleSpeed:.004+Math.random()*.003,colorVariant:Math.floor(Math.random()*3),active:!0,static:!0}},drawLightning(e,t,o,r,n,a,i,s,h,l,d){if(a<1)return;const y=(t+r)/2,u=(o+n)/2,M=Math.atan2(n-o,r-t),P=M+Math.PI/2,w=(Math.random()-.5)*i,m=y+Math.cos(P)*w,g=u+Math.sin(P)*w,f=a-1,p=i*s,z=l*.8;if(e.strokeStyle=d,e.lineWidth=l,e.lineCap="round",e.lineJoin="round",e.beginPath(),e.moveTo(t,o),e.lineTo(m,g),e.lineTo(r,n),e.stroke(),f>0&&(this.drawLightning(e,t,o,m,g,f,p,s,h,z,d),this.drawLightning(e,m,g,r,n,f,p,s,h,z,d),Math.random()<h&&f>1)){const v=Math.random()*i*.5,T=(Math.random()-.5)*Math.PI/3,S=m+Math.cos(M+T)*v,k=g+Math.sin(M+T)*v;this.drawLightning(e,m,g,S,k,f-1,p*.5,s,h*.5,z*.6,d)}},spawnSpecialParticle(e,t,o){const r=Math.random(),n=this.intensityConfig.medium;if(r<.15)return this.createBat(t,o,n);if(r<.16){if(e.some(i=>i.type==="witch"))return null;const a=Math.random()<.5;return{type:"witch",x:a?-100:t+100,y:Math.random()*(o*.4)+50,baseY:Math.random()*(o*.4)+50,vx:a?3+Math.random()*2:-(3+Math.random()*2),size:15+Math.random()*8,opacity:.85,waveAmplitude:15+Math.random()*20,waveFrequency:.002+Math.random()*.002,waveOffset:Math.random()*Math.PI*2,time:0,active:!0,static:!1}}return r<.18?{type:"floating-pumpkin",x:Math.random()*t,y:-50,size:8+Math.random()*6,vx:(Math.random()-.5)*.5,vy:.3+Math.random()*.5,opacity:.9,rotation:Math.random()*Math.PI*2,rotationSpeed:(Math.random()-.5)*.01,glowPhase:Math.random()*Math.PI*2,windOffset:Math.random()*Math.PI*2,windSpeed:.015,active:!0}:r<.2102?e.some(a=>a.type==="haunted-house")?null:{type:"haunted-house",x:Math.random()*t*.6+t*.2,y:o-100,size:40+Math.random()*20,opacity:.8,windowFlicker:0,active:!0,static:!0}:r<.2105?e.some(a=>a.type==="cauldron")?null:{type:"cauldron",x:Math.random()*t*.6+t*.2,y:o-40,size:25+Math.random()*10,opacity:1,bubbles:[],smoke:[],time:0,active:!0,static:!0}:null},updateSpecialParticles(e,t,o,r){this.lightningActive?(this.lightningTimer+=t,this.lightningTimer>=this.lightningDuration&&(this.lightningActive=!1,this.lightningTimer=0)):Math.random()<this.lightningChance&&(this.lightningActive=!0,this.lightningTimer=0),e.forEach(n=>{switch(n.time!==void 0&&(n.time+=t),n.type){case"moon":break;case"witch":(n.vx>0&&n.x>o+100||n.vx<0&&n.x<-100)&&(n.active=!1);break;case"floating-pumpkin":n.y>r+50&&(n.active=!1);break;case"cauldron":n.time%100<20&&n.bubbles.push({x:(Math.random()-.5)*n.size*.5,y:n.size*.3+Math.random()*n.size*.2,size:n.size*(.05+Math.random()*.1),vy:-.5-Math.random()*.5,opacity:1,life:1,fadeRate:.01+Math.random()*.005}),n.bubbles=n.bubbles.filter(a=>(a.y+=a.vy,a.vy*=.98,a.opacity-=a.fadeRate,a.opacity>0&&a.y>-n.size)),n.time%200<30&&n.smoke.push({x:(Math.random()-.5)*n.size*.3,y:-n.size*.5+Math.random()*n.size*.1,size:n.size*(.2+Math.random()*.3),vx:(Math.random()-.5)*.1,vy:-.2-Math.random()*.2,opacity:.5,life:1,fadeRate:.005+Math.random()*.003}),n.smoke=n.smoke.filter(a=>(a.x+=a.vx,a.y+=a.vy,a.size*=1.02,a.opacity-=a.fadeRate,a.opacity>0));break}})},drawBat:b,drawGhost:R,drawPumpkin:I,drawGravestone(e,t){const o=t.x,r=t.y,n=t.size;e.save(),e.globalAlpha=t.opacity,e.translate(o,r),e.rotate(t.rotation),e.fillStyle="#555555",e.strokeStyle="#333333",e.lineWidth=1,t.shape==="rounded"?(e.beginPath(),e.moveTo(-n*.5,n*.8),e.lineTo(-n*.5,-n*.3),e.arc(0,-n*.3,n*.5,Math.PI,0),e.lineTo(n*.5,n*.8),e.closePath(),e.fill(),e.stroke()):t.shape==="cross"?(e.fillRect(-n*.15,-n,n*.3,n*1.8),e.fillRect(-n*.5,-n*.3,n,n*.3)):(e.beginPath(),e.moveTo(-n*.4,n*.8),e.lineTo(-n*.5,-n*.5),e.lineTo(0,-n),e.lineTo(n*.5,-n*.5),e.lineTo(n*.4,n*.8),e.closePath(),e.fill(),e.stroke()),e.fillStyle="rgba(0, 100, 0, 0.3)",e.fillRect(-n*.4,n*.5,n*.8,n*.3),e.fillStyle="#222222",e.font=`${n*.4}px serif`,e.textAlign="center",e.textBaseline="middle",e.fillText("RIP",0,0),e.restore()},drawJackOLantern:C,drawHauntedHouse:A,drawCauldron(e,t,o){const r=t.x,n=t.y,a=t.size;e.save(),e.translate(r,n),e.fillStyle="#222222",e.strokeStyle="#111111",e.lineWidth=2,e.beginPath(),e.arc(0,0,a*.8,0,Math.PI),e.lineTo(-a*.8,a*.5),e.quadraticCurveTo(0,a*.8,a*.8,a*.5),e.closePath(),e.fill(),e.stroke(),e.strokeStyle="#1a1a1a",e.lineWidth=3,[-a*.5,0,a*.5].forEach(i=>{e.beginPath(),e.moveTo(i,a*.5),e.lineTo(i,a*.9),e.stroke()}),e.fillStyle="#00ff00",e.shadowColor="#00ff00",e.shadowBlur=15,e.beginPath(),e.ellipse(0,0,a*.7,a*.3,0,0,Math.PI*2),e.fill(),e.shadowBlur=0,t.bubbles.forEach(i=>{e.globalAlpha=i.opacity,e.fillStyle="#88ff88",e.beginPath(),e.arc(i.x,i.y,i.size,0,Math.PI*2),e.fill()}),e.globalAlpha=1,t.smoke.forEach(i=>{e.globalAlpha=i.opacity,e.fillStyle="#aaaaaa",e.beginPath(),e.arc(i.x,i.y,i.size,0,Math.PI*2),e.fill()}),e.restore()},drawSpider(e,t,o){const r=t.x,n=t.y,a=t.size,i=Math.sin(o*t.swingSpeed+t.swingPhase)*t.swingAmplitude;e.save(),e.globalAlpha=t.opacity,e.strokeStyle="#cccccc",e.lineWidth=1,e.setLineDash([2,2]),e.beginPath(),e.moveTo(r,n),e.lineTo(r+i,n+t.threadLength),e.stroke(),e.setLineDash([]),e.translate(r+i,n+t.threadLength),e.fillStyle="#000000",e.beginPath(),e.ellipse(0,0,a*.5,a*.7,0,0,Math.PI*2),e.fill(),e.beginPath(),e.arc(0,-a*.5,a*.3,0,Math.PI*2),e.fill(),e.strokeStyle="#1a1a1a",e.lineWidth=a*.1;const s=Math.sin(o*.005)*.2;for(let h=0;h<4;h++){const l=h/4*Math.PI-Math.PI/2,d=a*1.5;e.beginPath(),e.moveTo(-a*.3,-a*.2+h*a*.2),e.quadraticCurveTo(-a-Math.sin(l+s)*a*.3,-a*.2+h*a*.2-a*.5,-a*1.2,-a*.2+h*a*.2),e.stroke(),e.beginPath(),e.moveTo(a*.3,-a*.2+h*a*.2),e.quadraticCurveTo(a+Math.sin(l+s)*a*.3,-a*.2+h*a*.2-a*.5,a*1.2,-a*.2+h*a*.2),e.stroke()}e.fillStyle="#ff0000";for(let h=0;h<4;h++)e.beginPath(),e.arc(-a*.15+h%2*a*.3,-a*.55+Math.floor(h/2)*a*.1,a*.05,0,Math.PI*2),e.fill();e.restore()},drawSpiderSmall(e,t){e.save(),e.globalAlpha=t.opacity,e.translate(t.x,t.y),e.rotate(t.rotation),e.fillStyle="#1a1a1a",e.beginPath(),e.arc(0,0,t.size,0,Math.PI*2),e.fill(),e.strokeStyle="#1a1a1a",e.lineWidth=t.size*.3;for(let o=0;o<4;o++){const r=o/4*Math.PI-Math.PI/2;e.beginPath(),e.moveTo(0,0),e.lineTo(Math.cos(r)*t.size*2,Math.sin(r)*t.size*2),e.stroke(),e.beginPath(),e.moveTo(0,0),e.lineTo(-Math.cos(r)*t.size*2,Math.sin(r)*t.size*2),e.stroke()}e.restore()},drawWitch(e,t,o){const r=t.x,n=t.y+Math.sin(o*t.waveFrequency+t.waveOffset)*t.waveAmplitude,a=t.size,i=t.vx>0?1:-1;e.save(),e.globalAlpha=t.opacity,e.translate(r,n),i===-1&&e.scale(-1,1),e.strokeStyle="#8B4513",e.lineWidth=a*.12,e.lineCap="round",e.beginPath(),e.moveTo(a*.2,a*.6),e.lineTo(-a*1.5,a*.6),e.stroke(),e.strokeStyle="#D2691E",e.lineWidth=a*.06;for(let s=0;s<8;s++){const h=Math.PI/3*(s/7-.5);e.beginPath(),e.moveTo(-a*1.5,a*.6),e.lineTo(-a*1.5+Math.cos(h)*a*.4,a*.6+Math.sin(h)*a*.4),e.stroke()}e.fillStyle="#1a1a1a",e.strokeStyle="#0a0a0a",e.lineWidth=1,e.beginPath(),e.moveTo(a*.2,a*.6),e.quadraticCurveTo(-a*.5,a*.4,-a*.8,a*.1),e.lineTo(-a*.7,-a*.3),e.quadraticCurveTo(-a*.3,-a*.5,0,-a*.6),e.lineTo(a*.3,-a*.4),e.lineTo(a*.3,a*.5),e.closePath(),e.fill(),e.stroke(),e.fillStyle="#8B9355",e.beginPath(),e.ellipse(a*.25,-a*.6,a*.3,a*.35,0,0,Math.PI*2),e.fill(),e.fillStyle="#7a8245",e.beginPath(),e.moveTo(a*.45,-a*.6),e.quadraticCurveTo(a*.7,-a*.65,a*.72,-a*.5),e.lineTo(a*.6,-a*.52),e.quadraticCurveTo(a*.58,-a*.58,a*.4,-a*.55),e.closePath(),e.fill(),e.fillStyle="#2C1810",e.beginPath(),e.moveTo(a*.05,-a*.85),e.lineTo(a*.4,-a*1.6),e.lineTo(a*.5,-a*.8),e.closePath(),e.fill(),e.beginPath(),e.ellipse(a*.25,-a*.85,a*.5,a*.12,0,0,Math.PI*2),e.fill(),e.fillStyle="#ff6600",e.shadowColor="#ff6600",e.shadowBlur=a*.3,e.beginPath(),e.arc(a*.35,-a*.65,a*.08,0,Math.PI*2),e.fill(),e.shadowBlur=0,e.fillStyle="#8B9355",e.beginPath(),e.arc(a*.1,a*.5,a*.12,0,Math.PI*2),e.fill(),e.beginPath(),e.arc(-a*.3,a*.55,a*.1,0,Math.PI*2),e.fill(),e.strokeStyle="#1a1a1a",e.lineWidth=a*.1,e.beginPath(),e.moveTo(a*.15,a*.6),e.lineTo(a*.1,a*1),e.stroke(),e.beginPath(),e.moveTo(a*.05,a*.6),e.lineTo(a*.2,a*.95),e.stroke(),e.restore()},drawFloatingPumpkin(e,t){const o=t.x,r=t.y,n=t.size;e.save(),e.globalAlpha=t.opacity,e.translate(o,r),e.rotate(t.rotation),e.fillStyle="#ff6600",e.strokeStyle="#cc5200",e.lineWidth=n*.1,e.beginPath(),e.ellipse(0,0,n,n*.9,0,0,Math.PI*2),e.fill(),e.stroke();for(let i=-2;i<=2;i++)e.beginPath(),e.moveTo(i*n*.25,-n*.8),e.quadraticCurveTo(i*n*.3,0,i*n*.25,n*.8),e.stroke();e.fillStyle="#228B22",e.beginPath(),e.moveTo(-n*.15,-n*.8),e.lineTo(-n*.1,-n*1.1),e.lineTo(n*.1,-n*1.1),e.lineTo(n*.15,-n*.8),e.closePath(),e.fill();const a=.5+Math.sin(t.glowPhase+Date.now()*.005)*.5;e.fillStyle=`rgba(255, 200, 0, ${a})`,e.beginPath(),e.moveTo(-n*.4,-n*.3),e.lineTo(-n*.2,-n*.1),e.lineTo(-n*.6,-n*.1),e.closePath(),e.fill(),e.beginPath(),e.moveTo(n*.4,-n*.3),e.lineTo(n*.6,-n*.1),e.lineTo(n*.2,-n*.1),e.closePath(),e.fill(),e.beginPath(),e.moveTo(-n*.5,n*.2);for(let i=-4;i<=4;i++)e.lineTo(i*n*.12,n*.2+(i%2===0?n*.15:0));e.lineTo(n*.5,n*.2),e.closePath(),e.fill(),e.restore()},drawMoon(e,t,o){const r=t.x,n=t.y,a=t.size;e.save(),e.globalAlpha=t.opacity,e.translate(r,n);const i=.8+Math.sin(o*.001+t.glowPhase)*.2,s=e.createRadialGradient(0,0,0,0,0,a*1.5);s.addColorStop(0,`rgba(255, 255, 220, ${i})`),s.addColorStop(.4,`rgba(255, 255, 200, ${i*.5})`),s.addColorStop(.7,`rgba(255, 220, 150, ${i*.2})`),s.addColorStop(1,"rgba(255, 200, 100, 0)"),e.fillStyle=s,e.fillRect(-a*1.5,-a*1.5,a*3,a*3),e.fillStyle="#ffffdc",e.shadowColor="#ffffaa",e.shadowBlur=a*.3,e.beginPath(),e.arc(0,0,a,0,Math.PI*2),e.fill(),e.shadowBlur=0,e.fillStyle="rgba(200, 200, 170, 0.4)",e.beginPath(),e.arc(-a*.3,-a*.2,a*.2,0,Math.PI*2),e.fill(),e.beginPath(),e.arc(a*.4,a*.1,a*.15,0,Math.PI*2),e.fill(),e.beginPath(),e.arc(a*.1,a*.4,a*.18,0,Math.PI*2),e.fill(),e.beginPath(),e.arc(-a*.2,a*.5,a*.12,0,Math.PI*2),e.fill(),e.restore()},drawScarecrow:L,drawTwinklingStar(e,t,o){const r=t.x,n=t.y,a=t.size,i=.4+Math.sin(o*t.twinkleSpeed+t.twinklePhase)*.6;let s,h;switch(t.colorVariant){case 0:s=`rgba(255, 255, 255, ${i})`,h=`rgba(255, 255, 255, ${i*.3})`;break;case 1:s=`rgba(200, 150, 255, ${i})`,h=`rgba(150, 100, 255, ${i*.3})`;break;case 2:s=`rgba(255, 180, 100, ${i})`,h=`rgba(255, 150, 50, ${i*.3})`;break}e.save(),e.translate(r,n),e.shadowColor=h,e.shadowBlur=a*4*i,e.fillStyle=s,e.beginPath();for(let l=0;l<4;l++){const d=l/4*Math.PI-Math.PI/2,y=Math.cos(d)*a,u=Math.sin(d)*a,M=d+Math.PI/4,P=Math.cos(M)*(a*.3),w=Math.sin(M)*(a*.3);l===0?e.moveTo(y,u):e.lineTo(y,u),e.lineTo(P,w)}e.closePath(),e.fill(),e.shadowBlur=a*2*i,e.beginPath(),e.arc(0,0,a*.3,0,Math.PI*2),e.fill(),e.restore()},drawGlobalEffects(e,t,o,r){if(this.lightningActive){e.save(),e.globalAlpha=.8+Math.sin(this.lightningTimer*.01)*.2,e.shadowColor=this.lightningColor,e.shadowBlur=20;const n=o*(.4+Math.random()*.2),a=0,i=o*Math.random(),s=r;this.drawLightning(e,n,a,i,s,5+Math.floor(Math.random()*3),50+Math.random()*50,.7,.3,3+Math.random()*2,this.lightningColor),e.restore()}}};
@@ -1 +1 @@
1
- export default{name:"valentines",displayName:"Valentine's Day",emoji:"\u{1F495}",intensityConfig:{light:{count:40,speedRange:[.3,.8],sizeRange:[2,4],garlands:1,cupidChance:3e-4},medium:{count:80,speedRange:[.4,1.2],sizeRange:[2,5],garlands:2,cupidChance:5e-4},heavy:{count:150,speedRange:[.5,1.5],sizeRange:[3,6],garlands:3,cupidChance:8e-4}},particles:["heart","rose-petal","sparkle","lips"],decorations:["cupid","love-letter","heart-garland","envelope","butterfly","heart-moon","neon-sign"],colors:{primary:"#ff1493",secondary:"#ff69b4",accent:"#dc143c",light:"#ffb6c1",gold:"#ffd700"},createHeart(e,o,n){const s=Math.random();let l,a,h;const i=["#ff1493","#ff69b4","#dc143c","#ffb6c1","#ff0080"];return s<.33?(l=n.sizeRange[0]+Math.random()*(n.sizeRange[1]-n.sizeRange[0])*1.5,a=n.speedRange[0]+Math.random()*(n.speedRange[1]-n.speedRange[0]),h=.8+Math.random()*.2):s<.66?(l=n.sizeRange[0]+Math.random()*(n.sizeRange[1]-n.sizeRange[0]),a=n.speedRange[0]+Math.random()*(n.speedRange[1]-n.speedRange[0]),h=.6+Math.random()*.2):(l=n.sizeRange[0]+Math.random()*(n.sizeRange[1]-n.sizeRange[0])*.8,a=n.speedRange[0]+Math.random()*(n.speedRange[1]-n.speedRange[0])*.8,h=.4+Math.random()*.2),{type:"heart",x:Math.random()*e,y:Math.random()*o,size:l,vx:(Math.random()-.5)*.3,vy:(Math.random()-.7)*.2,speed:a*.3,opacity:h,color:i[Math.floor(Math.random()*i.length)],windOffset:Math.random()*Math.PI*2,windSpeed:.005+Math.random()*.01,rotation:Math.random()*Math.PI*2,rotationSpeed:(Math.random()-.5)*.01,pulsePhase:Math.random()*Math.PI*2,pulseSpeed:.002+Math.random()*.003,floatPhase:Math.random()*Math.PI*2,floatSpeed:.001+Math.random()*.002,active:!0,depth:s}},createRosePetal(e,o,n){const s=["#ff1493","#ff69b4","#dc143c","#ff758f","#ffb6c1"];return{type:"rose-petal",x:Math.random()*e,y:-20,size:1.5+Math.random()*2,speed:n.speedRange[0]+Math.random()*(n.speedRange[1]-n.speedRange[0])*.6,opacity:.7+Math.random()*.3,color:s[Math.floor(Math.random()*s.length)],windOffset:Math.random()*Math.PI*2,windSpeed:.02+Math.random()*.03,rotation:Math.random()*Math.PI*2,rotationSpeed:(Math.random()-.5)*.05,flutterPhase:Math.random()*Math.PI*2,active:!0}},createSparkle(e,o,n){return{type:"sparkle",x:Math.random()*e,y:Math.random()*o,size:.5+Math.random()*1.5,opacity:1,life:20+Math.random()*30,maxLife:20+Math.random()*30,color:Math.random()<.5?"#ffd700":"#ffffff",twinklePhase:Math.random()*Math.PI*2,active:!0,static:!0}},createLips(e,o,n){const s=["#dc143c","#ff1493","#c71585","#ff0066"];return{type:"lips",x:Math.random()*e,y:Math.random()*o,size:3+Math.random()*3,vx:(Math.random()-.5)*.4,vy:(Math.random()-.7)*.2,speed:.3+Math.random()*.2,opacity:.8+Math.random()*.2,color:s[Math.floor(Math.random()*s.length)],rotation:Math.random()*Math.PI*2,rotationSpeed:(Math.random()-.5)*.01,pulsePhase:Math.random()*Math.PI*2,pulseSpeed:.003+Math.random()*.002,floatPhase:Math.random()*Math.PI*2,floatSpeed:.001+Math.random()*.002,kissPhase:Math.random()*Math.PI*2,active:!0}},createHeartGarland(e,o,n={}){const s=8+Math.floor(Math.random()*5),l=[];for(let a=0;a<s;a++)l.push({offset:a/s,size:8+Math.random()*4,color:Math.random()<.5?"#ff1493":"#ff69b4",pulsePhase:Math.random()*Math.PI*2});return{type:"heart-garland",x:0,y:n.y!==void 0?n.y:50+Math.random()*100,width:e,hearts:l,sag:40+Math.random()*30,swayPhase:Math.random()*Math.PI*2,swayAmplitude:10+Math.random()*10,opacity:.8+Math.random()*.2,active:!0,static:!0}},createLoveLetter(e,o,n={}){const s=Math.random()<.5;return{type:"love-letter",x:s?-50:e+50,y:Math.random()*o*.6,baseY:Math.random()*o*.6,vx:s?1+Math.random()*1:-(1+Math.random()*1),size:12+Math.random()*6,opacity:.9+Math.random()*.1,rotation:(Math.random()-.5)*.3,rotationSpeed:(Math.random()-.5)*.005,waveAmplitude:15+Math.random()*15,waveFrequency:.002+Math.random()*.002,waveOffset:Math.random()*Math.PI*2,time:0,active:!0,static:!1}},createFallingParticle(e,o,n){const s=Math.random();return s<.6?this.createHeart(e,o,n):s<.85?this.createRosePetal(e,o,n):this.createLips(e,o,n)},createInitialDecorations(e,o,n){const s=[],l=n.garlands??2;for(let i=0;i<l;i++)s.push(this.createHeartGarland(e,o,{y:50+i*(o/(l+1))}));const a=4;for(let i=0;i<a;i++)s.push({type:"envelope",x:e/(a+1)*(i+1)+(Math.random()-.5)*30,y:o-25-Math.random()*10,size:15+Math.random()*5,opacity:.85,rotation:(Math.random()-.5)*.3,active:!0,static:!0});const h=n.butterflies??3;for(let i=0;i<h;i++)s.push({type:"butterfly",x:Math.random()*e,y:Math.random()*o*.6+50,baseY:Math.random()*o*.6+50,size:12+Math.random()*6,vx:(Math.random()-.5)*2,vy:0,waveOffset:Math.random()*Math.PI*2,waveFrequency:.003+Math.random()*.002,waveAmplitude:20+Math.random()*15,wingPhase:Math.random()*Math.PI*2,opacity:.9,color:Math.random()<.5?"pink":"purple",active:!0,static:!1});return s.push({type:"heart-moon",x:e*.85,y:o*.15,size:60+Math.random()*20,opacity:.9,glowPhase:Math.random()*Math.PI*2,active:!0,static:!0}),s},spawnSpecialParticle(e,o,n,s){const l=Math.random();if(l<s.cupidChance){if(e.some(h=>h.type==="cupid"))return null;const a=Math.random()<.5;return{type:"cupid",x:a?-100:o+100,y:Math.random()*n*.4+50,baseY:Math.random()*n*.4+50,vx:a?2+Math.random()*1.5:-(2+Math.random()*1.5),size:15+Math.random()*8,opacity:1,waveAmplitude:20+Math.random()*20,waveFrequency:.002+Math.random()*.002,waveOffset:Math.random()*Math.PI*2,time:0,wingPhase:Math.random()*Math.PI*2,active:!0,static:!1}}return l<.001?this.createLoveLetter(o,n):l<.0015?e.some(a=>a.type==="neon-sign"&&a.active)?null:{type:"neon-sign",x:o/2,y:n*.3,size:40+Math.random()*20,opacity:0,targetOpacity:1,phase:"fade-in",phaseTime:0,fadeInDuration:1500,stableDuration:5e3,fadeOutDuration:1e3,crackleIntensity:1,flickerPhase:Math.random()*Math.PI*2,glowPhase:Math.random()*Math.PI*2,tubeFlickers:[],active:!0,static:!1}:l<.02?this.createSparkle(o,n,s):null},drawHeart(e,o,n){const s=o.x,l=o.y,a=o.size,h=1+Math.sin(n*o.pulseSpeed+o.pulsePhase)*.15;e.save(),e.globalAlpha=o.opacity,e.translate(s,l),e.rotate(o.rotation),e.scale(h,h),e.fillStyle=o.color,e.shadowColor=o.color,e.shadowBlur=a*.8,e.beginPath(),e.moveTo(0,a*.3),e.bezierCurveTo(-a,-a*.3,-a*.6,-a,0,-a*.4),e.bezierCurveTo(a*.6,-a,a,-a*.3,0,a*.3),e.closePath(),e.fill(),e.shadowBlur=0,e.fillStyle="rgba(255, 255, 255, 0.3)",e.beginPath(),e.arc(-a*.25,-a*.5,a*.15,0,Math.PI*2),e.fill(),e.restore()},drawRosePetal(e,o,n){const s=o.x,l=o.y,a=o.size,h=Math.sin(n*.01+o.flutterPhase)*.3;e.save(),e.globalAlpha=o.opacity,e.translate(s,l),e.rotate(o.rotation+h),e.fillStyle=o.color,e.strokeStyle="rgba(139, 0, 0, 0.3)",e.lineWidth=.5,e.beginPath(),e.moveTo(0,0),e.bezierCurveTo(a*2,-a,a*2,a,0,0),e.closePath(),e.fill(),e.beginPath(),e.moveTo(0,0),e.quadraticCurveTo(a,0,a*1.5,0),e.stroke(),e.restore()},drawSparkle(e,o,n){const s=o.x,l=o.y,a=o.size,h=o.life/o.maxLife,i=(Math.sin(n*.01+o.twinklePhase)+1)*.5;e.save(),e.globalAlpha=o.opacity*h*i,e.translate(s,l),e.fillStyle=o.color,e.shadowColor=o.color,e.shadowBlur=a*2,e.beginPath();for(let r=0;r<4;r++){const d=r/4*Math.PI*2-Math.PI/2,f=Math.cos(d)*a*3,t=Math.sin(d)*a*3,M=d+Math.PI/4,u=Math.cos(M)*a*.5,P=Math.sin(M)*a*.5;r===0?e.moveTo(f,t):(e.lineTo(u,P),e.lineTo(f,t))}e.closePath(),e.fill(),e.restore()},drawLips(e,o,n){const s=o.x,l=o.y,a=o.size,h=1+Math.sin(n*o.pulseSpeed+o.pulsePhase)*.1,i=Math.sin(n*.008+o.kissPhase);e.save(),e.globalAlpha=o.opacity,e.translate(s,l),e.rotate(o.rotation),e.scale(h,h);const r=e.createRadialGradient(0,0,0,0,0,a*2);r.addColorStop(0,o.color),r.addColorStop(.6,o.color),r.addColorStop(1,"#8b0000"),e.fillStyle=r,e.strokeStyle="#8b0000",e.lineWidth=a*.1,e.beginPath(),e.moveTo(-a,0),e.bezierCurveTo(-a*.8,-a*.8,-a*.3,-a*1,0,-a*.6),e.bezierCurveTo(a*.3,-a*1,a*.8,-a*.8,a,0),e.fill(),e.stroke();const d=i*a*.15;if(e.beginPath(),e.moveTo(-a,0),e.bezierCurveTo(-a*.7,a*(.7+d),-a*.3,a*(1+d),0,a*(.8+d)),e.bezierCurveTo(a*.3,a*(1+d),a*.7,a*(.7+d),a,0),e.fill(),e.stroke(),e.globalAlpha=o.opacity*.5,e.fillStyle="rgba(255, 255, 255, 0.6)",e.beginPath(),e.ellipse(-a*.4,-a*.4,a*.2,a*.15,-.3,0,Math.PI*2),e.fill(),e.beginPath(),e.ellipse(a*.4,-a*.4,a*.2,a*.15,.3,0,Math.PI*2),e.fill(),e.beginPath(),e.ellipse(0,a*.5,a*.3,a*.2,0,0,Math.PI*2),e.fill(),i>.8){const f=a*1.5,t=Math.sin(o.kissPhase)*f,M=-Math.abs(Math.cos(o.kissPhase))*f;e.globalAlpha=o.opacity*(i-.8)*5,e.fillStyle="#ffd700",e.shadowColor="#ffd700",e.shadowBlur=a*.5,e.beginPath(),e.arc(t,M,a*.15,0,Math.PI*2),e.fill();for(let u=0;u<4;u++){const P=u/4*Math.PI*2+n*.01,m=t+Math.cos(P)*a*.4,y=M+Math.sin(P)*a*.4;e.beginPath(),e.moveTo(t,M),e.lineTo(m,y),e.lineWidth=a*.05,e.strokeStyle="#ffffff",e.stroke()}}e.restore()},drawCupid(e,o,n){const s=o.x,l=o.y,a=o.size,h=o.vx>0?1:-1;e.save(),e.globalAlpha=o.opacity,e.translate(s,l),h===-1&&e.scale(-1,1);const i=Math.sin(n*.015+o.wingPhase)*(Math.PI/6);e.fillStyle="#ffffff",e.strokeStyle="#ffb6c1",e.lineWidth=1.5,e.save(),e.translate(-a*.2,-a*.3),e.rotate(-i),e.beginPath(),e.moveTo(0,0),e.bezierCurveTo(-a*1.2,-a*.8,-a*1.5,-a*.3,-a*1.2,a*.3),e.bezierCurveTo(-a*.8,a*.2,-a*.3,0,0,0),e.closePath(),e.fill(),e.stroke(),e.restore(),e.fillStyle="#ffdbac",e.beginPath(),e.ellipse(0,0,a*.4,a*.5,0,0,Math.PI*2),e.fill(),e.beginPath(),e.ellipse(a*.3,-a*.6,a*.35,a*.4,0,0,Math.PI*2),e.fill(),e.fillStyle="#ffd700",e.beginPath(),e.arc(a*.1,-a*.9,a*.22,0,Math.PI*2),e.fill(),e.beginPath(),e.arc(a*.4,-a*.95,a*.18,0,Math.PI*2),e.fill(),e.beginPath(),e.arc(a*.15,-a*.75,a*.15,0,Math.PI*2),e.fill(),e.fillStyle="#000000",e.beginPath(),e.arc(a*.42,-a*.62,a*.05,0,Math.PI*2),e.fill(),e.fillStyle="rgba(255, 105, 180, 0.3)",e.beginPath(),e.arc(a*.25,-a*.5,a*.12,0,Math.PI*2),e.fill(),e.strokeStyle="#ffdbac",e.lineWidth=a*.15,e.lineCap="round",e.beginPath(),e.moveTo(-a*.15,a*.4),e.lineTo(-a*.3,a*.8),e.stroke(),e.beginPath(),e.moveTo(-a*.05,a*.4),e.lineTo(-a*.15,a*.75),e.stroke(),e.strokeStyle="#ffdbac",e.lineWidth=a*.12,e.beginPath(),e.moveTo(a*.1,-a*.2),e.lineTo(a*.6,-a*.3),e.stroke(),e.beginPath(),e.moveTo(a*.05,0),e.lineTo(a*.9,-a*.35),e.stroke(),e.strokeStyle="#8B4513",e.lineWidth=2.5,e.beginPath(),e.moveTo(a*.9,-a*.6),e.quadraticCurveTo(a*1.1,-a*.35,a*.9,-a*.1),e.stroke(),e.strokeStyle="#daa520",e.lineWidth=1.5,e.beginPath(),e.moveTo(a*.9,-a*.6),e.lineTo(a*.6,-a*.35),e.lineTo(a*.9,-a*.1),e.stroke(),e.strokeStyle="#8B4513",e.lineWidth=2,e.beginPath(),e.moveTo(a*.6,-a*.35),e.lineTo(a*1.8,-a*.35),e.stroke(),e.fillStyle="#dc143c",e.beginPath(),e.moveTo(a*1.8,-a*.35),e.lineTo(a*2,-a*.35),e.lineTo(a*1.9,-a*.25),e.closePath(),e.fill(),e.beginPath(),e.moveTo(a*1.8,-a*.35),e.lineTo(a*2,-a*.35),e.lineTo(a*1.9,-a*.45),e.closePath(),e.fill(),e.fillStyle="#ff69b4",e.beginPath(),e.moveTo(a*.6,-a*.35),e.lineTo(a*.5,-a*.25),e.lineTo(a*.5,-a*.45),e.closePath(),e.fill(),e.fillStyle="#ffffff",e.strokeStyle="#ffb6c1",e.lineWidth=1.5,e.save(),e.translate(a*.1,-a*.3),e.rotate(i),e.beginPath(),e.moveTo(0,0),e.bezierCurveTo(-a*1,-a*.6,-a*1.3,-a*.2,-a*1,a*.2),e.bezierCurveTo(-a*.6,a*.15,-a*.2,0,0,0),e.closePath(),e.fill(),e.stroke(),e.restore(),e.restore()},drawLoveLetter(e,o,n){const s=o.x,l=o.y,a=o.size;e.save(),e.globalAlpha=o.opacity,e.translate(s,l),e.rotate(o.rotation),e.fillStyle="#fff5e6",e.strokeStyle="#daa520",e.lineWidth=1,e.fillRect(-a,-a*.7,a*2,a*1.4),e.strokeRect(-a,-a*.7,a*2,a*1.4),e.fillStyle="#ffe4b3",e.beginPath(),e.moveTo(-a,-a*.7),e.lineTo(0,0),e.lineTo(a,-a*.7),e.closePath(),e.fill(),e.stroke(),e.fillStyle="#dc143c",e.shadowColor="#dc143c",e.shadowBlur=5,e.beginPath(),e.moveTo(0,a*.1),e.bezierCurveTo(-a*.3,-a*.1,-a*.2,-a*.3,0,-a*.15),e.bezierCurveTo(a*.2,-a*.3,a*.3,-a*.1,0,a*.1),e.closePath(),e.fill(),e.shadowBlur=0,e.restore()},drawHeartGarland(e,o,n){const s=o.y,l=o.width,a=o.sag,h=o.hearts;e.save(),e.globalAlpha=o.opacity;const i=Math.sin(n*.001+o.swayPhase)*o.swayAmplitude;e.strokeStyle="#daa520",e.lineWidth=2,e.beginPath(),e.moveTo(0,s),e.quadraticCurveTo(l/2,s+a+i,l,s),e.stroke(),h.forEach(r=>{const d=r.offset*l,f=s+Math.sin(Math.PI*r.offset)*(a+i),t=1+Math.sin(n*.003+r.pulsePhase)*.1;e.save(),e.translate(d,f),e.scale(t,t),e.fillStyle=r.color,e.shadowColor=r.color,e.shadowBlur=r.size*.5,e.beginPath(),e.moveTo(0,r.size*.3),e.bezierCurveTo(-r.size,-r.size*.3,-r.size*.6,-r.size,0,-r.size*.4),e.bezierCurveTo(r.size*.6,-r.size,r.size,-r.size*.3,0,r.size*.3),e.closePath(),e.fill(),e.shadowBlur=0,e.restore()}),e.restore()},drawEnvelope(e,o,n){const s=o.x,l=o.y,a=o.size;e.save(),e.globalAlpha=o.opacity,e.translate(s,l),e.rotate(o.rotation),e.fillStyle="#fff5f5",e.strokeStyle="#ff69b4",e.lineWidth=a*.05,e.fillRect(-a*.7,-a*.5,a*1.4,a),e.strokeRect(-a*.7,-a*.5,a*1.4,a),e.fillStyle="#ffe4e1",e.beginPath(),e.moveTo(-a*.7,-a*.5),e.lineTo(0,a*.1),e.lineTo(a*.7,-a*.5),e.closePath(),e.fill(),e.stroke(),e.fillStyle="#ff1493",e.shadowColor="#ff1493",e.shadowBlur=a*.3,e.beginPath(),e.moveTo(0,a*.25),e.bezierCurveTo(-a*.3,-a*.1,-a*.2,-a*.3,0,-a*.15),e.bezierCurveTo(a*.2,-a*.3,a*.3,-a*.1,0,a*.25),e.closePath(),e.fill(),e.shadowBlur=0,e.restore()},drawButterfly(e,o,n){const s=o.x+Math.sin(n*o.waveFrequency+o.waveOffset)*o.waveAmplitude,l=o.baseY+Math.cos(n*o.waveFrequency*.7+o.waveOffset)*(o.waveAmplitude*.6),a=o.size,h=o.vx>0?1:-1;e.save(),e.globalAlpha=o.opacity,e.translate(s,l),h===-1&&e.scale(-1,1);const i=Math.sin(n*.015+o.wingPhase)*(Math.PI/6),d={pink:{main:"#ffb3d9",accent:"#ff69b4",outline:"#ff1493"},purple:{main:"#dda0dd",accent:"#ba55d3",outline:"#9932cc"}}[o.color];e.save(),e.translate(-a*.15,0),e.rotate(-i),e.fillStyle=d.main,e.strokeStyle=d.outline,e.lineWidth=a*.03,e.beginPath(),e.moveTo(0,0),e.bezierCurveTo(-a*.8,-a*.6,-a*.5,-a*1.2,0,-a*.5),e.closePath(),e.fill(),e.stroke(),e.beginPath(),e.moveTo(0,0),e.bezierCurveTo(-a*.7,a*.4,-a*.4,a*.9,0,a*.4),e.closePath(),e.fill(),e.stroke(),e.fillStyle=d.accent,e.beginPath(),e.arc(-a*.4,-a*.5,a*.12,0,Math.PI*2),e.fill(),e.beginPath(),e.arc(-a*.35,a*.35,a*.1,0,Math.PI*2),e.fill(),e.restore(),e.save(),e.translate(a*.15,0),e.rotate(i),e.fillStyle=d.main,e.strokeStyle=d.outline,e.lineWidth=a*.03,e.beginPath(),e.moveTo(0,0),e.bezierCurveTo(a*.8,-a*.6,a*.5,-a*1.2,0,-a*.5),e.closePath(),e.fill(),e.stroke(),e.beginPath(),e.moveTo(0,0),e.bezierCurveTo(a*.7,a*.4,a*.4,a*.9,0,a*.4),e.closePath(),e.fill(),e.stroke(),e.fillStyle=d.accent,e.beginPath(),e.arc(a*.4,-a*.5,a*.12,0,Math.PI*2),e.fill(),e.beginPath(),e.arc(a*.35,a*.35,a*.1,0,Math.PI*2),e.fill(),e.restore(),e.fillStyle="#4a4a4a",e.fillRect(-a*.05,-a*.5,a*.1,a*.9),e.fillStyle="#2a2a2a",e.beginPath(),e.arc(0,-a*.55,a*.12,0,Math.PI*2),e.fill(),e.strokeStyle="#2a2a2a",e.lineWidth=a*.02,e.beginPath(),e.moveTo(0,-a*.6),e.quadraticCurveTo(-a*.15,-a*.8,-a*.2,-a*.75),e.stroke(),e.beginPath(),e.moveTo(0,-a*.6),e.quadraticCurveTo(a*.15,-a*.8,a*.2,-a*.75),e.stroke(),e.fillStyle=d.outline,e.beginPath(),e.arc(-a*.2,-a*.75,a*.04,0,Math.PI*2),e.fill(),e.beginPath(),e.arc(a*.2,-a*.75,a*.04,0,Math.PI*2),e.fill(),e.restore()},drawHeartMoon(e,o,n){const s=o.x,l=o.y,a=o.size,h=.3+Math.sin(n*.002+o.glowPhase)*.2;e.save(),e.globalAlpha=o.opacity,e.translate(s,l);const i=e.createRadialGradient(0,0,a*.5,0,0,a*2.5);i.addColorStop(0,`rgba(255, 182, 193, ${h*.8})`),i.addColorStop(.4,`rgba(255, 105, 180, ${h*.5})`),i.addColorStop(.7,`rgba(255, 20, 147, ${h*.3})`),i.addColorStop(1,"rgba(255, 20, 147, 0)"),e.fillStyle=i,e.beginPath(),e.arc(0,0,a*2.5,0,Math.PI*2),e.fill();const r=e.createRadialGradient(-a*.3,-a*.3,0,0,0,a);r.addColorStop(0,"#ffcce0"),r.addColorStop(.5,"#ffb3d9"),r.addColorStop(1,"#ff69b4"),e.fillStyle=r,e.beginPath(),e.moveTo(0,a*.3),e.bezierCurveTo(-a*.5,a*.5,-a,a*.2,-a,-a*.2),e.bezierCurveTo(-a,-a*.6,-a*.5,-a*.7,0,-a*.3),e.bezierCurveTo(a*.5,-a*.7,a,-a*.6,a,-a*.2),e.bezierCurveTo(a,a*.2,a*.5,a*.5,0,a*.3),e.closePath(),e.fill(),e.strokeStyle="#ff1493",e.lineWidth=a*.02,e.stroke(),e.fillStyle="rgba(255, 240, 245, 0.4)",e.beginPath(),e.arc(-a*.4,-a*.1,a*.15,0,Math.PI*2),e.fill(),e.beginPath(),e.arc(a*.3,0,a*.12,0,Math.PI*2),e.fill(),e.beginPath(),e.arc(-a*.2,a*.15,a*.1,0,Math.PI*2),e.fill(),e.fillStyle=`rgba(255, 255, 255, ${h})`;const d=[{x:-a*.3,y:-a*.4},{x:a*.2,y:-a*.3},{x:0,y:0},{x:-a*.5,y:a*.1},{x:a*.4,y:a*.15}];for(const f of d){e.save(),e.translate(f.x,f.y),e.beginPath();const t=a*.08;e.moveTo(0,-t),e.lineTo(t*.2,-t*.2),e.lineTo(t,0),e.lineTo(t*.2,t*.2),e.lineTo(0,t),e.lineTo(-t*.2,t*.2),e.lineTo(-t,0),e.lineTo(-t*.2,-t*.2),e.closePath(),e.fill(),e.restore()}e.restore()},drawNeonSign(e,o,n){const s=o.x,l=o.y,a=o.size;if(o.phaseTime+=16,o.phase==="fade-in"&&o.phaseTime>=o.fadeInDuration)o.phase="stable",o.phaseTime=0,o.opacity=o.targetOpacity,o.crackleIntensity=0;else if(o.phase==="stable"&&o.phaseTime>=o.stableDuration)o.phase="fade-out",o.phaseTime=0;else if(o.phase==="fade-out"&&o.phaseTime>=o.fadeOutDuration){o.active=!1;return}o.phase==="fade-in"?(o.opacity=o.phaseTime/o.fadeInDuration*o.targetOpacity,o.crackleIntensity=1-o.phaseTime/o.fadeInDuration):o.phase==="fade-out"&&(o.opacity=o.targetOpacity*(1-o.phaseTime/o.fadeOutDuration)),e.save(),e.translate(s,l);const h="#ff1493",i="#ff0066",r="#ffffff",d="Happy Valentine's Day",f=a;e.font=`bold ${f}px 'Arial Black', sans-serif`,e.textAlign="center",e.textBaseline="middle";const t=e.measureText(d).width;let M=0;o.crackleIntensity>0&&(M=(Math.random()-.5)*o.crackleIntensity*5);const u=d.split("");let P=-t/2;for(let m=0;m<u.length;m++){const y=u[m],b=e.measureText(y).width,T=(o.crackleIntensity>0?Math.random()<o.crackleIntensity*.3:!1)?o.opacity*(.3+Math.random()*.7):o.opacity;e.save(),e.translate(P+b/2,M),e.globalAlpha=T;const v=.8+Math.sin(n*.002+o.glowPhase+m*.5)*.2;e.shadowColor=h,e.shadowBlur=a*.8*v,e.fillStyle=h,e.fillText(y,0,0),e.shadowBlur=a*.5*v,e.fillStyle=i,e.fillText(y,0,0),e.shadowBlur=a*.3*v,e.fillStyle=r,e.fillText(y,0,0),e.shadowBlur=0,e.fillStyle=r,e.globalAlpha=T*.9,e.fillText(y,0,0),e.restore(),P+=b}if(o.crackleIntensity>.3){for(let m=0;m<3;m++)if(Math.random()<o.crackleIntensity*.5){const y=(Math.random()-.5)*t,b=(Math.random()-.5)*a*.3,g=2+Math.random()*3;e.save(),e.globalAlpha=o.opacity*Math.random(),e.fillStyle=Math.random()<.5?h:r,e.shadowColor=h,e.shadowBlur=g*4,e.beginPath(),e.arc(y,b,g,0,Math.PI*2),e.fill(),e.restore()}}(o.phase==="stable"||o.phase==="fade-out")&&(e.globalAlpha=o.opacity*.1,e.fillStyle="#ff1493",e.fillRect(-t*.55,-a*.6,t*1.1,a*1.2)),e.restore()}};
1
+ import{drawIllustratedButterfly as T}from"./butterfly-drawing.js";export default{name:"valentines",displayName:"Valentine's Day",emoji:"\u{1F495}",intensityConfig:{light:{count:40,speedRange:[.3,.8],sizeRange:[2,4],garlands:1,cupidChance:3e-4},medium:{count:80,speedRange:[.4,1.2],sizeRange:[2,5],garlands:2,cupidChance:5e-4},heavy:{count:150,speedRange:[.5,1.5],sizeRange:[3,6],garlands:3,cupidChance:8e-4}},particles:["heart","rose-petal","sparkle","lips"],decorations:["cupid","love-letter","heart-garland","envelope","butterfly","heart-moon","neon-sign"],colors:{primary:"#ff1493",secondary:"#ff69b4",accent:"#dc143c",light:"#ffb6c1",gold:"#ffd700"},createHeart(e,o,s){const n=Math.random();let l,a,i;const t=["#ff1493","#ff69b4","#dc143c","#ffb6c1","#ff0080"];return n<.33?(l=s.sizeRange[0]+Math.random()*(s.sizeRange[1]-s.sizeRange[0])*1.5,a=s.speedRange[0]+Math.random()*(s.speedRange[1]-s.speedRange[0]),i=.8+Math.random()*.2):n<.66?(l=s.sizeRange[0]+Math.random()*(s.sizeRange[1]-s.sizeRange[0]),a=s.speedRange[0]+Math.random()*(s.speedRange[1]-s.speedRange[0]),i=.6+Math.random()*.2):(l=s.sizeRange[0]+Math.random()*(s.sizeRange[1]-s.sizeRange[0])*.8,a=s.speedRange[0]+Math.random()*(s.speedRange[1]-s.speedRange[0])*.8,i=.4+Math.random()*.2),{type:"heart",x:Math.random()*e,y:Math.random()*o,size:l,vx:(Math.random()-.5)*.3,vy:(Math.random()-.7)*.2,speed:a*.3,opacity:i,color:t[Math.floor(Math.random()*t.length)],windOffset:Math.random()*Math.PI*2,windSpeed:.005+Math.random()*.01,rotation:Math.random()*Math.PI*2,rotationSpeed:(Math.random()-.5)*.01,pulsePhase:Math.random()*Math.PI*2,pulseSpeed:.002+Math.random()*.003,floatPhase:Math.random()*Math.PI*2,floatSpeed:.001+Math.random()*.002,active:!0,depth:n}},createRosePetal(e,o,s){const n=["#ff1493","#ff69b4","#dc143c","#ff758f","#ffb6c1"];return{type:"rose-petal",x:Math.random()*e,y:-20,size:1.5+Math.random()*2,speed:s.speedRange[0]+Math.random()*(s.speedRange[1]-s.speedRange[0])*.6,opacity:.7+Math.random()*.3,color:n[Math.floor(Math.random()*n.length)],windOffset:Math.random()*Math.PI*2,windSpeed:.02+Math.random()*.03,rotation:Math.random()*Math.PI*2,rotationSpeed:(Math.random()-.5)*.05,flutterPhase:Math.random()*Math.PI*2,active:!0}},createSparkle(e,o,s){return{type:"sparkle",x:Math.random()*e,y:Math.random()*o,size:.5+Math.random()*1.5,opacity:1,life:20+Math.random()*30,maxLife:20+Math.random()*30,color:Math.random()<.5?"#ffd700":"#ffffff",twinklePhase:Math.random()*Math.PI*2,active:!0,static:!0}},createLips(e,o,s){const n=["#dc143c","#ff1493","#c71585","#ff0066"];return{type:"lips",x:Math.random()*e,y:Math.random()*o,size:3+Math.random()*3,vx:(Math.random()-.5)*.4,vy:(Math.random()-.7)*.2,speed:.3+Math.random()*.2,opacity:.8+Math.random()*.2,color:n[Math.floor(Math.random()*n.length)],rotation:Math.random()*Math.PI*2,rotationSpeed:(Math.random()-.5)*.01,pulsePhase:Math.random()*Math.PI*2,pulseSpeed:.003+Math.random()*.002,floatPhase:Math.random()*Math.PI*2,floatSpeed:.001+Math.random()*.002,kissPhase:Math.random()*Math.PI*2,active:!0}},createHeartGarland(e,o,s={}){const n=8+Math.floor(Math.random()*5),l=[];for(let a=0;a<n;a++)l.push({offset:a/n,size:8+Math.random()*4,color:Math.random()<.5?"#ff1493":"#ff69b4",pulsePhase:Math.random()*Math.PI*2});return{type:"heart-garland",x:0,y:s.y!==void 0?s.y:50+Math.random()*100,width:e,hearts:l,sag:40+Math.random()*30,swayPhase:Math.random()*Math.PI*2,swayAmplitude:10+Math.random()*10,opacity:.8+Math.random()*.2,active:!0,static:!0}},createLoveLetter(e,o,s={}){const n=Math.random()<.5;return{type:"love-letter",x:n?-50:e+50,y:Math.random()*o*.6,baseY:Math.random()*o*.6,vx:n?1+Math.random()*1:-(1+Math.random()*1),size:12+Math.random()*6,opacity:.9+Math.random()*.1,rotation:(Math.random()-.5)*.3,rotationSpeed:(Math.random()-.5)*.005,waveAmplitude:15+Math.random()*15,waveFrequency:.002+Math.random()*.002,waveOffset:Math.random()*Math.PI*2,time:0,active:!0,static:!1}},createFallingParticle(e,o,s){const n=Math.random();return n<.6?this.createHeart(e,o,s):n<.85?this.createRosePetal(e,o,s):this.createLips(e,o,s)},createInitialDecorations(e,o,s){const n=[],l=s.garlands??2;for(let t=0;t<l;t++)n.push(this.createHeartGarland(e,o,{y:50+t*(o/(l+1))}));const a=4;for(let t=0;t<a;t++)n.push({type:"envelope",x:e/(a+1)*(t+1)+(Math.random()-.5)*30,y:o-25-Math.random()*10,size:15+Math.random()*5,opacity:.85,rotation:(Math.random()-.5)*.3,active:!0,static:!0});const i=s.butterflies??3;for(let t=0;t<i;t++)n.push({type:"butterfly",x:Math.random()*e,y:Math.random()*o*.6+50,baseY:Math.random()*o*.6+50,size:12+Math.random()*6,vx:(Math.random()-.5)*2,vy:0,waveOffset:Math.random()*Math.PI*2,waveFrequency:.003+Math.random()*.002,waveAmplitude:20+Math.random()*15,wingPhase:Math.random()*Math.PI*2,opacity:.9,color:Math.random()<.5?"pink":"purple",active:!0,static:!1});return n.push({type:"heart-moon",x:e*.85,y:o*.15,size:60+Math.random()*20,opacity:.9,glowPhase:Math.random()*Math.PI*2,active:!0,static:!0}),n},spawnSpecialParticle(e,o,s,n){const l=Math.random();if(l<n.cupidChance){if(e.some(i=>i.type==="cupid"))return null;const a=Math.random()<.5;return{type:"cupid",x:a?-100:o+100,y:Math.random()*s*.4+50,baseY:Math.random()*s*.4+50,vx:a?2+Math.random()*1.5:-(2+Math.random()*1.5),size:15+Math.random()*8,opacity:1,waveAmplitude:20+Math.random()*20,waveFrequency:.002+Math.random()*.002,waveOffset:Math.random()*Math.PI*2,time:0,wingPhase:Math.random()*Math.PI*2,active:!0,static:!1}}return l<.001?this.createLoveLetter(o,s):l<.0015?e.some(a=>a.type==="neon-sign"&&a.active)?null:{type:"neon-sign",x:o/2,y:s*.3,size:40+Math.random()*20,opacity:0,targetOpacity:1,phase:"fade-in",phaseTime:0,fadeInDuration:1500,stableDuration:5e3,fadeOutDuration:1e3,crackleIntensity:1,flickerPhase:Math.random()*Math.PI*2,glowPhase:Math.random()*Math.PI*2,tubeFlickers:[],active:!0,static:!1}:l<.02?this.createSparkle(o,s,n):null},drawHeart(e,o,s){const n=o.x,l=o.y,a=o.size,i=1+Math.sin(s*o.pulseSpeed+o.pulsePhase)*.15;e.save(),e.globalAlpha=o.opacity,e.translate(n,l),e.rotate(o.rotation),e.scale(i,i),e.fillStyle=o.color,e.shadowColor=o.color,e.shadowBlur=a*.8,e.beginPath(),e.moveTo(0,a*.3),e.bezierCurveTo(-a,-a*.3,-a*.6,-a,0,-a*.4),e.bezierCurveTo(a*.6,-a,a,-a*.3,0,a*.3),e.closePath(),e.fill(),e.shadowBlur=0,e.fillStyle="rgba(255, 255, 255, 0.3)",e.beginPath(),e.arc(-a*.25,-a*.5,a*.15,0,Math.PI*2),e.fill(),e.restore()},drawRosePetal(e,o,s){const n=o.x,l=o.y,a=o.size,i=Math.sin(s*.01+o.flutterPhase)*.3;e.save(),e.globalAlpha=o.opacity,e.translate(n,l),e.rotate(o.rotation+i),e.fillStyle=o.color,e.strokeStyle="rgba(139, 0, 0, 0.3)",e.lineWidth=.5,e.beginPath(),e.moveTo(0,0),e.bezierCurveTo(a*2,-a,a*2,a,0,0),e.closePath(),e.fill(),e.beginPath(),e.moveTo(0,0),e.quadraticCurveTo(a,0,a*1.5,0),e.stroke(),e.restore()},drawSparkle(e,o,s){const n=o.x,l=o.y,a=o.size,i=o.life/o.maxLife,t=(Math.sin(s*.01+o.twinklePhase)+1)*.5;e.save(),e.globalAlpha=o.opacity*i*t,e.translate(n,l),e.fillStyle=o.color,e.shadowColor=o.color,e.shadowBlur=a*2,e.beginPath();for(let r=0;r<4;r++){const d=r/4*Math.PI*2-Math.PI/2,f=Math.cos(d)*a*3,h=Math.sin(d)*a*3,M=d+Math.PI/4,u=Math.cos(M)*a*.5,P=Math.sin(M)*a*.5;r===0?e.moveTo(f,h):(e.lineTo(u,P),e.lineTo(f,h))}e.closePath(),e.fill(),e.restore()},drawLips(e,o,s){const n=o.x,l=o.y,a=o.size,i=1+Math.sin(s*o.pulseSpeed+o.pulsePhase)*.1,t=Math.sin(s*.008+o.kissPhase);e.save(),e.globalAlpha=o.opacity,e.translate(n,l),e.rotate(o.rotation),e.scale(i,i);const r=e.createRadialGradient(0,0,0,0,0,a*2);r.addColorStop(0,o.color),r.addColorStop(.6,o.color),r.addColorStop(1,"#8b0000"),e.fillStyle=r,e.strokeStyle="#8b0000",e.lineWidth=a*.1,e.beginPath(),e.moveTo(-a,0),e.bezierCurveTo(-a*.8,-a*.8,-a*.3,-a*1,0,-a*.6),e.bezierCurveTo(a*.3,-a*1,a*.8,-a*.8,a,0),e.fill(),e.stroke();const d=t*a*.15;if(e.beginPath(),e.moveTo(-a,0),e.bezierCurveTo(-a*.7,a*(.7+d),-a*.3,a*(1+d),0,a*(.8+d)),e.bezierCurveTo(a*.3,a*(1+d),a*.7,a*(.7+d),a,0),e.fill(),e.stroke(),e.globalAlpha=o.opacity*.5,e.fillStyle="rgba(255, 255, 255, 0.6)",e.beginPath(),e.ellipse(-a*.4,-a*.4,a*.2,a*.15,-.3,0,Math.PI*2),e.fill(),e.beginPath(),e.ellipse(a*.4,-a*.4,a*.2,a*.15,.3,0,Math.PI*2),e.fill(),e.beginPath(),e.ellipse(0,a*.5,a*.3,a*.2,0,0,Math.PI*2),e.fill(),t>.8){const f=a*1.5,h=Math.sin(o.kissPhase)*f,M=-Math.abs(Math.cos(o.kissPhase))*f;e.globalAlpha=o.opacity*(t-.8)*5,e.fillStyle="#ffd700",e.shadowColor="#ffd700",e.shadowBlur=a*.5,e.beginPath(),e.arc(h,M,a*.15,0,Math.PI*2),e.fill();for(let u=0;u<4;u++){const P=u/4*Math.PI*2+s*.01,m=h+Math.cos(P)*a*.4,y=M+Math.sin(P)*a*.4;e.beginPath(),e.moveTo(h,M),e.lineTo(m,y),e.lineWidth=a*.05,e.strokeStyle="#ffffff",e.stroke()}}e.restore()},drawCupid(e,o,s){const n=o.x,l=o.y,a=o.size,i=o.vx>0?1:-1;e.save(),e.globalAlpha=o.opacity,e.translate(n,l),i===-1&&e.scale(-1,1);const t=Math.sin(s*.015+o.wingPhase)*(Math.PI/6);e.fillStyle="#ffffff",e.strokeStyle="#ffb6c1",e.lineWidth=1.5,e.save(),e.translate(-a*.2,-a*.3),e.rotate(-t),e.beginPath(),e.moveTo(0,0),e.bezierCurveTo(-a*1.2,-a*.8,-a*1.5,-a*.3,-a*1.2,a*.3),e.bezierCurveTo(-a*.8,a*.2,-a*.3,0,0,0),e.closePath(),e.fill(),e.stroke(),e.restore(),e.fillStyle="#ffdbac",e.beginPath(),e.ellipse(0,0,a*.4,a*.5,0,0,Math.PI*2),e.fill(),e.beginPath(),e.ellipse(a*.3,-a*.6,a*.35,a*.4,0,0,Math.PI*2),e.fill(),e.fillStyle="#ffd700",e.beginPath(),e.arc(a*.1,-a*.9,a*.22,0,Math.PI*2),e.fill(),e.beginPath(),e.arc(a*.4,-a*.95,a*.18,0,Math.PI*2),e.fill(),e.beginPath(),e.arc(a*.15,-a*.75,a*.15,0,Math.PI*2),e.fill(),e.fillStyle="#000000",e.beginPath(),e.arc(a*.42,-a*.62,a*.05,0,Math.PI*2),e.fill(),e.fillStyle="rgba(255, 105, 180, 0.3)",e.beginPath(),e.arc(a*.25,-a*.5,a*.12,0,Math.PI*2),e.fill(),e.strokeStyle="#ffdbac",e.lineWidth=a*.15,e.lineCap="round",e.beginPath(),e.moveTo(-a*.15,a*.4),e.lineTo(-a*.3,a*.8),e.stroke(),e.beginPath(),e.moveTo(-a*.05,a*.4),e.lineTo(-a*.15,a*.75),e.stroke(),e.strokeStyle="#ffdbac",e.lineWidth=a*.12,e.beginPath(),e.moveTo(a*.1,-a*.2),e.lineTo(a*.6,-a*.3),e.stroke(),e.beginPath(),e.moveTo(a*.05,0),e.lineTo(a*.9,-a*.35),e.stroke(),e.strokeStyle="#8B4513",e.lineWidth=2.5,e.beginPath(),e.moveTo(a*.9,-a*.6),e.quadraticCurveTo(a*1.1,-a*.35,a*.9,-a*.1),e.stroke(),e.strokeStyle="#daa520",e.lineWidth=1.5,e.beginPath(),e.moveTo(a*.9,-a*.6),e.lineTo(a*.6,-a*.35),e.lineTo(a*.9,-a*.1),e.stroke(),e.strokeStyle="#8B4513",e.lineWidth=2,e.beginPath(),e.moveTo(a*.6,-a*.35),e.lineTo(a*1.8,-a*.35),e.stroke(),e.fillStyle="#dc143c",e.beginPath(),e.moveTo(a*1.8,-a*.35),e.lineTo(a*2,-a*.35),e.lineTo(a*1.9,-a*.25),e.closePath(),e.fill(),e.beginPath(),e.moveTo(a*1.8,-a*.35),e.lineTo(a*2,-a*.35),e.lineTo(a*1.9,-a*.45),e.closePath(),e.fill(),e.fillStyle="#ff69b4",e.beginPath(),e.moveTo(a*.6,-a*.35),e.lineTo(a*.5,-a*.25),e.lineTo(a*.5,-a*.45),e.closePath(),e.fill(),e.fillStyle="#ffffff",e.strokeStyle="#ffb6c1",e.lineWidth=1.5,e.save(),e.translate(a*.1,-a*.3),e.rotate(t),e.beginPath(),e.moveTo(0,0),e.bezierCurveTo(-a*1,-a*.6,-a*1.3,-a*.2,-a*1,a*.2),e.bezierCurveTo(-a*.6,a*.15,-a*.2,0,0,0),e.closePath(),e.fill(),e.stroke(),e.restore(),e.restore()},drawLoveLetter(e,o,s){const n=o.x,l=o.y,a=o.size;e.save(),e.globalAlpha=o.opacity,e.translate(n,l),e.rotate(o.rotation),e.fillStyle="#fff5e6",e.strokeStyle="#daa520",e.lineWidth=1,e.fillRect(-a,-a*.7,a*2,a*1.4),e.strokeRect(-a,-a*.7,a*2,a*1.4),e.fillStyle="#ffe4b3",e.beginPath(),e.moveTo(-a,-a*.7),e.lineTo(0,0),e.lineTo(a,-a*.7),e.closePath(),e.fill(),e.stroke(),e.fillStyle="#dc143c",e.shadowColor="#dc143c",e.shadowBlur=5,e.beginPath(),e.moveTo(0,a*.1),e.bezierCurveTo(-a*.3,-a*.1,-a*.2,-a*.3,0,-a*.15),e.bezierCurveTo(a*.2,-a*.3,a*.3,-a*.1,0,a*.1),e.closePath(),e.fill(),e.shadowBlur=0,e.restore()},drawHeartGarland(e,o,s){const n=o.y,l=o.width,a=o.sag,i=o.hearts;e.save(),e.globalAlpha=o.opacity;const t=Math.sin(s*.001+o.swayPhase)*o.swayAmplitude;e.strokeStyle="#daa520",e.lineWidth=2,e.beginPath(),e.moveTo(0,n),e.quadraticCurveTo(l/2,n+a+t,l,n),e.stroke(),i.forEach(r=>{const d=r.offset*l,f=n+Math.sin(Math.PI*r.offset)*(a+t),h=1+Math.sin(s*.003+r.pulsePhase)*.1;e.save(),e.translate(d,f),e.scale(h,h),e.fillStyle=r.color,e.shadowColor=r.color,e.shadowBlur=r.size*.5,e.beginPath(),e.moveTo(0,r.size*.3),e.bezierCurveTo(-r.size,-r.size*.3,-r.size*.6,-r.size,0,-r.size*.4),e.bezierCurveTo(r.size*.6,-r.size,r.size,-r.size*.3,0,r.size*.3),e.closePath(),e.fill(),e.shadowBlur=0,e.restore()}),e.restore()},drawEnvelope(e,o,s){const n=o.x,l=o.y,a=o.size;e.save(),e.globalAlpha=o.opacity,e.translate(n,l),e.rotate(o.rotation),e.fillStyle="#fff5f5",e.strokeStyle="#ff69b4",e.lineWidth=a*.05,e.fillRect(-a*.7,-a*.5,a*1.4,a),e.strokeRect(-a*.7,-a*.5,a*1.4,a),e.fillStyle="#ffe4e1",e.beginPath(),e.moveTo(-a*.7,-a*.5),e.lineTo(0,a*.1),e.lineTo(a*.7,-a*.5),e.closePath(),e.fill(),e.stroke(),e.fillStyle="#ff1493",e.shadowColor="#ff1493",e.shadowBlur=a*.3,e.beginPath(),e.moveTo(0,a*.25),e.bezierCurveTo(-a*.3,-a*.1,-a*.2,-a*.3,0,-a*.15),e.bezierCurveTo(a*.2,-a*.3,a*.3,-a*.1,0,a*.25),e.closePath(),e.fill(),e.shadowBlur=0,e.restore()},drawButterfly(e,o,s=0){const n=s*(o.waveFrequency||0)+(o.waveOffset||0),l=o.waveAmplitude||0,a=o.color==="purple";T(e,{x:o.x+Math.sin(n)*l,y:(o.baseY??o.y)+Math.cos(s*(o.waveFrequency||0)*.7+(o.waveOffset||0))*l*.6,size:o.size*1.6,heading:-Math.PI/2,flapPhase:s*.01+(o.wingPhase||0),colourUpper:a?"#b48aba":"#d897b3",colourLower:a?"#896eaa":"#bb7798",alpha:o.opacity??1})},drawHeartMoon(e,o,s){const n=o.x,l=o.y,a=o.size,i=.3+Math.sin(s*.002+o.glowPhase)*.2;e.save(),e.globalAlpha=o.opacity,e.translate(n,l);const t=e.createRadialGradient(0,0,a*.5,0,0,a*2.5);t.addColorStop(0,`rgba(255, 182, 193, ${i*.8})`),t.addColorStop(.4,`rgba(255, 105, 180, ${i*.5})`),t.addColorStop(.7,`rgba(255, 20, 147, ${i*.3})`),t.addColorStop(1,"rgba(255, 20, 147, 0)"),e.fillStyle=t,e.beginPath(),e.arc(0,0,a*2.5,0,Math.PI*2),e.fill();const r=e.createRadialGradient(-a*.3,-a*.3,0,0,0,a);r.addColorStop(0,"#ffcce0"),r.addColorStop(.5,"#ffb3d9"),r.addColorStop(1,"#ff69b4"),e.fillStyle=r,e.beginPath(),e.moveTo(0,a*.3),e.bezierCurveTo(-a*.5,a*.5,-a,a*.2,-a,-a*.2),e.bezierCurveTo(-a,-a*.6,-a*.5,-a*.7,0,-a*.3),e.bezierCurveTo(a*.5,-a*.7,a,-a*.6,a,-a*.2),e.bezierCurveTo(a,a*.2,a*.5,a*.5,0,a*.3),e.closePath(),e.fill(),e.strokeStyle="#ff1493",e.lineWidth=a*.02,e.stroke(),e.fillStyle="rgba(255, 240, 245, 0.4)",e.beginPath(),e.arc(-a*.4,-a*.1,a*.15,0,Math.PI*2),e.fill(),e.beginPath(),e.arc(a*.3,0,a*.12,0,Math.PI*2),e.fill(),e.beginPath(),e.arc(-a*.2,a*.15,a*.1,0,Math.PI*2),e.fill(),e.fillStyle=`rgba(255, 255, 255, ${i})`;const d=[{x:-a*.3,y:-a*.4},{x:a*.2,y:-a*.3},{x:0,y:0},{x:-a*.5,y:a*.1},{x:a*.4,y:a*.15}];for(const f of d){e.save(),e.translate(f.x,f.y),e.beginPath();const h=a*.08;e.moveTo(0,-h),e.lineTo(h*.2,-h*.2),e.lineTo(h,0),e.lineTo(h*.2,h*.2),e.lineTo(0,h),e.lineTo(-h*.2,h*.2),e.lineTo(-h,0),e.lineTo(-h*.2,-h*.2),e.closePath(),e.fill(),e.restore()}e.restore()},drawNeonSign(e,o,s){const n=o.x,l=o.y,a=o.size;if(o.phaseTime+=16,o.phase==="fade-in"&&o.phaseTime>=o.fadeInDuration)o.phase="stable",o.phaseTime=0,o.opacity=o.targetOpacity,o.crackleIntensity=0;else if(o.phase==="stable"&&o.phaseTime>=o.stableDuration)o.phase="fade-out",o.phaseTime=0;else if(o.phase==="fade-out"&&o.phaseTime>=o.fadeOutDuration){o.active=!1;return}o.phase==="fade-in"?(o.opacity=o.phaseTime/o.fadeInDuration*o.targetOpacity,o.crackleIntensity=1-o.phaseTime/o.fadeInDuration):o.phase==="fade-out"&&(o.opacity=o.targetOpacity*(1-o.phaseTime/o.fadeOutDuration)),e.save(),e.translate(n,l);const i="#ff1493",t="#ff0066",r="#ffffff",d="Happy Valentine's Day",f=a;e.font=`bold ${f}px 'Arial Black', sans-serif`,e.textAlign="center",e.textBaseline="middle";const h=e.measureText(d).width;let M=0;o.crackleIntensity>0&&(M=(Math.random()-.5)*o.crackleIntensity*5);const u=d.split("");let P=-h/2;for(let m=0;m<u.length;m++){const y=u[m],b=e.measureText(y).width,v=(o.crackleIntensity>0?Math.random()<o.crackleIntensity*.3:!1)?o.opacity*(.3+Math.random()*.7):o.opacity;e.save(),e.translate(P+b/2,M),e.globalAlpha=v;const p=.8+Math.sin(s*.002+o.glowPhase+m*.5)*.2;e.shadowColor=i,e.shadowBlur=a*.8*p,e.fillStyle=i,e.fillText(y,0,0),e.shadowBlur=a*.5*p,e.fillStyle=t,e.fillText(y,0,0),e.shadowBlur=a*.3*p,e.fillStyle=r,e.fillText(y,0,0),e.shadowBlur=0,e.fillStyle=r,e.globalAlpha=v*.9,e.fillText(y,0,0),e.restore(),P+=b}if(o.crackleIntensity>.3){for(let m=0;m<3;m++)if(Math.random()<o.crackleIntensity*.5){const y=(Math.random()-.5)*h,b=(Math.random()-.5)*a*.3,g=2+Math.random()*3;e.save(),e.globalAlpha=o.opacity*Math.random(),e.fillStyle=Math.random()<.5?i:r,e.shadowColor=i,e.shadowBlur=g*4,e.beginPath(),e.arc(y,b,g,0,Math.PI*2),e.fill(),e.restore()}}(o.phase==="stable"||o.phase==="fade-out")&&(e.globalAlpha=o.opacity*.1,e.fillStyle="#ff1493",e.fillRect(-h*.55,-a*.6,h*1.1,a*1.2)),e.restore()}};
@@ -0,0 +1 @@
1
+ export const CELEBRATION_THEMES={christmas:{label:"Christmas",traits:{snowflake:{label:"Snowflakes",types:["snowflake"],kind:"particle"},tree:{label:"Christmas trees",types:["tree"],count:"trees"},wreath:{label:"Wreaths",types:["wreath"],count:"wreaths"},snowman:{label:"Snowmen",types:["snowman"],count:"snowmen"},northStar:{label:"North star",types:["north-star"],count:"northStars"},sleigh:{label:"Santa's sleigh",types:["sleigh"]},robin:{label:"Robins",types:["robin"]},train:{label:"Steam train",types:["train"]},elf:{label:"Elves",types:["elf"]},peeingElf:{label:"Peeing elf",types:["peeing-elf"],chance:"peeingElfChance",enabled:!1},thievingElf:{label:"Thieving elf",types:["thieving-elf"],chance:"thievingElfChance",enabled:!1},firework:{label:"Fireworks",types:["firework","spark"]}}},halloween:{label:"Halloween",traits:{pumpkin:{label:"Falling pumpkins",types:["pumpkin"],kind:"particle"},bat:{label:"Bats",types:["bat"],kind:"particle"},ghost:{label:"Ghosts",types:["ghost"],kind:"particle"},spider:{label:"Spiders",types:["spider","spider-small"],count:"spiders"},gravestone:{label:"Gravestones",types:["gravestone"],count:"gravestones"},jackOLantern:{label:"Jack-o-lanterns",types:["jack-o-lantern"],count:"jackOLanterns"},scarecrow:{label:"Scarecrows",types:["scarecrow"],count:"scarecrows"},twinklingStar:{label:"Twinkling stars",types:["twinkling-star"],count:"twinklingStars"},hauntedHouse:{label:"Haunted house",types:["haunted-house"]},moon:{label:"Moon",types:["moon"]},witch:{label:"Witches",types:["witch"]},cauldron:{label:"Cauldron",types:["cauldron"]},floatingPumpkin:{label:"Floating pumpkins",types:["floating-pumpkin"]},lightning:{label:"Lightning",global:!0}}},valentines:{label:"Valentine's Day",traits:{heart:{label:"Hearts",types:["heart"],kind:"particle"},rosePetal:{label:"Rose petals",types:["rose-petal"],kind:"particle"},sparkle:{label:"Sparkles",types:["sparkle"],kind:"particle"},lips:{label:"Kisses",types:["lips"],kind:"particle"},heartGarland:{label:"Heart garlands",types:["heart-garland"],count:"garlands"},butterfly:{label:"Butterflies",types:["butterfly"],count:"butterflies"},envelope:{label:"Envelopes",types:["envelope"],count:"envelopes"},heartMoon:{label:"Heart moon",types:["heart-moon"]},cupid:{label:"Cupid",types:["cupid"],chance:"cupidChance"},loveLetter:{label:"Love letters",types:["love-letter"]},neonSign:{label:"Neon sign",types:["neon-sign"]}}},"guy-fawkes":{label:"Guy Fawkes Night",traits:{ember:{label:"Embers",types:["ember"],kind:"particle"},spark:{label:"Sparks",types:["spark","trail"],kind:"particle"},bonfire:{label:"Bonfires",types:["bonfire"],count:"bonfires"},guyEffigy:{label:"Guy effigies",types:["guy-effigy"]},catherineWheel:{label:"Catherine wheels",types:["catherine-wheel"]},romanCandle:{label:"Roman candles",types:["roman-candle"]},sparklerBundle:{label:"Sparklers",types:["sparkler-bundle"]},firework:{label:"Fireworks",types:["firework"],chance:"fireworkChance"},rocket:{label:"Rockets",types:["rocket"],chance:"rocketChance"},burst:{label:"Bursts",types:["burst"],chance:"burstChance"},moon:{label:"Moon",types:["moon"]},lightning:{label:"Lightning",global:!0}}},"st-patricks":{label:"St Patrick's Day",traits:{cloverPetal:{label:"Clover petals",types:["clover-petal"],kind:"particle"},shamrock:{label:"Shamrocks",types:["shamrock"],kind:"particle"},goldCoin:{label:"Gold coins",types:["gold-coin"],kind:"particle"},sparkle:{label:"Sparkles",types:["sparkle"],kind:"particle"},potOfGold:{label:"Pots of gold",types:["pot-of-gold"],count:"pots"},twinklingStar:{label:"Twinkling stars",types:["twinkling-star"],count:"twinklingStars"},leprechaun:{label:"Leprechauns",types:["leprechaun","static-leprechaun"],chance:"leprechaunChance"},rainbow:{label:"Rainbow",types:["rainbow"]},banshee:{label:"Banshee",types:["banshee"]},moon:{label:"Moon",types:["moon"]}}},"st-davids":{label:"St David's Day",traits:{daffodilPetal:{label:"Daffodil petals",types:["daffodil-petal"],kind:"particle"},daffodil:{label:"Daffodils",types:["daffodil"],kind:"particle"},springSparkle:{label:"Spring sparkles",types:["spring-sparkle"],kind:"particle"},leek:{label:"Leeks",types:["leek"],kind:"particle"},daffodilField:{label:"Daffodil fields",types:["daffodil-field"],count:"daffodilFields"},twinklingStar:{label:"Twinkling stars",types:["twinkling-star"],count:"twinklingStars"},welshDragon:{label:"Welsh dragon",types:["welsh-dragon"],chance:"dragonChance"},flag:{label:"Welsh flag",types:["flag"]},harp:{label:"Harp",types:["harp"]},leekBundle:{label:"Leek bundles",types:["leek-bundle"]}}},"st-georges":{label:"St George's Day",traits:{rosePetal:{label:"Rose petals",types:["rose-petal"],kind:"particle"},tudorRose:{label:"Tudor roses",types:["tudor-rose"],kind:"particle"},oakLeaf:{label:"Oak leaves",types:["oak-leaf"],kind:"particle"},sparkle:{label:"Sparkles",types:["sparkle"],kind:"particle"},englishRose:{label:"English roses",types:["english-rose"],count:"roses"},twinklingStar:{label:"Twinkling stars",types:["twinkling-star"],count:"twinklingStars"},knight:{label:"Knight",types:["knight"],chance:"knightChance"},dragon:{label:"Dragon",types:["dragon"]},castle:{label:"Castle",types:["castle"]},shield:{label:"Shields",types:["shield"]},stGeorgesCross:{label:"St George's cross",types:["st-georges-cross"]}}},"st-andrews":{label:"St Andrew's Day",traits:{heatherPetal:{label:"Heather petals",types:["heather-petal"],kind:"particle"},heather:{label:"Heather",types:["heather"],kind:"particle"},saltireSparkle:{label:"Saltire sparkles",types:["saltire-sparkle"],kind:"particle"},thistle:{label:"Thistles",types:["thistle"],kind:"particle"},thistlePlant:{label:"Thistle plants",types:["thistle-plant"],count:"thistles"},twinklingStar:{label:"Twinkling stars",types:["twinkling-star"],count:"twinklingStars"},bagpiper:{label:"Bagpiper",types:["bagpiper"],chance:"bagpiperChance"},saltireFlag:{label:"Saltire flag",types:["saltire-flag"]},tartanPattern:{label:"Tartan",types:["tartan-pattern"]},highlandScene:{label:"Highland scene",types:["highland-scene"]}}}};const c=a=>String(a).toLowerCase().replace(/[^a-z0-9]/g,"");export const traitAttribute=a=>a.replace(/[A-Z]/g,s=>"-"+s.toLowerCase());export function resolveCelebrationTraits(a,s={}){const n=new Set,r=new Set,i={},o=Object.entries(s).map(([l,e])=>[c(l),String(e).trim().toLowerCase()]),b=o.some(([l,e])=>["fallingonly","snowonly"].includes(l)&&["true","1","yes","on"].includes(e));for(const[l,e]of Object.entries(CELEBRATION_THEMES[a]?.traits||{})){const p=o.find(([t])=>[l,e.count,e.chance].filter(Boolean).some(d=>c(d)===t))?.[1];if(["off","false","0","no"].includes(p)||e.enabled===!1&&!["true","1","yes","on"].includes(p)||b&&e.kind!=="particle"){for(const t of e.types||[])n.add(t);e.global&&r.add(l);for(const t of[e.count,e.chance].filter(Boolean))i[t]=0}}return{disabledTypes:n,disabledGlobals:r,config:i}}
@@ -1 +1 @@
1
- (function(){"use strict";fetch("/api/effects/settings").then(function(y){return y.json()}).then(function(y){var z=y.respectMotion!==!1,A=y.defaultDuration||600,S=y.defaultAnimation||"fade",E=y.defaultThreshold!=null?y.defaultThreshold:.1,p=z&&window.matchMedia&&window.matchMedia("(prefers-reduced-motion: reduce)").matches,d=document.querySelector(".page-body");if(!d)return;function r(t,e){return t.getAttribute("data-fx-"+e)}function i(t,e,n){var a=r(t,e);return a!==null?parseFloat(a):n}function v(t,e,n){var a=r(t,e);return a===null?n:a==="true"||a==="1"}function b(t,e,n){var a=new IntersectionObserver(function(o){o[0].isIntersecting&&(a.unobserve(t),n())},{threshold:e});a.observe(t)}d.querySelectorAll(".dm-fx-reveal").forEach(function(t){var e=r(t,"animation")||S,n=i(t,"duration",A),a=i(t,"delay",0),o=i(t,"threshold",E),f=v(t,"once",!0);p||(t.style.opacity="0",t.style.transition="none",e==="slide-up"?t.style.transform="translateY(30px)":e==="slide-down"?t.style.transform="translateY(-30px)":e==="zoom"?t.style.transform="scale(0.85)":e==="flip"&&(t.style.transform="rotateY(90deg)"),requestAnimationFrame(function(){requestAnimationFrame(function(){t.style.transition="opacity "+n+"ms ease "+a+"ms, transform "+n+"ms ease "+a+"ms";var s=new IntersectionObserver(function(u){u.forEach(function(h){h.isIntersecting?(t.style.opacity="1",t.style.transform="",f&&s.unobserve(t)):f||(t.style.opacity="0",e==="slide-up"?t.style.transform="translateY(30px)":e==="slide-down"?t.style.transform="translateY(-30px)":e==="zoom"?t.style.transform="scale(0.85)":e==="flip"?t.style.transform="rotateY(90deg)":t.style.transform="")})},{threshold:o});s.observe(t)})}))}),d.querySelectorAll(".dm-fx-counter").forEach(function(t){var e=i(t,"to",0),n=i(t,"from",0),a=i(t,"duration",2e3),o=r(t,"prefix")||"",f=r(t,"suffix")||"",s=i(t,"decimals",0),u=r(t,"separator")||"";function h(m){var l=m.toFixed(s);if(u){var x=l.split(".");x[0]=x[0].replace(/\B(?=(\d{3})+(?!\d))/g,u),l=x.join(".")}return o+l+f}if(p){t.textContent=h(e);return}b(t,.5,function(){var m=null;requestAnimationFrame(function l(x){m||(m=x);var w=Math.min((x-m)/a,1),q=1-Math.pow(1-w,3);t.textContent=h(n+(e-n)*q),w<1&&requestAnimationFrame(l)})})}),p||d.querySelectorAll(".dm-fx-scramble").forEach(function(t){var e=i(t,"speed",50),n=t.textContent,a="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789!@#$%&",o=0;b(t,.3,function(){var f=setInterval(function(){for(var s="",u=0;u<n.length;u++)u<o||n[u]===" "?s+=n[u]:s+=a[Math.floor(Math.random()*a.length)];t.textContent=s,o<n.length?o++:clearInterval(f)},e)})}),p||d.querySelectorAll(".dm-fx-shake").forEach(function(t){var e=i(t,"intensity",5),n=i(t,"duration",500),a=r(t,"direction")||"horizontal",o=a==="vertical"?"translateY":"translateX";t.animate([{transform:o+"(0)"},{transform:o+"(-"+e+"px)"},{transform:o+"("+e+"px)"},{transform:o+"(-"+e+"px)"},{transform:o+"("+e+"px)"},{transform:o+"(0)"}],{duration:n,easing:"ease-in-out"})}),d.querySelectorAll(".dm-fx-ripple").forEach(function(t){t.style.position="relative",t.style.overflow="hidden",t.addEventListener("click",function(e){var n=r(t,"colour")||"rgba(255,255,255,0.3)",a=i(t,"duration",600),o=t.getBoundingClientRect(),f=Math.max(o.width,o.height)*2,s=document.createElement("span");s.style.cssText="position:absolute;border-radius:50%;pointer-events:none;width:"+f+"px;height:"+f+"px;left:"+(e.clientX-o.left-f/2)+"px;top:"+(e.clientY-o.top-f/2)+"px;background:"+n+";transform:scale(0);opacity:1;transition:transform "+a+"ms ease,opacity "+a+"ms ease;",t.appendChild(s),requestAnimationFrame(function(){s.style.transform="scale(1)",s.style.opacity="0"}),setTimeout(function(){s.remove()},a)})});var c=window.Domma&&window.Domma.effects;c&&(d.querySelectorAll(".dm-fx-breathe").forEach(function(t){if(!p){var e={};r(t,"amplitude")&&(e.amplitude=i(t,"amplitude",6)),r(t,"duration")&&(e.duration=i(t,"duration",3e3)),r(t,"easing")&&(e.easing=r(t,"easing")),r(t,"stagger")&&(e.stagger=i(t,"stagger",0)),c.breathe(t,e)}}),d.querySelectorAll(".dm-fx-pulse").forEach(function(t){if(!p){var e={};r(t,"scale")&&(e.scale=i(t,"scale",1.05)),r(t,"duration")&&(e.duration=i(t,"duration",2e3)),r(t,"easing")&&(e.easing=r(t,"easing")),c.pulse(t,e)}}),d.querySelectorAll(".dm-fx-scribe").forEach(function(t){var e={};r(t,"speed")&&(e.speed=i(t,"speed",50)),r(t,"delete-speed")&&(e.deleteSpeed=i(t,"delete-speed",30)),r(t,"cursor")&&(e.cursor=v(t,"cursor",!0)),r(t,"cursor-char")&&(e.cursorChar=r(t,"cursor-char")),r(t,"cursor-type")&&(e.cursorType=r(t,"cursor-type")),r(t,"mode")&&(e.mode=r(t,"mode")),r(t,"loop")&&(e.loop=v(t,"loop",!1)),r(t,"loop-delay")&&(e.loopDelay=i(t,"loop-delay",1e3)),r(t,"pause-on-hover")&&(e.pauseOnHover=v(t,"pause-on-hover",!1));var n=r(t,"actions");if(n)try{e.actions=JSON.parse(n)}catch{return}else{var a=t.textContent.trim();if(!a)return;t.textContent="",e.actions=[{render:a}]}c.scribe(t,e)}),d.querySelectorAll(".dm-fx-twinkle").forEach(function(t){var e={};r(t,"count")&&(e.count=i(t,"count",100)),r(t,"shape")&&(e.shape=r(t,"shape")),r(t,"colour")&&(e.colour=r(t,"colour")),r(t,"min-size")&&(e.minSize=i(t,"min-size",1)),r(t,"max-size")&&(e.maxSize=i(t,"max-size",3)),c.twinkle(t,e)}),typeof c.tickerTape=="function"&&d.querySelectorAll(".dm-fx-ticker-tape").forEach(function(t){if(!p){var e={};r(t,"palette")&&(e.palette=r(t,"palette")),r(t,"density")&&(e.density=i(t,"density",50)),r(t,"speed")&&(e.speed=i(t,"speed",1)),r(t,"sway")&&(e.sway=i(t,"sway",60)),r(t,"rotation-speed")&&(e.rotationSpeed=i(t,"rotation-speed",6)),r(t,"min-width")&&(e.minWidth=i(t,"min-width",5)),r(t,"max-width")&&(e.maxWidth=i(t,"max-width",9)),r(t,"min-height")&&(e.minHeight=i(t,"min-height",12)),r(t,"max-height")&&(e.maxHeight=i(t,"max-height",22)),r(t,"fade-start")&&(e.fadeStart=i(t,"fade-start",.55)),r(t,"burst")&&(e.burst=v(t,"burst",!1)),r(t,"burst-count")&&(e.burstCount=i(t,"burst-count",150)),r(t,"z-index")&&(e.zIndex=i(t,"z-index",1));var n=r(t,"mode");n==="page"?c.tickerTape(null,e):c.tickerTape(t,e)}}),typeof c.butterflies=="function"&&d.querySelectorAll(".dm-fx-butterflies").forEach(function(t){if(!p){var e={};r(t,"palette")&&(e.palette=r(t,"palette")),r(t,"density")&&(e.density=i(t,"density",18)),r(t,"speed")&&(e.speed=i(t,"speed",1)),r(t,"wander")&&(e.wander=i(t,"wander",1)),r(t,"rise-speed")&&(e.riseSpeed=i(t,"rise-speed",.4)),r(t,"flap-speed")&&(e.flapSpeed=i(t,"flap-speed",1)),r(t,"min-size")&&(e.minSize=i(t,"min-size",14)),r(t,"max-size")&&(e.maxSize=i(t,"max-size",26)),r(t,"two-tone")&&(e.twoTone=v(t,"two-tone",!0)),r(t,"burst")&&(e.burst=v(t,"burst",!1)),r(t,"burst-count")&&(e.burstCount=i(t,"burst-count",40)),r(t,"z-index")&&(e.zIndex=i(t,"z-index",1));var n=r(t,"mode");n==="page"?c.butterflies(null,e):c.butterflies(t,e)}}),typeof c.strobe=="function"&&d.querySelectorAll(".dm-fx-strobe").forEach(function(t){if(p)return;function e(s){var u=r(t,s);if(!u)return null;var h=u.split(",").map(function(m){return m.trim()}).filter(Boolean);return h.length?h:null}var n={};r(t,"preset")&&(n.preset=r(t,"preset")),r(t,"motion")&&(n.motion=r(t,"motion")),r(t,"speed")&&(n.speed=i(t,"speed",1)),r(t,"sweep-arc")&&(n.sweepArc=i(t,"sweep-arc",100)),r(t,"beam-width")&&(n.beamWidth=i(t,"beam-width",16)),r(t,"intensity")&&(n.intensity=i(t,"intensity",.7)),r(t,"flicker")&&(n.flicker=v(t,"flicker",!0)),r(t,"hz")&&(n.hz=i(t,"hz",10));var a=e("origins");a&&(n.origins=a);var o=e("colours");o&&(n.colours=o),r(t,"duration")&&(n.duration=i(t,"duration",null)),r(t,"z-index")&&(n.zIndex=i(t,"z-index",9999));var f=r(t,"mode");f==="page"?c.strobe(null,n):c.strobe(t,n)}));var g=d.querySelectorAll(".dm-fx-celebrate");g.length&&!p&&import("/public/js/celebrations/index.js?v=20260930-snowman").then(function(t){var e=t.CelebrationsEffect;g.forEach(function(n){var a=n.getAttribute("data-fx-theme")||"auto",o=n.getAttribute("data-fx-intensity")||"medium",f=n.getAttribute("data-fx-z-index")?parseInt(n.getAttribute("data-fx-z-index"),10):999;if(!(a==="auto"&&(a=e.getCurrentTheme(),!a))){var s={},u=["data-fx-theme","data-fx-intensity","data-fx-z-index"];Array.from(n.attributes).forEach(function(m){m.name.startsWith("data-fx-")&&!u.includes(m.name)&&(s[m.name.slice(8)]=m.value)});var h=new e({theme:a,intensity:o,enabled:!0,zIndex:f,overrides:s});h.init().then(function(){h.start()})}})}).catch(function(){})}).catch(function(){})})();
1
+ (function(){"use strict";fetch("/api/effects/settings").then(function(y){return y.json()}).then(function(y){var z=y.respectMotion!==!1,A=y.defaultDuration||600,S=y.defaultAnimation||"fade",E=y.defaultThreshold!=null?y.defaultThreshold:.1,p=z&&window.matchMedia&&window.matchMedia("(prefers-reduced-motion: reduce)").matches,d=document.querySelector(".page-body");if(!d)return;function r(t,e){return t.getAttribute("data-fx-"+e)}function i(t,e,n){var a=r(t,e);return a!==null?parseFloat(a):n}function v(t,e,n){var a=r(t,e);return a===null?n:a==="true"||a==="1"}function b(t,e,n){var a=new IntersectionObserver(function(o){o[0].isIntersecting&&(a.unobserve(t),n())},{threshold:e});a.observe(t)}d.querySelectorAll(".dm-fx-reveal").forEach(function(t){var e=r(t,"animation")||S,n=i(t,"duration",A),a=i(t,"delay",0),o=i(t,"threshold",E),f=v(t,"once",!0);p||(t.style.opacity="0",t.style.transition="none",e==="slide-up"?t.style.transform="translateY(30px)":e==="slide-down"?t.style.transform="translateY(-30px)":e==="zoom"?t.style.transform="scale(0.85)":e==="flip"&&(t.style.transform="rotateY(90deg)"),requestAnimationFrame(function(){requestAnimationFrame(function(){t.style.transition="opacity "+n+"ms ease "+a+"ms, transform "+n+"ms ease "+a+"ms";var s=new IntersectionObserver(function(u){u.forEach(function(h){h.isIntersecting?(t.style.opacity="1",t.style.transform="",f&&s.unobserve(t)):f||(t.style.opacity="0",e==="slide-up"?t.style.transform="translateY(30px)":e==="slide-down"?t.style.transform="translateY(-30px)":e==="zoom"?t.style.transform="scale(0.85)":e==="flip"?t.style.transform="rotateY(90deg)":t.style.transform="")})},{threshold:o});s.observe(t)})}))}),d.querySelectorAll(".dm-fx-counter").forEach(function(t){var e=i(t,"to",0),n=i(t,"from",0),a=i(t,"duration",2e3),o=r(t,"prefix")||"",f=r(t,"suffix")||"",s=i(t,"decimals",0),u=r(t,"separator")||"";function h(m){var l=m.toFixed(s);if(u){var x=l.split(".");x[0]=x[0].replace(/\B(?=(\d{3})+(?!\d))/g,u),l=x.join(".")}return o+l+f}if(p){t.textContent=h(e);return}b(t,.5,function(){var m=null;requestAnimationFrame(function l(x){m||(m=x);var w=Math.min((x-m)/a,1),q=1-Math.pow(1-w,3);t.textContent=h(n+(e-n)*q),w<1&&requestAnimationFrame(l)})})}),p||d.querySelectorAll(".dm-fx-scramble").forEach(function(t){var e=i(t,"speed",50),n=t.textContent,a="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789!@#$%&",o=0;b(t,.3,function(){var f=setInterval(function(){for(var s="",u=0;u<n.length;u++)u<o||n[u]===" "?s+=n[u]:s+=a[Math.floor(Math.random()*a.length)];t.textContent=s,o<n.length?o++:clearInterval(f)},e)})}),p||d.querySelectorAll(".dm-fx-shake").forEach(function(t){var e=i(t,"intensity",5),n=i(t,"duration",500),a=r(t,"direction")||"horizontal",o=a==="vertical"?"translateY":"translateX";t.animate([{transform:o+"(0)"},{transform:o+"(-"+e+"px)"},{transform:o+"("+e+"px)"},{transform:o+"(-"+e+"px)"},{transform:o+"("+e+"px)"},{transform:o+"(0)"}],{duration:n,easing:"ease-in-out"})}),d.querySelectorAll(".dm-fx-ripple").forEach(function(t){t.style.position="relative",t.style.overflow="hidden",t.addEventListener("click",function(e){var n=r(t,"colour")||"rgba(255,255,255,0.3)",a=i(t,"duration",600),o=t.getBoundingClientRect(),f=Math.max(o.width,o.height)*2,s=document.createElement("span");s.style.cssText="position:absolute;border-radius:50%;pointer-events:none;width:"+f+"px;height:"+f+"px;left:"+(e.clientX-o.left-f/2)+"px;top:"+(e.clientY-o.top-f/2)+"px;background:"+n+";transform:scale(0);opacity:1;transition:transform "+a+"ms ease,opacity "+a+"ms ease;",t.appendChild(s),requestAnimationFrame(function(){s.style.transform="scale(1)",s.style.opacity="0"}),setTimeout(function(){s.remove()},a)})});var c=window.Domma&&window.Domma.effects;c&&(d.querySelectorAll(".dm-fx-breathe").forEach(function(t){if(!p){var e={};r(t,"amplitude")&&(e.amplitude=i(t,"amplitude",6)),r(t,"duration")&&(e.duration=i(t,"duration",3e3)),r(t,"easing")&&(e.easing=r(t,"easing")),r(t,"stagger")&&(e.stagger=i(t,"stagger",0)),c.breathe(t,e)}}),d.querySelectorAll(".dm-fx-pulse").forEach(function(t){if(!p){var e={};r(t,"scale")&&(e.scale=i(t,"scale",1.05)),r(t,"duration")&&(e.duration=i(t,"duration",2e3)),r(t,"easing")&&(e.easing=r(t,"easing")),c.pulse(t,e)}}),d.querySelectorAll(".dm-fx-scribe").forEach(function(t){var e={};r(t,"speed")&&(e.speed=i(t,"speed",50)),r(t,"delete-speed")&&(e.deleteSpeed=i(t,"delete-speed",30)),r(t,"cursor")&&(e.cursor=v(t,"cursor",!0)),r(t,"cursor-char")&&(e.cursorChar=r(t,"cursor-char")),r(t,"cursor-type")&&(e.cursorType=r(t,"cursor-type")),r(t,"mode")&&(e.mode=r(t,"mode")),r(t,"loop")&&(e.loop=v(t,"loop",!1)),r(t,"loop-delay")&&(e.loopDelay=i(t,"loop-delay",1e3)),r(t,"pause-on-hover")&&(e.pauseOnHover=v(t,"pause-on-hover",!1));var n=r(t,"actions");if(n)try{e.actions=JSON.parse(n)}catch{return}else{var a=t.textContent.trim();if(!a)return;t.textContent="",e.actions=[{render:a}]}c.scribe(t,e)}),d.querySelectorAll(".dm-fx-twinkle").forEach(function(t){var e={};r(t,"count")&&(e.count=i(t,"count",100)),r(t,"shape")&&(e.shape=r(t,"shape")),r(t,"colour")&&(e.colour=r(t,"colour")),r(t,"min-size")&&(e.minSize=i(t,"min-size",1)),r(t,"max-size")&&(e.maxSize=i(t,"max-size",3)),c.twinkle(t,e)}),typeof c.tickerTape=="function"&&d.querySelectorAll(".dm-fx-ticker-tape").forEach(function(t){if(!p){var e={};r(t,"palette")&&(e.palette=r(t,"palette")),r(t,"density")&&(e.density=i(t,"density",50)),r(t,"speed")&&(e.speed=i(t,"speed",1)),r(t,"sway")&&(e.sway=i(t,"sway",60)),r(t,"rotation-speed")&&(e.rotationSpeed=i(t,"rotation-speed",6)),r(t,"min-width")&&(e.minWidth=i(t,"min-width",5)),r(t,"max-width")&&(e.maxWidth=i(t,"max-width",9)),r(t,"min-height")&&(e.minHeight=i(t,"min-height",12)),r(t,"max-height")&&(e.maxHeight=i(t,"max-height",22)),r(t,"fade-start")&&(e.fadeStart=i(t,"fade-start",.55)),r(t,"burst")&&(e.burst=v(t,"burst",!1)),r(t,"burst-count")&&(e.burstCount=i(t,"burst-count",150)),r(t,"z-index")&&(e.zIndex=i(t,"z-index",1));var n=r(t,"mode");n==="page"?c.tickerTape(null,e):c.tickerTape(t,e)}}),typeof c.butterflies=="function"&&d.querySelectorAll(".dm-fx-butterflies").forEach(function(t){if(!p){var e={};r(t,"palette")&&(e.palette=r(t,"palette")),r(t,"density")&&(e.density=i(t,"density",18)),r(t,"speed")&&(e.speed=i(t,"speed",1)),r(t,"wander")&&(e.wander=i(t,"wander",1)),r(t,"rise-speed")&&(e.riseSpeed=i(t,"rise-speed",.4)),r(t,"flap-speed")&&(e.flapSpeed=i(t,"flap-speed",1)),r(t,"min-size")&&(e.minSize=i(t,"min-size",14)),r(t,"max-size")&&(e.maxSize=i(t,"max-size",26)),r(t,"two-tone")&&(e.twoTone=v(t,"two-tone",!0)),r(t,"burst")&&(e.burst=v(t,"burst",!1)),r(t,"burst-count")&&(e.burstCount=i(t,"burst-count",40)),r(t,"z-index")&&(e.zIndex=i(t,"z-index",1));var n=r(t,"mode");n==="page"?c.butterflies(null,e):c.butterflies(t,e)}}),typeof c.strobe=="function"&&d.querySelectorAll(".dm-fx-strobe").forEach(function(t){if(p)return;function e(s){var u=r(t,s);if(!u)return null;var h=u.split(",").map(function(m){return m.trim()}).filter(Boolean);return h.length?h:null}var n={};r(t,"preset")&&(n.preset=r(t,"preset")),r(t,"motion")&&(n.motion=r(t,"motion")),r(t,"speed")&&(n.speed=i(t,"speed",1)),r(t,"sweep-arc")&&(n.sweepArc=i(t,"sweep-arc",100)),r(t,"beam-width")&&(n.beamWidth=i(t,"beam-width",16)),r(t,"intensity")&&(n.intensity=i(t,"intensity",.7)),r(t,"flicker")&&(n.flicker=v(t,"flicker",!0)),r(t,"hz")&&(n.hz=i(t,"hz",10));var a=e("origins");a&&(n.origins=a);var o=e("colours");o&&(n.colours=o),r(t,"duration")&&(n.duration=i(t,"duration",null)),r(t,"z-index")&&(n.zIndex=i(t,"z-index",9999));var f=r(t,"mode");f==="page"?c.strobe(null,n):c.strobe(t,n)}));var g=d.querySelectorAll(".dm-fx-celebrate");g.length&&!p&&import("/public/js/celebrations/index.js?v=20261001-options").then(function(t){var e=t.CelebrationsEffect;g.forEach(function(n){var a=n.getAttribute("data-fx-theme")||"auto",o=n.getAttribute("data-fx-intensity")||"medium",f=n.getAttribute("data-fx-z-index")?parseInt(n.getAttribute("data-fx-z-index"),10):999;if(!(a==="auto"&&(a=e.getCurrentTheme(),!a))){var s={},u=["data-fx-theme","data-fx-intensity","data-fx-z-index"];Array.from(n.attributes).forEach(function(m){m.name.startsWith("data-fx-")&&!u.includes(m.name)&&(s[m.name.slice(8)]=m.value)});var h=new e({theme:a,intensity:o,enabled:!0,zIndex:f,overrides:s});h.init().then(function(){h.start()})}})}).catch(function(){})}).catch(function(){})})();
@@ -154,7 +154,7 @@
154
154
  <script src="/public/js/forms.js?v=20260927-submit-btn" type="module"></script>
155
155
 
156
156
  <!-- Core effects runtime -->
157
- <script src="/public/js/effects.js?v=20260930-snowman"></script>
157
+ <script src="/public/js/effects.js?v=20261001-options"></script>
158
158
 
159
159
  <!-- Plugin body-end injection -->
160
160
  {{bodyEndInject}}