'",777);
setTimeout("if(document.getElementById('chkbei'))if(document.getElementById('mbeilauti'))document.getElementById('mbeilauti').innerHTML='
'",777);
}
}
setTimeout("if(location.href.indexOf('&id=1332&')>0 && document.getElementById('otherh1'))document.getElementById('otherh1').innerHTML='Abonnement'",1111);
setTimeout("if(document.form1.bei)if(location.href.indexOf('s_order')<0)document.form1.bei[1].click()",1111);
setTimeout("if(document.getElementById('dbeilauti'))document.getElementById('dbeilauti').style.display='none'",1);
setTimeout("if(document.getElementById('mbeilauti'))document.getElementById('mbeilauti').style.display='none'",1);
/////////////////////////////////////
function setSessionCookie(n,v){document.cookie=encodeURIComponent(n)+"="+encodeURIComponent(v)+"; path=/";}
function getSessionCookie(n){for(let c of document.cookie.split(";")){let[a,b]=c.trim().split("=");if(a===decodeURIComponent(n))return decodeURIComponent(b);}return null;}
document.addEventListener("DOMContentLoaded",function(){
const s=document.getElementById("timwomo");if(!s)return;
s.addEventListener("change",()=>setSessionCookie("timwomo_value",s.value));
const v=getSessionCookie("timwomo_value");
if(v!==null && location.href.indexOf("x=")!==-1)setTimeout(()=>{s.value=v;s.dispatchEvent(new Event("change"));},5555);
});
////////////////////////////////////
(function () {
var isMobilePhp = location.href.indexOf('mobile.php') !== -1;
function styleSelectById(id, fontSize) {
var select = document.getElementById(id);
if (!select) return;
styleSelect(select, fontSize);
}
function styleSelect(select, fontSize) {
select.style.textAlign = 'center';
select.style.textAlignLast = 'center';
select.style.marginTop = '5px';
select.style.marginBottom = '3px';
select.style.fontSize = fontSize;
for (var i = 0; i < select.options.length; i++) {
select.options[i].style.textAlign = 'center';
}
}
function styleTimrepeatEndState(el) {
if (!el) return;
el.style.textAlign = 'center';
el.style.textAlignLast = 'center';
el.style.fontSize = '200%';
el.style.marginTop = '12px';
el.style.marginBottom = '12px';
el.style.borderRadius = '10px';
el.style.padding = '4px 8px';
el.style.backgroundColor = '#fff6cf';
el.style.outline = '1px solid rgba(170,130,45,0.42)';
el.style.outlineOffset = '3px';
el.style.boxShadow = '0 0 10px rgba(180,140,60,0.14)';
for (var i = 0; i < el.options.length; i++) {
el.options[i].style.textAlign = 'center';
}
}
styleSelectById('timwomo', isMobilePhp ? '100%' : '130%');
styleSelectById('timjeden', '130%');
styleSelectById('timclosed', '100%');
var repeats = document.getElementsByName('timrepeat');
for (var i = 0; i < repeats.length; i++) {
styleTimrepeatEndState(repeats[i]);
}
})();(function() {
if (
location.href.indexOf('a=z') <= 0 ||
(/[?&]x=/.test(location.search) && !/[?&]x=0(?:&|$)/.test(location.search))
) return;
function getTarget() {
return document.getElementsByName('timrepeat')[0];
}
function setTargetPosition(el) {
if (!el || !el.options || el.options.length <= 9) return;
el.selectedIndex = 9;
}
function waitUntilTargetIsReady(callback) {
var stableCount = 0;
var maxTries = 50;
var lastTop = null;
var lastHeight = null;
function check() {
var el = getTarget();
setTargetPosition(el);
if (!el || !document.body.contains(el)) {
if (maxTries-- > 0) setTimeout(check, 100);
return;
}
var rect = el.getBoundingClientRect();
var currentTop = Math.round(rect.top);
var currentHeight = Math.round(rect.height);
if (
currentHeight > 0 &&
currentTop === lastTop &&
currentHeight === lastHeight
) {
stableCount++;
} else {
stableCount = 0;
lastTop = currentTop;
lastHeight = currentHeight;
}
if (stableCount >= 2 || maxTries-- <= 0) {
callback(el);
} else {
setTimeout(check, 120);
}
}
check();
}
function ensureHighlightStyle() {
if (document.getElementById('timrepeat-highlight-style')) return;
var style = document.createElement('style');
style.id = 'timrepeat-highlight-style';
style.innerHTML =
'@keyframes timrepeatElegantBloom {' +
' 0% { transform: scale(1); box-shadow: 0 0 0 rgba(190,145,30,0); }' +
' 24% { transform: scale(1.030); box-shadow: 0 0 28px rgba(190,145,30,0.42); }' +
' 52% { transform: scale(1.012); box-shadow: 0 0 38px rgba(190,145,30,0.50); }' +
' 76% { transform: scale(1.020); box-shadow: 0 0 24px rgba(190,145,30,0.34); }' +
' 100% { transform: scale(1); box-shadow: 0 0 16px rgba(190,145,30,0.24); }' +
'}' +
'@keyframes timrepeatElegantGlowOnce {' +
' 0% { background-color: #fff2ad; }' +
' 45% { background-color: #ffe680; }' +
' 100% { background-color: #fff6cf; }' +
'}';
document.head.appendChild(style);
}
function easeInOutCubic(t) {
return t < 0.5
? 4 * t * t * t
: 1 - Math.pow(-2 * t + 2, 3) / 2;
}
function slowScrollToElement(el, duration) {
var rect = el.getBoundingClientRect();
var startY = window.pageYOffset || document.documentElement.scrollTop || 0;
var targetY = startY + rect.top - ((window.innerHeight - rect.height) / 2);
var diff = targetY - startY;
var startTime = null;
function step(timestamp) {
if (!startTime) startTime = timestamp;
var elapsed = timestamp - startTime;
var progress = Math.min(elapsed / duration, 1);
var eased = easeInOutCubic(progress);
window.scrollTo(0, startY + diff * eased);
if (progress < 1) {
window.requestAnimationFrame(step);
}
}
window.requestAnimationFrame(step);
}
function prepareTarget(el) {
el.style.fontSize = '12px';
el.style.borderRadius = '8px';
el.style.padding = '3px 7px';
el.style.marginTop = '12px';
el.style.marginBottom = '12px';
el.style.backgroundColor = '#fff9d8';
el.style.outline = '1px solid rgba(185,140,35,0.30)';
el.style.outlineOffset = '3px';
el.style.boxShadow = '0 0 0 rgba(190,145,30,0)';
el.style.transition =
'font-size 850ms ease, ' +
'background-color 950ms ease, ' +
'box-shadow 950ms ease, ' +
'transform 950ms ease, ' +
'outline-color 950ms ease, ' +
'outline-offset 950ms ease';
}
function highlightTarget(el) {
ensureHighlightStyle();
var originalTransition = el.style.transition;
var originalTransform = el.style.transform;
prepareTarget(el);
setTargetPosition(el);
requestAnimationFrame(function() {
setTargetPosition(el);
el.style.fontSize = '400%';
el.style.borderRadius = '14px';
el.style.padding = '6px 12px';
el.style.backgroundColor = '#ffe680';
el.style.outline = '1px solid rgba(185,140,35,0.78)';
el.style.outlineOffset = '5px';
el.style.boxShadow = '0 0 32px rgba(190,145,30,0.42)';
el.style.animation = 'timrepeatElegantBloom 1500ms ease-in-out 0s 1';
});
setTimeout(function() {
setTargetPosition(el);
el.style.fontSize = '200%';
el.style.borderRadius = '10px';
el.style.padding = '4px 8px';
el.style.backgroundColor = '#fff2ad';
el.style.outline = '1px solid rgba(185,140,35,0.58)';
el.style.outlineOffset = '4px';
el.style.boxShadow = '0 0 18px rgba(190,145,30,0.26)';
}, 880);
setTimeout(function() {
el.style.animation = 'timrepeatElegantGlowOnce 1500ms ease-in-out 0s 1';
}, 1800);
setTimeout(function() {
el.style.animation = '';
el.style.transition =
'font-size 900ms ease, ' +
'background-color 1300ms ease, ' +
'box-shadow 1300ms ease, ' +
'transform 900ms ease, ' +
'outline-color 1300ms ease, ' +
'outline-offset 1300ms ease';
el.style.fontSize = '200%';
el.style.backgroundColor = '#fff6cf';
el.style.outline = '1px solid rgba(170,130,45,0.42)';
el.style.outlineOffset = '3px';
el.style.boxShadow = '0 0 10px rgba(180,140,60,0.14)';
el.style.transform = originalTransform;
}, 3400);
setTimeout(function() {
el.style.transition = originalTransition;
}, 4900);
}
function run(el) {
setTargetPosition(el);
prepareTarget(el);
setTimeout(function() {
setTargetPosition(el);
slowScrollToElement(el, 1500);
}, 120);
setTimeout(function() {
setTargetPosition(el);
try {
el.focus({ preventScroll: true });
} catch (e) {
el.focus();
}
highlightTarget(el);
}, 1050);
}
function start() {
waitUntilTargetIsReady(run);
}
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', start);
} else {
start();
}
window.addEventListener('load', function() {
if (!getTarget()) start();
});
})();
(function () {
function findAboParam() {
return document.getElementById('aboparam') ||
document.querySelector('[name="aboparam"]') ||
document.querySelector('.aboparam');
}
function start() {
var box = findAboParam();
if (!box) {
window.setTimeout(start, 300);
return;
}
if (box._aboBotanicalCanvasStarted) return;
box._aboBotanicalCanvasStarted = true;
var CFG = {
fps: 18,
opacity: 0.70,
dprMax: 1.5,
growth: {
startFastMs: 65000,
buildMs: 190000,
matureMs: 420000,
earlyGrowDelay: [125, 275],
buildGrowDelay: [360, 760],
matureGrowDelay: [1200, 2600],
calmGrowDelay: [4200, 8200],
mainSeedUntilMs: 180000,
mainSeedDelay: [4200, 8200],
refreshDelayBuild: [1300, 2600],
refreshDelayCalm: [2800, 5600]
},
structure: {
mainStraightness: 0.58,
mainTargetPull: 0.26,
mainPreviousAngleMemory: 0.16,
mainRandomness: 0.044,
verticalTargetLeftDrift: [0.006, 0.055],
verticalTargetRightDrift: [-0.055, -0.006],
verticalTargetNeutralDrift: [-0.026, 0.026],
verticalTargetEarlyLift: [0.24, 0.37],
verticalTargetLaterLift: [0.13, 0.25],
lowerBranchLimit: 0.34,
lowerBranchSuppression: 0.58,
branchOpenFromMain: [0.86, 1.14],
branchOpenFromBranch: [0.70, 1.00],
branchRandomness: 0.048,
upperBranchLengthFromMain: [40, 72],
upperBranchLengthFromBranch: [27, 50],
lowerBranchLengthFromMain: [12, 22],
lowerBranchLengthFromBranch: [7, 16],
upperHeightFactor: 0.42,
mainLength: [34, 58],
secondaryMainLength: [25, 44],
sprayLength: [17, 34],
mainBend: 0.16,
branchBend: 0.14,
decorativeTipChance: 0.56,
decorativeTipStrength: [0.60, 0.84],
structuralTipStrength: [0.88, 0.98],
earlyMainTipPreferenceMs: 48000,
earlyMainTipPreference: 0.62,
lateMainTipPreference: 0.22
},
bouquet: {
centerY: 0.41,
radiusX: 0.68,
radiusY: 0.68,
generousRadiusX: 0.82,
generousRadiusY: 0.82,
bottomFreeY: 0.97
},
floristry: {
leafDensityMain: 1,
leafDensityStructural: 2,
leafDensityBranch: 2,
leafSkipBranchChance: 0.07,
longLeafChance: 0.50,
leafDistributionJitter: 0.15,
leafDistributionMin: 0.12,
leafDistributionMax: 0.96,
leafAngleFromStem: [0.42, 0.74],
leafLifeMain: [1100000, 1900000],
leafLifeBranch: [1000000, 1800000],
budChanceOnMain: 0.18,
budChanceOnBranch: 0.60,
flowerChanceOnMain: 0.11,
flowerChanceOnBranch: 0.60,
sprayChanceOnBranch: 0.44,
budLife: [1000000, 1800000],
flowerLife: [1100000, 2000000],
sprayLife: [950000, 1700000],
crownRefreshStartMs: 18000,
crownRefreshBuildChance: 0.78,
crownRefreshCalmChance: 0.72,
crownX: [0.08, 0.92],
crownY: [0.04, 0.62]
},
freshness: {
fadeStart: 0.975,
minimumFade: 0.76,
maxStems: 720,
maxLeaves: 2100,
maxBuds: 520,
maxFlowers: 760,
maxSprays: 340,
maxTips: 220
},
visual: {
backgroundAlpha: 0.008,
stemColor: [44, 118, 48],
stemHighlightColor: [126, 168, 76],
leafColorA: [54, 138, 58],
leafColorB: [69, 152, 64],
leafColorC: [92, 152, 60],
leafVeinColor: [32, 90, 36],
budColor: [176, 202, 48],
budLightColor: [255, 238, 80],
flowerPaleColor: [255, 255, 178],
flowerWarmColor: [255, 224, 0],
flowerGreenColor: [246, 238, 86],
flowerCenterColor: [210, 148, 0],
sprayStemColor: [72, 136, 58],
sprayDotColor: [255, 232, 62],
softBackgroundColor: [118, 156, 76]
}
};
if (!box.style.position || box.style.position === 'static') {
box.style.position = 'relative';
}
box.style.overflow = 'visible';
var canvasBleed = Math.max(18, Math.round(box.getBoundingClientRect().width * 0.045));
var canvas = document.createElement('canvas');
canvas.setAttribute('aria-hidden', 'true');
canvas.style.position = 'absolute';
canvas.style.left = '-' + canvasBleed + 'px';
canvas.style.top = '0';
canvas.style.width = 'calc(100% + ' + (canvasBleed * 2) + 'px)';
canvas.style.height = '100%';
canvas.style.pointerEvents = 'none';
canvas.style.zIndex = '0';
canvas.style.opacity = String(CFG.opacity);
box.insertBefore(canvas, box.firstChild);
var children = box.children;
for (var i = 0; i < children.length; i++) {
if (children[i] !== canvas) {
children[i].style.position = 'relative';
children[i].style.zIndex = '0';
}
}
var ctx = canvas.getContext('2d');
if (!ctx) return;
var w = 0;
var h = 0;
var dpr = Math.min(window.devicePixelRatio || 1, CFG.dprMax);
var startedAt = performance.now();
var stems = [];
var leaves = [];
var buds = [];
var flowers = [];
var sprays = [];
var tips = [];
var lastFrame = 0;
var nextGrowAt = 0;
var nextMainSeedAt = 0;
var nextRefreshAt = 0;
var nextCleanupAt = 0;
var frameInterval = 1000 / CFG.fps;
function rnd(min, max) {
return min + Math.random() * (max - min);
}
function rndRange(a) {
return rnd(a[0], a[1]);
}
function clamp(v, min, max) {
return Math.max(min, Math.min(max, v));
}
function rgba(rgb, alpha) {
return 'rgba(' + rgb[0] + ',' + rgb[1] + ',' + rgb[2] + ',' + alpha.toFixed(3) + ')';
}
function easeOutCubic(t) {
t = clamp(t, 0, 1);
return 1 - Math.pow(1 - t, 3);
}
function easeOutQuart(t) {
t = clamp(t, 0, 1);
return 1 - Math.pow(1 - t, 4);
}
function normalizeAngle(a) {
while (a <= -Math.PI) a += Math.PI * 2;
while (a > Math.PI) a -= Math.PI * 2;
return a;
}
function weightedAngle(a, b, c, wa, wb, wc) {
var x = Math.cos(a) * wa + Math.cos(b) * wb + Math.cos(c) * wc;
var y = Math.sin(a) * wa + Math.sin(b) * wb + Math.sin(c) * wc;
return Math.atan2(y, x);
}
function scheduleGrow(now) {
var age = now - startedAt;
var delay;
if (age < CFG.growth.startFastMs) {
delay = rndRange(CFG.growth.earlyGrowDelay);
} else if (age < CFG.growth.buildMs) {
delay = rndRange(CFG.growth.buildGrowDelay);
} else if (age < CFG.growth.matureMs) {
delay = rndRange(CFG.growth.matureGrowDelay);
} else {
delay = rndRange(CFG.growth.calmGrowDelay);
}
nextGrowAt = now + delay;
}
function scheduleMainSeed(now) {
nextMainSeedAt = now + rndRange(CFG.growth.mainSeedDelay);
}
function scheduleRefresh(now) {
var age = now - startedAt;
var delay = age < CFG.growth.buildMs
? rndRange(CFG.growth.refreshDelayBuild)
: rndRange(CFG.growth.refreshDelayCalm);
nextRefreshAt = now + delay;
}
function bouquetCenterY() {
return h * CFG.bouquet.centerY;
}
function insideBouquet(x, y, generous) {
if (!w || !h) return true;
var cx = w * 0.50;
var cy = bouquetCenterY();
var rx = w * (generous ? CFG.bouquet.generousRadiusX : CFG.bouquet.radiusX);
var ry = h * (generous ? CFG.bouquet.generousRadiusY : CFG.bouquet.radiusY);
var dx = (x - cx) / rx;
var dy = (y - cy) / ry;
if (y > h * CFG.bouquet.bottomFreeY) return true;
return dx * dx + dy * dy <= (generous ? 1.24 : 1.12);
}
function verticalPull(x, y, side, age) {
var phase = Math.min(1, age / 52000);
var targetX;
if (side === 'left') {
targetX = x + rnd(w * CFG.structure.verticalTargetLeftDrift[0], w * CFG.structure.verticalTargetLeftDrift[1]);
} else if (side === 'right') {
targetX = x + rnd(w * CFG.structure.verticalTargetRightDrift[0], w * CFG.structure.verticalTargetRightDrift[1]);
} else {
targetX = x + rnd(w * CFG.structure.verticalTargetNeutralDrift[0], w * CFG.structure.verticalTargetNeutralDrift[1]);
}
targetX = clamp(targetX, w * 0.07, w * 0.93);
var lift = phase < 0.55
? rndRange(CFG.structure.verticalTargetEarlyLift)
: rndRange(CFG.structure.verticalTargetLaterLift);
var targetY = y - h * lift;
targetY = clamp(targetY, h * 0.08, h * 0.98);
return Math.atan2(targetY - y, targetX - x);
}
function scaleItem(item, sx, sy) {
var keysX = ['x', 'x1', 'x2', 'c1x', 'c2x'];
var keysY = ['y', 'y1', 'y2', 'c1y', 'c2y'];
for (var i = 0; i < keysX.length; i++) {
if (typeof item[keysX[i]] === 'number') item[keysX[i]] *= sx;
}
for (var j = 0; j < keysY.length; j++) {
if (typeof item[keysY[j]] === 'number') item[keysY[j]] *= sy;
}
}
function resize(keepPlant) {
var oldW = w || 1;
var oldH = h || 1;
var rect = box.getBoundingClientRect();
canvasBleed = Math.max(18, Math.round(rect.width * 0.045));
canvas.style.left = '-' + canvasBleed + 'px';
canvas.style.width = 'calc(100% + ' + (canvasBleed * 2) + 'px)';
w = Math.max(1, Math.floor(rect.width + canvasBleed * 2));
h = Math.max(1, Math.floor(rect.height));
canvas.width = Math.floor(w * dpr);
canvas.height = Math.floor(h * dpr);
ctx.setTransform(dpr, 0, 0, dpr, 0, 0);
if (keepPlant && tips.length && oldW > 1 && oldH > 1) {
var sx = w / oldW;
var sy = h / oldH;
for (var i = 0; i < stems.length; i++) scaleItem(stems[i], sx, sy);
for (var j = 0; j < leaves.length; j++) scaleItem(leaves[j], sx, sy);
for (var k = 0; k < buds.length; k++) scaleItem(buds[k], sx, sy);
for (var l = 0; l < flowers.length; l++) scaleItem(flowers[l], sx, sy);
for (var m = 0; m < sprays.length; m++) scaleItem(sprays[m], sx, sy);
for (var n = 0; n < tips.length; n++) scaleItem(tips[n], sx, sy);
} else {
seed();
}
}
function seed() {
stems = [];
leaves = [];
buds = [];
flowers = [];
sprays = [];
tips = [];
startedAt = performance.now();
var now = startedAt;
addMainTip(w * 0.060, h * 0.990, 'left', 1.18, now, true);
addMainTip(w * 0.145, h * 0.985, 'left', 1.06, now + 90, true);
addMainTip(w * 0.235, h * 0.975, 'left', 0.94, now + 180, false);
addMainTip(w * 0.940, h * 0.990, 'right', 1.18, now + 45, true);
addMainTip(w * 0.855, h * 0.985, 'right', 1.06, now + 135, true);
addMainTip(w * 0.765, h * 0.975, 'right', 0.94, now + 225, false);
scheduleGrow(now);
scheduleMainSeed(now);
scheduleRefresh(now);
nextCleanupAt = now + 4200;
}
function addMainTip(x, y, side, strength, now, strong) {
var angle = -Math.PI / 2 + rnd(-0.030, 0.030);
var tip = {
x: x + rnd(-3, 3),
y: y + rnd(-3, 1),
angle: angle,
generation: 0,
strength: strength,
side: side,
main: true,
decorative: false,
born: now
};
tips.push(tip);
addStem(now, tip, true, true, strong ? 'main' : 'secondary');
if (Math.random() < 0.70) {
addStem(now + rnd(220, 620), tip, true, false, 'secondary');
}
}
function addBottomSeed(now, preferredSide) {
var side = preferredSide || (Math.random() < 0.5 ? 'left' : 'right');
var x;
if (side === 'left') {
x = rnd(w * 0.045, w * 0.225);
} else {
x = rnd(w * 0.775, w * 0.955);
}
var tip = {
x: x,
y: rnd(h * 0.930, h * 0.995),
angle: -Math.PI / 2 + rnd(-0.030, 0.030),
generation: 0,
strength: rnd(0.84, 1.06),
side: side,
main: true,
decorative: false,
born: now
};
tips.push(tip);
addStem(now, tip, true, true, 'main');
if (Math.random() < 0.44) {
addStem(now + rnd(260, 720), tip, true, false, 'secondary');
}
trimTips(now);
}
function trimTips(now) {
if (tips.length <= CFG.freshness.maxTips) return;
var useful = [];
for (var i = 0; i < tips.length; i++) {
if (
tips[i].main ||
(!tips[i].decorative && tips[i].y > h * 0.16) ||
now - tips[i].born < 52000
) {
useful.push(tips[i]);
}
}
tips = useful.length > 42 ? useful : tips.slice(Math.max(0, tips.length - 115));
while (tips.length > CFG.freshness.maxTips) {
tips.shift();
}
}
function chooseTip(now) {
if (!tips.length) seed();
var age = now - startedAt;
var lower = [];
var middle = [];
var crown = [];
var mainTips = [];
var structuralTips = [];
for (var i = 0; i < tips.length; i++) {
var t = tips[i];
if (t.main) mainTips.push(t);
if (!t.decorative) structuralTips.push(t);
if (t.y > h * 0.66) {
lower.push(t);
} else if (t.y > h * 0.36) {
middle.push(t);
} else if (t.y > h * 0.10) {
crown.push(t);
}
}
if (
age < CFG.structure.earlyMainTipPreferenceMs &&
mainTips.length &&
Math.random() < CFG.structure.earlyMainTipPreference
) {
return mainTips[Math.floor(Math.random() * mainTips.length)];
}
if (age < CFG.growth.buildMs) {
if (mainTips.length && Math.random() < 0.40) {
return mainTips[Math.floor(Math.random() * mainTips.length)];
}
if (middle.length && Math.random() < 0.34) {
return middle[Math.floor(Math.random() * middle.length)];
}
if (crown.length && Math.random() < 0.20) {
return crown[Math.floor(Math.random() * crown.length)];
}
if (lower.length && Math.random() < 0.18) {
return lower[Math.floor(Math.random() * lower.length)];
}
} else {
if (mainTips.length && Math.random() < CFG.structure.lateMainTipPreference) {
return mainTips[Math.floor(Math.random() * mainTips.length)];
}
if (crown.length && Math.random() < 0.28) {
return crown[Math.floor(Math.random() * crown.length)];
}
if (structuralTips.length && Math.random() < 0.26) {
return structuralTips[Math.floor(Math.random() * structuralTips.length)];
}
if (middle.length && Math.random() < 0.18) {
return middle[Math.floor(Math.random() * middle.length)];
}
}
if (structuralTips.length && Math.random() < 0.80) {
return structuralTips[Math.floor(Math.random() * structuralTips.length)];
}
return tips[Math.floor(Math.random() * tips.length)];
}
function addStem(now, base, forced, mainGrowth, kind) {
if (!w || !h) return;
if (!base) base = chooseTip(now);
if (!base) return;
var age = now - startedAt;
if (base.y < h * 0.08 && !forced) {
return;
}
var side = base.side || (base.x < w * 0.5 ? 'left' : 'right');
var straightUp = -Math.PI / 2;
var desired = verticalPull(base.x, base.y, side, age);
var angle;
if (mainGrowth) {
angle = weightedAngle(
straightUp,
desired,
base.angle,
CFG.structure.mainStraightness,
CFG.structure.mainTargetPull,
CFG.structure.mainPreviousAngleMemory
);
angle += rnd(-CFG.structure.mainRandomness, CFG.structure.mainRandomness);
} else {
var heightFactor = 1 - (base.y / h);
if (
heightFactor < CFG.structure.lowerBranchLimit &&
!forced &&
Math.random() < CFG.structure.lowerBranchSuppression
) {
return;
}
var branchSide;
if (side === 'left') {
branchSide = Math.random() < 0.66 ? 1 : -1;
} else if (side === 'right') {
branchSide = Math.random() < 0.66 ? -1 : 1;
} else {
branchSide = Math.random() < 0.5 ? -1 : 1;
}
var branchOpen = base.main
? rndRange(CFG.structure.branchOpenFromMain)
: rndRange(CFG.structure.branchOpenFromBranch);
angle = straightUp +
branchSide * branchOpen +
rnd(-CFG.structure.branchRandomness, CFG.structure.branchRandomness);
if (base.y < h * 0.34) {
angle = weightedAngle(angle, straightUp, base.angle, 0.72, 0.22, 0.06);
}
if (!base.main && kind !== 'spray') {
angle = weightedAngle(angle, straightUp, base.angle, 0.70, 0.24, 0.06);
}
}
angle = normalizeAngle(angle);
var len;
var heightFactorForLength = 1 - (base.y / h);
if (kind === 'main') {
len = rndRange(CFG.structure.mainLength);
} else if (kind === 'spray') {
len = rndRange(CFG.structure.sprayLength);
} else if (mainGrowth) {
len = rndRange(CFG.structure.secondaryMainLength);
} else if (heightFactorForLength > CFG.structure.upperHeightFactor) {
len = base.main
? rndRange(CFG.structure.upperBranchLengthFromMain)
: rndRange(CFG.structure.upperBranchLengthFromBranch);
} else {
len = base.main
? rndRange(CFG.structure.lowerBranchLengthFromMain)
: rndRange(CFG.structure.lowerBranchLengthFromBranch);
}
len *= base.strength || 1;
var x2 = base.x + Math.cos(angle) * len;
var y2 = base.y + Math.sin(angle) * len;
var generousForBranch = forced || (!mainGrowth && kind !== 'main');
if (!insideBouquet(x2, y2, generousForBranch)) {
if (!forced && mainGrowth) return;
if (!mainGrowth) {
x2 = clamp(x2, -12, w + 12);
y2 = clamp(y2, h * 0.045, h + 8);
} else {
x2 = clamp(x2, w * 0.035, w * 0.965);
y2 = clamp(y2, h * 0.070, h * 0.995);
}
}
if (mainGrowth) {
if (x2 < 6 || x2 > w - 6 || y2 < 6 || y2 > h - 4) {
if (!forced) return;
x2 = clamp(x2, 8, w - 8);
y2 = clamp(y2, 8, h - 6);
}
} else {
if (x2 < -22 || x2 > w + 22 || y2 < 4 || y2 > h + 12) {
if (!forced) return;
x2 = clamp(x2, -16, w + 16);
y2 = clamp(y2, 6, h + 8);
}
}
var bend = mainGrowth
? rnd(-CFG.structure.mainBend, CFG.structure.mainBend)
: rnd(-CFG.structure.branchBend, CFG.structure.branchBend);
var c1x = base.x + Math.cos(angle + bend) * len * rnd(0.30, 0.42);
var c1y = base.y + Math.sin(angle + bend) * len * rnd(0.30, 0.42);
var c2x = base.x + Math.cos(angle - bend * 0.70) * len * rnd(0.68, 0.84);
var c2y = base.y + Math.sin(angle - bend * 0.70) * len * rnd(0.68, 0.84);
var stem = {
x1: base.x,
y1: base.y,
c1x: c1x,
c1y: c1y,
c2x: c2x,
c2y: c2y,
x2: x2,
y2: y2,
angle: angle,
start: now,
duration: kind === 'main' ? rnd(5200, 8500) : mainGrowth ? rnd(5600, 9300) : rnd(4200, 7200),
width: kind === 'main' ? rnd(1.12, 1.72) : mainGrowth ? rnd(0.82, 1.24) : rnd(0.42, 0.72),
alpha: kind === 'main' ? rnd(0.32, 0.48) : mainGrowth ? rnd(0.22, 0.36) : rnd(0.13, 0.23),
born: now,
life: kind === 'main' ? 999999999 : mainGrowth ? rnd(360000, 620000) : rnd(220000, 420000),
main: kind === 'main' || mainGrowth,
structural: !!mainGrowth,
side: side,
kind: kind || 'normal'
};
stems.push(stem);
var newTip = {
x: x2,
y: y2,
angle: angle,
generation: (base.generation || 0) + 1,
strength: mainGrowth
? Math.max(0.54, (base.strength || 1) * rndRange(CFG.structure.structuralTipStrength))
: Math.max(0.32, (base.strength || 1) * rndRange(CFG.structure.decorativeTipStrength)),
side: side,
main: !!mainGrowth,
decorative: !mainGrowth,
born: now
};
if (mainGrowth || Math.random() < CFG.structure.decorativeTipChance) {
tips.push(newTip);
}
trimTips(now);
addLeaves(stem, now);
if (y2 < h * 0.78 && y2 > h * 0.12) {
if (Math.random() < (mainGrowth ? CFG.floristry.budChanceOnMain : CFG.floristry.budChanceOnBranch)) {
addBud(x2, y2, angle, now + rnd(1200, 3200));
}
if (Math.random() < (mainGrowth ? CFG.floristry.flowerChanceOnMain : CFG.floristry.flowerChanceOnBranch)) {
addFlower(x2, y2, angle, now + rnd(1800, 5200));
}
if (!mainGrowth && Math.random() < CFG.floristry.sprayChanceOnBranch && y2 < h * 0.60) {
addSpray(x2, y2, angle, now + rnd(1600, 4200), side);
}
}
}
function pointOnCurve(s, t) {
var mt = 1 - t;
return {
x:
mt * mt * mt * s.x1 +
3 * mt * mt * t * s.c1x +
3 * mt * t * t * s.c2x +
t * t * t * s.x2,
y:
mt * mt * mt * s.y1 +
3 * mt * mt * t * s.c1y +
3 * mt * t * t * s.c2y +
t * t * t * s.y2
};
}
function tooCloseToExistingLeaf(x, y, minDist) {
var min2 = minDist * minDist;
for (var i = leaves.length - 1; i >= 0 && i > leaves.length - 90; i--) {
var dx = leaves[i].x - x;
var dy = leaves[i].y - y;
if (dx * dx + dy * dy < min2) return true;
}
return false;
}
function addLeaves(stem, now) {
var count;
if (stem.kind === 'main') {
count = CFG.floristry.leafDensityMain + (Math.random() < 0.30 ? 1 : 0);
} else if (stem.main) {
count = CFG.floristry.leafDensityStructural + (Math.random() < 0.22 ? 1 : 0);
} else {
count = CFG.floristry.leafDensityBranch;
}
count = Math.max(0, count);
for (var i = 0; i < count; i++) {
if (!stem.main && Math.random() < CFG.floristry.leafSkipBranchChance) continue;
var baseT =
CFG.floristry.leafDistributionMin +
(CFG.floristry.leafDistributionMax - CFG.floristry.leafDistributionMin) *
((i + 0.5) / Math.max(1, count));
var t = clamp(
baseT + rnd(-CFG.floristry.leafDistributionJitter, CFG.floristry.leafDistributionJitter),
CFG.floristry.leafDistributionMin,
CFG.floristry.leafDistributionMax
);
var p = pointOnCurve(stem, t);
if (tooCloseToExistingLeaf(p.x, p.y, stem.main ? 7 : 9)) {
continue;
}
var leafSide = i % 2 === 0 ? -1 : 1;
if (Math.random() < 0.32) leafSide *= -1;
var longLeaf = stem.kind === 'main' && Math.random() < CFG.floristry.longLeafChance;
var angleFromStem = CFG.floristry.leafAngleFromStem
? rndRange(CFG.floristry.leafAngleFromStem)
: rnd(0.42, 0.74);
leaves.push({
x: p.x,
y: p.y,
angle: stem.angle + leafSide * angleFromStem,
rx: longLeaf ? rnd(9.5, 15.2) : stem.main ? rnd(6.4, 10.8) : rnd(4.6, 8.2),
ry: longLeaf ? rnd(2.2, 3.5) : stem.main ? rnd(1.9, 3.2) : rnd(1.4, 2.4),
start: now + rnd(700, 2800),
duration: rnd(1900, 4200),
alpha: longLeaf ? rnd(0.20, 0.34) : stem.main ? rnd(0.17, 0.31) : rnd(0.14, 0.26),
veinAlpha: rnd(0.055, 0.13),
born: now,
life: stem.main ? rndRange(CFG.floristry.leafLifeMain) : rndRange(CFG.floristry.leafLifeBranch),
hue: rnd(0, 1)
});
}
}
function addBud(x, y, angle, startTime) {
buds.push({
x: x + rnd(-1.8, 1.8),
y: y + rnd(-1.8, 1.8),
angle: angle + rnd(-0.28, 0.28),
r: rnd(1.5, 3.2),
start: startTime,
duration: rnd(2200, 5200),
alpha: rnd(0.14, 0.28),
born: startTime,
life: rndRange(CFG.floristry.budLife)
});
}
function addFlower(x, y, angle, startTime) {
var pale = Math.random() < 0.62;
flowers.push({
x: x + rnd(-4.0, 4.0),
y: y + rnd(-4.0, 4.0),
angle: angle + rnd(-0.45, 0.45),
r: rnd(2.4, 5.3),
petals: Math.floor(rnd(5, 8.99)),
start: startTime,
duration: rnd(2600, 6200),
alpha: pale ? rnd(0.12, 0.23) : rnd(0.10, 0.19),
born: startTime,
life: rndRange(CFG.floristry.flowerLife),
pale: pale,
warm: Math.random() < 0.38
});
}
function addSpray(x, y, angle, startTime, side) {
var sprayAngle = angle + (side === 'left' ? rnd(-0.20, 0.42) : rnd(-0.42, 0.20));
var count = Math.floor(rnd(3, 7.99));
var dots = [];
for (var i = 0; i < count; i++) {
dots.push({
t: (i + 1) / (count + 1),
side: rnd(-1, 1),
r: rnd(0.7, 1.3)
});
}
sprays.push({
x: x,
y: y,
angle: sprayAngle,
len: rnd(16, 32),
count: count,
dots: dots,
start: startTime,
duration: rnd(2600, 6400),
alpha: rnd(0.10, 0.20),
born: startTime,
life: rndRange(CFG.floristry.sprayLife)
});
}
function freshFade(now, item) {
var age = now - item.born;
var life = item.life || 240000;
if (age <= 0) return 1;
if (life > 900000000) return 1;
if (age >= life) return 0;
if (age > life * CFG.freshness.fadeStart) {
var f = 1 - ((age - life * CFG.freshness.fadeStart) / (life * (1 - CFG.freshness.fadeStart)));
return Math.max(CFG.freshness.minimumFade, Math.min(1, f));
}
return 1;
}
function drawStem(s, p, fade) {
if (fade <= 0) return;
p = easeOutCubic(p);
ctx.beginPath();
ctx.moveTo(s.x1, s.y1);
var steps = 42;
var maxStep = Math.max(1, Math.floor(steps * p));
for (var i = 1; i <= maxStep; i++) {
var t = i / steps;
var pt = pointOnCurve(s, t);
ctx.lineTo(pt.x, pt.y);
}
var alpha = s.alpha * p * fade;
ctx.strokeStyle = rgba(CFG.visual.stemColor, alpha);
ctx.lineWidth = s.width;
ctx.lineCap = 'round';
ctx.lineJoin = 'round';
ctx.stroke();
if (s.main && p > 0.55) {
ctx.beginPath();
ctx.moveTo(s.x1, s.y1);
for (var j = 1; j <= maxStep; j++) {
var tt = j / steps;
var pp = pointOnCurve(s, tt);
ctx.lineTo(pp.x, pp.y);
}
ctx.strokeStyle = rgba(CFG.visual.stemHighlightColor, alpha * 0.22);
ctx.lineWidth = Math.max(0.35, s.width * 0.42);
ctx.stroke();
}
}
function drawLeaf(l, p, fade) {
if (p <= 0 || fade <= 0) return;
var eased = easeOutQuart(p);
var scale = 0.14 + 0.86 * eased;
ctx.save();
ctx.translate(l.x, l.y);
ctx.rotate(l.angle);
ctx.scale(scale, scale);
ctx.beginPath();
ctx.moveTo(-l.rx, 0);
ctx.bezierCurveTo(-l.rx * 0.48, -l.ry * 1.72, l.rx * 0.50, -l.ry * 1.48, l.rx, 0);
ctx.bezierCurveTo(l.rx * 0.50, l.ry * 1.48, -l.rx * 0.48, l.ry * 1.72, -l.rx, 0);
ctx.closePath();
var a = l.alpha * eased * fade;
if (l.hue < 0.34) {
ctx.fillStyle = rgba(CFG.visual.leafColorA, a);
} else if (l.hue < 0.72) {
ctx.fillStyle = rgba(CFG.visual.leafColorB, a);
} else {
ctx.fillStyle = rgba(CFG.visual.leafColorC, a);
}
ctx.fill();
ctx.beginPath();
ctx.moveTo(-l.rx * 0.70, 0);
ctx.lineTo(l.rx * 0.74, 0);
ctx.strokeStyle = rgba(CFG.visual.leafVeinColor, l.veinAlpha * eased * fade);
ctx.lineWidth = 0.42;
ctx.stroke();
ctx.restore();
}
function drawBud(b, p, fade) {
if (p <= 0 || fade <= 0) return;
var eased = easeOutCubic(p);
var r = b.r * eased;
ctx.save();
ctx.translate(b.x, b.y);
ctx.rotate(b.angle);
ctx.beginPath();
ctx.ellipse(0, 0, r * 0.68, r * 1.22, 0, 0, Math.PI * 2);
ctx.fillStyle = rgba(CFG.visual.budColor, b.alpha * eased * fade);
ctx.fill();
ctx.beginPath();
ctx.ellipse(0, -r * 0.20, r * 0.34, r * 0.72, 0, 0, Math.PI * 2);
ctx.fillStyle = rgba(CFG.visual.budLightColor, b.alpha * 0.45 * eased * fade);
ctx.fill();
ctx.restore();
}
function drawFlower(f, p, fade) {
if (p <= 0 || fade <= 0) return;
var eased = easeOutQuart(p);
var r = f.r * eased;
ctx.save();
ctx.translate(f.x, f.y);
ctx.rotate(f.angle);
for (var i = 0; i < f.petals; i++) {
var a = (Math.PI * 2 / f.petals) * i;
ctx.save();
ctx.rotate(a);
ctx.beginPath();
ctx.ellipse(0, -r * 0.72, r * 0.34, r * 0.82, 0, 0, Math.PI * 2);
if (f.pale) {
ctx.fillStyle = rgba(CFG.visual.flowerPaleColor, f.alpha * 0.82 * eased * fade);
} else if (f.warm) {
ctx.fillStyle = rgba(CFG.visual.flowerWarmColor, f.alpha * 0.78 * eased * fade);
} else {
ctx.fillStyle = rgba(CFG.visual.flowerGreenColor, f.alpha * 0.76 * eased * fade);
}
ctx.fill();
ctx.restore();
}
ctx.beginPath();
ctx.arc(0, 0, Math.max(0.7, r * 0.30), 0, Math.PI * 2);
ctx.fillStyle = rgba(CFG.visual.flowerCenterColor, f.alpha * 0.80 * eased * fade);
ctx.fill();
ctx.restore();
}
function drawSpray(s, p, fade) {
if (p <= 0 || fade <= 0) return;
var eased = easeOutCubic(p);
var len = s.len * eased;
ctx.save();
ctx.translate(s.x, s.y);
ctx.rotate(s.angle);
ctx.beginPath();
ctx.moveTo(0, 0);
ctx.quadraticCurveTo(len * 0.14, -len * 0.38, len * 0.06, -len);
ctx.strokeStyle = rgba(CFG.visual.sprayStemColor, s.alpha * eased * fade);
ctx.lineWidth = 0.55;
ctx.lineCap = 'round';
ctx.stroke();
for (var i = 0; i < s.dots.length; i++) {
var d = s.dots[i];
var t = d.t;
var px = len * 0.06 * t + Math.sin(t * Math.PI) * len * 0.08 * d.side;
var py = -len * t;
ctx.beginPath();
ctx.arc(px, py, d.r, 0, Math.PI * 2);
ctx.fillStyle = rgba(CFG.visual.sprayDotColor, s.alpha * 1.25 * eased * fade);
ctx.fill();
}
ctx.restore();
}
function cleanup(now) {
var i;
for (i = stems.length - 1; i >= 0; i--) {
if (stems[i].life < 900000000 && now - stems[i].born > stems[i].life) {
stems.splice(i, 1);
}
}
for (i = leaves.length - 1; i >= 0; i--) {
if (now - leaves[i].born > leaves[i].life) leaves.splice(i, 1);
}
for (i = buds.length - 1; i >= 0; i--) {
if (now - buds[i].born > buds[i].life) buds.splice(i, 1);
}
for (i = flowers.length - 1; i >= 0; i--) {
if (now - flowers[i].born > flowers[i].life) flowers.splice(i, 1);
}
for (i = sprays.length - 1; i >= 0; i--) {
if (now - sprays[i].born > sprays[i].life) sprays.splice(i, 1);
}
if (stems.length > CFG.freshness.maxStems) stems.splice(0, stems.length - CFG.freshness.maxStems);
if (leaves.length > CFG.freshness.maxLeaves) leaves.splice(0, leaves.length - CFG.freshness.maxLeaves);
if (buds.length > CFG.freshness.maxBuds) buds.splice(0, buds.length - CFG.freshness.maxBuds);
if (flowers.length > CFG.freshness.maxFlowers) flowers.splice(0, flowers.length - CFG.freshness.maxFlowers);
if (sprays.length > CFG.freshness.maxSprays) sprays.splice(0, sprays.length - CFG.freshness.maxSprays);
trimTips(now);
}
function refreshBouquet(now) {
var age = now - startedAt;
if (age < CFG.floristry.crownRefreshStartMs) return;
var crownChance = age < CFG.growth.buildMs
? CFG.floristry.crownRefreshBuildChance
: CFG.floristry.crownRefreshCalmChance;
if (Math.random() < crownChance) {
var x = rnd(w * CFG.floristry.crownX[0], w * CFG.floristry.crownX[1]);
var y = rnd(h * CFG.floristry.crownY[0], h * CFG.floristry.crownY[1]);
if (insideBouquet(x, y, true)) {
if (Math.random() < 0.38) {
addFlower(x, y, rnd(-Math.PI, Math.PI), now + rnd(0, 2400));
} else if (Math.random() < 0.76) {
addBud(x, y, rnd(-Math.PI, Math.PI), now + rnd(0, 2100));
} else {
addSpray(x, y, rnd(-2.4, -0.7), now + rnd(0, 2500), x < w * 0.5 ? 'left' : 'right');
}
}
}
if (Math.random() < 0.22) {
var base = chooseTip(now);
if (base && base.main && base.y > h * 0.22 && base.y < h * 0.78) {
addStem(now, base, false, false, 'spray');
}
}
}
function drawSoftBackground(now) {
var age = now - startedAt;
var p = easeOutCubic(Math.min(1, age / 52000));
if (p <= 0) return;
var cx = w * 0.5;
var cy = h * 0.50;
var rx = w * 0.42;
var ry = h * 0.40;
ctx.save();
ctx.beginPath();
ctx.ellipse(cx, cy, rx, ry, 0, 0, Math.PI * 2);
ctx.fillStyle = rgba(CFG.visual.softBackgroundColor, CFG.visual.backgroundAlpha * p);
ctx.fill();
ctx.restore();
}
function drawAll(now) {
ctx.clearRect(0, 0, w, h);
drawSoftBackground(now);
var i;
var p;
var fade;
for (i = 0; i < stems.length; i++) {
p = (now - stems[i].start) / stems[i].duration;
fade = freshFade(now, stems[i]);
drawStem(stems[i], p, fade);
}
for (i = 0; i < leaves.length; i++) {
p = (now - leaves[i].start) / leaves[i].duration;
fade = freshFade(now, leaves[i]);
drawLeaf(leaves[i], p, fade);
}
for (i = 0; i < sprays.length; i++) {
p = (now - sprays[i].start) / sprays[i].duration;
fade = freshFade(now, sprays[i]);
drawSpray(sprays[i], p, fade);
}
for (i = 0; i < buds.length; i++) {
p = (now - buds[i].start) / buds[i].duration;
fade = freshFade(now, buds[i]);
drawBud(buds[i], p, fade);
}
for (i = 0; i < flowers.length; i++) {
p = (now - flowers[i].start) / flowers[i].duration;
fade = freshFade(now, flowers[i]);
drawFlower(flowers[i], p, fade);
}
}
function animate(now) {
if (now - lastFrame < frameInterval) {
window.requestAnimationFrame(animate);
return;
}
lastFrame = now;
var age = now - startedAt;
if (age < CFG.growth.mainSeedUntilMs && now >= nextMainSeedAt) {
addBottomSeed(now);
scheduleMainSeed(now);
}
if (now >= nextGrowAt) {
var base = chooseTip(now);
if (base) {
var heightFactor = 1 - (base.y / h);
var mainGrowthChance;
if (base.main) {
mainGrowthChance = age < CFG.growth.buildMs ? 0.62 : 0.40;
} else {
mainGrowthChance = heightFactor < 0.42 ? 0.22 : 0.10;
}
addStem(now, base, false, Math.random() < mainGrowthChance, Math.random() < 0.12 ? 'secondary' : 'normal');
}
scheduleGrow(now);
}
if (now >= nextRefreshAt) {
refreshBouquet(now);
scheduleRefresh(now);
}
if (now >= nextCleanupAt) {
cleanup(now);
nextCleanupAt = now + 4200;
}
drawAll(now);
window.requestAnimationFrame(animate);
}
function handleResize() {
clearTimeout(box._aboBotanicalResizeTimer);
box._aboBotanicalResizeTimer = setTimeout(function () {
resize(true);
}, 160);
}
resize(false);
window.addEventListener('resize', handleResize);
window.requestAnimationFrame(animate);
}
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', start);
} else {
start();
}
window.addEventListener('load', function () {
start();
});
})();(function () {
var ua = navigator.userAgent;
var isIOSSafari =
/iP(ad|hone|od)/.test(ua) &&
/Safari/.test(ua) &&
!/CriOS|FxiOS|EdgiOS|OPiOS/.test(ua);
if (!isIOSSafari) return;
var lastScroll = 0;
function scrollToInvalidSelect(el) {
if (!el || el.tagName !== 'SELECT' || !el.required || el.validity.valid) return;
var now = Date.now();
if (now - lastScroll < 400) return;
lastScroll = now;
setTimeout(function () {
var rect = el.getBoundingClientRect();
var y = window.pageYOffset + rect.top - Math.round(window.innerHeight * 0.35);
window.scrollTo(0, y);
setTimeout(function () {
try {
el.focus();
} catch (e) {}
}, 80);
}, 30);
}
document.addEventListener('invalid', function (e) {
scrollToInvalidSelect(e.target);
}, true);
document.addEventListener('submit', function (e) {
var el = document.querySelector('select[required]:invalid');
if (el) {
scrollToInvalidSelect(el);
e.preventDefault();
e.stopPropagation();
}
}, true);
})();