diff --git a/src/components/WaveBackground.astro b/src/components/WaveBackground.astro
index 1fe69c8..1140b31 100644
--- a/src/components/WaveBackground.astro
+++ b/src/components/WaveBackground.astro
@@ -72,7 +72,8 @@ const pulseCore = theme === 'purple' ? '#fdf4ff' : '#f0fdfa';
-
+
+
@@ -422,9 +423,11 @@ const pulseCore = theme === 'purple' ? '#fdf4ff' : '#f0fdfa';
}
function runLogoPulse(durationMs: number) {
- if (!blob1 || !boxGroup) return;
+ if (!blob1) return;
const logo = isLogoTargetVisible();
- if (!logo) {
+ const entryPath = document.getElementById('threadLogoIn') as SVGPathElement | null;
+ const exitPath = document.getElementById('threadLogoOut') as SVGPathElement | null;
+ if (!logo || !entryPath || !exitPath) {
schedule();
return;
}
@@ -432,43 +435,37 @@ const pulseCore = theme === 'purple' ? '#fdf4ff' : '#f0fdfa';
updatePulseColors(false);
const rect = logo.getBoundingClientRect();
- const vw = window.innerWidth;
const logoLeftX = rect.left + 8;
const logoRightX = rect.right - 8;
const logoY = rect.top + rect.height / 2;
- // DYNAMIC PATHS — bygg paths som GARANTERAT passar logo-positionen.
- // Pulsen kommer från vänster off-screen, lite under logon, kurvar UPP in i logo-left,
- // glider genom logo, kurvar UT mot höger off-screen, lite över logon
- const offLeft = -100;
- const offRight = vw + 100;
- const dipY = logoY + rect.height * 0.7; // entry kommer underifrån vänster
- const riseY = logoY - rect.height * 0.7; // exit lämnar uppåt höger
+ // Använd permanenta wave-trådar (threadLogoIn + threadLogoOut)
+ // Hitta var de KORSAR logo-x-koordinater i screen-space
+ const entryTotal = entryPath.getTotalLength();
+ const exitTotal = exitPath.getTotalLength();
- const NS_local = 'http://www.w3.org/2000/svg';
- // Entry path (lila): från off-screen vänster (dipY) kurvar upp till logo-left
- // TYDLIG SOLID stroke + glow filter så användaren ser tråden ordentligt
- const entryPath = document.createElementNS(NS_local, 'path');
- entryPath.setAttribute('d', `M ${offLeft} ${dipY} C ${logoLeftX - 200} ${dipY}, ${logoLeftX - 80} ${logoY}, ${logoLeftX} ${logoY}`);
- entryPath.setAttribute('fill', 'none');
- entryPath.setAttribute('stroke', '#e879f9');
- entryPath.setAttribute('stroke-width', '2');
- entryPath.setAttribute('opacity', '0.85');
- entryPath.setAttribute('filter', 'url(#pulseGlowMid)');
- boxGroup.appendChild(entryPath);
+ // Sök på entryPath efter den punkt där SVG-pt.x motsvarar logoLeftX
+ // OBS: pathen är i SVG-koord (-1000..2600), klient-koord är getBoundingClientRect
+ // Vi mappar via path.getBoundingClientRect() vs path.getBBox()
+ function findLenForScreenX(p: SVGPathElement, targetScreenX: number, total: number): number {
+ // SVG till screen: använd ctm
+ const ctm = p.getScreenCTM();
+ if (!ctm) return total * 0.5;
+ let bestLen = total;
+ for (let l = 0; l <= total; l += 6) {
+ const pt = p.getPointAtLength(l);
+ const screenX = ctm.a * pt.x + ctm.c * pt.y + ctm.e;
+ if (screenX >= targetScreenX) {
+ bestLen = l;
+ break;
+ }
+ }
+ return bestLen;
+ }
- // Exit path (cyan): från logo-right kurvar upp till off-screen höger (riseY)
- const exitPath = document.createElementNS(NS_local, 'path');
- exitPath.setAttribute('d', `M ${logoRightX} ${logoY} C ${logoRightX + 80} ${logoY}, ${logoRightX + 200} ${riseY}, ${offRight} ${riseY}`);
- exitPath.setAttribute('fill', 'none');
- exitPath.setAttribute('stroke', '#4fd1c5');
- exitPath.setAttribute('stroke-width', '2');
- exitPath.setAttribute('opacity', '0.85');
- exitPath.setAttribute('filter', 'url(#pulseGlowMid)');
- boxGroup.appendChild(exitPath);
-
- const entryLen = entryPath.getTotalLength();
- const exitLen = exitPath.getTotalLength();
+ const entryLen = findLenForScreenX(entryPath, logoLeftX, entryTotal);
+ const exitStartLen = findLenForScreenX(exitPath, logoRightX, exitTotal);
+ const exitLen = Math.min(exitTotal, exitStartLen + (exitTotal - exitStartLen) * 0.9);
const phase1Duration = durationMs * 0.35;
const phase2Duration = durationMs * 0.30;
@@ -501,12 +498,16 @@ const pulseCore = theme === 'purple' ? '#fdf4ff' : '#f0fdfa';
const fade = fadeFactor(globalT);
if (elapsed <= phase1Duration) {
- // Glide in på entry-path (lila)
+ // Glide in på entry-path (lila, permanent tråd)
const t = elapsed / phase1Duration;
const len = t * entryLen;
const pt = entryPath.getPointAtLength(len);
- const angle = tangentAngle(entryPath, len, entryLen);
- applyTransform(blob1!, pt.x, pt.y, angle);
+ const angle = tangentAngle(entryPath, len, entryTotal);
+ // Konvertera SVG-koord till screen-koord
+ const ctm = entryPath.getScreenCTM();
+ const sx = ctm ? (ctm.a * pt.x + ctm.c * pt.y + ctm.e) : pt.x;
+ const sy = ctm ? (ctm.b * pt.x + ctm.d * pt.y + ctm.f) : pt.y;
+ applyTransform(blob1!, sx, sy, angle);
blob1!.setAttribute('opacity', String(fade));
} else if (elapsed <= phase1Duration + phase2Duration) {
// INSIDE logo — pulse vid logo-center, ändra logo-färg
@@ -526,12 +527,15 @@ const pulseCore = theme === 'purple' ? '#fdf4ff' : '#f0fdfa';
setPulseTint(greenColor);
}
} else {
- // Glide ut på exit-path (grön)
+ // Glide ut på exit-path (permanent cyan-tråd)
const t = Math.min((elapsed - phase1Duration - phase2Duration) / phase3Duration, 1);
- const len = t * exitLen;
+ const len = exitStartLen + (exitLen - exitStartLen) * t;
const pt = exitPath.getPointAtLength(len);
- const angle = tangentAngle(exitPath, len, exitLen);
- applyTransform(blob1!, pt.x, pt.y, angle);
+ const angle = tangentAngle(exitPath, len, exitTotal);
+ const ctm = exitPath.getScreenCTM();
+ const sx = ctm ? (ctm.a * pt.x + ctm.c * pt.y + ctm.e) : pt.x;
+ const sy = ctm ? (ctm.b * pt.x + ctm.d * pt.y + ctm.f) : pt.y;
+ applyTransform(blob1!, sx, sy, angle);
blob1!.setAttribute('opacity', String(fade));
if (logo!.getAttribute('data-logo-tint')) {
logo!.removeAttribute('data-logo-tint');
@@ -543,11 +547,7 @@ const pulseCore = theme === 'purple' ? '#fdf4ff' : '#f0fdfa';
} else {
blob1!.setAttribute('opacity', '0');
logo!.removeAttribute('data-logo-tint');
- // Cleanup dynamic paths
- if (entryPath.parentNode) entryPath.parentNode.removeChild(entryPath);
- if (exitPath.parentNode) exitPath.parentNode.removeChild(exitPath);
- // ÅTERSTÄLL pulse-gradient till default cyan-tema så nästa
- // vanliga wave-pulse inte har stale rosa färg
+ // Återställ pulse-gradient till default cyan-tema
updatePulseColors(false);
isPulsing = false;
}