Update design system to version 2.0, enhancing methodology and characteristics for a more technical aesthetic. Added new color palette variants and refined typography usage. Introduced new animations and interactions for improved user engagement. Updated favicon and apple touch icon assets. Revamped sections for better layout and visual hierarchy, including the Experience and Featured Project sections. Enhanced contact page with improved form handling and custom dropdown functionality.

This commit is contained in:
Nicholai 2025-12-06 19:46:31 -07:00
parent aae6f7a25a
commit 4689332679
14 changed files with 900 additions and 1023 deletions

View File

@ -1,20 +1,20 @@
{
"design_system": {
"name": "V7 Industrial Dark Mode System",
"version": "1.0",
"version": "2.0",
"methodology": {
"approach": "Brutalist/Industrial Dark UI",
"philosophy": "Grid-visible, high-contrast, typography-forward design with layered content and subtle glassmorphism",
"approach": "Brutalist/Industrial Dark UI with System/Terminal Aesthetics",
"philosophy": "Grid-visible, high-contrast, typography-forward design. Interfaces should feel like high-end technical equipment (F1 telemetry, server racks, terminals).",
"characteristics": [
"Dark mode native (not an option, the default)",
"Visible grid structure as design element",
"Massive typography as primary visual hierarchy",
"Visible grid structure as design element (10x10 interactive or 12-col static)",
"Massive typography as primary visual hierarchy (2-line stacks)",
"Minimal rounded corners (sharp, industrial aesthetic)",
"Heavy use of borders and dividers",
"Layered content with overlays and blend modes",
"Subtle animations and smooth transitions",
"Opacity-based depth system",
"Technical/monospace accents"
"Heavy use of borders, dividers, and technical labels (SYS.01, ///)",
"Layered content with overlays, video backgrounds, and blend modes",
"System-like animations: boot-up sequences, grid trails, status pulses",
"Opacity-based depth system (glass panels)",
"Technical/monospace accents for metadata (coordinates, time, IDs)"
]
},
"color_palette": {
@ -43,7 +43,7 @@
"hex": "#ff4d00",
"rgb": "255, 77, 0",
"name": "Vibrant Orange",
"usage": "Primary accent, CTAs, highlights, interactive elements",
"usage": "Primary accent, CTAs, highlights, interactive elements, status indicators",
"opacity_variants": [
{
"name": "brand_accent_5",
@ -74,6 +74,7 @@
"white": {
"hex": "#FFFFFF",
"opacity_scale": {
"2": "rgba(255, 255, 255, 0.02)",
"5": "rgba(255, 255, 255, 0.05)",
"10": "rgba(255, 255, 255, 0.1)",
"20": "rgba(255, 255, 255, 0.2)",
@ -125,37 +126,6 @@
}
]
}
},
"gradients": {
"primary_hero": {
"type": "linear-gradient",
"direction": "to top right",
"stops": [
"brand_accent",
"orange-500 (via)",
"brand_panel"
],
"css": "bg-gradient-to-tr from-brand-accent via-orange-500 to-brand-panel"
},
"fade_top": {
"type": "linear-gradient",
"direction": "to top",
"stops": [
"brand_dark",
"transparent (via)",
"transparent"
],
"usage": "Image overlays"
},
"card_dramatic": {
"type": "linear-gradient",
"direction": "to bottom right",
"stops": [
"orange-600",
"rose-700"
],
"usage": "Feature cards"
}
}
},
"typography": {
@ -163,43 +133,16 @@
"primary": {
"name": "Inter",
"type": "sans-serif",
"weights": [
300,
400,
500,
600,
700,
800
],
"usage": "Primary UI font",
"fallback": "sans-serif"
},
"mono": {
"name": "system-ui monospace",
"usage": "Numbers, technical details, small labels",
"usage": "Numbers, technical details, small labels, coordinates, clock",
"examples": [
"font-mono"
]
},
"available_alternatives": [
"Geist",
"Roboto",
"Montserrat",
"Poppins",
"Playfair Display",
"Instrument Serif",
"Merriweather",
"Bricolage Grotesque",
"Plus Jakarta Sans",
"Manrope",
"Space Grotesk",
"Work Sans",
"PT Serif",
"Geist Mono",
"Space Mono",
"Quicksand",
"Nunito"
]
}
},
"scale": {
"xs": {
@ -242,582 +185,119 @@
"line_height": "2.5rem",
"usage": "Page headings"
},
"5xl": {
"size": "3rem",
"line_height": "1",
"usage": "Large headings"
},
"6xl": {
"size": "3.75rem",
"line_height": "1",
"usage": "Hero headings"
},
"7xl": {
"size": "4.5rem",
"line_height": "1",
"usage": "Display text (md)"
},
"8xl": {
"size": "6rem",
"line_height": "1",
"usage": "Display text (lg)"
"usage": "Display text"
},
"massive": {
"sizes": [
"12rem",
"18rem (md)",
"22rem (lg)"
],
"line_height": "none",
"usage": "Hero display, massive branding"
"9xl": {
"size": "8rem",
"line_height": "0.85",
"usage": "Massive Headers (2-line stacks)"
}
},
"weights": {
"light": 300,
"normal": 400,
"medium": 500,
"semibold": 600,
"bold": 700,
"extrabold": 800
},
"letter_spacing": {
"tighter": "-0.05em",
"tight": "-0.025em",
"normal": "0",
"wide": "0.025em",
"wider": "0.05em",
"widest": "0.1em"
},
"text_transforms": {
"uppercase": {
"usage": "Labels, navigation, tags, metadata",
"typical_size": "xs or sm",
"typical_tracking": "widest or wider",
"typical_weight": "semibold or bold"
}
},
"line_heights": {
"none": "1",
"tight": "1.25",
"relaxed": "1.625"
},
"patterns": {
"small_label": {
"size": "text-xs",
"weight": "font-bold",
"technical_label": {
"size": "text-[10px]",
"weight": "font-bold or font-medium",
"family": "font-mono",
"transform": "uppercase",
"tracking": "tracking-widest",
"example": "text-xs font-bold uppercase tracking-widest"
"color": "text-slate-500 or text-brand-accent",
"example": "SYS.01 /// ACTIVE"
},
"hero_title": {
"size": "text-[12rem] md:text-[18rem] lg:text-[22rem]",
"massive_stack": {
"size": "text-6xl md:text-8xl lg:text-9xl",
"weight": "font-bold",
"line_height": "leading-none",
"line_height": "leading-[0.85]",
"tracking": "tracking-tighter",
"example_modifiers": "text-transparent bg-clip-text bg-gradient-to-tr"
},
"section_heading": {
"size": "text-4xl md:text-5xl lg:text-6xl",
"weight": "font-semibold",
"tracking": "tracking-tight",
"color": "text-white"
},
"body_text": {
"size": "text-sm md:text-base",
"color": "text-slate-400",
"line_height": "leading-relaxed",
"weight": "font-normal or font-medium"
},
"mono_detail": {
"family": "font-mono",
"size": "text-xs or text-sm",
"weight": "font-medium or font-semibold",
"usage": "Numbers, codes, technical info"
"structure": "Two or three lines, mixture of solid white and text-stroke or accent color"
}
}
},
"spacing": {
"scale": {
"0": "0px",
"1": "0.25rem",
"2": "0.5rem",
"3": "0.75rem",
"4": "1rem",
"6": "1.5rem",
"8": "2rem",
"10": "2.5rem",
"12": "3rem",
"16": "4rem",
"20": "5rem",
"24": "6rem",
"32": "8rem",
"48": "12rem"
},
"layout_padding": {
"mobile": "px-6",
"desktop": "lg:px-12",
"standard": "px-6 lg:px-12"
},
"section_spacing": {
"small": "py-8",
"medium": "py-12 md:py-16",
"large": "py-24",
"xlarge": "py-32 lg:py-48"
},
"component_spacing": {
"tight": "gap-2 or gap-3",
"normal": "gap-4 or gap-6",
"loose": "gap-8 or gap-12",
"extra_loose": "gap-12 md:gap-24"
}
},
"grid_system": {
"overlay": {
"enabled": true,
"purpose": "Visible design element",
"implementation": "Fixed position, pointer-events-none, opacity-10",
"columns": {
"mobile": 4,
"tablet": 6,
"desktop": 12
},
"styling": "border-r border-slate-500 h-full"
"interactive_overlay": {
"type": "10x10 Grid",
"interaction": "mousemove trail effect",
"style": "border border-white/5",
"active_state": "bg-brand-accent opacity-15",
"fade_out": "duration-800 ease-out"
},
"content_grid": {
"base": "grid grid-cols-1",
"tablet": "md:grid-cols-2 or md:grid-cols-4",
"desktop": "lg:grid-cols-12 or lg:grid-cols-2",
"gap": "gap-6 or gap-8 or gap-12"
},
"column_spans": {
"usage": "lg:col-span-{number}",
"common_patterns": [
"lg:col-span-3 (sidebar)",
"lg:col-span-9 (main content)",
"lg:col-span-4 / lg:col-span-8 (2:1 ratio)",
"lg:col-span-2 / lg:col-span-5 (asymmetric)"
]
}
},
"borders": {
"widths": {
"thin": "border or border-[1px]",
"medium": "border-2",
"thick": "border-[40px] (decorative)"
},
"colors": {
"subtle": "border-white/5",
"standard": "border-white/10 or border-white/20",
"visible": "border-white/30",
"slate_system": "border-slate-700 or border-slate-800",
"accent": "border-brand-accent"
},
"positions": {
"all": "border",
"top": "border-t or border-t-2",
"right": "border-r",
"bottom": "border-b",
"left": "border-l",
"horizontal": "border-x",
"vertical": "border-y"
},
"usage_patterns": {
"section_divider": "border-t border-slate-800",
"card": "border border-white/10 or border border-slate-800",
"active_state": "border-t-2 border-brand-accent",
"hover_state": "hover:border-brand-accent transition-colors"
}
},
"effects": {
"glassmorphism": {
"background": "bg-white/3 or rgba(255, 255, 255, 0.03)",
"backdrop": "backdrop-filter: blur(10px)",
"border": "border border-white/10",
"class_example": ".glass { background: rgba(255, 255, 255, 0.03); backdrop-filter: blur(10px); }"
},
"shadows": {
"accent_glow": "shadow-lg shadow-brand-accent/20",
"cyan_glow": "shadow-lg shadow-brand-cyan/20",
"red_glow": "shadow-lg shadow-brand-red/20",
"custom_glow": "shadow-[0_0_10px_rgba(255,77,0,0.5)]",
"drop_shadow": "drop-shadow-2xl"
},
"blur": {
"small": "blur-sm",
"backdrop": "backdrop-blur-sm"
},
"blend_modes": {
"multiply": "mix-blend-multiply",
"overlay": "mix-blend-overlay",
"luminosity": "mix-blend-luminosity"
},
"opacity": {
"scale": [
0,
5,
10,
20,
30,
40,
60,
90,
100
],
"usage": "opacity-{value}",
"common": {
"invisible": "opacity-0",
"barely_visible": "opacity-5 or opacity-10",
"subtle": "opacity-20 or opacity-30",
"medium": "opacity-40",
"visible": "opacity-60 or opacity-90",
"full": "opacity-100"
}
}
},
"animations": {
"transitions": {
"fast": "duration-300 or transition-all duration-300",
"medium": "duration-500",
"slow": "duration-700 or duration-1000",
"properties": {
"all": "transition-all",
"colors": "transition-colors",
"opacity": "transition-opacity",
"transform": "transition-transform"
},
"easing": {
"standard": "ease-out",
"smooth": "ease-in-out"
}
},
"transforms": {
"scale_subtle": "scale-100 hover:scale-105 transition-transform",
"scale_medium": "group-hover:scale-105 transition-all duration-700",
"scale_bold": "group-hover:scale-110",
"translate_x": "group-hover:translate-x-1 or group-hover:translate-x-0.5",
"translate_y": "translate-y-4 group-hover:translate-y-0"
},
"hover_states": {
"opacity_fade": "opacity-0 group-hover:opacity-100 transition-opacity duration-500",
"color_shift": "hover:text-white transition-colors",
"border_accent": "hover:border-brand-accent transition-all",
"background_lift": "hover:bg-white/5 transition-colors",
"combined": "hover:bg-brand-accent hover:text-brand-dark transition-all"
},
"keyframes": {
"pulse": {
"animation": "animate-pulse",
"usage": "Status indicators, live elements"
}
},
"delays": {
"stagger": "delay-100",
"usage": "Sequential reveals"
"data_table": {
"columns": 12,
"headers": "text-[10px] font-mono uppercase tracking-widest",
"rows": "border-b border-white/10 py-10 hover:border-brand-accent/30"
}
},
"components": {
"buttons": {
"primary": {
"base": "bg-brand-accent text-brand-dark",
"padding": "px-8 py-4",
"typography": "text-xs font-bold uppercase tracking-widest",
"hover": "hover:bg-amber-400 transition-colors",
"full_class": "bg-brand-accent text-brand-dark text-xs font-bold uppercase px-8 py-4 tracking-widest hover:bg-amber-400 transition-colors"
},
"secondary": {
"base": "bg-white text-brand-dark",
"padding": "px-8 py-4",
"typography": "text-xs font-bold uppercase tracking-widest",
"hover": "hover:bg-slate-100 transition-colors"
},
"ghost": {
"base": "bg-transparent border border-slate-700",
"padding": "px-8 py-4 or p-4",
"typography": "text-xs font-bold uppercase tracking-widest",
"hover": "hover:border-brand-accent hover:bg-brand-accent/5 transition-all"
},
"icon": {
"size": "w-12 h-12",
"base": "border border-slate-700 flex items-center justify-center",
"hover": "hover:bg-white/5 transition-colors",
"rounded": "Can be rounded-full for circular buttons"
},
"cta_with_icon": {
"structure": "inline-flex items-center gap-3",
"example": "VIEW CASE STUDY [icon]"
"terminal_action": {
"base": "bg-transparent border border-white/20",
"hover": "hover:border-brand-accent hover:bg-brand-accent/5",
"typography": "font-mono text-xs font-bold uppercase tracking-widest",
"icon": "Arrow or chevron, translates on hover"
}
},
"cards": {
"glass_card": {
"background": "bg-white/3 or rgba(255, 255, 255, 0.03)",
"rack_unit": {
"base": "border border-white/10 bg-white/[0.02]",
"hover": "hover:border-brand-accent/50 hover:bg-white/[0.04]",
"header": "border-b border-white/5 px-8 py-4 flex justify-between",
"indicator": "left-border strip (solid or translucent)",
"content": "p-8 lg:p-12 grid layout"
},
"glass_panel": {
"background": "bg-white/[0.02]",
"backdrop": "backdrop-blur-sm",
"border": "border border-white/5 or border-white/10",
"padding": "p-6 or p-8",
"hover": "hover:border-brand-accent/50 transition-all"
},
"panel_card": {
"background": "bg-brand-panel",
"border": "border border-slate-800",
"padding": "p-12 lg:p-20"
},
"project_card": {
"structure": "relative overflow-hidden cursor-pointer",
"image": "absolute inset-0 bg-cover bg-center",
"overlay": "absolute inset-0 bg-brand-dark/80 group-hover:bg-brand-dark/20 transition-colors duration-500",
"gradient": "absolute inset-0 bg-gradient-to-t from-brand-dark via-transparent to-transparent",
"content": "absolute bottom-0 left-0 w-full p-8 transform translate-y-4 group-hover:translate-y-0",
"hover": "group-hover:scale-105 transition-transform duration-1000"
},
"feature_card": {
"background": "bg-gradient-to-br from-orange-600 to-rose-700",
"overlay": "absolute inset-0 opacity-20 bg-cover bg-center mix-blend-overlay",
"padding": "p-12 md:p-16",
"min_height": "min-h-[400px]"
"border": "border border-white/10",
"hover": "hover:border-brand-accent/30"
}
},
"navigation": {
"header": {
"position": "fixed or relative",
"padding": "px-6 lg:px-12 pt-8",
"structure": "flex items-center justify-between",
"logo": "w-10 h-10 border border-white/20 flex items-center justify-center font-bold text-white tracking-tighter"
"inputs": {
"terminal_input": {
"style": "border-b border-white/20 bg-transparent py-4 text-xl",
"focus": "focus:border-brand-accent focus:outline-none",
"label": "floating label (peer-focus:-top-6), font-mono, tracking-widest"
},
"nav_links": {
"base": "text-xs font-semibold tracking-widest uppercase text-slate-500",
"hover": "hover:text-white transition-colors",
"active": "text-brand-accent",
"spacing": "gap-12"
},
"footer_nav": {
"grid": "grid grid-cols-4",
"item": "text-[10px] uppercase font-bold text-slate-400 tracking-wider text-center",
"hover": "hover:text-white hover:bg-slate-800 transition-colors",
"padding": "py-4"
"industrial_select": {
"trigger": "custom div mimicking terminal input",
"menu": "bg-brand-dark border border-white/20 shadow-2xl",
"option": "hover:bg-white/5 flex items-center gap-3",
"indicator": "accent dot reveals on hover"
}
},
"tabs": {
"container": "grid grid-cols-2 md:grid-cols-4 border-b border-slate-800",
"tab_item": {
"base": "p-6 border-t-2 border-transparent cursor-pointer transition-colors group",
"inactive": "hover:border-slate-700 bg-transparent",
"active": "border-brand-accent bg-white/5"
},
"tab_label": {
"number": "text-xs block mb-2",
"number_inactive": "text-slate-600",
"number_active": "text-brand-accent",
"text": "text-lg",
"text_inactive": "font-medium text-slate-400 group-hover:text-white",
"text_active": "font-semibold text-white"
}
},
"tags": {
"accent_tag": {
"base": "text-[10px] font-bold uppercase tracking-widest",
"background": "bg-brand-accent px-2 py-1",
"text": "text-brand-dark",
"extras": "rounded-sm shadow-lg shadow-brand-accent/20"
},
"category_tag": {
"base": "bg-black/20 or bg-slate-800",
"text": "text-white or text-slate-400",
"padding": "px-3 py-2",
"typography": "text-[10px] font-bold uppercase tracking-wider"
"visualizations": {
"telemetry_overlay": {
"usage": "Video backgrounds",
"elements": "Top/bottom data bars, grid overlays, F1-style stats",
"interaction": "Full card clickable, no modals"
},
"status_indicator": {
"dot": "w-2 h-2 bg-brand-accent rounded-full animate-pulse",
"glow": "shadow-[0_0_10px_rgba(255,77,0,0.5)]",
"label": "text-xs font-bold text-slate-500 tracking-widest uppercase font-mono"
}
},
"dividers": {
"line": "w-24 h-1 bg-white or bg-slate-600",
"hover_expand": "w-16 h-1 hover:w-24 transition-all",
"section": "border-t border-slate-800",
"decorative": "w-1 h-10 bg-brand-accent or w-0.5 h-12"
},
"image_treatments": {
"overlay_pattern": {
"dark_multiply": "absolute inset-0 bg-brand-dark/80 mix-blend-multiply",
"gradient_fade": "absolute inset-0 bg-gradient-to-t from-brand-dark via-transparent to-transparent opacity-90",
"texture": "absolute inset-0 opacity-20 bg-cover bg-center mix-blend-overlay"
},
"hover_zoom": "transition-transform duration-1000 group-hover:scale-105",
"aspect_ratios": "aspect-[4/3] or md:aspect-auto"
},
"metadata_display": {
"structure": "Border-t divider with label above content",
"label": "text-xs font-bold text-slate-500 uppercase mb-2",
"value": "text-white text-lg or text-sm",
"example": "<p class='text-xs font-bold text-slate-500 uppercase mb-2'>Year</p><p class='text-white text-lg'>2023 - 2024</p>"
}
},
"layout_patterns": {
"hero_section": {
"structure": "min-h-[90vh] flex flex-col justify-center",
"padding": "px-6 lg:px-12 pt-20",
"background": "Massive typography with background image at opacity-20",
"grid": "lg:grid-cols-12 with asymmetric column spans",
"title_treatment": "Text-transparent with gradient background-clip, drop-shadow",
"decorative_elements": "Blurred duplicate text layer beneath main text"
},
"two_column_split": {
"grid": "grid grid-cols-1 lg:grid-cols-2",
"borders": "border-t border-r border-b border-slate-800",
"min_height": "min-h-[600px] or min-h-[800px]",
"left_content": "Visual/image with overlays",
"right_content": "Details/text content with vertical padding"
},
"sidebar_layout": {
"grid": "lg:grid-cols-12",
"sidebar": "lg:col-span-3 border-r border-slate-800 p-8 lg:p-10 flex flex-col justify-between",
"main": "lg:col-span-9",
"sidebar_content": "Metadata, stats, navigation"
},
"masonry_grid": {
"base": "grid grid-cols-1 md:grid-cols-2",
"items": "aspect-[4/3] md:aspect-auto with hover effects",
"borders": "border-b border-r border-slate-800 pattern"
},
"full_width_section": {
"padding": "px-6 lg:px-12 py-24 or py-32 lg:py-48",
"border": "border-t border-slate-800",
"max_width": "max-w-7xl mx-auto (optional)"
}
},
"responsive_behavior": {
"breakpoints": {
"sm": "640px",
"md": "768px",
"lg": "1024px",
"xl": "1280px"
},
"patterns": {
"hide_mobile": "hidden md:block or hidden lg:flex",
"show_mobile_only": "lg:hidden",
"responsive_grid": "grid-cols-1 md:grid-cols-2 lg:grid-cols-12",
"responsive_text": "text-3xl md:text-5xl lg:text-6xl",
"responsive_spacing": "px-6 lg:px-12 or py-8 md:py-12 lg:py-16"
},
"mobile_considerations": {
"touch_targets": "Minimum 44px (h-12 w-12)",
"simplified_grids": "Single column on mobile, multi-column on tablet+",
"navigation": "Mobile controls shown below lg breakpoint",
"typography": "Scales down but maintains hierarchy"
}
},
"content_hierarchy": {
"levels": {
"1_mega_branding": {
"size": "text-[12rem] to text-[22rem]",
"treatment": "Gradient, transparent, decorative",
"purpose": "Brand presence, visual anchor"
},
"2_page_title": {
"size": "text-5xl to text-8xl",
"color": "text-white with optional text-slate-500 spans",
"weight": "font-semibold or font-bold"
},
"3_section_heading": {
"size": "text-4xl to text-6xl",
"color": "text-white",
"weight": "font-semibold"
},
"4_subsection": {
"size": "text-2xl to text-4xl",
"color": "text-white",
"weight": "font-medium to font-semibold"
},
"5_body": {
"size": "text-sm to text-lg",
"color": "text-slate-400 or text-slate-300",
"line_height": "leading-relaxed"
},
"6_metadata": {
"size": "text-xs or text-[10px]",
"transform": "uppercase",
"tracking": "tracking-widest or tracking-wider",
"color": "text-slate-500 or text-slate-600",
"weight": "font-bold or font-semibold"
"label": "font-mono text-xs uppercase tracking-widest"
}
}
},
"interactive_states": {
"hover": {
"color_shift": "hover:text-white hover:text-brand-accent",
"background": "hover:bg-white/5 hover:bg-slate-700",
"border": "hover:border-brand-accent hover:border-white",
"scale": "hover:scale-105",
"opacity": "hover:opacity-100 (from lower opacity)"
},
"active": {
"indicators": "Border-t-2 border-brand-accent, bg-white/5, text color change",
"emphasis": "Brighter text, accent color borders"
},
"disabled": {
"opacity": "opacity-40 or opacity-60",
"cursor": "cursor-default",
"colors": "text-slate-600"
},
"focus": {
"treatment": "Follow hover states, no default focus rings visible in design"
}
},
"special_effects": {
"text_stroke": {
"css": "-webkit-text-stroke: 1px rgba(255,255,255,0.1); color: transparent;",
"usage": "Outlined text effect for decorative elements"
},
"gradient_text": {
"classes": "text-transparent bg-clip-text bg-gradient-to-tr from-brand-accent via-orange-500 to-brand-panel",
"usage": "Hero titles, emphasis text"
},
"animated_background": {
"transition": "duration-700 ease-out",
"hover": "opacity changes, scale transforms",
"example": "Image backgrounds that fade/zoom on interaction"
},
"layered_depth": {
"technique": "Multiple absolute positioned divs with different opacities, blend modes",
"layers": [
"Base image (bg-cover)",
"Multiply blend overlay (bg-brand-dark/80)",
"Gradient overlay (bg-gradient-to-t opacity-90)",
"Content layer (z-10 or z-20)"
"animations": {
"intro_sequence": {
"trigger": "window.load",
"order": [
"Grid ripple (diagonal)",
"Text slide up",
"Metadata fade in",
"Portrait slow reveal"
]
},
"interactions": {
"grid_trail": "Instant active, slow fade out (800ms)",
"row_highlight": "Border color shift, text color shift",
"social_arrow": "Translate X+1 Y-1 on hover"
}
},
"accessibility_notes": {
"contrast": "High contrast maintained throughout (white on dark backgrounds)",
"focus_states": "Should be added for keyboard navigation",
"alt_text": "Images need descriptive alt text",
"aria_labels": "Interactive elements need proper labels",
"semantic_html": "Use proper heading hierarchy (currently div-heavy)",
"color_alone": "Don't rely on color alone for information"
},
"design_tokens_summary": {
"primary_background": "#0B0D11",
"secondary_background": "#151921",
"primary_accent": "#ff4d00",
"primary_text": "#FFFFFF",
"secondary_text": "#94A3B8",
"border_subtle": "rgba(255, 255, 255, 0.1)",
"border_standard": "#334155",
"font_primary": "Inter, sans-serif",
"font_mono": "monospace",
"radius_minimal": "0 or 2px (rarely used)",
"shadow_glow": "0 0 10px rgba(255,77,0,0.5)",
"transition_fast": "300ms",
"transition_medium": "500ms",
"transition_slow": "700ms"
},
"implementation_notes": {
"framework": "Tailwind CSS with custom config",
"icons": "Iconify (solar, lucide sets primarily)",
"responsive_images": "Multiple sizes served, lazyload recommended",
"performance": "Optimize large background images, consider lazy loading for below-fold content",
"browser_support": "Modern browsers (backdrop-filter, blend modes require recent versions)",
"dark_mode_only": "No light mode variant in this system"
}
}
}

BIN
public/apple-touch-icon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 55 KiB

BIN
public/favicon-192.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 63 KiB

BIN
public/favicon-32.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

BIN
public/favicon.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

View File

@ -20,7 +20,10 @@ const { title, description, image = FallbackImage } = Astro.props;
<!-- Global Metadata -->
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width,initial-scale=1" />
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
<link rel="icon" type="image/x-icon" href="/favicon.ico" />
<link rel="icon" type="image/png" sizes="32x32" href="/favicon-32.png" />
<link rel="icon" type="image/png" sizes="192x192" href="/favicon-192.png" />
<link rel="apple-touch-icon" sizes="180x180" href="/apple-touch-icon.png" />
<link rel="sitemap" href="/sitemap-index.xml" />
<link
rel="alternate"

View File

@ -1,143 +1,140 @@
---
---
<section id="experience" class="container mx-auto px-6 lg:px-12 py-32">
<div class="grid grid-cols-1 lg:grid-cols-12 gap-12 lg:gap-16">
<div class="lg:col-span-4 animate-on-scroll slide-right">
<!-- Experience heading with scroll-driven fill effect -->
<h2 class="text-3xl md:text-4xl font-bold uppercase tracking-tight mb-2 relative">
<span class="text-stroke-fill" data-text="Experience">Experience</span>
<section id="experience" class="container mx-auto px-6 lg:px-12 py-32 border-t border-white/10">
<!-- Section Header -->
<div class="grid grid-cols-1 lg:grid-cols-12 gap-12 mb-20">
<div class="lg:col-span-8">
<h2 class="text-6xl md:text-8xl lg:text-9xl font-bold uppercase tracking-tighter leading-[0.85] text-white">
<span class="block animate-on-scroll slide-up">Studio</span>
<span class="block text-transparent text-stroke animate-on-scroll slide-up stagger-1">History</span>
</h2>
<h2 class="text-3xl md:text-4xl font-bold uppercase tracking-tight mb-10">History</h2>
<p class="text-slate-400 text-base leading-relaxed mb-10 max-w-sm font-light">
Running my own VFX studio while taking on select freelance projects. I bridge the gap between
creative vision and technical execution.
</p>
<a href="https://biohazardvfx.com" target="_blank"
class="inline-flex items-center gap-3 text-xs font-mono uppercase text-brand-accent hover:text-white transition-colors duration-300 group">
Visit Biohazard VFX
<i data-lucide="arrow-up-right" class="w-4 h-4 transition-transform duration-300 group-hover:translate-x-0.5 group-hover:-translate-y-0.5"></i>
</a>
</div>
<div class="lg:col-span-8 relative">
<!-- Vertical line -->
<div class="absolute left-0 top-0 bottom-0 w-[1px] bg-gradient-to-b from-brand-accent via-slate-700/50 to-transparent"></div>
<!-- Item 1: Biohazard VFX -->
<div class="pl-10 lg:pl-14 mb-20 relative animate-on-scroll slide-up stagger-1">
<div class="absolute left-[-5px] top-2 w-3 h-3 bg-brand-dark border-2 border-brand-accent rounded-full"></div>
<div class="flex flex-col md:flex-row md:items-baseline gap-3 md:gap-4 mb-5">
<h3 class="text-xl md:text-2xl font-bold text-white uppercase tracking-tight">Biohazard VFX</h3>
<span class="font-mono text-[10px] text-brand-accent bg-brand-accent/10 px-3 py-1.5 tracking-wide">FOUNDER & OWNER</span>
<span class="font-mono text-xs text-slate-500 md:ml-auto">2022 — PRESENT</span>
</div>
<p class="text-slate-400 mb-8 leading-relaxed font-light">
Founded and continue to lead a VFX studio specializing in high-end commercial and music video work.
Delivered projects for Post Malone, ENHYPEN, and Nike. Architected a custom pipeline combining cloud and
self-hosted infrastructure.
</p>
<ul class="space-y-3">
<li class="flex items-start gap-4 text-sm text-slate-300 font-light">
<span class="text-brand-accent mt-0.5 text-xs">▹</span>
Designed 7-plate reconciliation workflows for ENHYPEN (projection mapping live action
onto CAD).
</li>
<li class="flex items-start gap-4 text-sm text-slate-300 font-light">
<span class="text-brand-accent mt-0.5 text-xs">▹</span>
Developed QA systems for AI-generated assets, transforming mid-tier output into
production-ready deliverables.
</li>
</ul>
</div>
<!-- Item 2: Stinkfilms / G-Star -->
<div class="pl-10 lg:pl-14 mb-20 relative animate-on-scroll slide-up stagger-2">
<div class="absolute left-[-5px] top-2 w-3 h-3 bg-slate-700 rounded-full transition-colors duration-300"></div>
<div class="flex flex-col md:flex-row md:items-baseline gap-3 md:gap-4 mb-5">
<h3 class="text-xl md:text-2xl font-bold text-white uppercase tracking-tight">Stinkfilms</h3>
<span class="font-mono text-[10px] text-slate-400 border border-slate-700 px-3 py-1.5 tracking-wide">GLOBAL PRODUCTION STUDIO</span>
<span class="font-mono text-xs text-slate-500 md:ml-auto">SUMMER 2024</span>
</div>
<p class="text-slate-400 mb-8 leading-relaxed font-light">
Led Biohazard VFX team (60+ artists) alongside director Felix Brady to create a brand film
for G-Star Raw.
</p>
<a href="/blog/gstar-raw-olympics/" class="block border border-white/10 bg-white/[0.02] p-6 lg:p-8 backdrop-blur-sm hover:border-brand-accent/30 transition-all duration-500 cursor-pointer group">
<h4 class="text-sm font-bold uppercase text-white mb-3 flex justify-between items-center tracking-wide">
Project: G-Star Raw Olympics Campaign
<i data-lucide="arrow-right"
class="w-4 h-4 opacity-0 group-hover:opacity-100 transition-all duration-300 text-brand-accent transform group-hover:translate-x-1"></i>
</h4>
<p class="text-sm text-slate-400 mb-5 leading-relaxed font-light">
Managed full CG environments in Blender/Houdini and integrated AI/ML workflows (Stable Diffusion reference gen, Copycat cleanup).
</p>
<span class="text-[10px] font-bold text-brand-accent uppercase tracking-widest group-hover:text-white transition-colors duration-300">
Read Case Study
</span>
</a>
</div>
<!-- Item 3: Freelance -->
<div class="pl-10 lg:pl-14 relative animate-on-scroll slide-up stagger-3">
<div class="absolute left-[-5px] top-2 w-3 h-3 bg-slate-700 rounded-full"></div>
<div class="flex flex-col md:flex-row md:items-baseline gap-3 md:gap-4 mb-5">
<h3 class="text-xl md:text-2xl font-bold text-white uppercase tracking-tight">Freelance</h3>
<span class="font-mono text-[10px] text-slate-400 border border-slate-700 px-3 py-1.5 tracking-wide">SELECT PROJECTS</span>
<span class="font-mono text-xs text-slate-500 md:ml-auto">ONGOING</span>
</div>
<p class="text-slate-400 leading-relaxed font-light">
Taking on select freelance compositing and 3D work alongside studio operations.
Previous clients include Abyss Digital and major labels (Atlantic, Interscope) —
David Kushner, Opium, Lil Durk, Don Toliver.
</p>
</div>
<div class="lg:col-span-4 flex flex-col justify-end pb-4">
<div class="font-mono text-xs text-slate-500 uppercase tracking-widest mb-4">/// Career Timeline</div>
<p class="text-slate-400 text-base leading-relaxed border-l border-brand-accent pl-6 animate-on-scroll fade-in stagger-2">
Bridging creative vision with technical execution. From running a dedicated VFX studio to high-end freelance supervision.
</p>
</div>
</div>
<!-- "Rack Mount" Layout -->
<div class="flex flex-col gap-6">
<!-- Unit 01: Biohazard (Active System) -->
<div class="group relative border border-white/10 bg-white/[0.02] hover:border-brand-accent/50 hover:bg-white/[0.04] transition-all duration-500 overflow-hidden animate-on-scroll slide-up stagger-1">
<!-- Active Indicator Strip -->
<div class="absolute top-0 left-0 w-1 h-full bg-brand-accent opacity-100"></div>
<div class="absolute top-0 left-0 w-full h-1 bg-brand-accent opacity-0 group-hover:opacity-100 transition-opacity duration-500"></div>
<!-- Technical Header -->
<div class="flex items-center justify-between px-8 py-4 border-b border-white/5 bg-white/[0.02]">
<div class="flex items-center gap-4">
<span class="font-mono text-[10px] text-brand-accent uppercase tracking-widest">SYS.01 /// ACTIVE</span>
<div class="h-px w-12 bg-white/10"></div>
</div>
<span class="font-mono text-[10px] text-slate-500 uppercase tracking-widest">2022 — PRESENT</span>
</div>
<div class="p-8 lg:p-12 grid grid-cols-1 lg:grid-cols-12 gap-12">
<div class="lg:col-span-4">
<h3 class="text-4xl font-bold text-white uppercase tracking-tight mb-2">Biohazard VFX</h3>
<span class="text-sm font-mono text-slate-400">Founder & Owner</span>
<div class="mt-8 flex flex-wrap gap-2">
<span class="px-2 py-1 text-[10px] font-mono uppercase border border-white/10 text-slate-400">Studio Lead</span>
<span class="px-2 py-1 text-[10px] font-mono uppercase border border-white/10 text-slate-400">Pipeline Arch</span>
</div>
</div>
<div class="lg:col-span-8 flex flex-col justify-between">
<p class="text-slate-300 leading-relaxed font-light text-lg mb-8">
Founded and lead a VFX studio specializing in high-end commercial and music video work.
Delivered projects for Post Malone, ENHYPEN, and Nike. Architected a custom pipeline combining cloud and self-hosted infrastructure.
</p>
<div class="grid grid-cols-1 md:grid-cols-2 gap-6 border-t border-white/5 pt-8">
<div>
<h4 class="text-[10px] font-mono text-slate-500 uppercase tracking-widest mb-2">Key Achievement</h4>
<p class="text-sm text-slate-400">Designed 7-plate reconciliation workflows for ENHYPEN (projection mapping live action onto CAD).</p>
</div>
<div>
<h4 class="text-[10px] font-mono text-slate-500 uppercase tracking-widest mb-2">System Impact</h4>
<p class="text-sm text-slate-400">Developed QA systems for AI-generated assets, transforming mid-tier output into production-ready deliverables.</p>
</div>
</div>
<div class="mt-8 flex justify-end">
<a href="https://biohazardvfx.com" target="_blank" class="inline-flex items-center gap-3 text-xs font-bold uppercase tracking-widest text-white hover:text-brand-accent transition-colors">
Visit Studio Uplink <svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M5 12h14"/><path d="m12 5 7 7-7 7"/></svg>
</a>
</div>
</div>
</div>
</div>
<!-- Split Row for Stink & Freelance -->
<div class="grid grid-cols-1 lg:grid-cols-2 gap-6">
<!-- Unit 02: Stinkfilms -->
<div class="group relative border border-white/10 bg-white/[0.02] hover:border-white/30 transition-all duration-500 overflow-hidden animate-on-scroll slide-up stagger-2">
<!-- Inactive Indicator Strip -->
<div class="absolute top-0 left-0 w-1 h-full bg-slate-700 opacity-50 group-hover:bg-white transition-colors"></div>
<!-- Technical Header -->
<div class="flex items-center justify-between px-8 py-4 border-b border-white/5 bg-white/[0.02]">
<div class="flex items-center gap-4">
<span class="font-mono text-[10px] text-slate-500 uppercase tracking-widest">SYS.02 /// ARCHIVED</span>
</div>
<span class="font-mono text-[10px] text-slate-500 uppercase tracking-widest">SUMMER 2024</span>
</div>
<div class="p-8 lg:p-10 flex flex-col h-full">
<div class="mb-6">
<h3 class="text-2xl font-bold text-white uppercase tracking-tight mb-1">Stinkfilms</h3>
<span class="text-xs font-mono text-slate-400">VFX Supervisor</span>
</div>
<p class="text-slate-400 leading-relaxed font-light text-sm mb-8 flex-grow">
Led Biohazard VFX team (60+ artists) alongside director Felix Brady to create a brand film for G-Star Raw.
Managed full CG environments in Blender/Houdini.
</p>
<div class="pt-6 border-t border-white/5">
<a href="/blog/gstar-raw-olympics/" class="inline-flex items-center gap-3 text-xs font-bold uppercase tracking-widest text-slate-300 hover:text-white transition-colors">
Access Case Data <svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M5 12h14"/><path d="m12 5 7 7-7 7"/></svg>
</a>
</div>
</div>
</div>
<!-- Unit 03: Freelance -->
<div class="group relative border border-white/10 bg-white/[0.02] hover:border-white/30 transition-all duration-500 overflow-hidden animate-on-scroll slide-up stagger-3">
<!-- Background Process Indicator Strip -->
<div class="absolute top-0 left-0 w-1 h-full bg-slate-700 opacity-50 group-hover:bg-white transition-colors"></div>
<!-- Technical Header -->
<div class="flex items-center justify-between px-8 py-4 border-b border-white/5 bg-white/[0.02]">
<div class="flex items-center gap-4">
<span class="font-mono text-[10px] text-slate-500 uppercase tracking-widest">SYS.03 /// DAEMON</span>
</div>
<span class="font-mono text-[10px] text-slate-500 uppercase tracking-widest">2016 — PRESENT</span>
</div>
<div class="p-8 lg:p-10 flex flex-col h-full">
<div class="mb-6">
<h3 class="text-2xl font-bold text-white uppercase tracking-tight mb-1">Freelance</h3>
<span class="text-xs font-mono text-slate-400">Senior Compositor</span>
</div>
<p class="text-slate-400 leading-relaxed font-light text-sm mb-8 flex-grow">
Taking on select freelance compositing and 3D work alongside studio operations.
Clients include Abyss Digital, Atlantic, Interscope.
</p>
<div class="pt-6 border-t border-white/5 flex flex-wrap gap-2">
<span class="px-2 py-1 text-[10px] font-mono uppercase border border-white/10 text-slate-500">Nuke</span>
<span class="px-2 py-1 text-[10px] font-mono uppercase border border-white/10 text-slate-500">Flame</span>
</div>
</div>
</div>
</div>
</div>
</section>
<style>
/* Text stroke fill effect */
.text-stroke-fill {
position: relative;
-webkit-text-stroke: 1px rgba(255, 255, 255, 0.2);
color: transparent;
}
.text-stroke-fill::before {
content: attr(data-text);
position: absolute;
left: 0;
top: 0;
color: var(--color-brand-accent);
-webkit-text-stroke: 0;
clip-path: inset(0 100% 0 0);
transition: clip-path 0.8s cubic-bezier(0.16, 1, 0.3, 1);
}
.text-stroke-fill.filled::before {
clip-path: inset(0 0 0 0);
}
</style>
<script>
// Scroll-driven fill effect for Experience heading
const experienceHeading = document.querySelector('.text-stroke-fill');
const fillObserver = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
// Add a slight delay for better effect
setTimeout(() => {
entry.target.classList.add('filled');
}, 200);
}
});
}, {
threshold: 0.5,
rootMargin: "0px 0px -100px 0px"
});
if (experienceHeading) {
fillObserver.observe(experienceHeading);
}
</script>

View File

@ -1,54 +1,100 @@
---
---
<section id="work" class="py-32">
<div class="container mx-auto px-6 lg:px-12 mb-14 animate-on-scroll slide-up">
<span class="text-xs font-mono text-brand-accent mb-4 block tracking-wide">/// HIGHLIGHT</span>
<h2 class="text-4xl md:text-6xl lg:text-7xl font-bold uppercase text-white tracking-tight">
G-Star Raw <span class="text-stroke">Olympics</span>
</h2>
<section id="work" class="relative overflow-hidden group min-h-screen flex flex-col cursor-pointer">
<!-- Main Link Overlay -->
<a href="/blog/gstar-raw-olympics/" class="absolute inset-0 z-30" aria-label="View G-Star Raw Olympics Case Study"></a>
<!-- Video Background -->
<div class="absolute inset-0 z-0">
<video
autoplay
loop
muted
playsinline
class="w-full h-full object-cover opacity-70 transition-opacity duration-700 group-hover:opacity-100"
>
<source src="/media/FF_PUFF_GStar_DC_v08_4608x3164.mp4" type="video/mp4" />
</video>
<!-- Cinematic Letterboxing / Gradient Vignette -->
<div class="absolute inset-0 bg-gradient-to-b from-brand-dark/80 via-transparent to-brand-dark/80 pointer-events-none"></div>
<div class="absolute inset-0 bg-gradient-to-r from-brand-dark/40 via-transparent to-brand-dark/40 pointer-events-none"></div>
<!-- Subtle Grid Overlay -->
<div class="absolute inset-0 bg-[linear-gradient(rgba(255,255,255,0.02)_1px,transparent_1px),linear-gradient(90deg,rgba(255,255,255,0.02)_1px,transparent_1px)] bg-[size:60px_60px] pointer-events-none opacity-30"></div>
</div>
<!-- Full Width Project Card -->
<div class="w-full h-[75vh] lg:h-[80vh] relative group overflow-hidden border-y border-white/10 animate-on-scroll scale-in">
<!-- Abstract Background representing the project -->
<div class="absolute inset-0 bg-[url('https://images.unsplash.com/photo-1618005182384-a83a8bd57fbe?q=80&w=2564&auto=format&fit=crop')] bg-cover bg-center transition-transform duration-[1.5s] ease-out group-hover:scale-105"></div>
<div class="absolute inset-0 bg-brand-dark/75 mix-blend-multiply transition-colors duration-700 group-hover:bg-brand-dark/60"></div>
<div class="absolute inset-0 bg-gradient-to-t from-brand-dark via-brand-dark/30 to-transparent opacity-95"></div>
<!-- Main Content Container - Spaced to frame the video -->
<div class="container mx-auto px-6 lg:px-12 relative z-10 flex-1 flex flex-col justify-between py-12 lg:py-16 pointer-events-none">
<!-- Grid Overlay on image -->
<div class="absolute inset-0 bg-[url('data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNDAiIGhlaWdodD0iNDAiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PHBhdHRlcm4gaWQ9ImEiIHdpZHRoPSI0MCIgaGVpZ2h0PSI0MCIgcGF0dGVyblVuaXRzPSJ1c2VyU3BhY2VPblVzZSI+PHBhdHRlcm4gaWQ9ImIiIHdpZHRoPSI0MCIgaGVpZ2h0PSI0MCIgcGF0dGVyblVuaXRzPSJ1c2VyU3BhY2VPblVzZSI+PGNpcmNsZSBjeD0iMiIgY3k9IjIiIHI9IjEiIGZpbGw9InJnYmEoMjU1LDI1NSwyNTUsMC4xKSIvPjwvcGF0dGVybj48cmVjdCB3aWR0aD0iNDAiIGhlaWdodD0iNDAiIGZpbGw9InVybCgjYikiLz48L3BhdHRlcm4+PC9kZWZzPjxyZWN0IHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjYSkiLz48L3N2Zz4=')] opacity-20"></div>
<div class="absolute bottom-0 left-0 w-full p-6 lg:p-14 flex flex-col md:flex-row items-end justify-between gap-8">
<div class="max-w-2xl transform translate-y-6 group-hover:translate-y-0 transition-transform duration-700 ease-out">
<div class="flex flex-wrap gap-2 mb-6">
<span class="bg-brand-accent text-brand-dark text-[10px] font-bold uppercase px-3 py-1.5 tracking-wide">VFX Supervision</span>
<span class="border border-white/30 text-white text-[10px] font-bold uppercase px-3 py-1.5 tracking-wide transition-colors duration-300 hover:border-white/50">AI/ML</span>
<span class="border border-white/30 text-white text-[10px] font-bold uppercase px-3 py-1.5 tracking-wide transition-colors duration-300 hover:border-white/50">Houdini</span>
</div>
<p class="text-lg md:text-xl lg:text-2xl text-white font-normal mb-8 leading-relaxed">
Managed full CG environment builds, procedural city generation, and integrated AI-generated
normal maps for relighting in Nuke.
</p>
<div class="flex flex-wrap items-center gap-6">
<a href="/blog/gstar-raw-olympics/"
class="inline-flex items-center gap-4 text-xs font-bold uppercase tracking-widest text-white hover:text-brand-accent transition-all duration-300 group/link">
Read Case Study
<i data-lucide="arrow-right" class="w-4 h-4 transition-transform duration-300 group-hover/link:translate-x-1"></i>
</a>
<a href="https://f.io/7ijf23Wm" target="_blank" rel="noopener"
class="inline-flex items-center gap-4 text-xs font-bold uppercase tracking-widest text-slate-400 hover:text-white transition-all duration-300 group/link">
Watch Making Of
<i data-lucide="play-circle" class="w-4 h-4 transition-transform duration-300 group-hover/link:scale-110"></i>
</a>
</div>
<!-- TOP HUD: Telemetry Data -->
<div class="grid grid-cols-2 md:grid-cols-4 gap-8 border-t border-white/20 pt-6 animate-on-scroll slide-up">
<div>
<span class="text-[9px] font-mono text-brand-accent uppercase tracking-widest block mb-1">/// Role</span>
<span class="text-xl md:text-2xl font-bold text-white uppercase tracking-tight">VFX Sup</span>
</div>
<div class="hidden md:block text-right opacity-80 group-hover:opacity-100 transition-opacity duration-500">
<span class="block text-[10px] uppercase text-slate-500 tracking-widest mb-2">Year</span>
<span class="block text-2xl font-bold text-white mb-6 tracking-tight">2024</span>
<span class="block text-[10px] uppercase text-slate-500 tracking-widest mb-2">Client</span>
<span class="block text-xl font-bold text-white tracking-tight">Stinkfilms</span>
<div>
<span class="text-[9px] font-mono text-brand-accent uppercase tracking-widest block mb-1">/// Client</span>
<span class="text-xl md:text-2xl font-bold text-white uppercase tracking-tight">Stink</span>
</div>
<div>
<span class="text-[9px] font-mono text-brand-accent uppercase tracking-widest block mb-1">/// Year</span>
<span class="text-xl md:text-2xl font-bold text-white uppercase tracking-tight">2024</span>
</div>
<div class="text-right md:text-left">
<span class="text-[9px] font-mono text-brand-accent uppercase tracking-widest block mb-1">/// Region</span>
<span class="text-xl md:text-2xl font-bold text-white uppercase tracking-tight">Global</span>
</div>
</div>
<!-- CENTER AREA: Clear for Video -->
<div class="flex-1 relative">
<!-- Side Vertical Title (Optional, unobtrusive) -->
<div class="hidden lg:block absolute -left-8 top-1/2 -translate-y-1/2 origin-left -rotate-90">
<h2 class="text-6xl font-bold text-transparent text-stroke uppercase tracking-tighter opacity-20 select-none">
G-Star Raw
</h2>
</div>
</div>
<!-- BOTTOM HUD: Project Details & Stats -->
<div class="border-b border-white/20 pb-6 animate-on-scroll slide-up stagger-1">
<div class="grid grid-cols-1 lg:grid-cols-12 gap-8 items-end">
<!-- Title & Description -->
<div class="lg:col-span-7">
<h2 class="text-5xl md:text-7xl font-bold uppercase text-white mb-4 tracking-tighter leading-none">
G-Star <span class="text-transparent text-stroke">Olympics</span>
</h2>
<p class="text-slate-300 font-light max-w-lg text-sm md:text-base leading-relaxed">
Full CG environment production for the 2024 Olympic Campaign.
Orchestrated procedural city generation and AI-enhanced lighting workflows.
</p>
</div>
<!-- Technical Stats (Mini-Table) -->
<div class="lg:col-span-5">
<div class="grid grid-cols-2 gap-x-8 gap-y-4 font-mono text-xs">
<div class="border-l border-brand-accent/30 pl-3">
<span class="block text-slate-500 text-[10px] uppercase mb-1">Shot Count</span>
<span class="block text-white font-bold">12 Sequences</span>
</div>
<div class="border-l border-brand-accent/30 pl-3">
<span class="block text-slate-500 text-[10px] uppercase mb-1">Resolution</span>
<span class="block text-white font-bold">4K DCI</span>
</div>
<div class="border-l border-brand-accent/30 pl-3">
<span class="block text-slate-500 text-[10px] uppercase mb-1">Pipeline</span>
<span class="block text-white font-bold">Houdini / Solaris</span>
</div>
<div class="border-l border-brand-accent/30 pl-3">
<span class="block text-slate-500 text-[10px] uppercase mb-1">Render</span>
<span class="block text-white font-bold">Karma XPU</span>
</div>
</div>
</div>
</div>
</div>
</div>
</section>

View File

@ -1,77 +1,100 @@
---
---
<section id="about" class="container mx-auto px-6 lg:px-12 min-h-[80vh] flex flex-col justify-center relative pb-24">
<div class="grid grid-cols-1 md:grid-cols-12 gap-8 lg:gap-12">
<div class="col-span-12">
<p class="font-mono text-brand-accent text-sm mb-6 tracking-wide animate-on-scroll fade-in">
/// TECHNICAL GENERALIST & VFX SUPERVISOR
</p>
<h1 class="text-5xl sm:text-6xl md:text-7xl lg:text-8xl xl:text-[9rem] font-extrabold text-massive uppercase leading-none tracking-tighter mb-10 text-white">
<span class="animate-on-scroll slide-up block stagger-1">Visual</span>
<span class="animate-on-scroll slide-up block stagger-2 text-transparent bg-clip-text bg-gradient-to-r from-brand-accent via-orange-400 to-white">Alchemist</span>
</h1>
</div>
<div class="col-span-12 md:col-span-7 lg:col-span-5 lg:col-start-8 mt-8 lg:mt-4 border-l-2 border-brand-accent/40 pl-8 animate-on-scroll slide-left stagger-3">
<p class="text-slate-400 text-base lg:text-lg leading-relaxed mb-10 font-light">
I am a problem solver who loves visual effects. With 10 years of experience creating end-to-end
visual content for clients like <span class="text-white font-medium">Post Malone</span>, <span class="text-white font-medium">Stinkfilms</span>, and <span class="text-white font-medium">Adidas</span>. Comfortable managing teams while staying
knee-deep in hands-on shot work.
</p>
<div class="flex gap-6">
<a href="#work"
class="group flex items-center gap-4 text-xs font-bold uppercase tracking-widest text-white hover:text-brand-accent transition-all duration-300">
<span class="w-10 h-[2px] bg-brand-accent group-hover:w-16 transition-all duration-500 ease-out"></span>
View Selected Works
</a>
</div>
<section id="hero" class="relative w-full h-screen overflow-hidden bg-brand-dark">
<!-- Background Image (Portrait) -->
<div class="absolute top-0 right-0 w-full md:w-1/2 h-full z-0">
<div class="relative w-full h-full">
<img
src="/media/nicholai-closeup-portrait.JPEG"
alt="Nicholai Portrait"
class="w-full h-full object-cover object-center opacity-0 mix-blend-luminosity md:opacity-0 transition-opacity duration-[2000ms] ease-out delay-500 intro-element"
id="hero-portrait"
/>
<div class="absolute inset-0 bg-gradient-to-l from-transparent via-brand-dark/50 to-brand-dark"></div>
<div class="absolute inset-0 bg-gradient-to-t from-brand-dark via-transparent to-transparent"></div>
</div>
</div>
<!-- Hero Footer -->
<div class="absolute bottom-8 w-full left-0 px-6 lg:px-12 hidden md:flex justify-between items-end animate-on-scroll fade-in stagger-5">
<div class="font-mono text-xs text-slate-500 tracking-wide opacity-60">
<span class="block text-slate-600 mb-1">LOCATION</span>
COLORADO SPRINGS, CO<br>
<span id="clock" class="text-slate-400">00:00:00</span>
<!-- The 100 Squares Grid Overlay -->
<div id="grid-container" class="absolute inset-0 z-10 w-full h-full grid grid-cols-10 grid-rows-10 pointer-events-none">
{Array.from({ length: 100 }).map((_, i) => (
<div class="grid-cell w-full h-full border border-white/5 opacity-0 transition-all duration-500 ease-out" data-index={i}></div>
))}
</div>
<!-- The Content -->
<!-- Adjusted pt to clear fixed nav since BaseLayout padding is removed -->
<div class="absolute inset-0 z-20 flex flex-col justify-between p-6 md:p-12 lg:p-16 pt-32 lg:pt-40 pointer-events-auto">
<!-- Top Metadata -->
<div class="flex justify-between items-start w-full intro-element opacity-0 translate-y-4 transition-all duration-1000 ease-out delay-300">
<div class="font-mono text-xs uppercase tracking-widest text-slate-500">
Portfolio 2026
</div>
<div class="font-mono text-xs text-slate-500 text-right tracking-wide">
<span class="block text-slate-600 mb-1 uppercase tracking-widest">Location</span>
Colorado Springs, CO<br>
<span id="clock" class="text-brand-accent">00:00:00 MST</span>
</div>
</div>
<!-- Scroll Indicator with animation -->
<div id="scroll-indicator" class="font-mono text-xs text-slate-500 text-right tracking-wide transition-all duration-500">
<span class="block text-slate-600 mb-1">EXPLORE</span>
<span class="inline-flex flex-col items-center">
SCROLL
<span class="scroll-arrow block mt-2 w-[1px] h-8 bg-gradient-to-b from-brand-accent to-transparent"></span>
</span>
<!-- Main Heading & Description -->
<div class="max-w-5xl">
<h1 class="text-6xl md:text-8xl lg:text-9xl tracking-tighter leading-[0.9] font-bold text-white mix-blend-overlay opacity-90 mb-8 perspective-text">
<span class="block intro-element opacity-0 translate-y-10 transition-all duration-1000 ease-out delay-100">VISUAL</span>
<span class="block text-brand-accent opacity-0 translate-y-10 transition-all duration-1000 ease-out delay-200 intro-element">ALCHEMIST</span>
</h1>
<p class="font-mono text-sm md:text-base max-w-lg text-slate-400 font-light leading-relaxed intro-element opacity-0 translate-y-6 transition-all duration-1000 ease-out delay-500">
I am a problem solver who loves visual effects. Creating end-to-end visual content for clients like Post Malone, Stinkfilms, and Adidas. Bridging creative vision with technical execution.
</p>
</div>
<!-- Bottom Navigation -->
<div class="flex justify-between items-end w-full intro-element opacity-0 transition-all duration-1000 ease-out delay-700">
<a href="#experience" class="flex items-center justify-center w-12 h-12 border border-white/10 rounded-full text-brand-accent hover:bg-brand-accent hover:text-brand-dark transition-all duration-300 group">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="group-hover:animate-bounce">
<path d="M12 5v14M19 12l-7 7-7-7"/>
</svg>
</a>
<div class="text-right font-mono text-xs text-slate-500 tracking-widest">
SCROLL TO EXPLORE
</div>
</div>
</div>
</section>
<style>
/* Scroll arrow bounce animation */
.scroll-arrow {
animation: scrollBounce 2s ease-in-out infinite;
.grid-cell.active {
background-color: var(--color-brand-accent);
opacity: 0.15;
transition: opacity 0s, background-color 0s; /* Instant on */
}
/* Fade out */
.grid-cell {
transition: opacity 0.8s ease-out, background-color 0.8s ease-out;
}
@keyframes scrollBounce {
0%, 100% {
transform: translateY(0);
opacity: 1;
}
50% {
transform: translateY(8px);
opacity: 0.6;
}
/* Initial Loaded State Classes */
.intro-visible {
opacity: 1 !important;
transform: translateY(0) !important;
}
/* Fade out on scroll */
#scroll-indicator.scrolled {
opacity: 0;
transform: translateY(10px);
pointer-events: none;
/* Portrait Loaded State */
.portrait-visible {
opacity: 0.4 !important; /* Mobile default */
}
@media (min-width: 768px) {
.portrait-visible {
opacity: 0.6 !important; /* Desktop default */
}
}
</style>
<script>
// Clock
function updateClock() {
const clock = document.getElementById('clock');
if (clock) {
@ -83,27 +106,104 @@
setInterval(updateClock, 1000);
updateClock();
// Scroll-driven fade for scroll indicator
const scrollIndicator = document.getElementById('scroll-indicator');
// Intro Animation Sequence
window.addEventListener('load', () => {
// Trigger Intro Elements
const introElements = document.querySelectorAll('.intro-element');
introElements.forEach(el => {
el.classList.add('intro-visible');
});
function handleScroll() {
if (scrollIndicator) {
const scrollY = window.scrollY;
// Start fading at 50px, fully hidden at 200px
const opacity = Math.max(0, 1 - (scrollY / 150));
const translateY = Math.min(20, scrollY / 10);
scrollIndicator.style.opacity = opacity.toString();
scrollIndicator.style.transform = `translateY(${translateY}px)`;
if (scrollY > 50) {
scrollIndicator.classList.add('scrolled');
} else {
scrollIndicator.classList.remove('scrolled');
}
// Trigger Portrait
const portrait = document.getElementById('hero-portrait');
if (portrait) {
portrait.classList.add('portrait-visible');
}
// Trigger Grid Ripple
const cells = document.querySelectorAll('.grid-cell');
// Diagonal sweep effect
cells.forEach((cell, i) => {
const row = Math.floor(i / 10);
const col = i % 10;
const delay = (row + col) * 50; // Diagonal delay
setTimeout(() => {
cell.classList.add('active');
setTimeout(() => {
cell.classList.remove('active');
}, 200);
}, delay);
});
});
// Robust Grid Interaction
const section = document.getElementById('hero');
const cells = document.querySelectorAll('.grid-cell');
if (section) {
section.addEventListener('mousemove', (e) => {
const rect = section.getBoundingClientRect();
// Calculate relative coordinates
const x = e.clientX - rect.left;
const y = e.clientY - rect.top;
// Calculate grid dimensions
const width = rect.width;
const height = rect.height;
// 10x10 grid
const col = Math.floor((x / width) * 10);
const row = Math.floor((y / height) * 10);
// Bounds check
if (col >= 0 && col < 10 && row >= 0 && row < 10) {
const index = row * 10 + col;
const cell = cells[index];
if (cell) {
// Remove active class from all others (optional, or let them fade)
// cell.classList.add('active');
// To prevent "sticking", we can use a timestamp or just let CSS transition handle fade out
// But we need to trigger the "hit"
// Logic: Add active, then remove it shortly after to trigger fade
cell.classList.add('active');
// Clear previous timeout if this cell was just hit?
// Simpler: Just add active. Use requestAnimationFrame to clear "old" active cells?
// Or just let the CSS transition handle the fade out when class is removed.
// Better approach for "trail":
// Add active class. Set a timeout to remove it.
if (cell.dataset.timeout) {
clearTimeout(Number(cell.dataset.timeout));
}
const timeoutId = setTimeout(() => {
cell.classList.remove('active');
}, 50); // Short "hold" time, then fade out via CSS
cell.dataset.timeout = String(timeoutId);
}
}
});
}
window.addEventListener('scroll', handleScroll, { passive: true });
handleScroll(); // Initial check
// Random pulse for liveliness
function pulseRandomSquare() {
// Only pulse if not currently interacting (optional, but keeps it cleaner)
const randomIndex = Math.floor(Math.random() * cells.length);
const cell = cells[randomIndex];
if(cell) {
cell.classList.add('active');
setTimeout(() => {
cell.classList.remove('active');
}, 200);
}
}
setInterval(pulseRandomSquare, 1500);
</script>

View File

@ -1,75 +1,111 @@
---
import { Image } from 'astro:assets';
---
<section id="skills" class="container mx-auto px-6 lg:px-12 py-32 bg-brand-panel border-y border-white/5">
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-10 lg:gap-12">
<div class="col-span-1 md:col-span-2 lg:col-span-4 mb-6 animate-on-scroll slide-up">
<h2 class="text-3xl md:text-4xl font-bold uppercase mb-3 tracking-tight">Technical Arsenal</h2>
<p class="text-slate-500 font-mono text-sm tracking-wide">/// SOFTWARE & LANGUAGES</p>
</div>
<!-- Compositing -->
<div class="animate-on-scroll slide-up stagger-1">
<h3 class="text-base font-bold text-white uppercase mb-6 flex items-center gap-3 tracking-wide">
<i data-lucide="layers" class="w-4 h-4 text-brand-accent"></i>
Compositing
</h3>
<div class="flex flex-wrap gap-2">
<span class="skill-tag">Nuke/NukeX</span>
<span class="skill-tag">ComfyUI</span>
<span class="skill-tag">After Effects</span>
<span class="skill-tag">Photoshop</span>
<span class="skill-tag">Deep Compositing</span>
<span class="skill-tag">Live Action VFX</span>
<section id="skills" class="bg-brand-dark py-32 lg:py-48 overflow-hidden relative cursor-default">
<div class="container mx-auto px-6 lg:px-12 relative z-10">
<!-- Header Section -->
<div class="mb-24 lg:mb-32 grid grid-cols-1 lg:grid-cols-12 gap-12">
<div class="lg:col-span-8">
<h2 class="text-6xl md:text-8xl lg:text-9xl font-bold uppercase tracking-tighter leading-[0.85] text-white">
<span class="block relative overflow-hidden">
<span class="animate-on-scroll slide-up block">Technical</span>
</span>
<span class="block relative overflow-hidden">
<span class="animate-on-scroll slide-up stagger-1 block text-stroke text-transparent">Arsenal</span>
</span>
</h2>
</div>
<div class="lg:col-span-4 flex items-end">
<p class="text-slate-400 text-lg leading-relaxed animate-on-scroll slide-up stagger-2 border-l-2 border-brand-accent pl-6">
A comprehensive suite of tools and workflows designed for high-fidelity visual production and pipeline automation.
</p>
</div>
</div>
<!-- 3D -->
<div class="animate-on-scroll slide-up stagger-2">
<h3 class="text-base font-bold text-white uppercase mb-6 flex items-center gap-3 tracking-wide">
<i data-lucide="box" class="w-4 h-4 text-brand-accent"></i>
3D Generalist
</h3>
<div class="flex flex-wrap gap-2">
<span class="skill-tag">Houdini</span>
<span class="skill-tag">Blender</span>
<span class="skill-tag">Maya</span>
<span class="skill-tag">USD</span>
<span class="skill-tag">Solaris/Karma</span>
<span class="skill-tag">Unreal Engine</span>
<span class="skill-tag">Substance</span>
<span class="skill-tag">Procedural Gen</span>
</div>
</div>
<!-- Skills Data Grid -->
<div class="w-full border-t border-white/10" id="skills-table">
<!-- AI/ML -->
<div class="animate-on-scroll slide-up stagger-3">
<h3 class="text-base font-bold text-white uppercase mb-6 flex items-center gap-3 tracking-wide">
<i data-lucide="cpu" class="w-4 h-4 text-brand-accent"></i>
AI/ML Integration
</h3>
<div class="flex flex-wrap gap-2">
<span class="skill-tag bg-brand-accent/10 border-brand-accent/40 text-brand-accent hover:bg-brand-accent/20">Stable Diffusion</span>
<span class="skill-tag">LoRA Training</span>
<span class="skill-tag">Dataset Prep</span>
<span class="skill-tag">Synthetic Data</span>
<span class="skill-tag">Prompt Engineering</span>
<!-- Table Header -->
<div class="grid grid-cols-12 gap-4 py-6 border-b border-white/10 text-[10px] font-mono uppercase tracking-widest text-slate-500 select-none">
<div class="col-span-2 md:col-span-1">/// ID</div>
<div class="col-span-10 md:col-span-4">Domain</div>
<div class="col-span-12 md:col-span-5 hidden md:block">Stack</div>
<div class="col-span-6 md:col-span-2 hidden md:block text-right">Proficiency</div>
</div>
</div>
<!-- Dev -->
<div class="animate-on-scroll slide-up stagger-4">
<h3 class="text-base font-bold text-white uppercase mb-6 flex items-center gap-3 tracking-wide">
<i data-lucide="code" class="w-4 h-4 text-brand-accent"></i>
Development
</h3>
<div class="flex flex-wrap gap-2">
<span class="skill-tag">Python</span>
<span class="skill-tag">JavaScript</span>
<span class="skill-tag">React</span>
<span class="skill-tag">Docker</span>
<span class="skill-tag">Linux</span>
<span class="skill-tag">Pipeline Dev</span>
<!-- Row 1: Compositing -->
<div class="skill-row group relative grid grid-cols-12 gap-4 py-10 border-b border-white/10 items-center transition-colors duration-300 hover:border-brand-accent/30" data-image="compositing">
<div class="col-span-2 md:col-span-1 text-brand-accent font-mono text-sm relative overflow-hidden">
<span class="block group-hover:-translate-y-full transition-transform duration-500">01</span>
<span class="absolute top-0 left-0 translate-y-full group-hover:translate-y-0 transition-transform duration-500">01</span>
</div>
<div class="col-span-10 md:col-span-4 relative overflow-hidden">
<h3 class="text-3xl md:text-5xl font-bold text-white uppercase tracking-tighter group-hover:text-brand-accent transition-colors duration-300">Compositing</h3>
<!-- Reveal Swipe Effect -->
<div class="absolute inset-0 bg-brand-accent transform scale-x-0 group-hover:scale-x-100 transition-transform duration-500 origin-left mix-blend-difference pointer-events-none opacity-0 group-hover:opacity-100"></div>
</div>
<div class="col-span-12 md:col-span-5 text-slate-400 font-mono text-xs md:text-sm tracking-wide group-hover:text-white transition-colors duration-300">
Nuke/NukeX • ComfyUI • After Effects • Photoshop
</div>
<div class="col-span-6 md:col-span-2 text-right hidden md:block">
<span class="inline-block px-3 py-1 border border-brand-accent/50 text-brand-accent text-[10px] font-bold uppercase tracking-widest bg-brand-accent/5">Expert</span>
</div>
</div>
<!-- Row 2: 3D Generalist -->
<div class="skill-row group relative grid grid-cols-12 gap-4 py-10 border-b border-white/10 items-center transition-colors duration-300 hover:border-brand-accent/30" data-image="3d">
<div class="col-span-2 md:col-span-1 text-brand-accent font-mono text-sm relative overflow-hidden">
<span class="block group-hover:-translate-y-full transition-transform duration-500">02</span>
<span class="absolute top-0 left-0 translate-y-full group-hover:translate-y-0 transition-transform duration-500">02</span>
</div>
<div class="col-span-10 md:col-span-4 relative overflow-hidden">
<h3 class="text-3xl md:text-5xl font-bold text-white uppercase tracking-tighter group-hover:text-brand-accent transition-colors duration-300">3D Generalist</h3>
</div>
<div class="col-span-12 md:col-span-5 text-slate-400 font-mono text-xs md:text-sm tracking-wide group-hover:text-white transition-colors duration-300">
Houdini • Blender • Maya • USD • Solaris
</div>
<div class="col-span-6 md:col-span-2 text-right hidden md:block">
<span class="inline-block px-3 py-1 border border-white/20 text-slate-300 text-[10px] font-bold uppercase tracking-widest">Advanced</span>
</div>
</div>
<!-- Row 3: AI / ML -->
<div class="skill-row group relative grid grid-cols-12 gap-4 py-10 border-b border-white/10 items-center transition-colors duration-300 hover:border-brand-accent/30" data-image="ai">
<div class="col-span-2 md:col-span-1 text-brand-accent font-mono text-sm relative overflow-hidden">
<span class="block group-hover:-translate-y-full transition-transform duration-500">03</span>
<span class="absolute top-0 left-0 translate-y-full group-hover:translate-y-0 transition-transform duration-500">03</span>
</div>
<div class="col-span-10 md:col-span-4 relative overflow-hidden">
<h3 class="text-3xl md:text-5xl font-bold text-white uppercase tracking-tighter group-hover:text-brand-accent transition-colors duration-300">AI Integration</h3>
</div>
<div class="col-span-12 md:col-span-5 text-slate-400 font-mono text-xs md:text-sm tracking-wide group-hover:text-white transition-colors duration-300">
Stable Diffusion • LoRA • Datasets • Python
</div>
<div class="col-span-6 md:col-span-2 text-right hidden md:block">
<span class="inline-block px-3 py-1 border border-brand-accent/50 text-brand-accent text-[10px] font-bold uppercase tracking-widest bg-brand-accent/5">Specialist</span>
</div>
</div>
<!-- Row 4: Development -->
<div class="skill-row group relative grid grid-cols-12 gap-4 py-10 border-b border-white/10 items-center transition-colors duration-300 hover:border-brand-accent/30" data-image="dev">
<div class="col-span-2 md:col-span-1 text-brand-accent font-mono text-sm relative overflow-hidden">
<span class="block group-hover:-translate-y-full transition-transform duration-500">04</span>
<span class="absolute top-0 left-0 translate-y-full group-hover:translate-y-0 transition-transform duration-500">04</span>
</div>
<div class="col-span-10 md:col-span-4 relative overflow-hidden">
<h3 class="text-3xl md:text-5xl font-bold text-white uppercase tracking-tighter group-hover:text-brand-accent transition-colors duration-300">Development</h3>
</div>
<div class="col-span-12 md:col-span-5 text-slate-400 font-mono text-xs md:text-sm tracking-wide group-hover:text-white transition-colors duration-300">
Python • React • Docker • Linux • Pipeline
</div>
<div class="col-span-6 md:col-span-2 text-right hidden md:block">
<span class="inline-block px-3 py-1 border border-white/20 text-slate-300 text-[10px] font-bold uppercase tracking-widest">Full Stack</span>
</div>
</div>
</div>
</div>
</section>

View File

@ -7,6 +7,14 @@ heroImage: '../../assets/blog-placeholder-1.jpg'
In summer 2024, Biohazard VFX partnered with Stinkfilms and director Felix Brady to create a visually striking brand film for G-Star Raw's Olympics campaign. This project pushed our team of 60+ artists to deliver high-end CG environments while pioneering new AI/ML integration workflows.
<div class="video-container my-10">
<video controls class="w-full border border-white/10">
<source src="/media/FF_PUFF_GStar_DC_v08_4608x3164.mp4" type="video/mp4" />
Your browser does not support the video tag.
</video>
<p class="text-slate-500 text-sm mt-3 font-mono">/// FINAL FILM</p>
</div>
## The Challenge
The creative brief called for expansive cityscapes and environments that would feel both futuristic and grounded in reality. The timeline was aggressive, and the scope was ambitious—exactly the kind of project we thrive on.
@ -43,6 +51,37 @@ Managing 60+ artists across multiple time zones required robust communication an
The final film delivered on time and exceeded client expectations. The combination of traditional VFX craft with cutting-edge AI tools allowed us to achieve a level of visual complexity that would have been prohibitively expensive using traditional methods alone.
## Shot Breakdowns
A closer look at some of the key shots and the techniques used to bring them to life.
<div class="grid grid-cols-1 md:grid-cols-2 gap-6 my-10">
<div class="video-container">
<video controls class="w-full border border-white/10">
<source src="/media/GSTR_01_260_breakdown.mp4" type="video/mp4" />
</video>
<p class="text-slate-500 text-sm mt-3 font-mono">/// SHOT BREAKDOWN 01</p>
</div>
<div class="video-container">
<video controls class="w-full border border-white/10">
<source src="/media/GSTR_03_070_v10_breakdown_v01.mp4" type="video/mp4" />
</video>
<p class="text-slate-500 text-sm mt-3 font-mono">/// SHOT BREAKDOWN 02</p>
</div>
</div>
## Making Of
Go behind the scenes to see how the team brought this project together.
<div class="video-container my-10">
<video controls class="w-full border border-white/10">
<source src="/media/FF_PUFF_GStar_DC_Making-of_v06_H264.mp4" type="video/mp4" />
Your browser does not support the video tag.
</video>
<p class="text-slate-500 text-sm mt-3 font-mono">/// MAKING OF</p>
</div>
---
*This project exemplifies the direction we're taking at Biohazard VFX: embracing new technology while never compromising on quality or artistic vision.*

View File

@ -9,9 +9,10 @@ import { SITE_TITLE, SITE_DESCRIPTION } from '../consts';
interface Props {
title?: string;
description?: string;
usePadding?: boolean;
}
const { title = SITE_TITLE, description = SITE_DESCRIPTION } = Astro.props;
const { title = SITE_TITLE, description = SITE_DESCRIPTION, usePadding = true } = Astro.props;
---
<!DOCTYPE html>
@ -24,7 +25,7 @@ const { title = SITE_TITLE, description = SITE_DESCRIPTION } = Astro.props;
<GridOverlay />
<Navigation />
<main class="relative z-10 pt-32 lg:pt-48 pb-24 min-h-screen">
<main class:list={["relative z-10 min-h-screen pb-24", { "pt-32 lg:pt-48": usePadding }]}>
<slot />
</main>

View File

@ -1,112 +1,287 @@
---
import BaseLayout from '../layouts/BaseLayout.astro';
import { SITE_TITLE, SITE_DESCRIPTION } from '../consts';
import { SITE_TITLE } from '../consts';
const pageTitle = `Contact | ${SITE_TITLE}`;
---
<BaseLayout title={`Contact | ${SITE_TITLE}`} description="Get in touch for collaboration or inquiries.">
<section class="container mx-auto px-6 lg:px-12">
<div class="mb-20 animate-on-scroll slide-up">
<h1 class="text-5xl md:text-7xl lg:text-8xl font-bold uppercase text-white mb-5 tracking-tighter">
Let's <span class="text-transparent bg-clip-text bg-gradient-to-r from-brand-accent via-orange-400 to-white">Talk</span>
</h1>
<p class="text-slate-500 font-mono text-sm tracking-wide">/// GET IN TOUCH</p>
</div>
<BaseLayout title={pageTitle} description="Get in touch for collaboration or inquiries." usePadding={false}>
<div class="grid grid-cols-1 lg:grid-cols-12 gap-12 lg:gap-20">
<!-- Contact Form -->
<div class="lg:col-span-7 animate-on-scroll slide-up stagger-1">
<form class="space-y-8" action="#" method="POST">
<div class="grid grid-cols-1 md:grid-cols-2 gap-6">
<div class="space-y-3">
<label for="name" class="text-xs font-bold uppercase tracking-widest text-slate-500 block">Name</label>
<input
type="text"
id="name"
name="name"
placeholder="Your Name"
class="w-full bg-white/[0.03] border border-slate-700 text-white px-5 py-4 focus:border-brand-accent focus:bg-white/[0.05] focus:outline-none transition-all duration-300 placeholder:text-slate-600"
required
/>
</div>
<div class="space-y-3">
<label for="email" class="text-xs font-bold uppercase tracking-widest text-slate-500 block">Email</label>
<input
type="email"
id="email"
name="email"
placeholder="name@example.com"
class="w-full bg-white/[0.03] border border-slate-700 text-white px-5 py-4 focus:border-brand-accent focus:bg-white/[0.05] focus:outline-none transition-all duration-300 placeholder:text-slate-600"
required
/>
</div>
</div>
<!-- Background Grid (Optional, low opacity) -->
<div class="fixed inset-0 z-0 pointer-events-none">
<div class="w-full h-full grid grid-cols-12 gap-4 opacity-[0.03]">
{Array.from({ length: 12 }).map((_) => (
<div class="h-full border-r border-white"></div>
))}
</div>
</div>
<div class="space-y-3">
<label for="subject" class="text-xs font-bold uppercase tracking-widest text-slate-500 block">Subject</label>
<select
id="subject"
name="subject"
class="w-full bg-white/[0.03] border border-slate-700 text-white px-5 py-4 focus:border-brand-accent focus:bg-white/[0.05] focus:outline-none transition-all duration-300 appearance-none cursor-pointer"
>
<option value="general" class="bg-brand-dark">General Inquiry</option>
<option value="project" class="bg-brand-dark">Project Collaboration</option>
<option value="freelance" class="bg-brand-dark">Freelance Availability</option>
<option value="other" class="bg-brand-dark">Other</option>
</select>
</div>
<section class="relative z-10 min-h-screen flex flex-col pt-32 lg:pt-48 pb-20 px-6 lg:px-12">
<div class="space-y-3">
<label for="message" class="text-xs font-bold uppercase tracking-widest text-slate-500 block">Message</label>
<textarea
id="message"
name="message"
rows="6"
placeholder="Tell me about your project..."
class="w-full bg-white/[0.03] border border-slate-700 text-white px-5 py-4 focus:border-brand-accent focus:bg-white/[0.05] focus:outline-none transition-all duration-300 placeholder:text-slate-600 resize-none"
required
></textarea>
</div>
<!-- Page Header -->
<div class="grid grid-cols-1 lg:grid-cols-12 gap-12 mb-20 lg:mb-32 border-b border-white/10 pb-12">
<div class="lg:col-span-8">
<h1 class="text-6xl md:text-8xl lg:text-9xl font-bold uppercase tracking-tighter leading-[0.85] text-white mb-8">
<span class="block animate-on-scroll slide-up">Project</span>
<span class="block text-brand-accent animate-on-scroll slide-up stagger-1">Inquiry</span>
</h1>
</div>
<div class="lg:col-span-4 flex flex-col justify-end">
<p class="font-mono text-sm text-slate-400 leading-relaxed mb-8 border-l border-brand-accent pl-6 animate-on-scroll fade-in stagger-2">
Available for freelance commissions and studio collaborations.
Currently booking Q3 2026.
</p>
</div>
</div>
<div class="pt-6">
<button type="submit" class="btn-primary group relative overflow-hidden">
<span class="relative z-10">Send Message</span>
<div class="absolute inset-0 bg-white opacity-0 group-hover:opacity-20 transition-opacity duration-300"></div>
</button>
</div>
</form>
</div>
<div class="grid grid-cols-1 lg:grid-cols-12 gap-12 lg:gap-24 flex-grow">
<!-- Sidebar Info -->
<div class="lg:col-span-5 space-y-12 animate-on-scroll slide-left stagger-2">
<div>
<h3 class="text-xs font-bold uppercase tracking-widest text-slate-500 mb-6">Contact Info</h3>
<a href="mailto:nicholai@nicholai.work" class="text-lg lg:text-xl text-white hover:text-brand-accent transition-colors duration-300 font-mono block">
nicholai@nicholai.work
</a>
</div>
<!-- Left Column: Contact Form -->
<div class="lg:col-span-7 animate-on-scroll slide-up stagger-3">
<div class="mb-8 flex items-center gap-3">
<span class="w-2 h-2 bg-brand-accent rounded-full animate-pulse"></span>
<span class="font-mono text-xs text-brand-accent uppercase tracking-widest">Transmission Uplink</span>
</div>
<div>
<h3 class="text-xs font-bold uppercase tracking-widest text-slate-500 mb-6">Location</h3>
<p class="text-base lg:text-lg text-slate-300 leading-relaxed font-light">
Colorado Springs, CO<br/>
Mountain Standard Time (MST)
</p>
</div>
<form class="space-y-12" action="#" method="POST">
<div class="group relative">
<input
type="text"
id="name"
name="name"
class="block w-full bg-transparent border-b border-white/20 py-4 text-xl text-white focus:outline-none focus:border-brand-accent transition-colors duration-300 placeholder-transparent peer"
placeholder="Name"
required
/>
<label for="name" class="absolute left-0 top-4 text-slate-500 text-sm font-mono uppercase tracking-widest transition-all duration-300 peer-focus:-top-6 peer-focus:text-xs peer-focus:text-brand-accent peer-valid:-top-6 peer-valid:text-xs peer-valid:text-slate-400 pointer-events-none">
/// Identification Name
</label>
</div>
<div class="pt-10 border-t border-white/10">
<h3 class="text-xs font-bold uppercase tracking-widest text-slate-500 mb-6">Availability</h3>
<div class="flex items-center gap-3 mb-4">
<span class="relative flex h-2.5 w-2.5">
<span class="animate-ping absolute inline-flex h-full w-full rounded-full bg-brand-accent opacity-75"></span>
<span class="relative inline-flex rounded-full h-2.5 w-2.5 bg-brand-accent"></span>
</span>
<span class="text-sm font-bold text-brand-accent uppercase tracking-wide">Open to opportunities</span>
</div>
<p class="text-slate-400 text-sm leading-relaxed font-light">
Currently accepting new projects for Q3 2026. Reach out to schedule a discovery call.
</p>
</div>
</div>
</div>
</section>
<div class="group relative">
<input
type="email"
id="email"
name="email"
class="block w-full bg-transparent border-b border-white/20 py-4 text-xl text-white focus:outline-none focus:border-brand-accent transition-colors duration-300 placeholder-transparent peer"
placeholder="Email"
required
/>
<label for="email" class="absolute left-0 top-4 text-slate-500 text-sm font-mono uppercase tracking-widest transition-all duration-300 peer-focus:-top-6 peer-focus:text-xs peer-focus:text-brand-accent peer-valid:-top-6 peer-valid:text-xs peer-valid:text-slate-400 pointer-events-none">
/// Return Address
</label>
</div>
<!-- Custom Dropdown -->
<div class="group relative" id="custom-select">
<input type="hidden" name="subject" id="subject-input" required>
<button type="button" id="select-trigger" class="block w-full text-left bg-transparent border-b border-white/20 py-4 text-xl text-white focus:outline-none focus:border-brand-accent transition-colors duration-300 flex justify-between items-center group-hover:border-white/40">
<span id="select-value" class="text-transparent">Select</span> <!-- Hidden placeholder text to keep height -->
<div class="text-brand-accent transform transition-transform duration-300" id="select-arrow">
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m6 9 6 6 6-6"/></svg>
</div>
</button>
<label id="select-label" class="absolute left-0 top-4 text-slate-500 text-sm font-mono uppercase tracking-widest transition-all duration-300 pointer-events-none">
/// Subject Protocol
</label>
<!-- Dropdown Menu -->
<div id="select-options" class="absolute left-0 top-full w-full bg-brand-dark border border-white/20 shadow-2xl z-50 hidden opacity-0 transform translate-y-2 transition-all duration-200 origin-top mt-2">
<div class="p-1">
<div class="option px-5 py-4 hover:bg-white/5 cursor-pointer text-white text-lg font-light transition-colors flex items-center gap-3 group/option" data-value="project">
<span class="w-1.5 h-1.5 rounded-full bg-brand-accent opacity-0 group-hover/option:opacity-100 transition-opacity"></span>
New Project Commission
</div>
<div class="option px-5 py-4 hover:bg-white/5 cursor-pointer text-white text-lg font-light transition-colors flex items-center gap-3 group/option" data-value="collab">
<span class="w-1.5 h-1.5 rounded-full bg-brand-accent opacity-0 group-hover/option:opacity-100 transition-opacity"></span>
Studio Collaboration
</div>
<div class="option px-5 py-4 hover:bg-white/5 cursor-pointer text-white text-lg font-light transition-colors flex items-center gap-3 group/option" data-value="press">
<span class="w-1.5 h-1.5 rounded-full bg-brand-accent opacity-0 group-hover/option:opacity-100 transition-opacity"></span>
Press / Media
</div>
<div class="option px-5 py-4 hover:bg-white/5 cursor-pointer text-white text-lg font-light transition-colors flex items-center gap-3 group/option" data-value="other">
<span class="w-1.5 h-1.5 rounded-full bg-brand-accent opacity-0 group-hover/option:opacity-100 transition-opacity"></span>
Other Inquiry
</div>
</div>
</div>
</div>
<div class="group relative">
<textarea
id="message"
name="message"
rows="4"
class="block w-full bg-transparent border-b border-white/20 py-4 text-xl text-white focus:outline-none focus:border-brand-accent transition-colors duration-300 placeholder-transparent peer resize-none"
placeholder="Message"
required
></textarea>
<label for="message" class="absolute left-0 top-4 text-slate-500 text-sm font-mono uppercase tracking-widest transition-all duration-300 peer-focus:-top-6 peer-focus:text-xs peer-focus:text-brand-accent peer-valid:-top-6 peer-valid:text-xs peer-valid:text-slate-400 pointer-events-none">
/// Message Data
</label>
</div>
<div class="pt-8">
<button type="submit" class="group relative inline-flex items-center justify-center gap-4 px-8 py-4 bg-transparent border border-white/20 hover:border-brand-accent hover:bg-brand-accent/5 transition-all duration-300">
<span class="font-mono text-xs font-bold uppercase tracking-widest text-white group-hover:text-brand-accent transition-colors">Transmit Message</span>
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="text-slate-500 group-hover:text-brand-accent group-hover:translate-x-1 transition-all"><line x1="22" y1="2" x2="11" y2="13"/><polygon points="22 2 15 22 11 13 2 9 22 2"/></svg>
</button>
</div>
</form>
</div>
<!-- Right Column: System Status / Info -->
<div class="lg:col-span-5 space-y-16 animate-on-scroll slide-left stagger-4">
<!-- Data Block 1 -->
<div class="relative pl-6 border-l border-white/10">
<h3 class="font-mono text-xs text-slate-500 uppercase tracking-widest mb-4">Direct Link</h3>
<a href="mailto:nicholai@nicholai.work" class="text-2xl md:text-3xl font-bold text-white hover:text-brand-accent transition-colors break-all">
nicholai@nicholai.work
</a>
</div>
<!-- Data Block 2 -->
<div class="relative pl-6 border-l border-white/10">
<h3 class="font-mono text-xs text-slate-500 uppercase tracking-widest mb-4">Coordinates</h3>
<p class="text-xl text-white font-light">
Colorado Springs, CO<br>
<span class="text-slate-500 text-base">United States</span>
</p>
<div class="mt-4 font-mono text-xs text-brand-accent">
38.8339° N, 104.8214° W
</div>
</div>
<!-- Data Block 3 -->
<div class="relative pl-6 border-l border-white/10">
<h3 class="font-mono text-xs text-slate-500 uppercase tracking-widest mb-4">Social Feed</h3>
<ul class="space-y-4">
<li>
<a href="#" class="flex items-center gap-4 group">
<span class="text-slate-400 group-hover:text-white transition-colors text-lg">Instagram</span>
<svg class="w-4 h-4 text-slate-600 group-hover:text-brand-accent transition-colors transform group-hover:translate-x-1 group-hover:-translate-y-1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><line x1="7" y1="17" x2="17" y2="7"/><polyline points="7 7 17 7 17 17"/></svg>
</a>
</li>
<li>
<a href="#" class="flex items-center gap-4 group">
<span class="text-slate-400 group-hover:text-white transition-colors text-lg">LinkedIn</span>
<svg class="w-4 h-4 text-slate-600 group-hover:text-brand-accent transition-colors transform group-hover:translate-x-1 group-hover:-translate-y-1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><line x1="7" y1="17" x2="17" y2="7"/><polyline points="7 7 17 7 17 17"/></svg>
</a>
</li>
<li>
<a href="#" class="flex items-center gap-4 group">
<span class="text-slate-400 group-hover:text-white transition-colors text-lg">Vimeo</span>
<svg class="w-4 h-4 text-slate-600 group-hover:text-brand-accent transition-colors transform group-hover:translate-x-1 group-hover:-translate-y-1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><line x1="7" y1="17" x2="17" y2="7"/><polyline points="7 7 17 7 17 17"/></svg>
</a>
</li>
</ul>
</div>
</div>
</div>
</section>
</BaseLayout>
<style>
/* Custom autofill styles to match dark theme */
input:-webkit-autofill,
input:-webkit-autofill:hover,
input:-webkit-autofill:focus,
textarea:-webkit-autofill,
textarea:-webkit-autofill:hover,
textarea:-webkit-autofill:focus {
-webkit-text-fill-color: white;
-webkit-box-shadow: 0 0 0px 1000px #0B0D11 inset;
transition: background-color 5000s ease-in-out 0s;
}
/* Label active state */
.label-active {
top: -1.5rem !important;
font-size: 0.75rem !important;
color: #94A3B8 !important;
}
/* Dropdown open state */
.dropdown-open #select-arrow {
transform: rotate(180deg);
color: white;
}
</style>
<script>
const selectContainer = document.getElementById('custom-select');
const selectTrigger = document.getElementById('select-trigger');
const selectOptions = document.getElementById('select-options');
const selectValue = document.getElementById('select-value');
const hiddenInput = document.getElementById('subject-input') as HTMLInputElement;
const selectLabel = document.getElementById('select-label');
const options = document.querySelectorAll('.option');
const arrow = document.getElementById('select-arrow');
if (selectTrigger && selectOptions && selectValue && hiddenInput && selectLabel) {
// Toggle Dropdown
selectTrigger.addEventListener('click', () => {
const isOpen = !selectOptions.classList.contains('hidden');
if (isOpen) {
closeDropdown();
} else {
openDropdown();
}
});
// Option Selection
options.forEach(option => {
option.addEventListener('click', (e) => {
const target = e.currentTarget as HTMLElement;
const value = target.dataset.value || '';
const text = target.innerText;
// Update UI
selectValue.textContent = text;
selectValue.classList.remove('text-transparent');
selectValue.classList.add('text-white');
// Update Data
hiddenInput.value = value;
// Update Label Style
selectLabel.classList.add('label-active');
selectLabel.classList.add('text-brand-accent'); // Highlight when selected
closeDropdown();
});
});
// Close clicking outside
document.addEventListener('click', (e) => {
if (selectContainer && !selectContainer.contains(e.target as Node)) {
closeDropdown();
}
});
function openDropdown() {
selectOptions?.classList.remove('hidden');
// Small delay for opacity transition
requestAnimationFrame(() => {
selectOptions?.classList.remove('opacity-0', 'translate-y-2');
});
selectContainer?.classList.add('dropdown-open');
}
function closeDropdown() {
selectOptions?.classList.add('opacity-0', 'translate-y-2');
setTimeout(() => {
selectOptions?.classList.add('hidden');
}, 200);
selectContainer?.classList.remove('dropdown-open');
}
}
</script>

View File

@ -6,7 +6,7 @@ import FeaturedProject from '../components/sections/FeaturedProject.astro';
import Skills from '../components/sections/Skills.astro';
---
<BaseLayout>
<BaseLayout usePadding={false}>
<Hero />
<!-- Gradient Divider -->