From e33dcdddac5e2e103279935b9e17e25d7a7e55e0 Mon Sep 17 00:00:00 2001 From: Marc Mintel Date: Mon, 11 May 2026 21:44:31 +0200 Subject: [PATCH] feat: replace literal decorations with AbstractBore and AbstractTrench Former-commit-id: 4f7c5fcc7203aa4a36aabd8ffc13cf9f28a0f77a --- components/blocks/CompetenceBentoGrid.tsx | 17 +- components/blocks/HeroSection.tsx | 17 +- components/blocks/HeroVideo.tsx | 6 +- components/blocks/ReferencesSlider.tsx | 17 +- components/blocks/ServiceDetailGrid.tsx | 6 +- components/blocks/SubCompanyTiles.tsx | 17 +- components/layout/Footer.tsx | 16 +- .../providers/PageTransitionShutter.tsx | 26 +--- components/ui/decorations/AbstractBore.tsx | 71 +++++++++ components/ui/decorations/AbstractTrench.tsx | 70 +++++++++ components/ui/decorations/DrillBitSpinner.tsx | 125 --------------- components/ui/decorations/DrillOrbit.tsx | 147 ------------------ components/ui/decorations/DrillTeeth.tsx | 62 -------- 13 files changed, 186 insertions(+), 411 deletions(-) create mode 100644 components/ui/decorations/AbstractBore.tsx create mode 100644 components/ui/decorations/AbstractTrench.tsx delete mode 100644 components/ui/decorations/DrillBitSpinner.tsx delete mode 100644 components/ui/decorations/DrillOrbit.tsx delete mode 100644 components/ui/decorations/DrillTeeth.tsx diff --git a/components/blocks/CompetenceBentoGrid.tsx b/components/blocks/CompetenceBentoGrid.tsx index 0b38fd35d..204410f00 100644 --- a/components/blocks/CompetenceBentoGrid.tsx +++ b/components/blocks/CompetenceBentoGrid.tsx @@ -7,8 +7,8 @@ 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'; -import { DrillTeeth } from '@/components/ui/decorations/DrillTeeth'; +import { AbstractBore } from '@/components/ui/decorations/AbstractBore'; +import { AbstractTrench } from '@/components/ui/decorations/AbstractTrench'; interface CompetenceBentoGridProps { badge?: string; @@ -170,15 +170,10 @@ export function CompetenceBentoGrid(props: CompetenceBentoGridProps) { })} - {/* Decorative: large abstract drill bit spinning slowly in background */} -
- -
- {/* Decorative: abstract earth strata / excavation layers */} - - - {/* Organic wave divider */} - + {/* Minimalist Abstract Drilling */} + + {/* Minimalist Abstract Trenching */} + ); } diff --git a/components/blocks/HeroSection.tsx b/components/blocks/HeroSection.tsx index 142f33a9b..a458c50ff 100644 --- a/components/blocks/HeroSection.tsx +++ b/components/blocks/HeroSection.tsx @@ -3,9 +3,8 @@ import Image from 'next/image'; 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'; -import { DrillTeeth } from '@/components/ui/decorations/DrillTeeth'; +import { AbstractBore } from '@/components/ui/decorations/AbstractBore'; +import { AbstractTrench } from '@/components/ui/decorations/AbstractTrench'; export interface HeroSectionProps { title: string; @@ -73,14 +72,10 @@ export const HeroSection: React.FC = (props) => { )} - {/* Decorative: large abstract drill bit spinning slowly in background */} -
- -
- {/* Decorative: abstract HDD bore trajectory */} - - {/* Organic wave divider — displaced earth strata */} - + {/* Minimalist Abstract Drilling (HDD) */} + + {/* Minimalist Abstract Trenching */} + ); diff --git a/components/blocks/HeroVideo.tsx b/components/blocks/HeroVideo.tsx index fd781aa07..e4e34916b 100644 --- a/components/blocks/HeroVideo.tsx +++ b/components/blocks/HeroVideo.tsx @@ -4,7 +4,7 @@ import { Button } from '@/components/ui/Button'; import Image from 'next/image'; import { motion, AnimatePresence } from 'framer-motion'; import { useState, useEffect } from 'react'; -import { DrillTeeth } from '@/components/ui/decorations/DrillTeeth'; +import { AbstractBore } from '@/components/ui/decorations/AbstractBore'; interface HeroVideoProps { data?: any; @@ -109,8 +109,8 @@ export function HeroVideo(props: HeroVideoProps) { - {/* Organic wave divider — displaced earth strata */} - + {/* Minimalist Abstract Drilling */} + ); } diff --git a/components/blocks/ReferencesSlider.tsx b/components/blocks/ReferencesSlider.tsx index 140de2ba5..4bd9a67fe 100644 --- a/components/blocks/ReferencesSlider.tsx +++ b/components/blocks/ReferencesSlider.tsx @@ -5,9 +5,8 @@ import { motion } from 'framer-motion'; 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'; -import { DrillTeeth } from '@/components/ui/decorations/DrillTeeth'; +import { AbstractBore } from '@/components/ui/decorations/AbstractBore'; +import { AbstractTrench } from '@/components/ui/decorations/AbstractTrench'; export interface Reference { id: string; @@ -154,14 +153,10 @@ export function ReferencesSlider(props: ReferencesSliderProps) { - {/* Decorative: large abstract drill bit spinning slowly in background */} -
- -
- {/* Decorative: abstract HDD bore trajectory */} - - {/* Organic wave divider */} - + {/* Minimalist Abstract Drilling */} + + {/* Minimalist Abstract Trenching */} + ); } diff --git a/components/blocks/ServiceDetailGrid.tsx b/components/blocks/ServiceDetailGrid.tsx index b75a0b058..6ada1c18f 100644 --- a/components/blocks/ServiceDetailGrid.tsx +++ b/components/blocks/ServiceDetailGrid.tsx @@ -3,7 +3,7 @@ import * as React from 'react'; import { motion, Variants } from 'framer-motion'; import { HoverShineOverlay } from '@/components/ui/HoverShineOverlay'; -import { DrillTeeth } from '@/components/ui/decorations/DrillTeeth'; +import { AbstractTrench } from '@/components/ui/decorations/AbstractTrench'; export interface ServicePanelData { id: string; @@ -230,8 +230,8 @@ export function ServiceDetailGrid({ })} - {/* Organic wave divider */} - + {/* Minimalist Abstract Trenching */} + ); } diff --git a/components/blocks/SubCompanyTiles.tsx b/components/blocks/SubCompanyTiles.tsx index 1994e780a..46ea0966b 100644 --- a/components/blocks/SubCompanyTiles.tsx +++ b/components/blocks/SubCompanyTiles.tsx @@ -4,9 +4,8 @@ import * as React from 'react'; 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'; -import { DrillTeeth } from '@/components/ui/decorations/DrillTeeth'; +import { AbstractBore } from '@/components/ui/decorations/AbstractBore'; +import { AbstractTrench } from '@/components/ui/decorations/AbstractTrench'; interface SubCompanyTilesProps { badge?: string; @@ -200,14 +199,10 @@ export function SubCompanyTiles(props: SubCompanyTilesProps) { })} - {/* Decorative: large abstract drill bit spinning slowly in background */} -
- -
- {/* Decorative: abstract HDD bore trajectory */} - - {/* Organic wave divider */} - + {/* Minimalist Abstract Drilling */} + + {/* Minimalist Abstract Trenching */} + ); } diff --git a/components/layout/Footer.tsx b/components/layout/Footer.tsx index b25ef9a21..21d3f10b5 100644 --- a/components/layout/Footer.tsx +++ b/components/layout/Footer.tsx @@ -4,8 +4,8 @@ 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'; -import { DrillTeeth } from '@/components/ui/decorations/DrillTeeth'; +import { AbstractBore } from '@/components/ui/decorations/AbstractBore'; +import { AbstractTrench } from '@/components/ui/decorations/AbstractTrench'; interface CompanyInfo { contactEmail: string; @@ -22,8 +22,6 @@ export function Footer({ companyInfo }: FooterProps) { return (
- {/* Organic wave divider at the top */} - {/* Subtle background tech grid */}
@@ -155,11 +153,11 @@ export function Footer({ companyInfo }: FooterProps) {
High Performance
- {/* Decorative: large abstract drill bit spinning slowly in background */} -
- -
- {/* Decorative: abstract earth strata */} + {/* Minimalist Abstract Drilling */} + + {/* Minimalist Abstract Trenching */} + + {/* Abstract earth strata */}
); diff --git a/components/providers/PageTransitionShutter.tsx b/components/providers/PageTransitionShutter.tsx index 1a12ca918..8e310d25b 100644 --- a/components/providers/PageTransitionShutter.tsx +++ b/components/providers/PageTransitionShutter.tsx @@ -4,7 +4,6 @@ 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(); @@ -159,28 +158,19 @@ export function PageTransitionShutter() { )} - {/* ── DrillBit loading indicator (replaces three dots) ── */} + {/* ── Abstract horizontal energy pulse (Loader) ── */} - {/* Outer pulsing ring */} - - {/* Background bore arc (full width, bottom) */} diff --git a/components/ui/decorations/AbstractBore.tsx b/components/ui/decorations/AbstractBore.tsx new file mode 100644 index 000000000..c635c92c6 --- /dev/null +++ b/components/ui/decorations/AbstractBore.tsx @@ -0,0 +1,71 @@ +'use client'; + +import { motion } from 'framer-motion'; + +interface AbstractBoreProps { + className?: string; + invert?: boolean; +} + +/** + * AbstractBore + * + * Visualizes Horizontal Directional Drilling (HDD). + * A smooth, parabolic underground arc. A beam of energy (the drill/cable) + * travels along this path, fading in gently at the start and fading out at the end. + * Purely abstract, no literal drill bits or circles. + */ +export function AbstractBore({ className = '', invert = false }: AbstractBoreProps) { + const color = invert ? 'rgba(10, 61, 40, 0.6)' : 'rgba(14, 122, 92, 0.6)'; + const glowColor = invert ? 'rgba(10, 61, 40, 1)' : 'rgba(20, 184, 138, 1)'; + + // Parabolic path: Starts left, dips deep in the middle, comes up right + const pathD = "M -100 50 C 200 50 300 250 500 250 C 700 250 800 50 1100 50"; + // The length of this cubic bezier is approx 1260 + const pathLength = 1260; + // The length of the moving beam + const beamLength = 200; + + return ( + + ); +} diff --git a/components/ui/decorations/AbstractTrench.tsx b/components/ui/decorations/AbstractTrench.tsx new file mode 100644 index 000000000..14686ebee --- /dev/null +++ b/components/ui/decorations/AbstractTrench.tsx @@ -0,0 +1,70 @@ +'use client'; + +import { motion } from 'framer-motion'; + +interface AbstractTrenchProps { + className?: string; + invert?: boolean; +} + +/** + * AbstractTrench + * + * Visualizes open trench construction (Offene Bauweise / Graben). + * A sharp, geometric profile representing a cut into the earth. + * A beam of energy flows through the trench, hugging the sharp corners, + * fading in and out at the horizontal edges. + * Purely abstract, architectural styling. + */ +export function AbstractTrench({ className = '', invert = false }: AbstractTrenchProps) { + const color = invert ? 'rgba(10, 61, 40, 0.6)' : 'rgba(14, 122, 92, 0.6)'; + const glowColor = invert ? 'rgba(10, 61, 40, 1)' : 'rgba(20, 184, 138, 1)'; + + // Geometric trench path: straight, 45-deg drop, straight bottom, 45-deg rise, straight + const pathD = "M -100 50 L 300 50 L 350 200 L 650 200 L 700 50 L 1100 50"; + // Length of this polyline is approx 1260 + const pathLength = 1260; + const beamLength = 250; + + return ( + + ); +} diff --git a/components/ui/decorations/DrillBitSpinner.tsx b/components/ui/decorations/DrillBitSpinner.tsx deleted file mode 100644 index a9647cb67..000000000 --- a/components/ui/decorations/DrillBitSpinner.tsx +++ /dev/null @@ -1,125 +0,0 @@ -'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. - * - * The wrapping div uses a radial-gradient mask so it fades naturally - * into whatever background it's placed on — no hard edge clipping. - */ - -interface DrillBitSpinnerProps { - size?: number; - color?: string; - duration?: number; - opacity?: number; - 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; - - 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 ( - - ); -} diff --git a/components/ui/decorations/DrillOrbit.tsx b/components/ui/decorations/DrillOrbit.tsx deleted file mode 100644 index 42be1f6c1..000000000 --- a/components/ui/decorations/DrillOrbit.tsx +++ /dev/null @@ -1,147 +0,0 @@ -'use client'; - -import { motion, useInView } from 'framer-motion'; -import { useRef } from 'react'; - -/** - * DrillOrbit - * - * A glowing point looping along a parabolic arc — - * abstractly evoking a horizontal directional drill path. - * - * The SVG has a horizontal linear-gradient mask: the entire - * element fades in from the edge and out toward the opposite side. - * The travelling dot also animates its own opacity to fade in/out - * at the path endpoints — no abrupt appearance or disappearance. - */ - -type Side = 'left' | 'right'; - -interface DrillOrbitProps { - side?: Side; - invert?: boolean; - className?: string; -} - -const PATH = 'M -20 80 C 150 80 200 340 400 340 C 600 340 650 80 820 80'; - -export function DrillOrbit({ - side = 'right', - invert = false, - className = '', -}: DrillOrbitProps) { - const ref = useRef(null); - const isInView = useInView(ref, { once: true, margin: '0px 0px -10% 0px' }); - - const color = invert ? '#084c39' : '#0e7a5c'; - const glowColor = invert ? 'rgba(8,76,57,0.35)' : 'rgba(14,122,92,0.45)'; - - // Fade from transparent → opaque → transparent over the animation cycle - // so the dot smoothly appears from the edge and disappears at the far edge. - const dotOpacityKeyframes = [0, 0, 1, 1, 1, 0, 0]; - const dotOpacityTimes = [0, 0.08, 0.18, 0.5, 0.82, 0.92, 1]; - - const transition = { - duration: 5.5, - ease: 'easeInOut' as const, - repeat: Infinity, - repeatDelay: 1.5, - }; - - return ( - - ); -} diff --git a/components/ui/decorations/DrillTeeth.tsx b/components/ui/decorations/DrillTeeth.tsx deleted file mode 100644 index 8dde05aa4..000000000 --- a/components/ui/decorations/DrillTeeth.tsx +++ /dev/null @@ -1,62 +0,0 @@ -import React from 'react'; - -/** - * DrillTeeth - * - * Abstract, minimalist section divider inspired by HDD bore paths. - * Not literal teeth — instead, a subtle organic wave that hints at - * earth strata displaced by subsurface drilling. - * - * Two gentle asymmetric curves create a refined, modern transition - * between sections. Think Stripe/Linear, not construction site. - * - * Usage: Place inside a section with `relative overflow-hidden`. - * The SVG renders outside the box via translate, creating overlap. - */ - -interface DrillTeethProps { - /** Which edge of the parent section */ - position?: 'top' | 'bottom'; - /** Fill color — should match the CURRENT section's background */ - fill?: string; - className?: string; -} - -export function DrillTeeth({ - position = 'bottom', - fill = 'currentColor', - className = '', -}: DrillTeethProps) { - const isTop = position === 'top'; - - return ( - - ); -}