0x265a…22cd

All memos sent from and to 0x265a…22cd.

<?xml version="1.0" encoding="UTF-8"?><svg xmlns="http://www.w3.org/2000/svg" width="2048" height="2048" viewBox="0 0 2048 2048" preserveAspectRatio="xMidYMid meet"><rect width="2048" height="2048" fill="{{BACKGROUND_COLOR}}"/><g id="spacetime-xxx"><rect width="2048" height="2048" fill="url(#stXXX)" opacity="0"><animate attributeName="opacity" dur="8s" begin="0s" keyTimes="0;0.2;0.3;0.55;0.7;0.8;1" values="0;0;0.5;0.8;0.5;0;0" repeatCount="indefinite"/></rect></g><g id="spacetime-streets"><rect width="2048" height="2048" fill="url(#stStreets)" opacity="0"><animate attributeName="opacity" dur="8s" begin="0s" keyTimes="0;0.2;0.3;0.55;0.7;0.8;1" values="0;0;0.3;0.9;0.3;0;0" repeatCount="indefinite"/></rect></g><g id="spacetime-dust"><rect width="2048" height="2048" fill="url(#stDust)" opacity="0"><animate attributeName="opacity" dur="8s" begin="0s" keyTimes="0;0.2;0.3;0.55;0.7;0.8;1" values="0;0.0;0.7;0.8;0.4;0.1;0" repeatCount="indefinite"/></rect></g><g id="spacetime-rings"><rect width="2048" height="2048" fill="url(#stRings)" opacity="0"><animate attributeName="opacity" dur="8s" begin="0s" keyTimes="0;0.2;0.3;0.55;0.7;0.8;1" values="0;0;0.3;0.8;0.3;0;0" repeatCount="indefinite"/></rect></g><g id="spacetime-drift"><rect width="2048" height="2048" fill="url(#stDrift)" opacity="0"><animate attributeName="opacity" dur="8s" begin="0s" keyTimes="0;0.2;0.3;0.55;0.7;0.8;1" values="0;0;0.3;0.8;0.3;0;0" repeatCount="indefinite"/></rect></g><g id="spacetime-markets"><rect width="2048" height="2048" fill="url(#stMarkets)" opacity="0"><animate attributeName="opacity" dur="8s" begin="0s" keyTimes="0;0.2;0.3;0.55;0.7;0.8;1" values="0;0;0.3;0.8;0.3;0;0" repeatCount="indefinite"/></rect></g><g id="spacetime-gang"><rect width="2048" height="2048" fill="url(#stGang)" opacity="0"><animate attributeName="opacity" dur="8s" begin="0s" keyTimes="0;0.2;0.3;0.55;0.7;0.8;1" values="0;0;0.3;0.8;0.3;0;0" repeatCount="indefinite"/></rect></g><g id="spacetime-entangled"><rect width="2048" height="2048" fill="url(#stEntangled)" opacity="0"><animate attributeName="opacity" dur="8s" begin="0s" keyTimes="0;0.2;0.3;0.55;0.7;0.8;1" values="0;0;0.3;0.8;0.3;0;0" repeatCount="indefinite"/></rect></g><g id="spacetime-portals"><rect width="2048" height="2048" fill="url(#stPortals)" opacity="0"><animate attributeName="opacity" dur="8s" begin="0s" keyTimes="0;0.2;0.3;0.55;0.7;0.8;1" values="0;0;0.3;0.8;0.3;0;0" repeatCount="indefinite"/></rect></g><g id="sun-trait"><circle cx="1530" cy="390" r="290" class="sky-trait-color" opacity="0"><animate attributeName="opacity" dur="8s" begin="0s" keyTimes="0;0.2;0.35;0.5;0.65;0.8;1" values="0;0;0.8;1;0.8;0;0" repeatCount="indefinite"/></circle><ellipse cx="1500" cy="390" rx="290" ry="290" class="sky-trait-color" opacity="0" filter="url(#motionBlur)"><animate attributeName="opacity" dur="8s" begin="0s" keyTimes="0;0.2;0.35;0.5;0.65;0.8;1" values="0;0;0.35;0.65;0.35;0;0" repeatCount="indefinite"/></ellipse></g><g id="comet-trait"><circle cx="380" cy="300" r="50" class="sky-trait-color" opacity="0"><animate attributeName="opacity" dur="8s" begin="0s" keyTimes="0;0.2;0.35;0.5;0.65;0.8;1" values="0;0;0.5;1;0.5;0;0" repeatCount="indefinite"/></circle><circle cx="360" cy="300" r="50" class="sky-trait-color" opacity="0" filter="url(#motionBlurb)"><animate attributeName="opacity" dur="8s" begin="0s" keyTimes="0;0.2;0.35;0.5;0.65;0.8;1" values="0;0;0.35;0.65;0.35;0;0" repeatCount="indefinite"/></circle><ellipse cx="300" cy="300" rx="150" ry="50" class="sky-trait-color" opacity="0" filter="url(#motionBlur)"><animate attributeName="opacity" dur="8s" begin="0s" keyTimes="0;0.2;0.35;0.5;0.65;0.8;1" values="0;0;0.35;0.65;0.35;0;0" repeatCount="indefinite"/></ellipse></g><g id="moonbow-trait"><circle cx="1024" cy="300" r="90" fill="url(#moonbowGradient)" opacity="0" filter="url(#motionBlur)"><animate attributeName="opacity" dur="8s" begin="0s" keyTimes="0;0.2;0.35;0.5;0.65;0.8;1" values="0;0;0.35;0.7;0.35;0;0" repeatCount="indefinite"/></circle><circle cx="974" cy="275" r="90" fill="url(#moonbowGradient)" opacity="0" filter="url(#motionBlur)"><animate attributeName="opacity" dur="8s" begin="0s" keyTimes="0;0.2;0.35;0.5;0.65;0.8;1" values="0;0;0.10;0.15;0.10;0;0" repeatCount="indefinite"/></circle></g><g id="nebula-trait"><path d="M 594 1760 Q 630 1705 650 1710 Q 680 1720 760 1660 Q 820 1630 844 1635 Q 914 1650 974 1635 Q 1024 1630 1054 1650 Q 1074 1655 1104 1645 Q 1154 1640 1174 1685 Q 1194 1720 1234 1710 Q 1254 1700 1284 1735" fill="none" class="sky-trait-stroke" stroke-width="8" opacity="0"><animate attributeName="opacity" dur="8s" begin="0s" keyTimes="0;0.2;0.35;0.5;0.65;0.8;1" values="0;0;0.4;0.8;0.4;0;0" repeatCount="indefinite"/></path><path d="M 754 1860 Q 730 1820 750 1830 Q 680 1835 710 1810 Q 820 1740 844 1735 Q 1004 1720 1064 1730 Q 1124 1800 1284 1830 Q 1300 1860 754 1860 Z" fill="none" class="sky-trait-stroke" stroke-width="220" opacity="0" filter="url(#motionBlur)"><animate attributeName="opacity" dur="8s" begin="0s" keyTimes="0;0.2;0.35;0.5;0.65;0.8;1" values="0;0;0.25;0.5;0.25;0;0" repeatCount="indefinite"/></path></g><g id="stars-trait"><g class="sky-trait-color" opacity="0"><circle cx="70" cy="280" r="7"/><circle cx="130" cy="210" r="6"/><circle cx="190" cy="315" r="8"/><circle cx="250" cy="265" r="6"/><circle cx="320" cy="350" r="8"/><circle cx="400" cy="175" r="6"/><circle cx="600" cy="250" r="7"/><circle cx="800" cy="335" r="8"/><circle cx="1000" cy="380" r="8"/><circle cx="1200" cy="305" r="7"/><circle cx="1400" cy="260" r="6"/><circle cx="1600" cy="350" r="7"/><circle cx="1800" cy="405" r="8"/><circle cx="520" cy="400" r="7"/><circle cx="735" cy="360" r="7"/><circle cx="950" cy="390" r="7"/><circle cx="1180" cy="415" r="8"/><circle cx="1325" cy="370" r="7"/><circle cx="1510" cy="340" r="7"/><circle cx="1730" cy="430" r="8"/><circle cx="1950" cy="320" r="6"/><animate attributeName="opacity" dur="8s" begin="0.5s" keyTimes="0;0.0;0.1;0.3;0.65;0.85;1" values="0;0;0.5;1;0.5;0;0" repeatCount="indefinite"/></g></g><defs><style> :root { --trait-color: {{PATTERN_COLOR}}; } .sky-trait-color { fill: var(--trait-color); } .sky-trait-stroke { stroke: var(--trait-color); } .spacetime-color { stroke: var(--trait-color); fill: var(--trait-color); } .spacetime-stroke { stroke: var(--trait-color); } /* Sky trait visibility control - all hidden by default */ #sun-trait, #comet-trait, #stars-trait, #moonbow-trait, #nebula-trait { display: none; } /* Show only the selected trait - change "sun" to desired trait */ #{{SKY_NAME}}-trait { display: block; } /* Location trait visibility control - all hidden by default */ #village-location, #town-location, #city-location, #metropolis-location, #megalopolis-location { display: none; } /* Show only the selected location - change to desired location */ #{{LOCATION_NAME}}-location { display: block; } /* Spacetime visibility control - all hidden by default */ #spacetime-xxx, #spacetime-streets, #spacetime-drift, #spacetime-markets, #spacetime-portals, #spacetime-gang, #spacetime-dust, #spacetime-rings, #spacetime-entangled { display: none; } /* Show only the selected spacetime style — change ONE line below */ #spacetime-{{SPACETIME_NAME}} { display: block; } </style><linearGradient id="g" gradientUnits="userSpaceOnUse" x1="0" y1="0" x2="2048" y2="0"><stop offset="50%" stop-color="{{COLOR1A}}"><animate attributeName="stop-color" dur="8s" values="{{COLOR1B}};{{COLOR1C}};{{COLOR2}};{{COLOR3}};{{COLOR4}};{{COLOR5A}};{{COLOR5B}}" keyTimes="0;0.2;0.25;0.39;0.6;0.8;1" repeatCount="indefinite"/></stop></linearGradient><linearGradient id="moonbowGradient" gradientUnits="userSpaceOnUse" x1="1024" y1="210" x2="1024" y2="390"><stop offset="0%" stop-color="#f5de10"/><stop offset="100%" stop-color="{{PATTERN_COLOR2}}"/></linearGradient><pattern id="stXXX" patternUnits="userSpaceOnUse" width="205" height="205"><rect x="0" y="0" width="205" height="205" fill="none"/><path d="M0 0 L205 205 M205 0 L0 205" fill="none" stroke="url(#g)" stroke-width="10" stroke-opacity="0.8"/><path d="M0 0 L205 205 M205 0 L0 205" fill="none" stroke="url(#g)" stroke-width="30" stroke-opacity="0.4" filter="url(#motionBlurb)"/><animateTransform attributeName="patternTransform" type="translate" from="0 0" to="-205 0" dur="8s" repeatCount="indefinite"/></pattern><pattern id="stStreets" patternUnits="userSpaceOnUse" width="205" height="205"><rect x="0" y="0" width="200" height="200" fill="none"/><path d="M0 0 L200 0 L200 200 L0 200 Z" fill="none" stroke="url(#g)" stroke-width="35" stroke-opacity="0.9"/><g><line x1="80" y1="100" x2="120" y2="100" stroke="url(#g)" stroke-width="12" stroke-linecap="round" stroke-opacity="0.9"/><animateTransform attributeName="transform" type="rotate" dur="8s" repeatCount="indefinite" keyTimes="0;0.16;0.33;0.5;0.66;0.83;1" values="0 100 100; 22 100 100; -15 100 100; 35 100 100; -8 100 100; 12 100 100; 0 100 100" calcMode="spline" keySplines="0.25 0.1 0.25 1;0.25 0.1 0.25 1;0.25 0.1 0.25 1;0.25 0.1 0.25 1;0.25 0.1 0.25 1;0.25 0.1 0.25 1"/></g><animateTransform attributeName="patternTransform" type="translate" from="0 0" to="-200 0" dur="8s" repeatCount="indefinite"/></pattern><pattern id="stPortals" patternUnits="userSpaceOnUse" width="205" height="205"><rect x="0" y="0" width="200" height="200" fill="none"/><line x1="0" y1="20" x2="200" y2="20" stroke="url(#g)" stroke-width="24" stroke-linecap="round" stroke-opacity="0.65"><animate attributeName="y1" dur="8s" repeatCount="indefinite" keyTimes="0;0.25;0.5;0.75;1" values="20;100;180;100;20" calcMode="spline" keySplines="0.25 0.1 0.25 1;0.25 0.1 0.25 1;0.25 0.1 0.25 1;0.25 0.1 0.25 1"/><animate attributeName="y2" dur="8s" repeatCount="indefinite" keyTimes="0;0.25;0.5;0.75;1" values="20;100;180;100;20" calcMode="spline" keySplines="0.25 0.1 0.25 1;0.25 0.1 0.25 1;0.25 0.1 0.25 1;0.25 0.1 0.25 1"/></line><line x1="0" y1="20" x2="200" y2="20" stroke="url(#g)" stroke-width="34" stroke-linecap="round" stroke-opacity="0.25" filter="url(#motionBlurb)"><animate attributeName="y1" dur="8s" begin="0.4s" repeatCount="indefinite" keyTimes="0;0.25;0.5;0.75;1" values="20;100;180;100;20" calcMode="spline" keySplines="0.25 0.1 0.25 1;0.25 0.1 0.25 1;0.25 0.1 0.25 1;0.25 0.1 0.25 1"/><animate attributeName="y2" dur="8s" begin="0.4s" repeatCount="indefinite" keyTimes="0;0.25;0.5;0.75;1" values="20;100;180;100;20" calcMode="spline" keySplines="0.25 0.1 0.25 1;0.25 0.1 0.25 1;0.25 0.1 0.25 1;0.25 0.1 0.25 1"/></line><line x1="20" y1="0" x2="20" y2="200" stroke="url(#g)" stroke-width="24" stroke-linecap="round" stroke-opacity="0.65"><animate attributeName="x1" dur="8s" begin="0.2s" repeatCount="indefinite" keyTimes="0;0.25;0.5;0.75;1" values="20;100;180;100;20" calcMode="spline" keySplines="0.25 0.1 0.25 1;0.25 0.1 0.25 1;0.25 0.1 0.25 1;0.25 0.1 0.25 1"/><animate attributeName="x2" dur="8s" begin="0.2s" repeatCount="indefinite" keyTimes="0;0.25;0.5;0.75;1" values="20;100;180;100;20" calcMode="spline" keySplines="0.25 0.1 0.25 1;0.25 0.1 0.25 1;0.25 0.1 0.25 1;0.25 0.1 0.25 1"/></line><line x1="20" y1="0" x2="20" y2="200" stroke="url(#g)" stroke-width="34" stroke-linecap="round" stroke-opacity="0.25" filter="url(#motionBlurb)"><animate attributeName="x1" dur="8s" begin="0.6s" repeatCount="indefinite" keyTimes="0;0.25;0.5;0.75;1" values="20;100;180;100;20" calcMode="spline" keySplines="0.25 0.1 0.25 1;0.25 0.1 0.25 1;0.25 0.1 0.25 1;0.25 0.1 0.25 1"/><animate attributeName="x2" dur="8s" begin="0.6s" repeatCount="indefinite" keyTimes="0;0.25;0.5;0.75;1" values="20;100;180;100;20" calcMode="spline" keySplines="0.25 0.1 0.25 1;0.25 0.1 0.25 1;0.25 0.1 0.25 1;0.25 0.1 0.25 1"/></line><animateTransform attributeName="patternTransform" type="translate" from="0 0" to="-205 0" dur="8s" repeatCount="indefinite"/></pattern><pattern id="stGang" patternUnits="userSpaceOnUse" width="205" height="205"><rect x="0" y="0" width="200" height="200" fill="none"/><rect x="70" y="70" width="15" height="15" fill="none" stroke="url(#g)" stroke-width="8" stroke-opacity="1"><animate attributeName="x" dur="8s" repeatCount="indefinite" keyTimes="0;0.25;0.5;0.75;1" values="70;110;70;30;70" calcMode="spline" keySplines="0.25 0.1 0.25 1;0.25 0.1 0.25 1;0.25 0.1 0.25 1;0.25 0.1 0.25 1"/><animate attributeName="y" dur="8s" repeatCount="indefinite" keyTimes="0;0.25;0.5;0.75;1" values="70;30;110;70;70" calcMode="spline" keySplines="0.25 0.1 0.25 1;0.25 0.1 0.25 1;0.25 0.1 0.25 1;0.25 0.1 0.25 1"/></rect><rect x="90" y="70" width="15" height="15" fill="none" stroke="url(#g)" stroke-width="8" stroke-opacity="1"><animate attributeName="x" dur="8s" repeatCount="indefinite" keyTimes="0;0.25;0.5;0.75;1" values="110;150;110;70;110" calcMode="spline" keySplines="0.25 0.1 0.25 1;0.25 0.1 0.25 1;0.25 0.1 0.25 1;0.25 0.1 0.25 1"/><animate attributeName="y" dur="8s" repeatCount="indefinite" keyTimes="0;0.25;0.5;0.75;1" values="70;30;110;70;70" calcMode="spline" keySplines="0.25 0.1 0.25 1;0.25 0.1 0.25 1;0.25 0.1 0.25 1;0.25 0.1 0.25 1"/></rect><rect x="120" y="160" width="15" height="15" fill="none" stroke="url(#g)" stroke-width="8" stroke-opacity="1"><animate attributeName="x" dur="8s" begin="0.3s" repeatCount="indefinite" keyTimes="0;0.25;0.5;0.75;1" values="120;80;140;120;120" calcMode="spline" keySplines="0.25 0.1 0.25 1;0.25 0.1 0.25 1;0.25 0.1 0.25 1;0.25 0.1 0.25 1"/><animate attributeName="y" dur="8s" begin="0.3s" repeatCount="indefinite" keyTimes="0;0.25;0.5;0.75;1" values="160;160;100;160;160" calcMode="spline" keySplines="0.25 0.1 0.25 1;0.25 0.1 0.25 1;0.25 0.1 0.25 1;0.25 0.1 0.25 1"/></rect><rect x="140" y="160" width="15" height="15" fill="none" stroke="url(#g)" stroke-width="8" stroke-opacity="1"><animate attributeName="x" dur="8s" begin="0.3s" repeatCount="indefinite" keyTimes="0;0.25;0.5;0.75;1" values="160;120;180;160;160" calcMode="spline" keySplines="0.25 0.1 0.25 1;0.25 0.1 0.25 1;0.25 0.1 0.25 1;0.25 0.1 0.25 1"/><animate attributeName="y" dur="8s" begin="0.3s" repeatCount="indefinite" keyTimes="0;0.25;0.5;0.75;1" values="160;160;100;160;160" calcMode="spline" keySplines="0.25 0.1 0.25 1;0.25 0.1 0.25 1;0.25 0.1 0.25 1;0.25 0.1 0.25 1"/></rect><animateTransform attributeName="patternTransform" type="translate" from="0 0" to="-205 0" dur="8s" repeatCount="indefinite"/></pattern><pattern id="stMarkets" patternUnits="userSpaceOnUse" width="205" height="205"><rect x="0" y="0" width="205" height="205" fill="none"/><path d="M 0 55 Q 20 80 40 120 Q 60 60 80 140 Q 100 40 120 160 Q 140 80 160 120 Q 180 60 210 55" fill="none" stroke="url(#g)" stroke-width="8" stroke-opacity="0.8"><animate attributeName="d" dur="8s" repeatCount="indefinite" keyTimes="0;0.25;0.5;0.75;1" values="M 0 55 Q 20 100 40 90 Q 60 120 80 70 Q 100 140 120 60 Q 140 110 160 90 Q 180 120 210 55; M 0 55 Q 20 70 40 120 Q 60 90 80 110 Q 100 80 120 130 Q 140 100 160 80 Q 180 110 210 55; M 0 55 Q 20 130 40 80 Q 60 110 80 90 Q 100 130 120 80 Q 140 90 160 120 Q 180 100 210 55; M 0 55 Q 20 90 40 110 Q 60 130 80 80 Q 100 140 120 60 Q 140 110 160 90 Q 180 130 210 55; M 0 55 Q 20 100 40 90 Q 60 120 80 70 Q 100 140 120 60 Q 140 110 160 90 Q 180 120 210 55" calcMode="spline" keySplines="0.25 0.1 0.25 1;0.25 0.1 0.25 1;0.25 0.1 0.25 1;0.25 0.1 0.25 1"/></path><path d="M 0 55 Q 20 80 40 120 Q 60 60 80 140 Q 100 40 120 160 Q 140 80 160 120 Q 180 60 210 55" fill="none" stroke="url(#g)" stroke-width="25" stroke-opacity="0.5" filter="url(#motionBlurb)"><animate attributeName="d" dur="8s" begin="0.4s" repeatCount="indefinite" keyTimes="0;0.25;0.5;0.75;1" values="M 0 55 Q 20 100 40 90 Q 60 120 80 70 Q 100 140 120 60 Q 140 110 160 90 Q 180 120 210 55; M 0 55 Q 20 70 40 120 Q 60 90 80 110 Q 100 80 120 130 Q 140 100 160 80 Q 180 110 210 55; M 0 55 Q 20 130 40 80 Q 60 110 80 90 Q 100 130 120 80 Q 140 90 160 120 Q 180 100 210 55; M 0 55 Q 20 90 40 110 Q 60 130 80 80 Q 100 140 120 60 Q 140 110 160 90 Q 180 130 210 55; M 0 55 Q 20 100 40 90 Q 60 120 80 70 Q 100 140 120 60 Q 140 110 160 90 Q 180 120 210 55" calcMode="spline" keySplines="0.25 0.1 0.25 1;0.25 0.1 0.25 1;0.25 0.1 0.25 1;0.25 0.1 0.25 1"/></path><animateTransform attributeName="patternTransform" type="translate" from="0 0" to="-205 0" dur="8s" repeatCount="indefinite"/></pattern><pattern id="stDrift" patternUnits="userSpaceOnUse" width="205" height="205"><rect x="0" y="0" width="200" height="205" fill="none"/><line x1="0" y1="-10" x2="0" y2="235" stroke="url(#g)" stroke-width="25" stroke-opacity="0.9"/><rect x="15" y="20" width="28" height="12" stroke="url(#g)" fill="url(#g)" fill-opacity="0.7" filter="url(#motionBlurb)"/><rect x="15" y="60" width="58" height="12" stroke="url(#g)" fill="url(#g)" fill-opacity="0.7" filter="url(#motionBlurb)"/><rect x="15" y="100" width="98" height="12" stroke="url(#g)" fill="url(#g)" fill-opacity="0.7" filter="url(#motionBlurb)"/><rect x="15" y="140" width="58" height="12" stroke="url(#g)" fill="url(#g)" fill-opacity="0.7" filter="url(#motionBlurb)"/><rect x="15" y="180" width="28" height="12" stroke="url(#g)" fill="url(#g)" fill-opacity="0.7" filter="url(#motionBlurb)"/><animateTransform attributeName="patternTransform" type="translate" from="0 0" to="-805 0" dur="8s" repeatCount="indefinite"/></pattern><pattern id="stRings" patternUnits="userSpaceOnUse" width="205" height="205"><rect x="0" y="0" width="200" height="200" fill="none"/><circle r="3.9" stroke="url(#g)" fill="url(#g)" stroke-width="2" stroke-opacity="0.9"><animateMotion dur="8s" repeatCount="indefinite" path="M 100 55 A 70 45 0 1 1 99.9 55"/></circle><circle r="3.5" stroke="url(#g)" fill="url(#g)" stroke-width="2" stroke-opacity="0.9" filter="url(#motionBlurb)"><animateMotion dur="8s" begin="0.15s" repeatCount="indefinite" path="M 100 55 A 70 45 0 1 1 99.9 55"/></circle><circle r="3" stroke="url(#g)" fill="url(#g)" stroke-width="2" stroke-opacity="0.9" filter="url(#motionBlurb)"><animateMotion dur="8s" begin="0.30s" repeatCount="indefinite" path="M 100 55 A 70 45 0 1 1 99.9 55"/></circle><circle r="3" stroke="url(#g)" fill="url(#g)" stroke-width="2" stroke-opacity="0.9" filter="url(#motionBlurb)"><animateMotion dur="8s" begin="0.45s" repeatCount="indefinite" path="M 100 55 A 70 45 0 1 1 99.9 55"/></circle><circle r="2" stroke="url(#g)" fill="url(#g)" stroke-width="2" stroke-opacity="0.9" filter="url(#motionBlurb)"><animateMotion dur="8s" begin="0.60s" repeatCount="indefinite" path="M 100 55 A 70 45 0 1 1 99.9 55"/></circle><circle r="2" stroke="url(#g)" fill="url(#g)" stroke-width="2" stroke-opacity="0.9" filter="url(#motionBlurb)"><animateMotion dur="8s" begin="0.75s" repeatCount="indefinite" path="M 100 55 A 70 45 0 1 1 99.9 55"/></circle><circle r="1" stroke="url(#g)" fill="url(#g)" stroke-width="2" stroke-opacity="0.9" filter="url(#motionBlurb)"><animateMotion dur="8s" begin="0.9s" repeatCount="indefinite" path="M 100 55 A 70 45 0 1 1 99.9 55"/></circle><circle r="1" stroke="url(#g)" fill="url(#g)" stroke-width="2" stroke-opacity="0.9" filter="url(#motionBlurb)"><animateMotion dur="8s" begin="1.05s" repeatCount="indefinite" path="M 100 55 A 70 45 0 1 1 99.9 55"/></circle><circle r="3.9" stroke="url(#g)" fill="url(#g)" stroke-width="2" stroke-opacity="0.9"><animateMotion dur="8s" begin="0.2s" repeatCount="indefinite" path="M 100 55 A 60 60 0 1 1 99.9 55"/></circle><circle r="3.5" stroke="url(#g)" fill="url(#g)" stroke-width="2" stroke-opacity="0.9" filter="url(#motionBlurb)"><animateMotion dur="8s" begin="0.35s" repeatCount="indefinite" path="M 100 55 A 60 60 0 1 1 99.9 55"/></circle><circle r="3" stroke="url(#g)" fill="url(#g)" stroke-width="2" stroke-opacity="0.9" filter="url(#motionBlurb)"><animateMotion dur="8s" begin="0.50s" repeatCount="indefinite" path="M 100 55 A 60 60 0 1 1 99.9 55"/></circle><circle r="3" stroke="url(#g)" fill="url(#g)" stroke-width="2" stroke-opacity="0.9" filter="url(#motionBlurb)"><animateMotion dur="8s" begin="0.65s" repeatCount="indefinite" path="M 100 55 A 60 60 0 1 1 99.9 55"/></circle><circle r="2" stroke="url(#g)" fill="url(#g)" stroke-width="2" stroke-opacity="0.9" filter="url(#motionBlurb)"><animateMotion dur="8s" begin="0.80s" repeatCount="indefinite" path="M 100 55 A 60 60 0 1 1 99.9 55"/></circle><circle r="2" stroke="url(#g)" fill="url(#g)" stroke-width="2" stroke-opacity="0.9" filter="url(#motionBlurb)"><animateMotion dur="8s" begin="0.95s" repeatCount="indefinite" path="M 100 55 A 60 60 0 1 1 99.9 55"/></circle><circle r="1" stroke="url(#g)" fill="url(#g)" stroke-width="2" stroke-opacity="0.9" filter="url(#motionBlurb)"><animateMotion dur="8s" begin="1.1s" repeatCount="indefinite" path="M 100 55 A 60 60 0 1 1 99.9 55"/></circle><circle r="1" stroke="url(#g)" fill="url(#g)" stroke-width="2" stroke-opacity="0.9" filter="url(#motionBlurb)"><animateMotion dur="8s" begin="1.25s" repeatCount="indefinite" path="M 100 55 A 60 60 0 1 1 99.9 55"/></circle><circle r="3.9" stroke="url(#g)" fill="url(#g)" stroke-width="2" stroke-opacity="0.9"><animateMotion dur="8s" begin="0.4s" repeatCount="indefinite" path="M 100 55 A 45 70 0 1 1 99.9 55"/></circle><circle r="3.5" stroke="url(#g)" fill="url(#g)" stroke-width="2" stroke-opacity="0.9" filter="url(#motionBlurb)"><animateMotion dur="8s" begin="0.55s" repeatCount="indefinite" path="M 100 55 A 45 70 0 1 1 99.9 55"/></circle><circle r="3" stroke="url(#g)" fill="url(#g)" stroke-width="2" stroke-opacity="0.9" filter="url(#motionBlurb)"><animateMotion dur="8s" begin="0.70s" repeatCount="indefinite" path="M 100 55 A 45 70 0 1 1 99.9 55"/></circle><circle r="3" stroke="url(#g)" fill="url(#g)" stroke-width="2" stroke-opacity="0.9" filter="url(#motionBlurb)"><animateMotion dur="8s" begin="0.85s" repeatCount="indefinite" path="M 100 55 A 45 70 0 1 1 99.9 55"/></circle><circle r="2" stroke="url(#g)" fill="url(#g)" stroke-width="2" stroke-opacity="0.9" filter="url(#motionBlurb)"><animateMotion dur="8s" begin="1.0s" repeatCount="indefinite" path="M 100 55 A 45 70 0 1 1 99.9 55"/></circle><circle r="2" stroke="url(#g)" fill="url(#g)" stroke-width="2" stroke-opacity="0.9" filter="url(#motionBlurb)"><animateMotion dur="8s" begin="1.15s" repeatCount="indefinite" path="M 100 55 A 45 70 0 1 1 99.9 55"/></circle><circle r="1" stroke="url(#g)" fill="url(#g)" stroke-width="1" stroke-opacity="0.9" filter="url(#motionBlurb)"><animateMotion dur="8s" begin="1.3s" repeatCount="indefinite" path="M 100 55 A 45 70 0 1 1 99.9 55"/></circle><animateTransform attributeName="patternTransform" type="translate" from="0 0" to="-205 0" dur="8s" repeatCount="indefinite"/></pattern><pattern id="stEntangled" patternUnits="userSpaceOnUse" width="205" height="205"><rect x="0" y="0" width="200" height="200" fill="none"/><circle r="6" stroke="url(#g)" fill="url(#g)" fill-opacity="1" cx="185" cy="185"><animate attributeName="cx" dur="8s" repeatCount="indefinite" keyTimes="0;0.25;0.5;0.75;1" values="185;185;100;185;185"/><animate attributeName="cy" dur="8s" repeatCount="indefinite" keyTimes="0;0.25;0.5;0.75;1" values="185;185;100;15;15"/></circle><circle r="6" stroke="url(#g)" fill="url(#g)" fill-opacity=".9" stroke-opacity=".9" cx="185" cy="185" filter="url(#motionBlurb)"><animate attributeName="cx" dur="8s" begin="0.25s" repeatCount="indefinite" keyTimes="0;0.25;0.5;0.75;1" values="185;185;100;185;185"/><animate attributeName="cy" dur="8s" begin="0.25s" repeatCount="indefinite" keyTimes="0;0.25;0.5;0.75;1" values="185;185;100;15;15"/></circle><circle r="5" stroke="url(#g)" fill="url(#g)" fill-opacity=".8" stroke-opacity=".8" cx="185" cy="185" filter="url(#motionBlurb)"><animate attributeName="cx" dur="8s" begin="0.5s" repeatCount="indefinite" keyTimes="0;0.25;0.5;0.75;1" values="185;185;100;185;185"/><animate attributeName="cy" dur="8s" begin="0.5s" repeatCount="indefinite" keyTimes="0;0.25;0.5;0.75;1" values="185;185;100;15;15"/></circle><circle r="5" stroke="url(#g)" fill="url(#g)" fill-opacity=".8" stroke-opacity=".8" cx="185" cy="185" filter="url(#motionBlurb)"><animate attributeName="cx" dur="8s" begin="0.75s" repeatCount="indefinite" keyTimes="0;0.25;0.5;0.75;1" values="185;185;100;185;185"/><animate attributeName="cy" dur="8s" begin="0.75s" repeatCount="indefinite" keyTimes="0;0.25;0.5;0.75;1" values="185;185;100;15;15"/></circle><circle r="3.9" stroke="url(#g)" fill="url(#g)" fill-opacity=".7" stroke-opacity=".7" cx="185" cy="185" filter="url(#motionBlurb)"><animate attributeName="cx" dur="8s" begin="1.0s" repeatCount="indefinite" keyTimes="0;0.25;0.5;0.75;1" values="185;185;100;185;185"/><animate attributeName="cy" dur="8s" begin="1.0s" repeatCount="indefinite" keyTimes="0;0.25;0.5;0.75;1" values="185;185;100;15;15"/></circle><circle r="3.9" stroke="url(#g)" fill="url(#g)" fill-opacity=".7" stroke-opacity=".7" cx="185" cy="185" filter="url(#motionBlurb)"><animate attributeName="cx" dur="8s" begin="1.25s" repeatCount="indefinite" keyTimes="0;0.25;0.5;0.75;1" values="185;185;100;185;185"/><animate attributeName="cy" dur="8s" begin="1.25s" repeatCount="indefinite" keyTimes="0;0.25;0.5;0.75;1" values="185;185;100;15;15"/></circle><circle r="6" stroke="url(#g)" fill="url(#g)" fill-opacity="1" cx="15" cy="185"><animate attributeName="cx" dur="8s" repeatCount="indefinite" keyTimes="0;0.25;0.5;0.75;1" values="15;15;100;15;15"/><animate attributeName="cy" dur="8s" repeatCount="indefinite" keyTimes="0;0.25;0.5;0.75;1" values="185;185;100;15;15"/></circle><circle r="6" stroke="url(#g)" fill="url(#g)" fill-opacity=".9" stroke-opacity=".9" cx="15" cy="185" filter="url(#motionBlurb)"><animate attributeName="cx" dur="8s" begin="0.25s" repeatCount="indefinite" keyTimes="0;0.25;0.5;0.75;1" values="15;15;100;15;15"/><animate attributeName="cy" dur="8s" begin="0.25s" repeatCount="indefinite" keyTimes="0;0.25;0.5;0.75;1" values="185;185;100;15;15"/></circle><circle r="5" cstroke="url(#g)" fill="url(#g)" fill-opacity=".8" stroke-opacity=".8" cx="15" cy="185" filter="url(#motionBlurb)"><animate attributeName="cx" dur="8s" begin="0.5s" repeatCount="indefinite" keyTimes="0;0.25;0.5;0.75;1" values="15;15;100;15;15"/><animate attributeName="cy" dur="8s" begin="0.5s" repeatCount="indefinite" keyTimes="0;0.25;0.5;0.75;1" values="185;185;100;15;15"/></circle><circle r="5" stroke="url(#g)" fill="url(#g)" fill-opacity=".8" stroke-opacity=".8" cx="15" cy="185" filter="url(#motionBlurb)"><animate attributeName="cx" dur="8s" begin="0.75s" repeatCount="indefinite" keyTimes="0;0.25;0.5;0.75;1" values="15;15;100;15;15"/><animate attributeName="cy" dur="8s" begin="0.75s" repeatCount="indefinite" keyTimes="0;0.25;0.5;0.75;1" values="185;185;100;15;15"/></circle><circle r="3.9" stroke="url(#g)" fill="url(#g)" fill-opacity=".7" stroke-opacity=".7" cx="15" cy="185" filter="url(#motionBlurb)"><animate attributeName="cx" dur="8s" begin="1.0s" repeatCount="indefinite" keyTimes="0;0.25;0.5;0.75;1" values="15;15;100;15;15"/><animate attributeName="cy" dur="8s" begin="1.0s" repeatCount="indefinite" keyTimes="0;0.25;0.5;0.75;1" values="185;185;100;15;15"/></circle><circle r="3.9" stroke="url(#g)" fill="url(#g)" fill-opacity=".7" stroke-opacity=".7" cx="15" cy="185" filter="url(#motionBlurb)"><animate attributeName="cx" dur="8s" begin="1.25s" repeatCount="indefinite" keyTimes="0;0.25;0.5;0.75;1" values="15;15;100;15;15"/><animate attributeName="cy" dur="8s" begin="1.25s" repeatCount="indefinite" keyTimes="0;0.25;0.5;0.75;1" values="185;185;100;15;15"/></circle><animateTransform attributeName="patternTransform" type="translate" from="-15 0" to="-205 -205" dur="8s" repeatCount="indefinite"/></pattern><pattern id="stDust" patternUnits="userSpaceOnUse" width="205" height="205"><rect x="0" y="0" width="200" height="200" fill="none"/><circle r="5" stroke="url(#g)" fill="url(#g)" fill-opacity="1.0" cx="170" cy="100"><animate attributeName="cx" dur="8s" repeatCount="indefinite" keyTimes="0;0.15;0.5;0.9;1" values="170;130;90;50;10"/></circle><circle r="4" stroke="url(#g)" fill="url(#g)" fill-opacity="1.0" cx="185" cy="100" filter="url(#motionBlurb)"><animate attributeName="cx" dur="8s" repeatCount="indefinite" keyTimes="0;0.15;0.5;0.9;1" values="185;145;105;65;25"/></circle><circle r="3" stroke="url(#g)" fill="url(#g)" fill-opacity="1.0" cx="200" cy="100" filter="url(#motionBlurb)"><animate attributeName="cx" dur="8s" repeatCount="indefinite" keyTimes="0;0.15;0.5;0.9;1" values="200;160;120;80;40"/></circle><circle r="5" stroke="url(#g)" fill="url(#g)" fill-opacity="1.0" cx="185" cy="35"><animate attributeName="cx" dur="8s" begin="0.2s" repeatCount="indefinite" keyTimes="0;0.05;0.5;0.95;1" values="185;160;135;110;85"/></circle><circle r="4" stroke="url(#g)" fill="url(#g)" fill-opacity="1.0" cx="200" cy="35" filter="url(#motionBlurb)"><animate attributeName="cx" dur="8s" begin="0.2s" repeatCount="indefinite" keyTimes="0;0.05;0.5;0.95;1" values="200;175;150;125;100"/></circle><circle r="3" stroke="url(#g)" fill="url(#g)" fill-opacity="1.0" cx="50" cy="20"><animate attributeName="cx" dur="8s" begin="0.4s" repeatCount="indefinite" keyTimes="0;0.05;0.5;0.95;1" values="50;40;30;20;10"/></circle><circle r="3" stroke="url(#g)" fill="url(#g)" fill-opacity="1.0" cx="30" cy="90"><animate attributeName="cx" dur="8s" begin="0.4s" repeatCount="indefinite" keyTimes="0;0.05;0.5;0.95;1" values="30;25;20;15;10"/></circle><circle r="3" stroke="url(#g)" fill="url(#g)" fill-opacity="1.0" cx="150" cy="170"><animate attributeName="cx" dur="8s" begin="0.4s" repeatCount="indefinite" keyTimes="0;0.05;0.5;0.95;1" values="150;140;130;120;110"/></circle><circle r="3" stroke="url(#g)" fill="url(#g)" fill-opacity="1.0" cx="170" cy="70"><animate attributeName="cx" dur="8s" begin="0.4s" repeatCount="indefinite" keyTimes="0;0.05;0.5;0.95;1" values="170;160;150;140;130"/></circle><circle r="3" stroke="url(#g)" fill="url(#g)" fill-opacity="1.0" cx="90" cy="120"><animate attributeName="cx" dur="8s" begin="0.4s" repeatCount="indefinite" keyTimes="0;0.05;0.5;0.95;1" values="70;60;50;40;30"/></circle><circle r="3" stroke="url(#g)" fill="url(#g)" fill-opacity="1.0" cx="60" cy="190"><animate attributeName="cx" dur="8s" begin="0.4s" repeatCount="indefinite" keyTimes="0;0.05;0.5;0.95;1" values="60;50;40;30;20"/></circle><animateTransform attributeName="patternTransform" type="translate" from="0 0" to="-200 0" dur="8s" repeatCount="indefinite"/></pattern><filter id="motionBlur" filterUnits="userSpaceOnUse"><feGaussianBlur stdDeviation="15" /></filter><filter id="motionBlurb" filterUnits="userSpaceOnUse"><feGaussianBlur stdDeviation="5" /></filter></defs><g><g id="village-location"><path d="M 714 964 L 964 944 L 1044 994 L 1114 1004 L 1204 1024 L 1272 1054 L 1250 1114 L 894 1114 L 714 1114 L 664 1074 L 714 1024 Z" fill="none" stroke="url(#g)" stroke-width="32" opacity="0.0" filter="url(#motionBlur2)"><animate attributeName="opacity" dur="8s" begin="0s" keyTimes="0;0.5;0.6;0.7;0.8;0.9;1" values="0;0;0.5;1;0.5;0;0" repeatCount="indefinite"/></path></g><g id="town-location"><defs><g id="car-trail-town-1" stroke-width="32"><path d="M 714 964 L 964 944 L 1044 994 L 1114 1004 L 1204 1024 L 1272 1054 L 1250 1114 L 894 1114 L 714 1114 L 664 1074 L 714 1024 Z" fill="none" stroke="url(#g)" filter="url(#motionBlur2)"/></g><g id="car-trail-town-2" stroke-width="24" opacity="0.6"><path d="M 614 964 L 864 944 L 944 994 L 1014 1004 L 1104 1024 L 1172 1054 L 1150 1114 L 794 1114 L 614 1114 L 564 1074 L 614 1024 Z" fill="none" stroke="url(#g)"/></g></defs><g opacity="0.0"><use href="#car-trail-town-1"/><use href="#car-trail-town-2"/><animate attributeName="opacity" dur="8s" begin="0s" keyTimes="0;0.5;0.6;0.7;0.8;0.9;1" values="0;0;0.5;1;0.5;0;0" repeatCount="indefinite"/></g></g><g id="city-location"><defs><g id="car-trail-city-1" stroke-width="32"><path d="M 714 964 L 964 944 L 1044 994 L 1114 1004 L 1204 1024 L 1272 1054 L 1250 1114 L 894 1114 L 714 1114 L 664 1074 L 714 1024 Z" fill="none" stroke="url(#g)" filter="url(#motionBlur2)"/></g><g id="car-trail-city-2" stroke-width="24" opacity="0.6"><path d="M 614 964 L 864 944 L 944 994 L 1014 1004 L 1104 1024 L 1172 1054 L 1150 1114 L 794 1114 L 614 1114 L 564 1074 L 614 1024 Z" fill="none" stroke="url(#g)"/></g><g id="car-trail-city-3" stroke-width="20" opacity="0.4"><path d="M 514 964 L 764 944 L 844 994 L 914 1004 L 1004 1024 L 1072 1054 L 1050 1114 L 694 1114 L 514 1114 L 464 1074 L 514 1024 Z" fill="none" stroke="url(#g)"/></g></defs><g opacity="0.0"><use href="#car-trail-city-1"/><use href="#car-trail-city-2"/><use href="#car-trail-city-3"/><animate attributeName="opacity" dur="8s" begin="0s" keyTimes="0;0.5;0.6;0.7;0.8;0.9;1" values="0;0;0.5;1;0.5;0;0" repeatCount="indefinite"/></g></g><g id="metropolis-location"><defs><g id="car-trail-metropolis-1" stroke-width="32"><path d="M 714 964 L 964 944 L 1044 994 L 1114 1004 L 1204 1024 L 1272 1054 L 1250 1114 L 894 1114 L 714 1114 L 664 1074 L 714 1024 Z" fill="none" stroke="url(#g)" filter="url(#motionBlur2)"/></g><g id="car-trail-metropolis-2" stroke-width="24" opacity="0.6"><path d="M 614 964 L 864 944 L 944 994 L 1014 1004 L 1104 1024 L 1172 1054 L 1150 1114 L 794 1114 L 614 1114 L 564 1074 L 614 1024 Z" fill="none" stroke="url(#g)"/></g><g id="car-trail-metropolis-3" stroke-width="20" opacity="0.4"><path d="M 514 964 L 764 944 L 844 994 L 914 1004 L 1004 1024 L 1072 1054 L 1050 1114 L 694 1114 L 514 1114 L 464 1074 L 514 1024 Z" fill="none" stroke="url(#g)"/></g><g id="car-trail-metropolis-4" stroke-width="16" opacity="0.2"><path d="M 414 964 L 664 944 L 744 994 L 814 1004 L 904 1024 L 972 1054 L 950 1114 L 594 1114 L 414 1114 L 364 1074 L 414 1024 Z" fill="none" stroke="url(#g)"/></g></defs><g opacity="0.0"><use href="#car-trail-metropolis-1"/><use href="#car-trail-metropolis-2"/><use href="#car-trail-metropolis-3"/><use href="#car-trail-metropolis-4"/><animate attributeName="opacity" dur="8s" begin="0s" keyTimes="0;0.5;0.6;0.7;0.8;0.9;1" values="0;0;0.5;1;0.5;0;0" repeatCount="indefinite"/></g></g><g id="megalopolis-location"><defs><g id="car-trail-megalopolis-1" stroke-width="32"><path d="M 714 964 L 964 944 L 1044 994 L 1114 1004 L 1204 1024 L 1272 1054 L 1250 1114 L 894 1114 L 714 1114 L 664 1074 L 714 1024 Z" fill="none" stroke="url(#g)" filter="url(#motionBlur2)"/></g><g id="car-trail-megalopolis-2" stroke-width="24" opacity="0.6"><path d="M 614 964 L 864 944 L 944 994 L 1014 1004 L 1104 1024 L 1172 1054 L 1150 1114 L 794 1114 L 614 1114 L 564 1074 L 614 1024 Z" fill="none" stroke="url(#g)"/></g><g id="car-trail-megalopolis-3" stroke-width="20" opacity="0.4"><path d="M 514 964 L 764 944 L 844 994 L 914 1004 L 1004 1024 L 1072 1054 L 1050 1114 L 694 1114 L 514 1114 L 464 1074 L 514 1024 Z" fill="none" stroke="url(#g)"/></g><g id="car-trail-megalopolis-4" stroke-width="16" opacity="0.2"><path d="M 414 964 L 664 944 L 744 994 L 814 1004 L 904 1024 L 972 1054 L 950 1114 L 594 1114 L 414 1114 L 364 1074 L 414 1024 Z" fill="none" stroke="url(#g)"/></g><g id="car-trail-megalopolis-5" stroke-width="12" opacity="0.1"><path d="M 314 964 L 564 944 L 644 994 L 714 1004 L 804 1024 L 872 1054 L 850 1114 L 494 1114 L 314 1114 L 264 1074 L 314 1024 Z" fill="none" stroke="url(#g)"/></g></defs><g opacity="0.0"><use href="#car-trail-megalopolis-1"/><use href="#car-trail-megalopolis-2"/><use href="#car-trail-megalopolis-3"/><use href="#car-trail-megalopolis-4"/><use href="#car-trail-megalopolis-5"/><animate attributeName="opacity" dur="8s" begin="0s" keyTimes="0;0.5;0.6;0.7;0.8;0.9;1" values="0;0;0.5;1;0.5;0;0" repeatCount="indefinite"/></g></g><g id="village-location"><path d="M 524 874 L 844 874 L 934 874 L 1224 874 L 1314 874 L 1359 874 L 1414 934 L 1434 1094 L 1414 1174 L 934 1174 L 844 1174 L 524 1174 Z" fill="none" stroke="url(#g)" stroke-width="32" opacity="0.0"><animate attributeName="opacity" dur="8s" begin="0s" keyTimes="0;0.3;0.4;0.5;0.6;0.7;1" values="0;0;0.5;1;0.5;0;0" repeatCount="indefinite"/></path></g><g id="town-location"><defs><g id="bus-trail-town-1" stroke-width="32"><path d="M 524 874 L 844 874 L 934 874 L 1224 874 L 1314 874 L 1359 874 L 1414 934 L 1434 1094 L 1414 1174 L 934 1174 L 844 1174 L 524 1174 Z" fill="none" stroke="url(#g)"/></g><g id="bus-trail-town-2" stroke-width="24" opacity="0.6"><path d="M 424 874 L 744 874 L 834 874 L 1124 874 L 1214 874 L 1259 874 L 1314 934 L 1334 1094 L 1314 1174 L 834 1174 L 744 1174 L 424 1174 Z" fill="none" stroke="url(#g)"/></g></defs><g opacity="0.0"><use href="#bus-trail-town-1"/><use href="#bus-trail-town-2"/><animate attributeName="opacity" dur="8s" begin="0s" keyTimes="0;0.3;0.4;0.5;0.6;0.7;1" values="0;0;0.5;1;0.5;0;0" repeatCount="indefinite"/></g></g><g id="city-location"><defs><g id="bus-trail-city-1" stroke-width="32"><path d="M 524 874 L 844 874 L 934 874 L 1224 874 L 1314 874 L 1359 874 L 1414 934 L 1434 1094 L 1414 1174 L 934 1174 L 844 1174 L 524 1174 Z" fill="none" stroke="url(#g)"/></g><g id="bus-trail-city-2" stroke-width="24" opacity="0.6"><path d="M 424 874 L 744 874 L 834 874 L 1124 874 L 1214 874 L 1259 874 L 1314 934 L 1334 1094 L 1314 1174 L 834 1174 L 744 1174 L 424 1174 Z" fill="none" stroke="url(#g)"/></g><g id="bus-trail-city-3" stroke-width="20" opacity="0.4"><path d="M 324 874 L 644 874 L 734 874 L 1024 874 L 1114 874 L 1159 874 L 1214 934 L 1234 1094 L 1214 1174 L 734 1174 L 644 1174 L 324 1174 Z" fill="none" stroke="url(#g)"/></g></defs><g opacity="0.0"><use href="#bus-trail-city-1"/><use href="#bus-trail-city-2"/><use href="#bus-trail-city-3"/><animate attributeName="opacity" dur="8s" begin="0s" keyTimes="0;0.3;0.4;0.5;0.6;0.7;1" values="0;0;0.5;1;0.5;0;0" repeatCount="indefinite"/></g></g><g id="metropolis-location"><defs><g id="bus-trail-metropolis-1" stroke-width="32"><path d="M 524 874 L 844 874 L 934 874 L 1224 874 L 1314 874 L 1359 874 L 1414 934 L 1434 1094 L 1414 1174 L 934 1174 L 844 1174 L 524 1174 Z" fill="none" stroke="url(#g)"/></g><g id="bus-trail-metropolis-2" stroke-width="24" opacity="0.6"><path d="M 424 874 L 744 874 L 834 874 L 1124 874 L 1214 874 L 1259 874 L 1314 934 L 1334 1094 L 1314 1174 L 834 1174 L 744 1174 L 424 1174 Z" fill="none" stroke="url(#g)"/></g><g id="bus-trail-metropolis-3" stroke-width="20" opacity="0.4"><path d="M 324 874 L 644 874 L 734 874 L 1024 874 L 1114 874 L 1159 874 L 1214 934 L 1234 1094 L 1214 1174 L 734 1174 L 644 1174 L 324 1174 Z" fill="none" stroke="url(#g)"/></g><g id="bus-trail-metropolis-4" stroke-width="16" opacity="0.2"><path d="M 224 874 L 544 874 L 634 874 L 924 874 L 1014 874 L 1059 874 L 1114 934 L 1134 1094 L 1114 1174 L 634 1174 L 544 1174 L 224 1174 Z" fill="none" stroke="url(#g)"/></g></defs><g opacity="0.0"><use href="#bus-trail-metropolis-1"/><use href="#bus-trail-metropolis-2"/><use href="#bus-trail-metropolis-3"/><use href="#bus-trail-metropolis-4"/><animate attributeName="opacity" dur="8s" begin="0s" keyTimes="0;0.3;0.4;0.5;0.6;0.7;1" values="0;0;0.5;1;0.5;0;0" repeatCount="indefinite"/></g></g><g id="megalopolis-location"><defs><g id="bus-trail-megalopolis-1" stroke-width="32"><path d="M 524 874 L 844 874 L 934 874 L 1224 874 L 1314 874 L 1359 874 L 1414 934 L 1434 1094 L 1414 1174 L 934 1174 L 844 1174 L 524 1174 Z" fill="none" stroke="url(#g)"/></g><g id="bus-trail-megalopolis-2" stroke-width="24" opacity="0.6"><path d="M 424 874 L 744 874 L 834 874 L 1124 874 L 1214 874 L 1259 874 L 1314 934 L 1334 1094 L 1314 1174 L 834 1174 L 744 1174 L 424 1174 Z" fill="none" stroke="url(#g)"/></g><g id="bus-trail-megalopolis-3" stroke-width="20" opacity="0.4"><path d="M 324 874 L 644 874 L 734 874 L 1024 874 L 1114 874 L 1159 874 L 1214 934 L 1234 1094 L 1214 1174 L 734 1174 L 644 1174 L 324 1174 Z" fill="none" stroke="url(#g)"/></g><g id="bus-trail-megalopolis-4" stroke-width="16" opacity="0.2"><path d="M 224 874 L 544 874 L 634 874 L 924 874 L 1014 874 L 1059 874 L 1114 934 L 1134 1094 L 1114 1174 L 634 1174 L 544 1174 L 224 1174 Z" fill="none" stroke="url(#g)"/></g><g id="bus-trail-megalopolis-5" stroke-width="12" opacity="0.1"><path d="M 124 874 L 444 874 L 534 874 L 824 874 L 914 874 L 959 874 L 1014 934 L 1034 1094 L 1014 1174 L 534 1174 L 444 1174 L 124 1174 Z" fill="none" stroke="url(#g)"/></g></defs><g opacity="0.0"><use href="#bus-trail-megalopolis-1"/><use href="#bus-trail-megalopolis-2"/><use href="#bus-trail-megalopolis-3"/><use href="#bus-trail-megalopolis-4"/><use href="#bus-trail-megalopolis-5"/><animate attributeName="opacity" dur="8s" begin="0s" keyTimes="0;0.3;0.4;0.5;0.6;0.7;1" values="0;0;0.5;1;0.5;0;0" repeatCount="indefinite"/></g></g><g id="village-location"><path d="M 324 874 L 844 874 L 934 874 L 1514 874 L 1514 874 L 1564 964 L 1704 1024 L 1722 1084 L 1604 1174 L 934 1174 L 844 1174 L 324 1174 Z" fill="none" stroke="url(#g)" stroke-width="32" opacity="0.0"><animate attributeName="opacity" dur="8s" begin="0s" keyTimes="0;0.1;0.2;0.3;0.4;0.5;1" values="0;0;0.5;1;0.5;0;0" repeatCount="indefinite"/></path></g><g id="town-location"><defs><g id="train-trail-town-1" stroke-width="32"><path d="M 324 874 L 844 874 L 934 874 L 1514 874 L 1514 874 L 1564 964 L 1704 1024 L 1722 1084 L 1604 1174 L 934 1174 L 844 1174 L 324 1174 Z" fill="none" stroke="url(#g)"/></g><g id="train-trail-town-2" stroke-width="24" opacity="0.6"><path d="M 224 874 L 744 874 L 834 874 L 1414 874 L 1414 874 L 1464 964 L 1604 1024 L 1622 1084 L 1504 1174 L 834 1174 L 744 1174 L 224 1174 Z" fill="none" stroke="url(#g)"/></g></defs><g opacity="0.0"><use href="#train-trail-town-1"/><use href="#train-trail-town-2"/><animate attributeName="opacity" dur="8s" begin="0s" keyTimes="0;0.1;0.2;0.3;0.4;0.5;1" values="0;0;0.5;1;0.5;0;0" repeatCount="indefinite"/></g></g><g id="city-location"><defs><g id="train-trail-city-1" stroke-width="32"><path d="M 324 874 L 844 874 L 934 874 L 1514 874 L 1514 874 L 1564 964 L 1704 1024 L 1722 1084 L 1604 1174 L 934 1174 L 844 1174 L 324 1174 Z" fill="none" stroke="url(#g)"/></g><g id="train-trail-city-2" stroke-width="24" opacity="0.6"><path d="M 224 874 L 744 874 L 834 874 L 1414 874 L 1414 874 L 1464 964 L 1604 1024 L 1622 1084 L 1504 1174 L 834 1174 L 744 1174 L 224 1174 Z" fill="none" stroke="url(#g)"/></g><g id="train-trail-city-3" stroke-width="20" opacity="0.4"><path d="M 124 874 L 644 874 L 734 874 L 1314 874 L 1314 874 L 1364 964 L 1504 1024 L 1522 1084 L 1404 1174 L 734 1174 L 644 1174 L 124 1174 Z" fill="none" stroke="url(#g)"/></g></defs><g opacity="0.0"><use href="#train-trail-city-1"/><use href="#train-trail-city-2"/><use href="#train-trail-city-3"/><animate attributeName="opacity" dur="8s" begin="0s" keyTimes="0;0.1;0.2;0.3;0.4;0.5;1" values="0;0;0.5;1;0.5;0;0" repeatCount="indefinite"/></g></g><g id="metropolis-location"><defs><g id="train-trail-metropolis-1" stroke-width="32"><path d="M 324 874 L 844 874 L 934 874 L 1514 874 L 1514 874 L 1564 964 L 1704 1024 L 1722 1084 L 1604 1174 L 934 1174 L 844 1174 L 324 1174 Z" fill="none" stroke="url(#g)"/></g><g id="train-trail-metropolis-2" stroke-width="24" opacity="0.6"><path d="M 224 874 L 744 874 L 834 874 L 1414 874 L 1414 874 L 1464 964 L 1604 1024 L 1622 1084 L 1504 1174 L 834 1174 L 744 1174 L 224 1174 Z" fill="none" stroke="url(#g)"/></g><g id="train-trail-metropolis-3" stroke-width="20" opacity="0.4"><path d="M 124 874 L 644 874 L 734 874 L 1314 874 L 1314 874 L 1364 964 L 1504 1024 L 1522 1084 L 1404 1174 L 734 1174 L 644 1174 L 124 1174 Z" fill="none" stroke="url(#g)"/></g><g id="train-trail-metropolis-4" stroke-width="16" opacity="0.2"><path d="M 24 874 L 544 874 L 634 874 L 1214 874 L 1214 874 L 1264 964 L 1404 1024 L 1422 1084 L 1304 1174 L 634 1174 L 544 1174 L 24 1174 Z" fill="none" stroke="url(#g)"/></g></defs><g opacity="0.0"><use href="#train-trail-metropolis-1"/><use href="#train-trail-metropolis-2"/><use href="#train-trail-metropolis-3"/><use href="#train-trail-metropolis-4"/><animate attributeName="opacity" dur="8s" begin="0s" keyTimes="0;0.1;0.2;0.3;0.4;0.5;1" values="0;0;0.5;1;0.5;0;0" repeatCount="indefinite"/></g></g><g id="megalopolis-location"><defs><g id="train-trail-1" stroke-width="32"><path d="M 324 874 L 844 874 L 934 874 L 1514 874 L 1514 874 L 1564 964 L 1704 1024 L 1722 1084 L 1604 1174 L 934 1174 L 844 1174 L 324 1174 Z" fill="none" stroke="url(#g)"/></g><g id="train-trail-2" stroke-width="24" opacity="0.6"><path d="M 224 874 L 744 874 L 834 874 L 1414 874 L 1414 874 L 1464 964 L 1604 1024 L 1622 1084 L 1504 1174 L 834 1174 L 744 1174 L 224 1174 Z" fill="none" stroke="url(#g)"/></g><g id="train-trail-3" stroke-width="20" opacity="0.4"><path d="M 124 874 L 644 874 L 734 874 L 1314 874 L 1314 874 L 1364 964 L 1504 1024 L 1522 1084 L 1404 1174 L 734 1174 L 644 1174 L 124 1174 Z" fill="none" stroke="url(#g)"/></g><g id="train-trail-4" stroke-width="16" opacity="0.2"><path d="M 24 874 L 544 874 L 634 874 L 1214 874 L 1214 874 L 1264 964 L 1404 1024 L 1422 1084 L 1304 1174 L 634 1174 L 544 1174 L 24 1174 Z" fill="none" stroke="url(#g)"/></g><g id="train-trail-5" stroke-width="12" opacity="0.1"><path d="M -76 874 L 444 874 L 534 874 L 1114 874 L 1114 874 L 1164 964 L 1304 1024 L 1322 1084 L 1204 1174 L 534 1174 L 444 1174 L -76 1174 Z" fill="none" stroke="url(#g)"/></g></defs><g opacity="0.0"><use href="#train-trail-1"/><use href="#train-trail-2"/><use href="#train-trail-3"/><use href="#train-trail-4"/><use href="#train-trail-5"/><animate attributeName="opacity" dur="8s" begin="0s" keyTimes="0;0.1;0.2;0.3;0.4;0.5;1" values="0;0;0.5;1;0.5;0;0" repeatCount="indefinite"/></g></g></g></svg>
"}; let _seed; let vehicles = []; const vehicleTypes = ["train", "bus", "car"]; const morphDuration = 120; let numTrains; const trainLength = 100; const trainHeight = 20; let bgs; // Background settings object let rAlpha; // Random alpha factor for backgrounds let entropyType; let bgTrait; // Sky trait let st; // Spacetime settings object let pBgo = 0, pMgo = 0, pFgo = 0; // Parallax offsets const tsBg = 100, tsMg = 100, tsFg = 100; // Tile sizes const pBgsp = 0.2, pMgsp = 0.5, pFgsp = 1.0; // Parallax speeds let basesp; // Base speed for vehicles const COLOR_CHANGE_COOLDOWN = 180; const COLOR_LERP_DURATION = 60; let lastColorChangeFrame = -COLOR_CHANGE_COOLDOWN; let colorTransitionTarget = null; let colorTransitionStartColors = {}; let colorTransitionProgress = 1; const { PI, sin, cos, floor, round, abs, sqrt, max, min } = Math; const TWO_PI = 2 * PI; function map(value, start1, stop1, start2, stop2) { return start2 + (stop2 - start2) * ((value - start1) / (stop1 - start1)); } function lerp(start, stop, amt) { return start + (stop - start) * amt; } function easeInOut(t) { return t < 0.5 ? 2 * t * t : -1 + (4 - 2 * t) * t; } function rand() { _seed ^= _seed << 13; _seed ^= _seed >>> 17; _seed ^= _seed << 5; return (_seed >>> 0) / 4294967296; } function random(a, b) { if (a === undefined) return rand(); if (b === undefined) { b = a; a = 0; } return rand() * (b - a) + a; } const hl = { randomElement: arr => arr[floor(rand() * arr.length)] }; const PERLIN_YWRAPB = 4; const PERLIN_YWRAP = 1 << PERLIN_YWRAPB; const PERLIN_SIZE = 4095; const PERLIN_OCTAVES = 4; const PERLIN_AMP_FALLOFF = 0.5; let perlin_noise_array; function seedNoise() { perlin_noise_array = new Array(PERLIN_SIZE + 1); for (let i_pn = 0; i_pn < PERLIN_SIZE + 1; i_pn++) { perlin_noise_array[i_pn] = floor(random(256)); } } const scaled_cosine = (i_sc) => 0.5 * (1.0 - cos(i_sc * PI)); function noise(x_noise, y_noise = 0) { if (perlin_noise_array === undefined) { seedNoise(); } if (x_noise < 0) x_noise = -x_noise; if (y_noise < 0) y_noise = -y_noise; let xi_noise = floor(x_noise); let yi_noise = floor(y_noise); let xf_noise = x_noise - xi_noise; let yf_noise = y_noise - yi_noise; let rxf_noise, ryf_noise; let r_noise = 0; let ampl_noise = 0.5; let n1_noise, n2_noise; for (let o_noise = 0; o_noise < PERLIN_OCTAVES; o_noise++) { let of_noise = xi_noise + (yi_noise << PERLIN_YWRAPB); rxf_noise = scaled_cosine(xf_noise); ryf_noise = scaled_cosine(yf_noise); n1_noise = perlin_noise_array[of_noise & PERLIN_SIZE] / 255.0; n1_noise += rxf_noise * ((perlin_noise_array[(of_noise + 1) & PERLIN_SIZE] / 255.0) - n1_noise); n2_noise = perlin_noise_array[(of_noise + PERLIN_YWRAP) & PERLIN_SIZE] / 255.0; n2_noise += rxf_noise * ((perlin_noise_array[(of_noise + PERLIN_YWRAP + 1) & PERLIN_SIZE] / 255.0) - n2_noise); n1_noise += ryf_noise * (n2_noise - n1_noise); r_noise += n1_noise * ampl_noise; ampl_noise *= PERLIN_AMP_FALLOFF; xi_noise <<= 1; xf_noise *= 2; yi_noise <<= 1; yf_noise *= 2; if (xf_noise >= 1.0) { xi_noise++; xf_noise--; } if (yf_noise >= 1.0) { yi_noise++; yf_noise--; } } return max(0, min(1, r_noise)); } function parseColor(c) { if (typeof c === 'string' && c.startsWith('#')) { let bigint = parseInt(c.slice(1), 16); return { r: (bigint >> 16) & 255, g: (bigint >> 8) & 255, b: bigint & 255, a: 1 }; } else if (Array.isArray(c)) { let [h, s, b_val, a_val] = c; h %= 360; s /= 100; b_val /= 100; a_val = (a_val === undefined) ? 1 : a_val; let i = floor(h / 60), f = h / 60 - i, p = b_val * (1 - s), q = b_val * (1 - f * s), t = b_val * (1 - (1 - f) * s); let r_rgb, g_rgb, b_rgb_val; switch (i % 6) { case 0: r_rgb = b_val; g_rgb = t; b_rgb_val = p; break; case 1: r_rgb = q; g_rgb = b_val; b_rgb_val = p; break; case 2: r_rgb = p; g_rgb = b_val; b_rgb_val = t; break; case 3: r_rgb = p; g_rgb = q; b_rgb_val = b_val; break; case 4: r_rgb = t; g_rgb = p; b_rgb_val = b_val; break; case 5: r_rgb = b_val; g_rgb = p; b_rgb_val = q; break; default: r_rgb = 0; g_rgb = 0; b_rgb_val = 0; } return { r: r_rgb * 255, g: g_rgb * 255, b: b_rgb_val * 255, a: a_val }; } else if (typeof c === 'object' && c !== null && 'r' in c && 'g' in c && 'b' in c) { return { ...c, a: c.a === undefined ? 1 : c.a }; } return { r: 0, g: 0, b: 0, a: 1 }; } function toCanvasRGBA(rgba) { return `rgba(${round(rgba.r)},${round(rgba.g)},${round(rgba.b)},${rgba.a})`; } function lerpColor(color1, color2, amt) { let c1 = parseColor(color1); let c2 = parseColor(color2); return { r: lerp(c1.r, c2.r, amt), g: lerp(c1.g, c2.g, amt), b: lerp(c1.b, c2.b, amt), a: lerp(c1.a, c2.a, amt) }; } function color(...args) { if (args.length === 1) return parseColor(args[0]); if (args.length >= 3) return parseColor([args[0], args[1], args[2], args[3]]); return parseColor(null); } class MorphingVehicle { constructor(x, y, currentBasesp) { this.x = x; this.y = y; this.baseLength = trainLength; this.baseHeight = trainHeight; this.sp = random(currentBasesp, currentBasesp * 2); this.color = color(hl.randomElement(bgs.trc)); this.baseY = y; this.fadeInStart = frameCount; this.fadeInDuration = random(30, 90); this.fadeOutStart = frameCount + random(300, 900); this.fadeOutDuration = random(60, 120); this.isMorphing = false; this.holdDuration = floor(random(60, 240)); this.holdCounter = 0; this.currentType = hl.randomElement(vehicleTypes); this.nextType = this.getNextType(); this.morphProgress = 0; this.vertices = this.getShapeVertices(this.currentType); this.targetVertices = this.getShapeVertices(this.nextType); this.fixVertexCount(); } update() { this.x += this.sp; if (entropyType === "Wabisabi") { this.y = this.baseY + map(noise(this.x * 0.005, frameCount * 0.003), 0, 1, -10, 10); this.x += map(noise(this.x * 0.007, frameCount * 0.003), 0, 1, -2, 2); } else if (entropyType === "Freestyle") { this.y = this.baseY + map(noise(this.x * 0.005, frameCount * 0.005), 0, 1, -50, 50); this.x += map(noise(this.x * 0.003, frameCount * 0.005), 0, 1, -3, 3); } if (entropyType === "Balance") { this.y = this.baseY + sin(frameCount * 0.05 + this.x * 0.01) * 20; } if (this.x > width + this.baseLength || frameCount >= this.fadeOutStart + this.fadeOutDuration) { this.reset(); return; } if (!this.isMorphing) { this.holdCounter++; if (this.holdCounter >= this.holdDuration) { this.isMorphing = true; this.holdCounter = 0; } } else { this.morphProgress += 1 / morphDuration; if (this.morphProgress >= 1) { this.currentType = this.nextType; this.vertices = this.targetVertices; this.nextType = this.getNextType(); this.targetVertices = this.getShapeVertices(this.nextType); this.fixVertexCount(); this.morphProgress = 0; this.isMorphing = false; this.holdDuration = floor(random(60, 240)); } } } display() { let alpha; if (frameCount < this.fadeInStart + this.fadeInDuration) alpha = map(frameCount, this.fadeInStart, this.fadeInStart + this.fadeInDuration, 0, 1); else if (frameCount < this.fadeOutStart) alpha = 1; else if (frameCount < this.fadeOutStart + this.fadeOutDuration) alpha = map(frameCount, this.fadeOutStart, this.fadeOutStart + this.fadeOutDuration, 1, 0); else alpha = 0; if (alpha <= 0) return; let morphedVertices = this.vertices.map((v, i) => ({ x: lerp(v.x, this.targetVertices[i].x, easeInOut(this.morphProgress)), y: lerp(v.y, this.targetVertices[i].y, easeInOut(this.morphProgress)) })); let finalColor = { ...this.color, a: this.color.a * alpha }; ctx.strokeStyle = toCanvasRGBA(finalColor); ctx.lineWidth = 3; ctx.fillStyle = 'transparent'; ctx.beginPath(); if (morphedVertices.length > 0) { ctx.moveTo(this.x + morphedVertices[0].x, this.y + morphedVertices[0].y); for (let i = 1; i < morphedVertices.length; i++) { ctx.lineTo(this.x + morphedVertices[i].x, this.y + morphedVertices[i].y); } } ctx.closePath(); ctx.stroke(); } reset() { this.x = random(-this.baseLength, width); this.y = random(height * 0.05, height * 0.95); this.baseY = this.y; this.sp = random(basesp, basesp * 2); this.color = color(hl.randomElement(bgs.trc)); this.fadeInStart = frameCount; this.fadeInDuration = random(30, 90); this.fadeOutStart = frameCount + random(300, 900); this.fadeOutDuration = random(60, 120); this.currentType = hl.randomElement(vehicleTypes); this.nextType = this.getNextType(); this.morphProgress = 0; this.isMorphing = false; this.holdCounter = 0; this.holdDuration = floor(random(60, 240)); this.vertices = this.getShapeVertices(this.currentType); this.targetVertices = this.getShapeVertices(this.nextType); this.fixVertexCount(); } getNextType() { return vehicleTypes[(vehicleTypes.indexOf(this.currentType) + 1) % vehicleTypes.length]; } getShapeVertices(type) { let L = this.baseLength, H = this.baseHeight; if (type === "train") return [{x:-L,y:-H*.5},{x:-L*.3,y:-H*.5},{x:-L*.15,y:-H*.5},{x:L*.15,y:-H*.5},{x:L*.2,y:-H*.5},{x:L*.25,y:-H*.2},{x:L*.35,y:0},{x:L*.38,y:H*.2},{x:L*.3,y:H*.5},{x:-L*.15,y:H*.5},{x:-L*.3,y:H*.5},{x:-L,y:H*.5}]; if (type === "bus") return [{x:-L*.5,y:-H*.5},{x:-L*.3,y:-H*.5},{x:-L*.15,y:-H*.5},{x:0,y:-H*.5},{x:L*.15,y:-H*.5},{x:L*.25,y:-H*.5},{x:L*.3,y:-H*.3},{x:L*.32,y:H*.3},{x:L*.3,y:H*.5},{x:-L*.15,y:H*.5},{x:-L*.3,y:H*.5},{x:-L*.5,y:H*.5}]; if (type === "car") return [{x:-L*.3,y:-H*.35},{x:-L*.1,y:-H*.5},{x:0,y:-H*.5},{x:L*.1,y:-H*.2},{x:L*.2,y:-H*.1},{x:L*.27,y:H*.1},{x:L*.25,y:H*.3},{x:L*.1,y:H*.3},{x:-L*.1,y:H*.3},{x:-L*.3,y:H*.3},{x:-L*.35,y:H*.1},{x:-L*.3,y:-H*.1}]; return []; } fixVertexCount() { let maxLen = max(this.vertices.length, this.targetVertices.length); while (this.vertices.length < maxLen) this.vertices.push({ ...this.vertices[this.vertices.length - 1] }); while (this.targetVertices.length < maxLen) this.targetVertices.push({ ...this.targetVertices[this.targetVertices.length - 1] }); } } let effectStates = {}; function initializeArtwork() { // Read data injected by the smart contract const traits = window.GOM_TRAITS; if (!traits || !traits.hash || !traits.rand_indices) { document.body.innerHTML = `<pre style="color:red;">Error: Trait data not found.</pre>`; return; } const rand_indices = traits.rand_indices.split(',').map(n => parseInt(n)); _seed = parseInt(traits.hash.slice(2, 18), 16); perlin_noise_array = undefined; // --- START: Trait Generation using On-Chain Indices --- const numTrainsOptions = [1,1,3,3,3,3,3,11,11,11,11,11,11,11,11,11,21,21,21,33]; numTrains = numTrainsOptions[rand_indices[0]]; const rAlphaOptions = [37, 38, 39]; rAlpha = rAlphaOptions[rand_indices[1]] / 1000.0; const bgsOptions = [ { sn: "Kabuki", trc: ["#fa4e28","#A10D2E","#E63946","#F4A261","#f0d507"], bgt_raw: [240,77,28], bgb_raw: [240,70,39], trailColor: "#B51A15"}, { sn: "Diamond Sky", trc: ["#a7fae7","#fca9e3","#b97af5","#f2ffed","#ff6b84"], bgt_raw: [199,100.0,98.04], bgb_raw: [197,87,98], trailColor: "#fcfcfc"}, { sn: "Red Silk", trc: ["#ff6b84","#ff1c1c","#ffc505","#e4b7e8","#f2e8b6"], bgt_raw: [358,94.44,35], bgb_raw: [355,70.0,25], trailColor: "#fcd4d4"}, { sn: "Green Tea", trc: ["#a34ea3","#e4b7e8","#aae6e6","#9e9ef7","#f5c4c4"], bgt_raw: [111,50,60], bgb_raw: [111,58,73], trailColor: "#EA1DC3"}, { sn: "Sand Wave", trc: ["#dbf1ff","#F2EBEF","#00acd0","#6270a3","#026bc7"], bgt_raw: [50,50,65], bgb_raw: [50,50,77], trailColor: "#afe3ed"}, { sn: "Whispers of History", trc: ["#f51b05","#a60228","#343deb","#f5f0f0","#202691"], bgt_raw: [220,15,5], bgb_raw: [355,96,18], trailColor: "#850303"}, { sn: "Plum Blossom", trc: ["#b50719","#d1ba02","#E5D0A8","#607D3B","#B18969"], bgt_raw: [290,65,39], bgb_raw: [284,63,55], trailColor: "#f7d7f7"}, { sn: "Typhoon", trc: ["#66a3d4","#333f4d","#5ebda4","#A3A3A3","#414B56"], bgt_raw: [119,15,92], bgb_raw: [192,35,95], trailColor: "#65c1f7"}, { sn: "Maple Leaves", trc: ["#D81159","#8B0000","#F4A261","#264653","#A53860"], bgt_raw: [38,35,92.16], bgb_raw: [32,27,92], trailColor: "#fa5050"} ]; bgs = bgsOptions[rand_indices[2]]; bgs.bgt = [...bgs.bgt_raw, rAlpha]; bgs.bgb = [...bgs.bgb_raw, rAlpha]; const stOptions = [ { spt: "Markets", _a:bgs.bgb, _b:bgs.trailColor, _c:bgs.bgb, wa:0, uta:!1, wb:3, utb:!0, wc:0, utc:!1 }, { spt: "Streets Imaginaire",_a:bgs.bgb, _b:bgs.trailColor, _c:bgs.trailColor, wa:35, uta:!1, wb:3, utb:!0, wc:15, utc:!0 }, { spt: "XXX", _a:bgs.bgb, _b:bgs.bgb, _c:bgs.trailColor, wa:10, uta:!1, wb:5, utb:!1, wc:1, utc:!0 }, { spt: "Drift", _a:bgs.bgb, _b:bgs.bgb, _c:bgs.trailColor, wa:0, uta:!1, wb:25, utb:!1, wc:3, utc:!0 }, { spt: "Portals", _a:bgs.trailColor, _b:bgs.trailColor, _c:bgs.bgb, wa:3, uta:!0, wb:2, utb:!0, wc:10, utc:!1 }, { spt: "Gang", _a:bgs.trailColor, _b:bgs.trailColor, _c:bgs.trailColor, wa:3, uta:!0, wb:1, utb:!0, wc:1, utc:!0 }, { spt: "Dust", _a:bgs.trailColor, _b:bgs.trailColor, _c:bgs.trailColor, wa:1, uta:!0, wb:1, utb:!0, wc:1.5,utc:!0 }, { spt: "Rings", _a:bgs.trailColor, _b:bgs.trailColor, _c:bgs.trailColor, wa:1.5,uta:!0, wb:1, utb:!0, wc:0.5,utc:!0 }, { spt: "Entangled", _a:bgs.trailColor, _b:bgs.bgb, _c:bgs.bgb, wa:3, uta:!0, wb:0, utb:!1, wc:0, utc:!1 } ]; st = stOptions[rand_indices[3]]; st.acla = Array.isArray(st._a) ? color(...st._a) : color(st._a); st.aclb = Array.isArray(st._b) ? color(...st._b) : color(st._b); st.aclc = Array.isArray(st._c) ? color(...st._c) : color(st._c); st.weighta = st.wa; st.usesTrailColorA = st.uta; st.weightb = st.wb; st.usesTrailColorB = st.utb; st.weightc = st.wc; st.usesTrailColorC = st.utc; entropyType = ({0.039:"Wabisabi", 0.038:"Balance", 0.037:"Freestyle"})[rAlpha.toFixed(3)]; const bgTraitOptions = ["Comet", "Sun", "Stars", "Moonbow", "Nebula"]; bgTrait = bgTraitOptions[rand_indices[4]]; basesp = sqrt(width * height) * 0.002; vehicles = []; for (let i = 0; i < numTrains; i++) { vehicles.push(new MorphingVehicle(random(-trainLength, width), random(height * 0.05, height * 0.95), basesp)); } effectStates = {}; if (bgTrait === "Sun") effectStates.sun = initSun(); if (bgTrait === "Comet") effectStates.comet = initComet(); if (bgTrait === "Stars") { effectStates.stars = []; for (let i = 0; i < 500; i++) { effectStates.stars.push({ x: random(width), y: random(height), size: random(1, 3) }); } effectStates.starRotationCenter = { x: random(width/3-width*.25, width/3+width*.25), y: random(height/3-height*.25, height/3+height*.25) }; effectStates.starRotation = random(TWO_PI); effectStates.starRotationsp = random(0.0005, 0.002) * (random() < 0.5 ? 1 : -1); } if (bgTrait === "Moonbow") effectStates.moonbow = initMoonbow(); if (bgTrait === "Nebula") effectStates.nebula = initNebula(); drawBgTile.ballX = undefined; if (perlin_noise_array === undefined) { seedNoise(); } } function renderFrame() { let bgTopColor = color(...bgs.bgt); ctx.fillStyle = toCanvasRGBA(bgTopColor); ctx.fillRect(0, 0, width, height); if (colorTransitionProgress < 1 && colorTransitionTarget) { colorTransitionProgress += 1 / COLOR_LERP_DURATION; colorTransitionProgress = min(1, colorTransitionProgress); let lerpAmt = easeInOut(colorTransitionProgress); if(st.usesTrailColorA) st.acla = lerpColor(colorTransitionStartColors.a, colorTransitionTarget, lerpAmt); if(st.usesTrailColorB) st.aclb = lerpColor(colorTransitionStartColors.b, colorTransitionTarget, lerpAmt); if(st.usesTrailColorC) st.aclc = lerpColor(colorTransitionStartColors.c, colorTransitionTarget, lerpAmt); } if (random() < 0.05 && frameCount >= lastColorChangeFrame + COLOR_CHANGE_COOLDOWN && colorTransitionProgress >=1) { let visVehicles = vehicles.filter(v => v.x >= 0 && v.x <= width); if (visVehicles.length > 0) { let visColors = visVehicles.map(v => v.color); if (visColors.length > 0) { colorTransitionTarget = hl.randomElement(visColors); colorTransitionStartColors = { a: {...st.acla}, b: {...st.aclb}, c: {...st.aclc} }; colorTransitionProgress = 0; lastColorChangeFrame = frameCount; } } } drawpLayers(); drawAdditionalBackground(); for (let vehicle of vehicles) { vehicle.update(); vehicle.display(); } } function drawpLayers() { ctx.save(); drawBackgroundLayer(); drawMidgroundLayer(); drawForegroundLayer(); ctx.restore(); } function drawBackgroundLayer() { pBgo += pBgsp; let oX = pBgo % tsBg; for (let x = -tsBg; x < width + tsBg; x += tsBg) for (let y = 0; y < height; y += tsBg) { ctx.save(); ctx.translate(x - oX, y); drawBgTile(); ctx.restore(); } } function drawMidgroundLayer() { pMgo += pMgsp; let oX = pMgo % tsMg; for (let x = -tsMg; x < width + tsMg; x += tsMg) for (let y = 0; y < height; y += tsMg) { ctx.save(); ctx.translate(x - oX, y); drawMgTile(); ctx.restore(); } } function drawForegroundLayer() { pFgo += pFgsp; let oX = pFgo % tsFg; for (let x = -tsFg; x < width + tsFg; x += tsFg) for (let y = 0; y < height; y += tsFg) { ctx.save(); ctx.translate(x - oX, y); drawFgTile(); ctx.restore(); } } function drawBgTile() { let cola = st.acla; if (st.weighta <= 0) return; ctx.strokeStyle = toCanvasRGBA(cola); ctx.lineWidth = st.weighta; ctx.fillStyle = 'transparent'; ctx.beginPath(); const spt = st.spt; if (spt === "Markets" && typeof noise === 'function') { ctx.moveTo(0, map(noise(0, frameCount * 0.01), 0, 1, 0, tsBg)); for (let x = 5; x <= tsBg; x += 5) ctx.lineTo(x, map(noise(x * 0.05, frameCount * 0.01), 0, 1, 0, tsBg)); } else if (spt === "Streets Imaginaire") { ctx.lineCap = 'square'; ctx.moveTo(0,0);ctx.lineTo(tsBg,0); ctx.moveTo(0,0);ctx.lineTo(0,tsBg); ctx.moveTo(0,tsBg);ctx.lineTo(tsBg,tsBg); ctx.moveTo(tsBg,0);ctx.lineTo(tsBg,tsBg); } else if (spt === "XXX") { ctx.moveTo(0,0);ctx.lineTo(tsBg,0); ctx.moveTo(0,0);ctx.lineTo(0,tsBg); ctx.moveTo(0,tsBg);ctx.lineTo(tsBg,tsBg); ctx.moveTo(tsBg,0);ctx.lineTo(tsBg,tsBg); ctx.moveTo(0,0);ctx.lineTo(tsBg,tsBg); ctx.moveTo(tsBg,0);ctx.lineTo(0,tsBg); } else if (spt === "Drift") { ctx.moveTo(0,0);ctx.lineTo(tsBg,0); } else if (spt === "Portals") { let y = map(sin(frameCount*0.02),-1,1,0,tsBg); ctx.moveTo(0,y);ctx.lineTo(tsBg,y); let x = map(sin(frameCount*0.02),-1,1,0,tsBg); ctx.moveTo(x,0);ctx.lineTo(x,tsBg); } else if (spt === "Gang" && typeof noise === 'function') { let oX = map(noise(frameCount*0.0025),0,1,-90,90), oY = map(noise(frameCount*0.0025+100),0,1,-90,90); ctx.save(); ctx.translate(tsBg/2+oX, tsBg/2+oY); ctx.strokeRect(-tsBg*.1,0,tsBg*.07,tsBg*.07); ctx.strokeRect(tsBg*.1,0,tsBg*.07,tsBg*.07); ctx.restore(); ctx.closePath(); return; } else if (spt === "Dust") { if (drawBgTile.ballX === undefined) { drawBgTile.ballX = tsBg/2; drawBgTile.ballY = tsBg/2; drawBgTile.ballVX = 2; drawBgTile.ballVY = 3; } drawBgTile.ballX += drawBgTile.ballVX; drawBgTile.ballY += drawBgTile.ballVY; if (drawBgTile.ballX<0||drawBgTile.ballX>tsBg) { drawBgTile.ballX=max(0,min(tsBg,drawBgTile.ballX)); drawBgTile.ballVX*=-1; } if (drawBgTile.ballY<0||drawBgTile.ballY>tsBg) { drawBgTile.ballY=max(0,min(tsBg,drawBgTile.ballY)); drawBgTile.ballVY*=-1; } ctx.lineWidth = st.weighta; ctx.beginPath(); ctx.ellipse(drawBgTile.ballX,drawBgTile.ballY,tsBg*.01,tsBg*.01,0,0,TWO_PI); ctx.stroke(); ctx.closePath(); return; } else if (spt === "Rings") { let ang=frameCount*.015, pX=map(cos(ang),-1,1,0,tsBg), pY=map(sin(ang*1.2),-1,1,0,tsBg); ctx.beginPath(); ctx.ellipse(pX,pY,1,1,0,0,TWO_PI); ctx.stroke(); ctx.closePath(); return; } else if (spt === "Entangled" && typeof noise === 'function') { let sd=floor(noise(frameCount*.001)*1e4), raw=sin(sd*.00123), ang=map(raw,-1,1,-PI/4,PI/4); if(sd%2===0)ang=PI-ang; let dX=cos(ang),dY=sin(ang),rX=tsBg/2+dX*frameCount,rY=tsBg/2+dY*frameCount; const mB=(p,s)=>abs(((p%(2*s))+(2*s))%(2*s)-s); ctx.beginPath();ctx.ellipse(mB(rX,tsBg),mB(rY,tsBg),1.5,1.5,0,0,TWO_PI);ctx.stroke();ctx.closePath();return; } ctx.stroke(); } function drawMgTile() { let colb = st.aclb; if (st.weightb <= 0) return; ctx.strokeStyle = toCanvasRGBA(colb); ctx.lineWidth = st.weightb; ctx.fillStyle = 'transparent'; ctx.beginPath(); const spt = st.spt; if (spt === "Markets" && typeof noise === 'function') { ctx.moveTo(0, map(noise(0, frameCount * 0.01), 0, 1, 0, tsMg)); for (let x = 5; x <= tsMg; x += 5) ctx.lineTo(x, map(noise(x * 0.05, frameCount * 0.01), 0, 1, 0, tsMg)); } else if (spt === "Streets Imaginaire" && typeof noise === 'function') { ctx.save(); ctx.translate(tsMg/2,tsMg/2); ctx.rotate(noise(frameCount*.01)*TWO_PI); ctx.lineWidth=3; ctx.moveTo(-tsMg*.1,0); ctx.lineTo(tsMg*.1,0); ctx.stroke(); ctx.restore(); ctx.closePath(); return; } else if (spt === "XXX") { ctx.moveTo(0,0);ctx.lineTo(tsMg,0); ctx.moveTo(0,0);ctx.lineTo(0,tsMg); ctx.moveTo(0,tsMg);ctx.lineTo(tsMg,tsMg); ctx.moveTo(tsMg,0);ctx.lineTo(tsMg,tsMg); ctx.moveTo(0,0);ctx.lineTo(tsMg,tsMg); ctx.moveTo(tsMg,0);ctx.lineTo(0,tsMg); } else if (spt === "Drift") { ctx.moveTo(0,0);ctx.lineTo(tsMg,tsMg); ctx.moveTo(tsMg,0);ctx.lineTo(0,tsMg); } else if (spt === "Portals") { let y=map(sin(frameCount*.02),-1,1,0,tsMg); ctx.moveTo(0,y);ctx.lineTo(tsMg,y); let x=map(sin(frameCount*.02),-1,1,0,tsMg); ctx.moveTo(x,0);ctx.lineTo(x,tsMg); } else if (spt === "Gang") { let s2=map(sin(frameCount*.05),-1,1,-99,-90),seta=tsMg/2; ctx.moveTo(0,seta);ctx.lineTo(tsMg+s2,seta); ctx.moveTo(0,seta);ctx.lineTo(0,tsMg+s2+seta); ctx.moveTo(0,tsMg+s2+seta);ctx.lineTo(tsMg+s2,tsMg+s2+seta); ctx.moveTo(tsMg+s2,seta);ctx.lineTo(tsMg+s2,tsMg+s2+seta); let s2b=map(sin(frameCount*.05),-1,1,-99,-90),gap2=tsMg/5; ctx.moveTo(gap2,seta);ctx.lineTo(gap2+tsMg+s2b,seta); ctx.moveTo(gap2,seta);ctx.lineTo(gap2,tsMg+s2b+seta); ctx.moveTo(gap2,tsMg+s2b+seta);ctx.lineTo(gap2+tsMg+s2b,tsMg+s2b+seta); ctx.moveTo(gap2+tsMg+s2b,seta);ctx.lineTo(gap2+tsMg+s2b,tsMg+s2b+seta); } else if (spt === "Dust") { ctx.beginPath(); ctx.ellipse(0,tsMg,1,1,0,0,TWO_PI); ctx.fillStyle=toCanvasRGBA(colb); ctx.fill(); ctx.closePath(); return; } else if (spt === "Rings") { let ang=frameCount*.015, pX=map(cos(ang),-1,1,0,tsMg), pY=map(sin(ang*1.2),-1,1,0,tsMg); ctx.beginPath(); ctx.ellipse(pX,pY,1,1,0,0,TWO_PI); ctx.stroke(); ctx.closePath(); return; } else if (spt === "Entangled") { ctx.moveTo(0,0);ctx.lineTo(tsMg,tsMg); } ctx.stroke(); } function drawFgTile() { let colc = st.aclc; if (st.weightc <= 0) return; ctx.strokeStyle = toCanvasRGBA(colc); ctx.lineWidth = st.weightc; ctx.fillStyle = 'transparent'; ctx.lineCap = 'square'; ctx.beginPath(); const spt = st.spt; if (spt === "Streets Imaginaire") { ctx.moveTo(0,0);ctx.lineTo(tsFg,0); ctx.moveTo(0,0);ctx.lineTo(0,tsFg); ctx.moveTo(0,tsFg);ctx.lineTo(tsFg,tsFg); ctx.moveTo(tsFg,0);ctx.lineTo(tsFg,tsFg); } else if (spt === "XXX") { ctx.moveTo(0,0);ctx.lineTo(tsFg,tsFg); ctx.moveTo(tsFg,0);ctx.lineTo(0,tsFg); } else if (spt === "Drift") { ctx.beginPath(); ctx.moveTo(0,0);ctx.lineTo(0,tsFg); ctx.stroke(); ctx.beginPath(); ctx.moveTo(tsFg,0);ctx.lineTo(tsFg,tsFg); ctx.stroke(); ctx.fillStyle=toCanvasRGBA(colc); let cX=tsFg/10, pS=max(1,st.weightc); for(let i=5;i<tsFg;i+=10) ctx.fillRect(cX-pS/2,i-pS/2,pS,pS); return; } else if (spt === "Portals" || spt === "Gang") { ctx.moveTo(0,0);ctx.lineTo(0,tsFg); ctx.moveTo(tsFg,0);ctx.lineTo(tsFg,tsFg); } else if (spt === "Dust") { ctx.beginPath(); ctx.ellipse(0,tsFg/2,1.5,1.5,0,0,TWO_PI); ctx.fillStyle=toCanvasRGBA(colc); ctx.fill(); ctx.closePath(); return; } else if (spt === "Rings") { let ang=frameCount*.015,pX=map(cos(ang),-1,1,0,tsFg),pY=map(sin(ang*1.2),-1,1,0,tsFg); ctx.beginPath();ctx.ellipse(pX,pY,1,1,0,0,TWO_PI);ctx.stroke();ctx.closePath();return; } else if (spt === "Entangled") { ctx.moveTo(0,0);ctx.lineTo(tsFg,tsFg); } if (spt !== "Markets" && spt !== "Drift" && spt !== "Dust" && spt !== "Rings") { ctx.stroke(); } } function initSun() { return { active:!0, startTime:frameCount, cycleTime:1200, pauseTime:300, startY:random(height/1.5,height/1.05), endY:random(height/1.5,height/1.05) }; } function initComet() { return { active:!0, startTime:frameCount, cycleTime:1000, pauseTime:120, fromLeft:random()<.5, startY:random(height*.2,height*.8), endY:random(height*.3,height*.05), horizontalDir:random()<.5?1:-1 }; } function initMoonbow() { return { active:!0, startTime:frameCount, cycleTime:random(1200,2000), pauseTime:random(150,200), startX:-80, startY:random(height/8,height/2.2), endX:width+80, endY:random(height/8,height/2.2), size:random(25,50) }; } function initNebula() { let iW=random(100,150); return { active:!0, startTime:frameCount, cycleTime:random(1800,2300), pauseTime:random(120,300), startX:random(width), startY:height+80, endX:random(width), endY:-80, nebulaWidth:iW, nebulaHeight:iW/3 }; } function manageEffectLifecycle(effectName, initFn) { if (!effectStates[effectName]) effectStates[effectName] = initFn(); let state = effectStates[effectName], isActive = !1, t = null; if (state.active) { t = (frameCount - state.startTime) / state.cycleTime; if (t >= 1) { state.active = !1; state.pauseStart = frameCount; t = null; } else isActive = !0; } else if (frameCount - state.pauseStart > state.pauseTime) { effectStates[effectName] = initFn(); } return { isActive: isActive, t: t, state: state }; } function drawAdditionalBackground() { ctx.save(); ctx.strokeStyle = 'transparent'; const currentBgTrait = bgTrait; if (currentBgTrait === "Sun") { let eS = manageEffectLifecycle("sun", initSun); if (eS.isActive) { let s=eS.state, t=eS.t, sX=lerp(width+150,-150,t), sY=lerp(s.startY,s.endY,t)-sin(PI*t)*250; let iC=color(bgs.trailColor), oC=color(bgs.trailColor); iC.a=1; oC.a=1; for(let r=40;r>0;r-=4){ let intr=map(r,0,40,1,0), curC=lerpColor(iC,oC,intr); ctx.fillStyle=toCanvasRGBA(curC); ctx.beginPath(); let rad=r*1.75; ctx.ellipse(sX,sY,rad,rad,0,0,TWO_PI); ctx.fill(); } } } else if (currentBgTrait === "Comet") { let eS = manageEffectLifecycle("comet", initComet); if (eS.isActive) { let c=eS.state, t=eS.t, cX=c.fromLeft?lerp(-50,width+50,t):lerp(width+50,-50,t), cY=lerp(c.startY,c.endY,t)-sin(t*PI)*c.endY; let bCometC=color(bgs.trailColor); bCometC.a=1; ctx.fillStyle=toCanvasRGBA(bCometC); ctx.beginPath(); ctx.ellipse(cX,cY,15,15,0,0,TWO_PI); ctx.fill(); let tDX=c.fromLeft?-1:1, tDY=0, tL=15, bTEC=color(...bgs.bgb); for(let i=0;i<tL;i++){ let intr=map(i,0,tL,0,1), tailC=lerpColor(bCometC,bTEC,intr); tailC.a=map(i,0,tL,1,0); let tX=cX+tDX*i,tY=cY+tDY*i,tRad=(30-i*.15)/2; if(tRad<=0)continue; ctx.fillStyle=toCanvasRGBA(tailC);ctx.beginPath();ctx.ellipse(tX,tY,tRad,tRad,0,0,TWO_PI);ctx.fill(); } } } else if (currentBgTrait === "Stars") { effectStates.starRotation += effectStates.starRotationsp; let cx_s=effectStates.starRotationCenter.x, cy_s=effectStates.starRotationCenter.y, theta=effectStates.starRotation; let starC=color(bgs.trailColor); ctx.fillStyle=toCanvasRGBA(starC); for(let s_star of effectStates.stars){ let dX=s_star.x-cx_s,dY=s_star.y-cy_s,rX=dX*cos(theta)-dY*sin(theta)+cx_s,rY=dX*sin(theta)+dY*cos(theta)+cy_s; ctx.beginPath();let rad=s_star.size/2;ctx.ellipse(rX,rY,rad,rad,0,0,TWO_PI);ctx.fill(); } } else if (currentBgTrait === "Moonbow") { let eS = manageEffectLifecycle("moonbow", initMoonbow); if (eS.isActive) { let bh=eS.state, t=eS.t, bX=lerp(width+80,-80,t), bY=lerp(bh.startY,bh.endY,t), pY=bY+sin(PI*t)*100; ctx.save();ctx.translate(bX,pY); let rad=bh.size,c1=color("#f5de10"),c2=color(bgs.trailColor); for(let ym=-rad;ym<=rad;ym++){let intr=map(ym,-rad,rad,0,1),gC=lerpColor(c1,c2,intr);gC.a=map(abs(ym),0,rad,.05,.01);ctx.fillStyle=toCanvasRGBA(gC);let sH=2*sqrt(max(0,rad*rad-ym*ym));if(sH>0)ctx.fillRect(-sH/2,ym,sH,1);} ctx.restore(); } } else if (currentBgTrait === "Nebula") { let eS = manageEffectLifecycle("nebula", initNebula); if (eS.isActive && typeof noise === 'function') { let bh=eS.state, t=eS.t, bX=lerp(bh.startX,bh.endX,t), bY=lerp(bh.startY,bh.endY,t), pX=bX+sin(t*TWO_PI*3)*50; ctx.save();ctx.translate(pX,bY); let nebC=color(...bgs.bgb); ctx.fillStyle=toCanvasRGBA(nebC); let topEdgePts=[]; for(let xn=-bh.nebulaWidth/2;xn<=bh.nebulaWidth/2;xn++){let sH=bh.nebulaHeight*sqrt(max(0,1-(2*xn/bh.nebulaWidth)*(2*xn/bh.nebulaWidth)));if(sH>0){topEdgePts.push({x:xn,y:-sH/2});ctx.fillStyle=toCanvasRGBA(nebC);ctx.fillRect(xn,-sH/2,1,sH);}} if(topEdgePts.length>1){let distArcPts=[];for(let p of topEdgePts){let nV=noise((p.x+1e3)*.01,frameCount*.002);distArcPts.push({x:p.x,y:p.y+map(nV,0,1,-35,35)});} let arcC=color(bgs.trailColor);arcC.a=.8;ctx.strokeStyle=toCanvasRGBA(arcC);ctx.lineCap='round';ctx.lineJoin='round';let minW=1,maxW=3;for(let i=1;i<distArcPts.length;i++){let p1=distArcPts[i-1],p2=distArcPts[i],tArc=(i-.5)/(distArcPts.length-1);ctx.lineWidth=lerp(maxW,minW,abs(tArc-.5)*2);ctx.beginPath();ctx.moveTo(p1.x,p1.y);ctx.lineTo(p2.x,p2.y);ctx.stroke();}} ctx.restore(); } } ctx.restore(); } if (typeof window !== 'undefined') { window.GOM_ART = { initialize: initializeArtwork, render: renderFrame }; } else if (typeof self !== 'undefined') { self.GOM_ART = { initialize: initializeArtwork, render: renderFrame }; } // --- Renderer Setup and Execution --- window.ctx = canvas.getContext('2d'); window.width = canvas.width; window.height = canvas.height; window.frameCount = 0; try { if (window.GOM_ART && typeof window.GOM_ART.initialize === 'function') { window.GOM_ART.initialize(); function animate() { window.frameCount++; window.GOM_ART.render(); requestAnimationFrame(animate); } animate(); } else { throw new Error("GOM_ART object not found after script execution."); } } catch (e) { console.error("Error during animation setup:", e); document.body.innerHTML = `<pre style="color:red;font-family:sans-serif;">Error: ${e.message}</pre>`; } </script> </body> </html>
<!DOCTYPE html> <html> <head> <title>GOM Renderer</title> <style>body{margin:0;overflow:hidden;background-color:#000;}</style> </head> <body> <canvas id="artCanvas"></canvas> <script> const canvas = document.getElementById('artCanvas'); canvas.width = window.innerWidth; canvas.height = window.innerHeight; window.GOM_TRAITS = { hash: "