diff --git a/components/blocks/CompetenceBentoGrid.tsx b/components/blocks/CompetenceBentoGrid.tsx index a8aae7282..b27df180f 100644 --- a/components/blocks/CompetenceBentoGrid.tsx +++ b/components/blocks/CompetenceBentoGrid.tsx @@ -7,6 +7,7 @@ import { useState, useEffect } from 'react'; import { Button } from '@/components/ui/Button'; import { HoverShineOverlay } from '@/components/ui/HoverShineOverlay'; import { StratumLines } from '@/components/ui/decorations/StratumLines'; +import { DrillBitSpinner } from '@/components/ui/decorations/DrillBitSpinner'; interface CompetenceBentoGridProps { badge?: string; @@ -168,6 +169,10 @@ export function CompetenceBentoGrid(props: CompetenceBentoGridProps) { })} + {/* Decorative: large abstract drill bit spinning slowly in background */} +
+ +
{/* Decorative: abstract earth strata / excavation layers */} diff --git a/components/blocks/HeroSection.tsx b/components/blocks/HeroSection.tsx index 445d202a3..ae47b59e0 100644 --- a/components/blocks/HeroSection.tsx +++ b/components/blocks/HeroSection.tsx @@ -4,6 +4,7 @@ import Reveal from '@/components/Reveal'; import { Badge, Container, Heading } from '@/components/ui'; import { Button } from '@/components/ui/Button'; import { DrillOrbit } from '@/components/ui/decorations/DrillOrbit'; +import { DrillBitSpinner } from '@/components/ui/decorations/DrillBitSpinner'; export interface HeroSectionProps { title: string; @@ -71,6 +72,10 @@ export const HeroSection: React.FC = (props) => { )} + {/* Decorative: large abstract drill bit spinning slowly in background */} +
+ +
{/* Decorative: abstract HDD bore trajectory */} diff --git a/components/blocks/ReferencesSlider.tsx b/components/blocks/ReferencesSlider.tsx index 93aca8cef..463fa25ed 100644 --- a/components/blocks/ReferencesSlider.tsx +++ b/components/blocks/ReferencesSlider.tsx @@ -6,6 +6,7 @@ import Link from 'next/link'; import Image from 'next/image'; import { HoverShineOverlay } from '@/components/ui/HoverShineOverlay'; import { DrillOrbit } from '@/components/ui/decorations/DrillOrbit'; +import { DrillBitSpinner } from '@/components/ui/decorations/DrillBitSpinner'; export interface Reference { id: string; @@ -152,6 +153,10 @@ export function ReferencesSlider(props: ReferencesSliderProps) { + {/* Decorative: large abstract drill bit spinning slowly in background */} +
+ +
{/* Decorative: abstract HDD bore trajectory */} diff --git a/components/blocks/SubCompanyTiles.tsx b/components/blocks/SubCompanyTiles.tsx index 416086502..ef76ed1f7 100644 --- a/components/blocks/SubCompanyTiles.tsx +++ b/components/blocks/SubCompanyTiles.tsx @@ -5,6 +5,7 @@ import { motion, Variants } from 'framer-motion'; import Image from 'next/image'; import { HoverShineOverlay } from '@/components/ui/HoverShineOverlay'; import { DrillOrbit } from '@/components/ui/decorations/DrillOrbit'; +import { DrillBitSpinner } from '@/components/ui/decorations/DrillBitSpinner'; interface SubCompanyTilesProps { badge?: string; @@ -198,6 +199,10 @@ export function SubCompanyTiles(props: SubCompanyTilesProps) { })} + {/* Decorative: large abstract drill bit spinning slowly in background */} +
+ +
{/* Decorative: abstract HDD bore trajectory */} diff --git a/components/layout/Footer.tsx b/components/layout/Footer.tsx index 8a722ad5d..258075b21 100644 --- a/components/layout/Footer.tsx +++ b/components/layout/Footer.tsx @@ -4,6 +4,7 @@ import { useLocale } from 'next-intl'; import { ShieldCheck, Leaf, Lock, Accessibility, Zap } from 'lucide-react'; import { LanguageSwitcher } from './LanguageSwitcher'; import { StratumLines } from '@/components/ui/decorations/StratumLines'; +import { DrillBitSpinner } from '@/components/ui/decorations/DrillBitSpinner'; interface CompanyInfo { contactEmail: string; @@ -151,6 +152,10 @@ export function Footer({ companyInfo }: FooterProps) {
High Performance
+ {/* Decorative: large abstract drill bit spinning slowly in background */} +
+ +
{/* Decorative: abstract earth strata */} diff --git a/components/providers/PageTransitionShutter.tsx b/components/providers/PageTransitionShutter.tsx index 84c1d5bdc..a53de6886 100644 --- a/components/providers/PageTransitionShutter.tsx +++ b/components/providers/PageTransitionShutter.tsx @@ -4,6 +4,7 @@ import React from 'react'; import { motion, AnimatePresence } from 'framer-motion'; import { useTransition } from './TransitionProvider'; import Image from 'next/image'; +import { DrillBitSpinner } from '@/components/ui/decorations/DrillBitSpinner'; export function PageTransitionShutter() { const { isTransitioning, transitionMessage } = useTransition(); @@ -144,35 +145,36 @@ export function PageTransitionShutter() { )} - {/* Extremely minimalist transition indicator */} - - {[0, 1, 2].map((i) => ( - - ))} + {/* Outer pulsing ring */} + + + - {/* Abstract HDD bore arc — decorative element during page transitions */} + {/* Background bore arc (full width, bottom) */} - diff --git a/components/ui/decorations/DrillBitSpinner.tsx b/components/ui/decorations/DrillBitSpinner.tsx new file mode 100644 index 000000000..1cb69cabd --- /dev/null +++ b/components/ui/decorations/DrillBitSpinner.tsx @@ -0,0 +1,131 @@ +'use client'; + +import { motion } from 'framer-motion'; + +/** + * DrillBitSpinner + * + * Abstract animated drill head cross-section. + * Resembles an HDD tri-blade drill bit seen from the front. + * + * - 3 rotating cutting blades at 120° intervals + * - Outer halo ring + * - Inner core circle + * - Continuous rotation with optional pulse glow + * + * Zero layout impact — position it absolutely in its parent. + */ + +interface DrillBitSpinnerProps { + /** Diameter in pixels */ + size?: number; + /** Color of the drill elements */ + color?: string; + /** Rotation duration in seconds */ + duration?: number; + /** Overall opacity 0–1 */ + opacity?: number; + /** Whether to show a pulse glow ring */ + glow?: boolean; + className?: string; +} + +export function DrillBitSpinner({ + size = 120, + color = '#0e7a5c', + duration = 8, + opacity = 1, + glow = true, + className = '', +}: DrillBitSpinnerProps) { + const r = size / 2; + const outerR = r * 0.92; + const bladeLen = r * 0.62; + const bladeW = r * 0.18; + const coreR = r * 0.22; + + // 3 blade tip positions at 120° intervals + // Each blade: a rounded rectangle swept from center outward + const blades = [0, 120, 240].map((deg) => { + const rad = (deg * Math.PI) / 180; + return { + x: r + Math.cos(rad) * (bladeLen * 0.5), + y: r + Math.sin(rad) * (bladeLen * 0.5), + rotate: deg, + }; + }); + + return ( + + ); +}