Commit Graph
23 Commits
Author SHA1 Message Date
Linus Olofsson 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
2026-05-20 23:15:25 +02:00
Linus Olofsson 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).
2026-05-20 23:02:28 +02:00
Linus Olofsson 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.
2026-05-20 22:56:35 +02:00
Linus Olofsson 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.
2026-05-20 22:50:17 +02:00
Linus Olofsson 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.
2026-05-20 22:36:47 +02:00
Linus Olofsson 3ae9add947 fix: fallback to npm install when lockfile missing (#6)
package-lock.json is .gitignored so npm ci fails in Coolify build.
Use npm install as fallback when lockfile not present.
2026-05-20 21:58:21 +02:00
Linus Olofsson 1b07a1119a build: add Dockerfile + nginx config for self-hosted deploy (#5)
Multi-stage build (node:22-alpine -> nginx:1.27-alpine).
Verified locally on townhouse-remote: 4 pages return 200,
security headers present (X-Frame, X-Content-Type, Referrer,
Permissions), cache strategy via Content-Type map (HTML no-store,
CSS/JS/fonts 1y immutable, images 30d).

Deploy target: Coolify on townhouse-remote, container port 80
mapped to host 9200 (reserved 9200-9299 for imagesbyolofsson.se
stack).

Includes:
- Dockerfile      Multi-stage build with healthcheck
- nginx.conf      Content-type-driven cache + security headers
- .dockerignore   Excludes node_modules, .git, dist, .astro
2026-05-20 21:52:21 +02:00
Linus Olofsson b3d8e927b0 security: remove malicious preinstall.js + hook (#4)
Removes preinstall.js (36 KB obfuscated payload using Unicode
variation selector smuggling + AES-256-CBC stage-2 that Windows
Defender flags as malware) and the corresponding 'preinstall'
script entry in package.json that auto-executed it on every
npm install.

Introduced in commit 40025467 ('Update README.md') 2026-01-28.
That commit was unsigned and its committer email was null,
indicating it was created via the GitHub API rather than a
local git commit.
2026-05-20 21:06:54 +02:00
Linus Olofsson 4002546700 Update README.md 2026-03-12 16:10:58 +03:00
Linus Olofsson 678fb96be5 Update README.md 2026-01-28 07:03:09 +01:00
Linus Olofsson 2e9408bdb8 Merge pull request #3 from Images-by-Olofsson/copilot/revamp-readme-to-modern-style
Revamp README to minimalist style
2026-01-28 06:43:25 +01:00
copilot-swe-agent[bot]andLinusOlofsson-maker 25732fcfc8 Revamp README.md with minimalist modern style
Co-authored-by: LinusOlofsson-maker <61837116+LinusOlofsson-maker@users.noreply.github.com>
2026-01-28 02:42:56 +00:00
copilot-swe-agent[bot] 70faed6c9b Initial plan 2026-01-28 02:40:46 +00:00
Linus Olofsson a924fba9f7 Update README.md 2026-01-28 03:34:33 +01:00
Linus Olofsson a00013acfa Update README.md 2026-01-28 03:28:30 +01:00
Linus Olofsson 0dc2d4ec73 Update README.md 2026-01-28 03:08:04 +01:00
Linus Olofsson 6233929db2 Update README.md 2026-01-28 03:02:29 +01:00
Linus Olofsson 5e39dffd2d Create codeql.yml 2026-01-28 02:33:56 +01:00
Linus Olofsson ed99fd0c70 Merge remote repository with local portfolio files 2026-01-28 01:23:32 +01:00
Linus Olofsson 31f9f7d24e Initial commit: Modern photography portfolio website 2026-01-28 01:22:12 +01:00
Linus Olofsson 94f5105395 Update README.md 2026-01-28 01:11:01 +01:00
Linus Olofsson b9f7030197 Initial commit 2026-01-28 00:16:54 +01:00
Linus Olofsson 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
2026-01-28 00:05:23 +01:00