Animation Effects

**Referenced Files in This Document** - [custom-cursor.js](file://src/assets/js/modules/custom-cursor.js) - [03-custom-cursor.css](file://src/assets/css/modules/03-custom-cursor.css) - [hero-animations.js](file://src/assets/js/modules/hero-animations.js) - [hero-parallax.js](file://src/assets/js/modules/hero-parallax.js) - [06-parallax-hero-three-js-scroll-driven-terrain.css](file://src/assets/css/modules/06-parallax-hero-three-js-scroll-driven-terrain.css) - [poll-bar-animation.js](file://src/assets/js/modules/poll-bar-animation.js) - [32-news-page-detail-fix-poll-bar-animation-trigger.css](file://src/assets/css/modules/32-news-page-detail-fix-poll-bar-animation-trigger.css) - [polling-bar.njk](file://src/_includes/macros/polling-bar.njk) - [team-card-flip.js](file://src/assets/js/modules/team-card-flip.js) - [12-team-grid-homepage-teaser.css](file://src/assets/css/modules/12-team-grid-homepage-teaser.css) - [team-flip-card.njk](file://src/_includes/macros/team-flip-card.njk) - [accordion.js](file://src/assets/js/modules/accordion.js) - [29-reduced-motion.css](file://src/assets/css/modules/29-reduced-motion.css) - [main.js](file://src/assets/js/main.js)

Table of Contents

  1. Introduction
  2. Project Structure
  3. Core Components
  4. Architecture Overview
  5. Detailed Component Analysis
  6. Dependency Analysis
  7. Performance Considerations
  8. Troubleshooting Guide
  9. Conclusion
  10. Appendices

Introduction

This document explains the animation and effect systems across the project, focusing on:

  • Custom cursor with smooth tracking, hover states, and interaction feedback
  • Hero animation system including parallax effects, scroll-driven terrain animations, and 3D camera movement
  • Poll bar animation with dynamic progress indicators and real-time updates
  • Team card flip animation with 3D perspective and transition effects
  • Accordion system with smooth expand/collapse animations and accessibility considerations It also provides practical examples, performance guidance, browser compatibility notes, and integration tips.

Project Structure

The animation system is organized around modular JavaScript and CSS files, integrated via a single initialization entry point. Key areas:

  • Cursor: JS module initializes GSAP-driven tracking and hover states; CSS defines styles and reduced-motion behavior
  • Hero: Two complementary systems—one using GSAP for 2D/2.5D animations and another using Three.js for 3D terrain and camera movement
  • Polling: Macro renders segments; JS observes visibility to animate widths; CSS controls transitions
  • Team cards: CSS handles 3D flip on hover; JS toggles flip on touch devices
  • Accordion: JS manages expand/collapse and height/opacity transitions
graph TB
Main["main.js<br/>Initialization"] --> CursorJS["custom-cursor.js"]
Main --> HeroAnim["hero-animations.js"]
Main --> Parallax["hero-parallax.js"]
Main --> PollJS["poll-bar-animation.js"]
Main --> TeamFlip["team-card-flip.js"]
Main --> Accordion["accordion.js"]
CursorCSS["03-custom-cursor.css"] --> CursorJS
ReducedMotion["29-reduced-motion.css"] --> CursorJS
ReducedMotion --> HeroAnim
ParallaxCSS["06-parallax-hero-three-js-scroll-driven-terrain.css"] --> Parallax
PollCSS["32-news-page-detail-fix-poll-bar-animation-trigger.css"] --> PollJS
TeamCSS["12-team-grid-homepage-teaser.css"] --> TeamFlip
MacroPoll["polling-bar.njk"] --> PollJS
MacroTeam["team-flip-card.njk"] --> TeamFlip

Diagram sources

  • [main.js:15-36](file://src/assets/js/main.js#L15-L36)
  • [custom-cursor.js:1-28](file://src/assets/js/modules/custom-cursor.js#L1-L28)
  • [03-custom-cursor.css:1-46](file://src/assets/css/modules/03-custom-cursor.css#L1-L46)
  • [hero-animations.js:1-307](file://src/assets/js/modules/hero-animations.js#L1-L307)
  • [hero-parallax.js:1-462](file://src/assets/js/modules/hero-parallax.js#L1-L462)
  • [06-parallax-hero-three-js-scroll-driven-terrain.css:1-193](file://src/assets/css/modules/06-parallax-hero-three-js-scroll-driven-terrain.css#L1-L193)
  • [poll-bar-animation.js:1-20](file://src/assets/js/modules/poll-bar-animation.js#L1-L20)
  • [32-news-page-detail-fix-poll-bar-animation-trigger.css:1-9](file://src/assets/css/modules/32-news-page-detail-fix-poll-bar-animation-trigger.css#L1-L9)
  • [polling-bar.njk:1-39](file://src/_includes/macros/polling-bar.njk#L1-L39)
  • [team-card-flip.js:1-14](file://src/assets/js/modules/team-card-flip.js#L1-L14)
  • [12-team-grid-homepage-teaser.css:1-117](file://src/assets/css/modules/12-team-grid-homepage-teaser.css#L1-L117)
  • [team-flip-card.njk:1-18](file://src/_includes/macros/team-flip-card.njk#L1-L18)
  • [accordion.js:1-35](file://src/assets/js/modules/accordion.js#L1-L35)
  • [29-reduced-motion.css:1-646](file://src/assets/css/modules/29-reduced-motion.css#L1-L646)

Section sources

  • [main.js:15-36](file://src/assets/js/main.js#L15-L36)

Core Components

  • Custom cursor: Desktop-only smooth mouse tracking with layered followers, hover scaling and opacity changes, and automatic disabling on coarse-pointer devices
  • Hero animations: GSAP-driven reveals, particle backgrounds, SVG line drawing, waypoint rings, and split-flap text; plus scroll-driven parallax for non-Three.js heroes
  • Parallax hero (Three.js): Full-screen 3D terrain, camera movement along a curve, additive glow effects, trail rendering, and day/night theme switching
  • Poll bar: IntersectionObserver triggers width animation to data-driven percentages
  • Team card flip: 3D flip on hover for capable devices; click toggle for touch devices
  • Accordion: Expand/collapse with height and opacity transitions; close others behavior

Section sources

  • [custom-cursor.js:1-28](file://src/assets/js/modules/custom-cursor.js#L1-L28)
  • [03-custom-cursor.css:1-46](file://src/assets/css/modules/03-custom-cursor.css#L1-L46)
  • [hero-animations.js:1-307](file://src/assets/js/modules/hero-animations.js#L1-L307)
  • [hero-parallax.js:1-462](file://src/assets/js/modules/hero-parallax.js#L1-L462)
  • [06-parallax-hero-three-js-scroll-driven-terrain.css:1-193](file://src/assets/css/modules/06-parallax-hero-three-js-scroll-driven-terrain.css#L1-L193)
  • [poll-bar-animation.js:1-20](file://src/assets/js/modules/poll-bar-animation.js#L1-L20)
  • [32-news-page-detail-fix-poll-bar-animation-trigger.css:1-9](file://src/assets/css/modules/32-news-page-detail-fix-poll-bar-animation-trigger.css#L1-L9)
  • [polling-bar.njk:1-39](file://src/_includes/macros/polling-bar.njk#L1-L39)
  • [team-card-flip.js:1-14](file://src/assets/js/modules/team-card-flip.js#L1-L14)
  • [12-team-grid-homepage-teaser.css:1-117](file://src/assets/css/modules/12-team-grid-homepage-teaser.css#L1-L117)
  • [team-flip-card.njk:1-18](file://src/_includes/macros/team-flip-card.njk#L1-L18)
  • [accordion.js:1-35](file://src/assets/js/modules/accordion.js#L1-L35)

Architecture Overview

The initialization pipeline loads optional libraries and registers plugins, then runs feature-specific setup routines. GSAP and ScrollTrigger are conditionally required for advanced animations.

sequenceDiagram
participant DOM as "DOM Ready"
participant Main as "main.js"
participant Cursor as "custom-cursor.js"
participant Hero as "hero-animations.js"
participant Parallax as "hero-parallax.js"
participant Poll as "poll-bar-animation.js"
participant Team as "team-card-flip.js"
participant Acc as "accordion.js"
DOM->>Main : "DOMContentLoaded"
Main->>Main : "Load modules"
Main->>Main : "Register GSAP/ScrollTrigger if available"
Main->>Team : "initTeamCardFlip()"
Main->>Acc : "initAccordion()"
Main->>Poll : "initPollAnimation()"
alt GSAP available
Main->>Cursor : "initCustomCursor()"
Main->>Hero : "initHeroAnimations()"
Main->>Hero : "initScrollReveals()"
opt Three.js hero present
Main->>Parallax : "Three.js scene runs independently"
end
else GSAP missing
Main-->>DOM : "Skip advanced animations"
end

Diagram sources

  • [main.js:15-36](file://src/assets/js/main.js#L15-L36)
  • [custom-cursor.js:1-28](file://src/assets/js/modules/custom-cursor.js#L1-L28)
  • [hero-animations.js:1-307](file://src/assets/js/modules/hero-animations.js#L1-L307)
  • [hero-parallax.js:1-462](file://src/assets/js/modules/hero-parallax.js#L1-L462)
  • [poll-bar-animation.js:1-20](file://src/assets/js/modules/poll-bar-animation.js#L1-L20)
  • [team-card-flip.js:1-14](file://src/assets/js/modules/team-card-flip.js#L1-L14)
  • [accordion.js:1-35](file://src/assets/js/modules/accordion.js#L1-L35)

Detailed Component Analysis

Custom Cursor

  • Behavior: On desktop, tracks mouse with two overlapping elements (cursor and follower) using GSAP for smooth easing. Adds hover class to scale and expand follower on interactive elements.
  • Device handling: Automatically hides on coarse-pointer devices or below a width threshold.
  • Styles: Uses CSS variables for themes, backdrop filters, shadows, and transitions. Reduced-motion media query disables cursor animations.
sequenceDiagram
participant User as "Mouse Move"
participant JS as "custom-cursor.js"
participant GSAP as "GSAP"
participant DOM as "cursor/cursor-follower"
participant CSS as "03-custom-cursor.css"
User->>JS : "mousemove"
JS->>GSAP : "Tween cursor/follower to (x,y)"
User->>JS : "enter/leave interactive element"
JS->>DOM : "add/remove .hover"
CSS-->>DOM : "scale/opacity transitions"

Diagram sources

  • [custom-cursor.js:16-24](file://src/assets/js/modules/custom-cursor.js#L16-L24)
  • [03-custom-cursor.css:15-43](file://src/assets/css/modules/03-custom-cursor.css#L15-L43)

Section sources

  • [custom-cursor.js:1-28](file://src/assets/js/modules/custom-cursor.js#L1-L28)
  • [03-custom-cursor.css:1-46](file://src/assets/css/modules/03-custom-cursor.css#L1-L46)
  • [29-reduced-motion.css:5-13](file://src/assets/css/modules/29-reduced-motion.css#L5-L13)

Hero Animations (GSAP)

  • Home hero: Staggered text reveal, optional particle background, Southern Cross twinkling, topo line drawing, and waypoint rings triggered by a drawn path. Scroll-driven parallax moves elements based on progress.
  • Other heroes: Slide-up reveal for titles and subtitles with staggered timing.
  • Scroll reveals: IntersectionObserver-based fade-in without ScrollTrigger overhead.
flowchart TD
Start(["initHeroAnimations"]) --> CheckHome{"Is homepage hero?"}
CheckHome --> |Yes| Setup["Hide text, init particles if canvas exists"]
Setup --> Reduced{"prefers-reduced-motion?"}
Reduced --> |Yes| Staggered["Staggered opacity/y reveal"]
Reduced --> |No| Advanced["initSouthernCross + initTopoLines + initNavPath"]
CheckHome --> |No| Other["Slide-up reveal timeline"]
Advanced --> Parallax["ScrollTrigger parallax onUpdate"]
Parallax --> Done(["Complete"])
Staggered --> Done
Other --> Done

Diagram sources

  • [hero-animations.js:3-44](file://src/assets/js/modules/hero-animations.js#L3-L44)
  • [hero-animations.js:106-152](file://src/assets/js/modules/hero-animations.js#L106-L152)
  • [hero-animations.js:155-209](file://src/assets/js/modules/hero-animations.js#L155-L209)
  • [hero-animations.js:283-304](file://src/assets/js/modules/hero-animations.js#L283-L304)

Section sources

  • [hero-animations.js:1-307](file://src/assets/js/modules/hero-animations.js#L1-L307)

Parallax Hero (Three.js)

  • Scene: Fog, camera, renderer with pixel ratio clamping, responsive resize
  • Terrain: Procedural heightfield built with noise, normals computed, plane rotated to face up
  • Contour lines: Computed off-main-thread using requestIdleCallback chunks and reassembled as BufferGeometry
  • Path: Catmull-Rom curve with sampled waypoints; route preview and waypoint points
  • Effects: Additive glow sprites, trail buffer with color fading, spark particles sampling trail positions
  • Camera: Smoothly follows path with look-ahead; sky layer translates horizontally; text scrambles at scroll thresholds
  • Theme: Applies day/night color schemes and textures based on theme class changes
classDiagram
class SceneSetup {
+renderer
+scene
+camera
+resize()
}
class Terrain {
+geometry
+material
+computeHeight()
}
class Contours {
+lineSegments
+buildChunks()
}
class Path {
+curve
+route
+waypoints
}
class Effects {
+halo
+core
+trail
+sparks
+appendTrailPoint()
+updateTrailFade()
+updateSparks()
}
class Camera {
+followCurve()
+lookAt()
}
class TextScramble {
+scramble()
}
SceneSetup --> Terrain : "adds"
SceneSetup --> Contours : "adds"
SceneSetup --> Path : "adds"
SceneSetup --> Effects : "adds"
Effects --> Camera : "updates"
TextScramble --> SceneSetup : "updates text"

Diagram sources

  • [hero-parallax.js:3-25](file://src/assets/js/modules/hero-parallax.js#L3-L25)
  • [hero-parallax.js:26-68](file://src/assets/js/modules/hero-parallax.js#L26-L68)
  • [hero-parallax.js:78-149](file://src/assets/js/modules/hero-parallax.js#L78-L149)
  • [hero-parallax.js:151-182](file://src/assets/js/modules/hero-parallax.js#L151-L182)
  • [hero-parallax.js:215-296](file://src/assets/js/modules/hero-parallax.js#L215-L296)
  • [hero-parallax.js:368-446](file://src/assets/js/modules/hero-parallax.js#L368-L446)
  • [hero-parallax.js:309-367](file://src/assets/js/modules/hero-parallax.js#L309-L367)

Section sources

  • [hero-parallax.js:1-462](file://src/assets/js/modules/hero-parallax.js#L1-L462)
  • [06-parallax-hero-three-js-scroll-driven-terrain.css:1-193](file://src/assets/css/modules/06-parallax-hero-three-js-scroll-driven-terrain.css#L1-L193)

Poll Bar Animation

  • Markup: Macro generates two adjacent segments with data attributes and initial zero widths
  • JS: Observes segments with IntersectionObserver; on threshold met, sets width to dataset value and stops observing
  • CSS: Transition on width for smooth easing
sequenceDiagram
participant Viewport as "Viewport"
participant Macro as "polling-bar.njk"
participant DOM as ".poll-bar-segment"
participant IO as "IntersectionObserver"
participant CSS as "32-news-page-detail-fix-poll-bar-animation-trigger.css"
Macro-->>DOM : "Render segments with data-value"
Viewport->>IO : "Scroll toward .poll-bar-segment"
IO->>DOM : "On intersect : set style.width = dataset.value + '%'"
CSS-->>DOM : "Transition width"

Diagram sources

  • [polling-bar.njk:7-10](file://src/_includes/macros/polling-bar.njk#L7-L10)
  • [poll-bar-animation.js:7-17](file://src/assets/js/modules/poll-bar-animation.js#L7-L17)
  • [32-news-page-detail-fix-poll-bar-animation-trigger.css:5-7](file://src/assets/css/modules/32-news-page-detail-fix-poll-bar-animation-trigger.css#L5-L7)

Section sources

  • [polling-bar.njk:1-39](file://src/_includes/macros/polling-bar.njk#L1-L39)
  • [poll-bar-animation.js:1-20](file://src/assets/js/modules/poll-bar-animation.js#L1-L20)
  • [32-news-page-detail-fix-poll-bar-animation-trigger.css:1-9](file://src/assets/css/modules/32-news-page-detail-fix-poll-bar-animation-trigger.css#L1-L9)

Team Card Flip

  • CSS: 3D perspective and preserve-3d; hover rotates Y 180deg; explicit flipped state for touch devices
  • JS: Detects no-hover capability and toggles flipped class on click
flowchart TD
Start(["Click .team-card"]) --> HoverCheck{"hover: none?"}
HoverCheck --> |Yes| Toggle["Add/remove 'flipped' class"]
HoverCheck --> |No| CSSHover["CSS :hover rotates .team-card-inner"]
Toggle --> End(["Flip visible"])
CSSHover --> End

Diagram sources

  • [team-card-flip.js:3-10](file://src/assets/js/modules/team-card-flip.js#L3-L10)
  • [12-team-grid-homepage-teaser.css:18-36](file://src/assets/css/modules/12-team-grid-homepage-teaser.css#L18-L36)
  • [12-team-grid-homepage-teaser.css:38-40](file://src/assets/css/modules/12-team-grid-homepage-teaser.css#L38-L40)

Section sources

  • [team-card-flip.js:1-14](file://src/assets/js/modules/team-card-flip.js#L1-L14)
  • [12-team-grid-homepage-teaser.css:1-117](file://src/assets/css/modules/12-team-grid-homepage-teaser.css#L1-L117)
  • [team-flip-card.njk:1-18](file://src/_includes/macros/team-flip-card.njk#L1-L18)

Accordion

  • Behavior: Clicking a header toggles the associated content’s active state; closes other open items; animates height and opacity
  • Accessibility: Uses closest and querySelector to scope behavior to each item
flowchart TD
Click(["Click .accordion-header"]) --> FindItem["Find .accordion-item"]
FindItem --> GetContent["Get .accordion-content and .accordion-inner"]
GetContent --> IsOpen{"item.classList.contains('active')?"}
IsOpen --> |Yes| Close["Remove active, set height=0, opacity=0"]
IsOpen --> |No| CloseOthers["Remove active from others"]
CloseOthers --> Open["Add active, set height to innerHeight or auto, opacity=1"]
Close --> End(["Done"])
Open --> End

Diagram sources

  • [accordion.js:3-31](file://src/assets/js/modules/accordion.js#L3-L31)

Section sources

  • [accordion.js:1-35](file://src/assets/js/modules/accordion.js#L1-L35)

Dependency Analysis

  • Initialization depends on optional libraries: GSAP and ScrollTrigger are registered conditionally
  • Cursor and hero animations require GSAP; parallax hero requires Three.js
  • Poll bar relies on IntersectionObserver; fallbacks are minimal
  • Reduced-motion media query affects cursor and logo animations
graph LR
GSAP["GSAP"] --> Cursor["custom-cursor.js"]
GSAP --> Hero["hero-animations.js"]
ScrollTrigger["ScrollTrigger"] --> Hero
Three["Three.js"] --> Parallax["hero-parallax.js"]
IO["IntersectionObserver"] --> Poll["poll-bar-animation.js"]
RM["prefers-reduced-motion"] --> Cursor
RM --> Hero

Diagram sources

  • [main.js:28-35](file://src/assets/js/main.js#L28-L35)
  • [custom-cursor.js:1-28](file://src/assets/js/modules/custom-cursor.js#L1-L28)
  • [hero-animations.js:1-307](file://src/assets/js/modules/hero-animations.js#L1-L307)
  • [hero-parallax.js:1-462](file://src/assets/js/modules/hero-parallax.js#L1-L462)
  • [poll-bar-animation.js:1-20](file://src/assets/js/modules/poll-bar-animation.js#L1-L20)
  • [29-reduced-motion.css:5-13](file://src/assets/css/modules/29-reduced-motion.css#L5-L13)

Section sources

  • [main.js:15-36](file://src/assets/js/main.js#L15-L36)

Performance Considerations

  • requestAnimationFrame usage:
    • Three.js loop uses a dedicated animate function with sleep/wake logic to pause when hidden or faded out
    • Scrambling text uses requestAnimationFrame with cancellation to avoid wasted frames
  • GPU acceleration:
    • Three.js materials configured for additive blending and depth writes disabled where appropriate
    • Trail and spark rendering use typed arrays and buffer geometry for efficient GPU upload
  • Memory management:
    • Geometry disposal replaces old contour geometry with new instances
    • Trail buffers copy within to maintain a moving window, avoiding unbounded growth
  • Off-main-thread work:
    • Contour generation uses requestIdleCallback to chunk heavy computation
  • Scroll performance:
    • Scroll-driven parallax uses ScrollTrigger with scrubbing and onUpdate to avoid layout thrashing
    • IntersectionObserver avoids ScrollTrigger overhead for simple fades
  • Reduced motion:
    • Media query short-circuits animations and cursor for users who prefer less motion

Section sources

  • [hero-parallax.js:85-149](file://src/assets/js/modules/hero-parallax.js#L85-L149)
  • [hero-parallax.js:309-367](file://src/assets/js/modules/hero-parallax.js#L309-L367)
  • [hero-parallax.js:437-446](file://src/assets/js/modules/hero-parallax.js#L437-L446)
  • [hero-parallax.js:459-462](file://src/assets/js/modules/hero-parallax.js#L459-L462)
  • [hero-animations.js:283-304](file://src/assets/js/modules/hero-animations.js#L283-L304)
  • [29-reduced-motion.css:5-13](file://src/assets/css/modules/29-reduced-motion.css#L5-L13)

Troubleshooting Guide

  • GSAP not loaded:
    • Symptom: console warning and animations skipped
    • Action: Ensure GSAP and ScrollTrigger are included before initialization
    • Reference: [main.js:33-35](file://src/assets/js/main.js#L33-L35)
  • Cursor not appearing:
    • Symptom: cursor hidden on mobile or coarse-pointer devices
    • Action: Verify device detection and media query overrides
    • Reference: [custom-cursor.js:8-12](file://src/assets/js/modules/custom-cursor.js#L8-L12), [03-custom-cursor.css:41-43](file://src/assets/css/modules/03-custom-cursor.css#L41-L43)
  • Poll bar not animating:
    • Symptom: segments remain at 0%
    • Action: Confirm IntersectionObserver threshold and element visibility; ensure data-value attributes are numeric
    • Reference: [poll-bar-animation.js:7-17](file://src/assets/js/modules/poll-bar-animation.js#L7-L17), [polling-bar.njk:8-9](file://src/_includes/macros/polling-bar.njk#L8-L9)
  • Team card not flipping:
    • Symptom: no flip on hover or click
    • Action: Check hover media query and flipped class toggling
    • Reference: [12-team-grid-homepage-teaser.css:34-36](file://src/assets/css/modules/12-team-grid-homepage-teaser.css#L34-L36), [team-card-flip.js:4-10](file://src/assets/js/modules/team-card-flip.js#L4-L10)
  • Accordion not closing others:
    • Symptom: multiple panels open
    • Action: Verify event scoping and active class toggling
    • Reference: [accordion.js:13-29](file://src/assets/js/modules/accordion.js#L13-L29)

Section sources

  • [main.js:33-35](file://src/assets/js/main.js#L33-L35)
  • [custom-cursor.js:8-12](file://src/assets/js/modules/custom-cursor.js#L8-L12)
  • [03-custom-cursor.css:41-43](file://src/assets/css/modules/03-custom-cursor.css#L41-L43)
  • [poll-bar-animation.js:7-17](file://src/assets/js/modules/poll-bar-animation.js#L7-L17)
  • [polling-bar.njk:8-9](file://src/_includes/macros/polling-bar.njk#L8-L9)
  • [12-team-grid-homepage-teaser.css:34-36](file://src/assets/css/modules/12-team-grid-homepage-teaser.css#L34-L36)
  • [team-card-flip.js:4-10](file://src/assets/js/modules/team-card-flip.js#L4-L10)
  • [accordion.js:13-29](file://src/assets/js/modules/accordion.js#L13-L29)

Conclusion

The animation system blends lightweight CSS transitions with robust JS-driven effects. GSAP powers sophisticated hero animations and cursor behavior, while Three.js elevates the parallax hero with GPU-accelerated 3D rendering. Poll bars, team cards, and accordions provide cohesive micro-interactions. Performance-conscious patterns—requestAnimationFrame loops, off-main-thread work, and reduced-motion support—ensure smooth experiences across devices.

Appendices

Practical Examples and Customization Tips

  • Custom cursor
    • Adjust easing and durations in the cursor module
    • Modify hover scale/opacity in CSS variables for brand alignment
    • Reference: [custom-cursor.js:16-19](file://src/assets/js/modules/custom-cursor.js#L16-L19), [03-custom-cursor.css:15-43](file://src/assets/css/modules/03-custom-cursor.css#L15-L43)
  • Hero animations
    • Add or modify timeline stages in the hero module
    • Tune ScrollTrigger scrub timing for smoother parallax
    • Reference: [hero-animations.js:142-151](file://src/assets/js/modules/hero-animations.js#L142-L151)
  • Parallax hero (Three.js)
    • Change fog color and material colors via theme observer
    • Adjust trail length and glow textures for performance or style
    • Reference: [hero-parallax.js:449-462](file://src/assets/js/modules/hero-parallax.js#L449-L462)
  • Poll bar
    • Swap transition timing function for different feel
    • Reference: [32-news-page-detail-fix-poll-bar-animation-trigger.css:6](file://src/assets/css/modules/32-news-page-detail-fix-poll-bar-animation-trigger.css#L6)
  • Team card
    • Replace 3D rotation with 2D transforms for simpler devices
    • Reference: [12-team-grid-homepage-teaser.css:34-36](file://src/assets/css/modules/12-team-grid-homepage-teaser.css#L34-L36)
  • Accordion
    • Extend to allow multiple open items by removing “close others” logic
    • Reference: [accordion.js:13-19](file://src/assets/js/modules/accordion.js#L13-L19)

Browser Compatibility Notes

  • GSAP and ScrollTrigger: Required for advanced animations; graceful degradation occurs if unavailable
  • IntersectionObserver: Used for poll bar and scroll reveals; falls back to static styles if unsupported
  • Reduced motion: Respects user preference to minimize motion
  • Pointer/media queries: Cursor and team card behavior adapt to device capabilities

Section sources

  • [main.js:28-35](file://src/assets/js/main.js#L28-L35)
  • [poll-bar-animation.js:7-17](file://src/assets/js/modules/poll-bar-animation.js#L7-L17)
  • [29-reduced-motion.css:5-13](file://src/assets/css/modules/29-reduced-motion.css#L5-L13)