336ac26e64c3d3bd0900f77cfa03df8eb65ca08f
18
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
336ac26e64 |
fix(pulse): use SVG-coords directly (no double-transform) (#23)
Pulse-blob is inside the SAME SVG as the path, so applyTransform should use raw SVG coords (pt.x, pt.y) — not getScreenCTM-converted ones. Double-transform was pushing pulse to SVG-X 9794+ which renders off-screen-right. Also phase2 now uses entryPath-end + exitPath-start positions in SVG-coord-space so the inside-logo glide is continuous with phase1 and phase3. |
||
|
|
2591b46616 |
fix(logo-threads): Bezier paths pass exactly through logo-center (#22)
Cubic Bezier (C/S) locks Y=287 across X=900..1900 (full logo span). |
||
|
|
6e88cf4cd4 |
fix(logo-threads): Y-align to cross logo (#21)
* fix(pulse): split halves now meet simultaneously + no backtracking Two bugs fixed after Linus feedback: 1. Path-form: top/bottom split halves used Bezier curves that could loop back on themselves when entry.x lay outside box X-range. Now use clamped startX/endX (max(xL+r, min(xR-r, entry.x))) so pathen alltid rör sig framåt (entry.x → exit.x), aldrig vänder. 2. Synchronized meeting: previously each blob moved at fixed velocity along its own path → shorter path arrived first and waited. Now both blobs share a phase2T (0→1) progress fraction, so they meet at exit-point simultaneously. The path with different length simply moves at a slightly different speed (averaged). Phase2 duration based on avg(topLen,bottomLen)/velocity so total animation time stays consistent. * feat: logo-pulse with pink->green color transition Adds a 4th pulse target: the IMAGES BY OLOFSSON hero-text logo. 20% chance per pulse-slot when logo is visible (footer scrolled in). Flow: 1. New purple wave-thread on bottom-left (mirror of cyan wave1 on right) 2. Pulse glides in along purple thread to logo-left edge 3. Pulse enters logo + tints smoky-path stroke pink (#e879f9) + adds pink text-shadow halo on h1 4. Mid-passage: tint transitions to green (#4fd1c5) — matches default smoke + cyan glow 5. Pulse exits logo via wave1 (existing cyan thread on right) 6. Logo tint reverts to default (white smokeShift animation) CSS-side: data-logo-tint attribute on #text-wrapper drives stroke + text-shadow overrides with 0.6-0.8s transitions for smooth fade. * fix(logo-pulse): dynamic paths anchored to logo + 50% probability Previous version tried to use existing wave1+threadPurple paths for logo-pulse glide-in/out, but those paths are in SVG-fixed coordinates that don't align with logo's viewport position when hero is scrolled into view. wave1 has translateX(2283) which pushes it off-screen for ultrawide viewports. Fix: build dynamic Bezier paths anchored to the logo's actual getBoundingClientRect() position at pulse-time: - Entry path: from (offLeft, logoY+dipOffset) curves up into logo-left - Exit path: from logo-right curves up to (offRight, logoY-riseOffset) Paths are appended to box-trail-group, used for one pulse, then removed in cleanup. No reliance on fixed wave-thread coordinates. Also raises LOGO_PROBABILITY 20%->50% so the effect is visible more often when hero is in view. * fix(logo-pulse): visible entry/exit threads + restore pulse color after Two bugs fixed: 1. Entry+exit paths were stroke=transparent — pulse appeared to spawn out of nothing. Now stroke=url(#gradPurple) on entry (subtle pink thread visible from off-screen left) and stroke=url(#gradMain) on exit (cyan thread visible going off-screen right). Both at stroke-width 0.8 + opacity 0.55 to match other wave-thread style. 2. After logo-pulse completed, pulse-gradient stops were left in pink state — next regular wave-pulse rendered as stale pink instead of cyan/theme color. Now updatePulseColors(false) is called in cleanup to restore default cyan-tema. * fix(logo-pulse): entry/exit threads now properly visible Previous version used gradient strokes (gradPurple/gradMain) which have stop-opacity 0 at ends + 0.45 mid, multiplied by path-opacity 0.55 = ~0.25 effective opacity. Practically invisible. Now solid stroke colors (#e879f9 pink, #4fd1c5 cyan), stroke-width 2 (was 0.8), opacity 0.85 (was 0.55), plus pulseGlowMid filter for soft halo. Should be clearly visible from off-screen edges to logo. * feat(logo-pulse): permanent visible threads (no dynamic creation) Previously dynamic paths were built/destroyed per pulse, were too thick (stroke-width 2 + glow), and persisted incorrectly causing visual artifacts. Now: - threadLogoIn: permanent purple wave-thread, same style as other wave-threads (gradPurple stroke, stroke-width 0.7, opacity 0.55) - threadLogoOut: permanent cyan wave-thread (gradMain stroke 0.7, opacity 0.50) - runLogoPulse uses these permanent paths via getPointAtLength - getScreenCTM converts SVG-coords to screen-coords so pulse follows thread even with scroll/viewport variance * fix(logo-threads): align Y-coords to actually cross logo Logo Y-center is approx 287 in screen-coords. Previous thread Y-coords (400-600) only grazed logo-bottom or sat entirely below it. Adjusted: - threadLogoIn: M-1000 500 Q 200 350 850 287 T 2600 200 Kommer från nedre-vänster (Y=500), kurvar UPP till logo-center (Y=287), fortsätter upp till övre-höger (Y=200) - threadLogoOut: M-1000 350 Q 400 200 850 287 T 2600 500 Kommer från övre-vänster (Y=350), genom logo-center (Y=287), ner till nedre-höger (Y=500) — vertikalt motsatt entry-tråd |
||
|
|
650221b74b |
feat(logo-pulse): permanent visible threads (#20)
* fix(pulse): split halves now meet simultaneously + no backtracking Two bugs fixed after Linus feedback: 1. Path-form: top/bottom split halves used Bezier curves that could loop back on themselves when entry.x lay outside box X-range. Now use clamped startX/endX (max(xL+r, min(xR-r, entry.x))) so pathen alltid rör sig framåt (entry.x → exit.x), aldrig vänder. 2. Synchronized meeting: previously each blob moved at fixed velocity along its own path → shorter path arrived first and waited. Now both blobs share a phase2T (0→1) progress fraction, so they meet at exit-point simultaneously. The path with different length simply moves at a slightly different speed (averaged). Phase2 duration based on avg(topLen,bottomLen)/velocity so total animation time stays consistent. * feat: logo-pulse with pink->green color transition Adds a 4th pulse target: the IMAGES BY OLOFSSON hero-text logo. 20% chance per pulse-slot when logo is visible (footer scrolled in). Flow: 1. New purple wave-thread on bottom-left (mirror of cyan wave1 on right) 2. Pulse glides in along purple thread to logo-left edge 3. Pulse enters logo + tints smoky-path stroke pink (#e879f9) + adds pink text-shadow halo on h1 4. Mid-passage: tint transitions to green (#4fd1c5) — matches default smoke + cyan glow 5. Pulse exits logo via wave1 (existing cyan thread on right) 6. Logo tint reverts to default (white smokeShift animation) CSS-side: data-logo-tint attribute on #text-wrapper drives stroke + text-shadow overrides with 0.6-0.8s transitions for smooth fade. * fix(logo-pulse): dynamic paths anchored to logo + 50% probability Previous version tried to use existing wave1+threadPurple paths for logo-pulse glide-in/out, but those paths are in SVG-fixed coordinates that don't align with logo's viewport position when hero is scrolled into view. wave1 has translateX(2283) which pushes it off-screen for ultrawide viewports. Fix: build dynamic Bezier paths anchored to the logo's actual getBoundingClientRect() position at pulse-time: - Entry path: from (offLeft, logoY+dipOffset) curves up into logo-left - Exit path: from logo-right curves up to (offRight, logoY-riseOffset) Paths are appended to box-trail-group, used for one pulse, then removed in cleanup. No reliance on fixed wave-thread coordinates. Also raises LOGO_PROBABILITY 20%->50% so the effect is visible more often when hero is in view. * fix(logo-pulse): visible entry/exit threads + restore pulse color after Two bugs fixed: 1. Entry+exit paths were stroke=transparent — pulse appeared to spawn out of nothing. Now stroke=url(#gradPurple) on entry (subtle pink thread visible from off-screen left) and stroke=url(#gradMain) on exit (cyan thread visible going off-screen right). Both at stroke-width 0.8 + opacity 0.55 to match other wave-thread style. 2. After logo-pulse completed, pulse-gradient stops were left in pink state — next regular wave-pulse rendered as stale pink instead of cyan/theme color. Now updatePulseColors(false) is called in cleanup to restore default cyan-tema. * fix(logo-pulse): entry/exit threads now properly visible Previous version used gradient strokes (gradPurple/gradMain) which have stop-opacity 0 at ends + 0.45 mid, multiplied by path-opacity 0.55 = ~0.25 effective opacity. Practically invisible. Now solid stroke colors (#e879f9 pink, #4fd1c5 cyan), stroke-width 2 (was 0.8), opacity 0.85 (was 0.55), plus pulseGlowMid filter for soft halo. Should be clearly visible from off-screen edges to logo. * feat(logo-pulse): permanent visible threads (no dynamic creation) Previously dynamic paths were built/destroyed per pulse, were too thick (stroke-width 2 + glow), and persisted incorrectly causing visual artifacts. Now: - threadLogoIn: permanent purple wave-thread, same style as other wave-threads (gradPurple stroke, stroke-width 0.7, opacity 0.55) - threadLogoOut: permanent cyan wave-thread (gradMain stroke 0.7, opacity 0.50) - runLogoPulse uses these permanent paths via getPointAtLength - getScreenCTM converts SVG-coords to screen-coords so pulse follows thread even with scroll/viewport variance |
||
|
|
23880f746b |
fix(logo-pulse): threads properly visible (solid + glow) (#19)
* fix(pulse): split halves now meet simultaneously + no backtracking Two bugs fixed after Linus feedback: 1. Path-form: top/bottom split halves used Bezier curves that could loop back on themselves when entry.x lay outside box X-range. Now use clamped startX/endX (max(xL+r, min(xR-r, entry.x))) so pathen alltid rör sig framåt (entry.x → exit.x), aldrig vänder. 2. Synchronized meeting: previously each blob moved at fixed velocity along its own path → shorter path arrived first and waited. Now both blobs share a phase2T (0→1) progress fraction, so they meet at exit-point simultaneously. The path with different length simply moves at a slightly different speed (averaged). Phase2 duration based on avg(topLen,bottomLen)/velocity so total animation time stays consistent. * feat: logo-pulse with pink->green color transition Adds a 4th pulse target: the IMAGES BY OLOFSSON hero-text logo. 20% chance per pulse-slot when logo is visible (footer scrolled in). Flow: 1. New purple wave-thread on bottom-left (mirror of cyan wave1 on right) 2. Pulse glides in along purple thread to logo-left edge 3. Pulse enters logo + tints smoky-path stroke pink (#e879f9) + adds pink text-shadow halo on h1 4. Mid-passage: tint transitions to green (#4fd1c5) — matches default smoke + cyan glow 5. Pulse exits logo via wave1 (existing cyan thread on right) 6. Logo tint reverts to default (white smokeShift animation) CSS-side: data-logo-tint attribute on #text-wrapper drives stroke + text-shadow overrides with 0.6-0.8s transitions for smooth fade. * fix(logo-pulse): dynamic paths anchored to logo + 50% probability Previous version tried to use existing wave1+threadPurple paths for logo-pulse glide-in/out, but those paths are in SVG-fixed coordinates that don't align with logo's viewport position when hero is scrolled into view. wave1 has translateX(2283) which pushes it off-screen for ultrawide viewports. Fix: build dynamic Bezier paths anchored to the logo's actual getBoundingClientRect() position at pulse-time: - Entry path: from (offLeft, logoY+dipOffset) curves up into logo-left - Exit path: from logo-right curves up to (offRight, logoY-riseOffset) Paths are appended to box-trail-group, used for one pulse, then removed in cleanup. No reliance on fixed wave-thread coordinates. Also raises LOGO_PROBABILITY 20%->50% so the effect is visible more often when hero is in view. * fix(logo-pulse): visible entry/exit threads + restore pulse color after Two bugs fixed: 1. Entry+exit paths were stroke=transparent — pulse appeared to spawn out of nothing. Now stroke=url(#gradPurple) on entry (subtle pink thread visible from off-screen left) and stroke=url(#gradMain) on exit (cyan thread visible going off-screen right). Both at stroke-width 0.8 + opacity 0.55 to match other wave-thread style. 2. After logo-pulse completed, pulse-gradient stops were left in pink state — next regular wave-pulse rendered as stale pink instead of cyan/theme color. Now updatePulseColors(false) is called in cleanup to restore default cyan-tema. * fix(logo-pulse): entry/exit threads now properly visible Previous version used gradient strokes (gradPurple/gradMain) which have stop-opacity 0 at ends + 0.45 mid, multiplied by path-opacity 0.55 = ~0.25 effective opacity. Practically invisible. Now solid stroke colors (#e879f9 pink, #4fd1c5 cyan), stroke-width 2 (was 0.8), opacity 0.85 (was 0.55), plus pulseGlowMid filter for soft halo. Should be clearly visible from off-screen edges to logo. |
||
|
|
57767a112e |
fix(logo-pulse): visible entry/exit threads + restore pulse color (#18)
* fix(pulse): split halves now meet simultaneously + no backtracking Two bugs fixed after Linus feedback: 1. Path-form: top/bottom split halves used Bezier curves that could loop back on themselves when entry.x lay outside box X-range. Now use clamped startX/endX (max(xL+r, min(xR-r, entry.x))) so pathen alltid rör sig framåt (entry.x → exit.x), aldrig vänder. 2. Synchronized meeting: previously each blob moved at fixed velocity along its own path → shorter path arrived first and waited. Now both blobs share a phase2T (0→1) progress fraction, so they meet at exit-point simultaneously. The path with different length simply moves at a slightly different speed (averaged). Phase2 duration based on avg(topLen,bottomLen)/velocity so total animation time stays consistent. * feat: logo-pulse with pink->green color transition Adds a 4th pulse target: the IMAGES BY OLOFSSON hero-text logo. 20% chance per pulse-slot when logo is visible (footer scrolled in). Flow: 1. New purple wave-thread on bottom-left (mirror of cyan wave1 on right) 2. Pulse glides in along purple thread to logo-left edge 3. Pulse enters logo + tints smoky-path stroke pink (#e879f9) + adds pink text-shadow halo on h1 4. Mid-passage: tint transitions to green (#4fd1c5) — matches default smoke + cyan glow 5. Pulse exits logo via wave1 (existing cyan thread on right) 6. Logo tint reverts to default (white smokeShift animation) CSS-side: data-logo-tint attribute on #text-wrapper drives stroke + text-shadow overrides with 0.6-0.8s transitions for smooth fade. * fix(logo-pulse): dynamic paths anchored to logo + 50% probability Previous version tried to use existing wave1+threadPurple paths for logo-pulse glide-in/out, but those paths are in SVG-fixed coordinates that don't align with logo's viewport position when hero is scrolled into view. wave1 has translateX(2283) which pushes it off-screen for ultrawide viewports. Fix: build dynamic Bezier paths anchored to the logo's actual getBoundingClientRect() position at pulse-time: - Entry path: from (offLeft, logoY+dipOffset) curves up into logo-left - Exit path: from logo-right curves up to (offRight, logoY-riseOffset) Paths are appended to box-trail-group, used for one pulse, then removed in cleanup. No reliance on fixed wave-thread coordinates. Also raises LOGO_PROBABILITY 20%->50% so the effect is visible more often when hero is in view. * fix(logo-pulse): visible entry/exit threads + restore pulse color after Two bugs fixed: 1. Entry+exit paths were stroke=transparent — pulse appeared to spawn out of nothing. Now stroke=url(#gradPurple) on entry (subtle pink thread visible from off-screen left) and stroke=url(#gradMain) on exit (cyan thread visible going off-screen right). Both at stroke-width 0.8 + opacity 0.55 to match other wave-thread style. 2. After logo-pulse completed, pulse-gradient stops were left in pink state — next regular wave-pulse rendered as stale pink instead of cyan/theme color. Now updatePulseColors(false) is called in cleanup to restore default cyan-tema. |
||
|
|
11c75caaad |
fix(logo-pulse): dynamic viewport-anchored paths (#17)
* fix(pulse): split halves now meet simultaneously + no backtracking Two bugs fixed after Linus feedback: 1. Path-form: top/bottom split halves used Bezier curves that could loop back on themselves when entry.x lay outside box X-range. Now use clamped startX/endX (max(xL+r, min(xR-r, entry.x))) so pathen alltid rör sig framåt (entry.x → exit.x), aldrig vänder. 2. Synchronized meeting: previously each blob moved at fixed velocity along its own path → shorter path arrived first and waited. Now both blobs share a phase2T (0→1) progress fraction, so they meet at exit-point simultaneously. The path with different length simply moves at a slightly different speed (averaged). Phase2 duration based on avg(topLen,bottomLen)/velocity so total animation time stays consistent. * feat: logo-pulse with pink->green color transition Adds a 4th pulse target: the IMAGES BY OLOFSSON hero-text logo. 20% chance per pulse-slot when logo is visible (footer scrolled in). Flow: 1. New purple wave-thread on bottom-left (mirror of cyan wave1 on right) 2. Pulse glides in along purple thread to logo-left edge 3. Pulse enters logo + tints smoky-path stroke pink (#e879f9) + adds pink text-shadow halo on h1 4. Mid-passage: tint transitions to green (#4fd1c5) — matches default smoke + cyan glow 5. Pulse exits logo via wave1 (existing cyan thread on right) 6. Logo tint reverts to default (white smokeShift animation) CSS-side: data-logo-tint attribute on #text-wrapper drives stroke + text-shadow overrides with 0.6-0.8s transitions for smooth fade. * fix(logo-pulse): dynamic paths anchored to logo + 50% probability Previous version tried to use existing wave1+threadPurple paths for logo-pulse glide-in/out, but those paths are in SVG-fixed coordinates that don't align with logo's viewport position when hero is scrolled into view. wave1 has translateX(2283) which pushes it off-screen for ultrawide viewports. Fix: build dynamic Bezier paths anchored to the logo's actual getBoundingClientRect() position at pulse-time: - Entry path: from (offLeft, logoY+dipOffset) curves up into logo-left - Exit path: from logo-right curves up to (offRight, logoY-riseOffset) Paths are appended to box-trail-group, used for one pulse, then removed in cleanup. No reliance on fixed wave-thread coordinates. Also raises LOGO_PROBABILITY 20%->50% so the effect is visible more often when hero is in view. |
||
|
|
3f5fb4b7fd |
feat: logo-pulse with pink->green color transition (#16)
* fix(pulse): split halves now meet simultaneously + no backtracking Two bugs fixed after Linus feedback: 1. Path-form: top/bottom split halves used Bezier curves that could loop back on themselves when entry.x lay outside box X-range. Now use clamped startX/endX (max(xL+r, min(xR-r, entry.x))) so pathen alltid rör sig framåt (entry.x → exit.x), aldrig vänder. 2. Synchronized meeting: previously each blob moved at fixed velocity along its own path → shorter path arrived first and waited. Now both blobs share a phase2T (0→1) progress fraction, so they meet at exit-point simultaneously. The path with different length simply moves at a slightly different speed (averaged). Phase2 duration based on avg(topLen,bottomLen)/velocity so total animation time stays consistent. * feat: logo-pulse with pink->green color transition Adds a 4th pulse target: the IMAGES BY OLOFSSON hero-text logo. 20% chance per pulse-slot when logo is visible (footer scrolled in). Flow: 1. New purple wave-thread on bottom-left (mirror of cyan wave1 on right) 2. Pulse glides in along purple thread to logo-left edge 3. Pulse enters logo + tints smoky-path stroke pink (#e879f9) + adds pink text-shadow halo on h1 4. Mid-passage: tint transitions to green (#4fd1c5) — matches default smoke + cyan glow 5. Pulse exits logo via wave1 (existing cyan thread on right) 6. Logo tint reverts to default (white smokeShift animation) CSS-side: data-logo-tint attribute on #text-wrapper drives stroke + text-shadow overrides with 0.6-0.8s transitions for smooth fade. |
||
|
|
71ea7c7ce9 |
fix(pulse): split halves now meet simultaneously + no backtracking (#15)
Two bugs fixed after Linus feedback: 1. Path-form: top/bottom split halves used Bezier curves that could loop back on themselves when entry.x lay outside box X-range. Now use clamped startX/endX (max(xL+r, min(xR-r, entry.x))) so pathen alltid rör sig framåt (entry.x → exit.x), aldrig vänder. 2. Synchronized meeting: previously each blob moved at fixed velocity along its own path → shorter path arrived first and waited. Now both blobs share a phase2T (0→1) progress fraction, so they meet at exit-point simultaneously. The path with different length simply moves at a slightly different speed (averaged). Phase2 duration based on avg(topLen,bottomLen)/velocity so total animation time stays consistent. |
||
|
|
ece7693ad5 |
feat: mark about-page boxes as trail-targets (#14)
Adds data-trail-box to: - The main about-card (profile + bio + buttons) - The 3 gear-cards (Camera Body, Lenses, Editing) These boxes will now intercept wave-thread pulses and trigger the split-around-box animation, same as contact + home boxes. |
||
|
|
d6d062a3b2 |
feat(pulse): 55% probability of split via box (#13)
* feat: random light pulse along threads + box outlines A blurred light pulse glides along one of the 5 wave threads (wave1/2/3, thread1/2) every 2.5-7s. Color matches the active theme (cyan on home/portfolio/about, pink/magenta on contact). Pulse also follows the outline of designated boxes marked with data-trail-box: - Home: 'Looking for inspiration?' + 'Ready to collaborate?' - Contact: 'Waiting to hear from you' card Boxes are rebuilt on every pulse so they stay aligned during scroll and respect viewport (off-screen boxes are skipped). Pulse uses requestAnimationFrame + path.getPointAtLength for native smoothness, fade-in 15% / hold 70% / fade-out 15%, screen blend mode so it blends with the dark background. * feat(pulse): slower, brighter, comet-shaped pulse along paths Slower (9-13s per glide vs 4.5-6.5s), three-layer comet shape (soft halo + mid glow + bright core), rotated to path tangent, ease-in-out timing, mix-blend-mode screen. Fixes: pulse not tracking path was a parallax-offset coordinate mismatch. Cleaned up via getSpeedKey() helper. * fix(pulse): tone down white core so theme color dominates Core was pure white (#ffffff) which washed out the theme color. Now tinted (#fdf4ff for purple, #f0fdfa for cyan) and smaller (10x3 vs 14x4) with 75% opacity so the purple/pink and cyan glow layers come through more visibly. * feat(pulse): double the glide duration Threads: 18-26s (was 9-13s). Boxes: 14-18s (was 7-9s). * feat(pulse): split into two halves around boxes When a thread-pulse hits a data-trail-box bound, it splits: one half glides along the top of the box outline, the other along the bottom. They re-merge on the far side and continue as one along the rest of the thread. Implementation: - Two pulse-blob groups (blob-1, blob-2) in SVG - Box-intersection scan samples path every 4px to find entry + exit points - Phase 1: blob-1 glides from start to entry - Phase 2: blob-1 follows top-half of box outline, blob-2 follows bottom-half (both spawned dynamically) - Phase 3: blob-1 continues from exit to end, blob-2 hides - Velocity kept constant across phases so split makes the animation longer rather than faster * fix(pulse): remove direct box-pulses + smooth split transition Two fixes after review: 1. Removed runBoxPulse() entirely. Pulses now spawn ONLY on the 5 wave threads. Box outlines are followed only via the split mechanism when a thread-pulse intersects a box. 2. Smooth split transition via Bezier curves: split-path now starts at the EXACT thread intersection point (entryX/Y) and ends at exact exit point, curving smoothly up/down to the box top/bottom edge. Previously the path jumped to box.cy which caused a visible teleport when entering the split phase. * feat(pulse): bias 55% of pulses to threads that hit a box Before each pulse, split wavePaths into intersecting (those that currently cross a data-trail-box) and non-intersecting. Roll a die: 55% of the time pick from intersecting, 45% from non-intersecting. Falls back to the other bucket if one is empty (e.g. no boxes visible on the page). |
||
|
|
a71883215b |
fix(pulse): smooth split + no direct box pulses (#12)
* feat: random light pulse along threads + box outlines A blurred light pulse glides along one of the 5 wave threads (wave1/2/3, thread1/2) every 2.5-7s. Color matches the active theme (cyan on home/portfolio/about, pink/magenta on contact). Pulse also follows the outline of designated boxes marked with data-trail-box: - Home: 'Looking for inspiration?' + 'Ready to collaborate?' - Contact: 'Waiting to hear from you' card Boxes are rebuilt on every pulse so they stay aligned during scroll and respect viewport (off-screen boxes are skipped). Pulse uses requestAnimationFrame + path.getPointAtLength for native smoothness, fade-in 15% / hold 70% / fade-out 15%, screen blend mode so it blends with the dark background. * feat(pulse): slower, brighter, comet-shaped pulse along paths Slower (9-13s per glide vs 4.5-6.5s), three-layer comet shape (soft halo + mid glow + bright core), rotated to path tangent, ease-in-out timing, mix-blend-mode screen. Fixes: pulse not tracking path was a parallax-offset coordinate mismatch. Cleaned up via getSpeedKey() helper. * fix(pulse): tone down white core so theme color dominates Core was pure white (#ffffff) which washed out the theme color. Now tinted (#fdf4ff for purple, #f0fdfa for cyan) and smaller (10x3 vs 14x4) with 75% opacity so the purple/pink and cyan glow layers come through more visibly. * feat(pulse): double the glide duration Threads: 18-26s (was 9-13s). Boxes: 14-18s (was 7-9s). * feat(pulse): split into two halves around boxes When a thread-pulse hits a data-trail-box bound, it splits: one half glides along the top of the box outline, the other along the bottom. They re-merge on the far side and continue as one along the rest of the thread. Implementation: - Two pulse-blob groups (blob-1, blob-2) in SVG - Box-intersection scan samples path every 4px to find entry + exit points - Phase 1: blob-1 glides from start to entry - Phase 2: blob-1 follows top-half of box outline, blob-2 follows bottom-half (both spawned dynamically) - Phase 3: blob-1 continues from exit to end, blob-2 hides - Velocity kept constant across phases so split makes the animation longer rather than faster * fix(pulse): remove direct box-pulses + smooth split transition Two fixes after review: 1. Removed runBoxPulse() entirely. Pulses now spawn ONLY on the 5 wave threads. Box outlines are followed only via the split mechanism when a thread-pulse intersects a box. 2. Smooth split transition via Bezier curves: split-path now starts at the EXACT thread intersection point (entryX/Y) and ends at exact exit point, curving smoothly up/down to the box top/bottom edge. Previously the path jumped to box.cy which caused a visible teleport when entering the split phase. |
||
|
|
539b251287 |
feat(pulse): split into two halves around boxes (#11)
* feat: random light pulse along threads + box outlines A blurred light pulse glides along one of the 5 wave threads (wave1/2/3, thread1/2) every 2.5-7s. Color matches the active theme (cyan on home/portfolio/about, pink/magenta on contact). Pulse also follows the outline of designated boxes marked with data-trail-box: - Home: 'Looking for inspiration?' + 'Ready to collaborate?' - Contact: 'Waiting to hear from you' card Boxes are rebuilt on every pulse so they stay aligned during scroll and respect viewport (off-screen boxes are skipped). Pulse uses requestAnimationFrame + path.getPointAtLength for native smoothness, fade-in 15% / hold 70% / fade-out 15%, screen blend mode so it blends with the dark background. * feat(pulse): slower, brighter, comet-shaped pulse along paths Slower (9-13s per glide vs 4.5-6.5s), three-layer comet shape (soft halo + mid glow + bright core), rotated to path tangent, ease-in-out timing, mix-blend-mode screen. Fixes: pulse not tracking path was a parallax-offset coordinate mismatch. Cleaned up via getSpeedKey() helper. * fix(pulse): tone down white core so theme color dominates Core was pure white (#ffffff) which washed out the theme color. Now tinted (#fdf4ff for purple, #f0fdfa for cyan) and smaller (10x3 vs 14x4) with 75% opacity so the purple/pink and cyan glow layers come through more visibly. * feat(pulse): double the glide duration Threads: 18-26s (was 9-13s). Boxes: 14-18s (was 7-9s). * feat(pulse): split into two halves around boxes When a thread-pulse hits a data-trail-box bound, it splits: one half glides along the top of the box outline, the other along the bottom. They re-merge on the far side and continue as one along the rest of the thread. Implementation: - Two pulse-blob groups (blob-1, blob-2) in SVG - Box-intersection scan samples path every 4px to find entry + exit points - Phase 1: blob-1 glides from start to entry - Phase 2: blob-1 follows top-half of box outline, blob-2 follows bottom-half (both spawned dynamically) - Phase 3: blob-1 continues from exit to end, blob-2 hides - Velocity kept constant across phases so split makes the animation longer rather than faster |
||
|
|
af9a71a37e |
fix(pulse): tone down white core (#10)
* feat: random light pulse along threads + box outlines A blurred light pulse glides along one of the 5 wave threads (wave1/2/3, thread1/2) every 2.5-7s. Color matches the active theme (cyan on home/portfolio/about, pink/magenta on contact). Pulse also follows the outline of designated boxes marked with data-trail-box: - Home: 'Looking for inspiration?' + 'Ready to collaborate?' - Contact: 'Waiting to hear from you' card Boxes are rebuilt on every pulse so they stay aligned during scroll and respect viewport (off-screen boxes are skipped). Pulse uses requestAnimationFrame + path.getPointAtLength for native smoothness, fade-in 15% / hold 70% / fade-out 15%, screen blend mode so it blends with the dark background. * feat(pulse): slower, brighter, comet-shaped pulse along paths Slower (9-13s per glide vs 4.5-6.5s), three-layer comet shape (soft halo + mid glow + bright core), rotated to path tangent, ease-in-out timing, mix-blend-mode screen. Fixes: pulse not tracking path was a parallax-offset coordinate mismatch. Cleaned up via getSpeedKey() helper. * fix(pulse): tone down white core so theme color dominates Core was pure white (#ffffff) which washed out the theme color. Now tinted (#fdf4ff for purple, #f0fdfa for cyan) and smaller (10x3 vs 14x4) with 75% opacity so the purple/pink and cyan glow layers come through more visibly. * feat(pulse): double the glide duration Threads: 18-26s (was 9-13s). Boxes: 14-18s (was 7-9s). |
||
|
|
7bad958a38 |
feat(pulse): slower, brighter, comet-shaped pulse along paths
Slower (9-13s per glide vs 4.5-6.5s), three-layer comet shape (soft halo + mid glow + bright core), rotated to path tangent, ease-in-out timing, mix-blend-mode screen. Fixes: pulse not tracking path was a parallax-offset coordinate mismatch. Cleaned up via getSpeedKey() helper. |
||
|
|
33c9ea4157 |
feat: random light pulse along threads + box outlines
A blurred light pulse glides along one of the 5 wave threads (wave1/2/3, thread1/2) every 2.5-7s. Color matches the active theme (cyan on home/portfolio/about, pink/magenta on contact). Pulse also follows the outline of designated boxes marked with data-trail-box: - Home: 'Looking for inspiration?' + 'Ready to collaborate?' - Contact: 'Waiting to hear from you' card Boxes are rebuilt on every pulse so they stay aligned during scroll and respect viewport (off-screen boxes are skipped). Pulse uses requestAnimationFrame + path.getPointAtLength for native smoothness, fade-in 15% / hold 70% / fade-out 15%, screen blend mode so it blends with the dark background. |
||
|
|
3e8a4ddc40 |
fix: add astro.config.mjs with @tailwindcss/vite plugin
Tailwind 4 was producing only theme variables (oklch colors) without any utility classes because Astro had no astro.config.mjs wiring the @tailwindcss/vite plugin. Result: site rendered unstyled despite all components and HTML being correct. Verified locally after fix: - CSS bundle grew from 21 KB (theme only) to 36 KB (theme + utilities) - 23 utility-class definitions present (bg-neutral-900, text-white, min-h-screen, backdrop-blur, font-bold, flex etc) Also adds @source directive in global.css to ensure Tailwind scans .astro files for class usage. |
||
|
|
b0b633d32b |
Initial commit: Modern photography portfolio with Astro
- Built with Astro 5.16.7 and Tailwind CSS 4.1.18 - Features advanced animations (waves, 3D scroll, smoke effects) - Fully responsive design with mobile-first approach - SEO optimized with semantic HTML - Interactive elements and smooth transitions - Professional portfolio showcase |