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:
parent
aae6f7a25a
commit
4689332679
688
dev/design.json
688
dev/design.json
@ -1,20 +1,20 @@
|
|||||||
{
|
{
|
||||||
"design_system": {
|
"design_system": {
|
||||||
"name": "V7 Industrial Dark Mode System",
|
"name": "V7 Industrial Dark Mode System",
|
||||||
"version": "1.0",
|
"version": "2.0",
|
||||||
"methodology": {
|
"methodology": {
|
||||||
"approach": "Brutalist/Industrial Dark UI",
|
"approach": "Brutalist/Industrial Dark UI with System/Terminal Aesthetics",
|
||||||
"philosophy": "Grid-visible, high-contrast, typography-forward design with layered content and subtle glassmorphism",
|
"philosophy": "Grid-visible, high-contrast, typography-forward design. Interfaces should feel like high-end technical equipment (F1 telemetry, server racks, terminals).",
|
||||||
"characteristics": [
|
"characteristics": [
|
||||||
"Dark mode native (not an option, the default)",
|
"Dark mode native (not an option, the default)",
|
||||||
"Visible grid structure as design element",
|
"Visible grid structure as design element (10x10 interactive or 12-col static)",
|
||||||
"Massive typography as primary visual hierarchy",
|
"Massive typography as primary visual hierarchy (2-line stacks)",
|
||||||
"Minimal rounded corners (sharp, industrial aesthetic)",
|
"Minimal rounded corners (sharp, industrial aesthetic)",
|
||||||
"Heavy use of borders and dividers",
|
"Heavy use of borders, dividers, and technical labels (SYS.01, ///)",
|
||||||
"Layered content with overlays and blend modes",
|
"Layered content with overlays, video backgrounds, and blend modes",
|
||||||
"Subtle animations and smooth transitions",
|
"System-like animations: boot-up sequences, grid trails, status pulses",
|
||||||
"Opacity-based depth system",
|
"Opacity-based depth system (glass panels)",
|
||||||
"Technical/monospace accents"
|
"Technical/monospace accents for metadata (coordinates, time, IDs)"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"color_palette": {
|
"color_palette": {
|
||||||
@ -43,7 +43,7 @@
|
|||||||
"hex": "#ff4d00",
|
"hex": "#ff4d00",
|
||||||
"rgb": "255, 77, 0",
|
"rgb": "255, 77, 0",
|
||||||
"name": "Vibrant Orange",
|
"name": "Vibrant Orange",
|
||||||
"usage": "Primary accent, CTAs, highlights, interactive elements",
|
"usage": "Primary accent, CTAs, highlights, interactive elements, status indicators",
|
||||||
"opacity_variants": [
|
"opacity_variants": [
|
||||||
{
|
{
|
||||||
"name": "brand_accent_5",
|
"name": "brand_accent_5",
|
||||||
@ -74,6 +74,7 @@
|
|||||||
"white": {
|
"white": {
|
||||||
"hex": "#FFFFFF",
|
"hex": "#FFFFFF",
|
||||||
"opacity_scale": {
|
"opacity_scale": {
|
||||||
|
"2": "rgba(255, 255, 255, 0.02)",
|
||||||
"5": "rgba(255, 255, 255, 0.05)",
|
"5": "rgba(255, 255, 255, 0.05)",
|
||||||
"10": "rgba(255, 255, 255, 0.1)",
|
"10": "rgba(255, 255, 255, 0.1)",
|
||||||
"20": "rgba(255, 255, 255, 0.2)",
|
"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": {
|
"typography": {
|
||||||
@ -163,43 +133,16 @@
|
|||||||
"primary": {
|
"primary": {
|
||||||
"name": "Inter",
|
"name": "Inter",
|
||||||
"type": "sans-serif",
|
"type": "sans-serif",
|
||||||
"weights": [
|
|
||||||
300,
|
|
||||||
400,
|
|
||||||
500,
|
|
||||||
600,
|
|
||||||
700,
|
|
||||||
800
|
|
||||||
],
|
|
||||||
"usage": "Primary UI font",
|
"usage": "Primary UI font",
|
||||||
"fallback": "sans-serif"
|
"fallback": "sans-serif"
|
||||||
},
|
},
|
||||||
"mono": {
|
"mono": {
|
||||||
"name": "system-ui monospace",
|
"name": "system-ui monospace",
|
||||||
"usage": "Numbers, technical details, small labels",
|
"usage": "Numbers, technical details, small labels, coordinates, clock",
|
||||||
"examples": [
|
"examples": [
|
||||||
"font-mono"
|
"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": {
|
"scale": {
|
||||||
"xs": {
|
"xs": {
|
||||||
@ -242,582 +185,119 @@
|
|||||||
"line_height": "2.5rem",
|
"line_height": "2.5rem",
|
||||||
"usage": "Page headings"
|
"usage": "Page headings"
|
||||||
},
|
},
|
||||||
"5xl": {
|
|
||||||
"size": "3rem",
|
|
||||||
"line_height": "1",
|
|
||||||
"usage": "Large headings"
|
|
||||||
},
|
|
||||||
"6xl": {
|
"6xl": {
|
||||||
"size": "3.75rem",
|
"size": "3.75rem",
|
||||||
"line_height": "1",
|
"line_height": "1",
|
||||||
"usage": "Hero headings"
|
"usage": "Hero headings"
|
||||||
},
|
},
|
||||||
"7xl": {
|
|
||||||
"size": "4.5rem",
|
|
||||||
"line_height": "1",
|
|
||||||
"usage": "Display text (md)"
|
|
||||||
},
|
|
||||||
"8xl": {
|
"8xl": {
|
||||||
"size": "6rem",
|
"size": "6rem",
|
||||||
"line_height": "1",
|
"line_height": "1",
|
||||||
"usage": "Display text (lg)"
|
"usage": "Display text"
|
||||||
},
|
},
|
||||||
"massive": {
|
"9xl": {
|
||||||
"sizes": [
|
"size": "8rem",
|
||||||
"12rem",
|
"line_height": "0.85",
|
||||||
"18rem (md)",
|
"usage": "Massive Headers (2-line stacks)"
|
||||||
"22rem (lg)"
|
|
||||||
],
|
|
||||||
"line_height": "none",
|
|
||||||
"usage": "Hero display, massive branding"
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"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": {
|
"patterns": {
|
||||||
"small_label": {
|
"technical_label": {
|
||||||
"size": "text-xs",
|
"size": "text-[10px]",
|
||||||
"weight": "font-bold",
|
"weight": "font-bold or font-medium",
|
||||||
|
"family": "font-mono",
|
||||||
"transform": "uppercase",
|
"transform": "uppercase",
|
||||||
"tracking": "tracking-widest",
|
"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": {
|
"massive_stack": {
|
||||||
"size": "text-[12rem] md:text-[18rem] lg:text-[22rem]",
|
"size": "text-6xl md:text-8xl lg:text-9xl",
|
||||||
"weight": "font-bold",
|
"weight": "font-bold",
|
||||||
"line_height": "leading-none",
|
"line_height": "leading-[0.85]",
|
||||||
"tracking": "tracking-tighter",
|
"tracking": "tracking-tighter",
|
||||||
"example_modifiers": "text-transparent bg-clip-text bg-gradient-to-tr"
|
"structure": "Two or three lines, mixture of solid white and text-stroke or accent color"
|
||||||
},
|
|
||||||
"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"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"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": {
|
"grid_system": {
|
||||||
"overlay": {
|
"interactive_overlay": {
|
||||||
"enabled": true,
|
"type": "10x10 Grid",
|
||||||
"purpose": "Visible design element",
|
"interaction": "mousemove trail effect",
|
||||||
"implementation": "Fixed position, pointer-events-none, opacity-10",
|
"style": "border border-white/5",
|
||||||
"columns": {
|
"active_state": "bg-brand-accent opacity-15",
|
||||||
"mobile": 4,
|
"fade_out": "duration-800 ease-out"
|
||||||
"tablet": 6,
|
|
||||||
"desktop": 12
|
|
||||||
},
|
|
||||||
"styling": "border-r border-slate-500 h-full"
|
|
||||||
},
|
},
|
||||||
"content_grid": {
|
"data_table": {
|
||||||
"base": "grid grid-cols-1",
|
"columns": 12,
|
||||||
"tablet": "md:grid-cols-2 or md:grid-cols-4",
|
"headers": "text-[10px] font-mono uppercase tracking-widest",
|
||||||
"desktop": "lg:grid-cols-12 or lg:grid-cols-2",
|
"rows": "border-b border-white/10 py-10 hover:border-brand-accent/30"
|
||||||
"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"
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"components": {
|
"components": {
|
||||||
"buttons": {
|
"buttons": {
|
||||||
"primary": {
|
"terminal_action": {
|
||||||
"base": "bg-brand-accent text-brand-dark",
|
"base": "bg-transparent border border-white/20",
|
||||||
"padding": "px-8 py-4",
|
"hover": "hover:border-brand-accent hover:bg-brand-accent/5",
|
||||||
"typography": "text-xs font-bold uppercase tracking-widest",
|
"typography": "font-mono text-xs font-bold uppercase tracking-widest",
|
||||||
"hover": "hover:bg-amber-400 transition-colors",
|
"icon": "Arrow or chevron, translates on hover"
|
||||||
"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]"
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"cards": {
|
"cards": {
|
||||||
"glass_card": {
|
"rack_unit": {
|
||||||
"background": "bg-white/3 or rgba(255, 255, 255, 0.03)",
|
"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",
|
"backdrop": "backdrop-blur-sm",
|
||||||
"border": "border border-white/5 or border-white/10",
|
"border": "border border-white/10",
|
||||||
"padding": "p-6 or p-8",
|
"hover": "hover:border-brand-accent/30"
|
||||||
"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]"
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"navigation": {
|
"inputs": {
|
||||||
"header": {
|
"terminal_input": {
|
||||||
"position": "fixed or relative",
|
"style": "border-b border-white/20 bg-transparent py-4 text-xl",
|
||||||
"padding": "px-6 lg:px-12 pt-8",
|
"focus": "focus:border-brand-accent focus:outline-none",
|
||||||
"structure": "flex items-center justify-between",
|
"label": "floating label (peer-focus:-top-6), font-mono, tracking-widest"
|
||||||
"logo": "w-10 h-10 border border-white/20 flex items-center justify-center font-bold text-white tracking-tighter"
|
|
||||||
},
|
},
|
||||||
"nav_links": {
|
"industrial_select": {
|
||||||
"base": "text-xs font-semibold tracking-widest uppercase text-slate-500",
|
"trigger": "custom div mimicking terminal input",
|
||||||
"hover": "hover:text-white transition-colors",
|
"menu": "bg-brand-dark border border-white/20 shadow-2xl",
|
||||||
"active": "text-brand-accent",
|
"option": "hover:bg-white/5 flex items-center gap-3",
|
||||||
"spacing": "gap-12"
|
"indicator": "accent dot reveals on hover"
|
||||||
},
|
|
||||||
"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"
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"tabs": {
|
"visualizations": {
|
||||||
"container": "grid grid-cols-2 md:grid-cols-4 border-b border-slate-800",
|
"telemetry_overlay": {
|
||||||
"tab_item": {
|
"usage": "Video backgrounds",
|
||||||
"base": "p-6 border-t-2 border-transparent cursor-pointer transition-colors group",
|
"elements": "Top/bottom data bars, grid overlays, F1-style stats",
|
||||||
"inactive": "hover:border-slate-700 bg-transparent",
|
"interaction": "Full card clickable, no modals"
|
||||||
"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"
|
|
||||||
},
|
},
|
||||||
"status_indicator": {
|
"status_indicator": {
|
||||||
"dot": "w-2 h-2 bg-brand-accent rounded-full animate-pulse",
|
"dot": "w-2 h-2 bg-brand-accent rounded-full animate-pulse",
|
||||||
"glow": "shadow-[0_0_10px_rgba(255,77,0,0.5)]",
|
"label": "font-mono text-xs uppercase tracking-widest"
|
||||||
"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"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"interactive_states": {
|
"animations": {
|
||||||
"hover": {
|
"intro_sequence": {
|
||||||
"color_shift": "hover:text-white hover:text-brand-accent",
|
"trigger": "window.load",
|
||||||
"background": "hover:bg-white/5 hover:bg-slate-700",
|
"order": [
|
||||||
"border": "hover:border-brand-accent hover:border-white",
|
"Grid ripple (diagonal)",
|
||||||
"scale": "hover:scale-105",
|
"Text slide up",
|
||||||
"opacity": "hover:opacity-100 (from lower opacity)"
|
"Metadata fade in",
|
||||||
},
|
"Portrait slow reveal"
|
||||||
"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)"
|
|
||||||
]
|
]
|
||||||
|
},
|
||||||
|
"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
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
BIN
public/favicon-192.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 63 KiB |
BIN
public/favicon-32.png
Normal file
BIN
public/favicon-32.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 2.1 KiB |
BIN
public/favicon.ico
Normal file
BIN
public/favicon.ico
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 15 KiB |
@ -20,7 +20,10 @@ const { title, description, image = FallbackImage } = Astro.props;
|
|||||||
<!-- Global Metadata -->
|
<!-- Global Metadata -->
|
||||||
<meta charset="utf-8" />
|
<meta charset="utf-8" />
|
||||||
<meta name="viewport" content="width=device-width,initial-scale=1" />
|
<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="sitemap" href="/sitemap-index.xml" />
|
||||||
<link
|
<link
|
||||||
rel="alternate"
|
rel="alternate"
|
||||||
|
|||||||
@ -1,143 +1,140 @@
|
|||||||
---
|
---
|
||||||
---
|
---
|
||||||
<section id="experience" class="container mx-auto px-6 lg:px-12 py-32">
|
<section id="experience" class="container mx-auto px-6 lg:px-12 py-32 border-t border-white/10">
|
||||||
<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">
|
<!-- Section Header -->
|
||||||
<!-- Experience heading with scroll-driven fill effect -->
|
<div class="grid grid-cols-1 lg:grid-cols-12 gap-12 mb-20">
|
||||||
<h2 class="text-3xl md:text-4xl font-bold uppercase tracking-tight mb-2 relative">
|
<div class="lg:col-span-8">
|
||||||
<span class="text-stroke-fill" data-text="Experience">Experience</span>
|
<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>
|
||||||
<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>
|
||||||
|
<div class="lg:col-span-4 flex flex-col justify-end pb-4">
|
||||||
<div class="lg:col-span-8 relative">
|
<div class="font-mono text-xs text-slate-500 uppercase tracking-widest mb-4">/// Career Timeline</div>
|
||||||
<!-- Vertical line -->
|
<p class="text-slate-400 text-base leading-relaxed border-l border-brand-accent pl-6 animate-on-scroll fade-in stagger-2">
|
||||||
<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>
|
Bridging creative vision with technical execution. From running a dedicated VFX studio to high-end freelance supervision.
|
||||||
|
</p>
|
||||||
<!-- 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>
|
</div>
|
||||||
</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>
|
</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>
|
|
||||||
|
|||||||
@ -1,54 +1,100 @@
|
|||||||
---
|
---
|
||||||
---
|
---
|
||||||
<section id="work" class="py-32">
|
<section id="work" class="relative overflow-hidden group min-h-screen flex flex-col cursor-pointer">
|
||||||
<div class="container mx-auto px-6 lg:px-12 mb-14 animate-on-scroll slide-up">
|
<!-- Main Link Overlay -->
|
||||||
<span class="text-xs font-mono text-brand-accent mb-4 block tracking-wide">/// HIGHLIGHT</span>
|
<a href="/blog/gstar-raw-olympics/" class="absolute inset-0 z-30" aria-label="View G-Star Raw Olympics Case Study"></a>
|
||||||
<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>
|
<!-- Video Background -->
|
||||||
</h2>
|
<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>
|
</div>
|
||||||
|
|
||||||
<!-- Full Width Project Card -->
|
<!-- Main Content Container - Spaced to frame the video -->
|
||||||
<div class="w-full h-[75vh] lg:h-[80vh] relative group overflow-hidden border-y border-white/10 animate-on-scroll scale-in">
|
<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">
|
||||||
<!-- 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>
|
|
||||||
|
|
||||||
<!-- Grid Overlay on image -->
|
<!-- TOP HUD: Telemetry Data -->
|
||||||
<div class="absolute inset-0 bg-[url('data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNDAiIGhlaWdodD0iNDAiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PHBhdHRlcm4gaWQ9ImEiIHdpZHRoPSI0MCIgaGVpZ2h0PSI0MCIgcGF0dGVyblVuaXRzPSJ1c2VyU3BhY2VPblVzZSI+PHBhdHRlcm4gaWQ9ImIiIHdpZHRoPSI0MCIgaGVpZ2h0PSI0MCIgcGF0dGVyblVuaXRzPSJ1c2VyU3BhY2VPblVzZSI+PGNpcmNsZSBjeD0iMiIgY3k9IjIiIHI9IjEiIGZpbGw9InJnYmEoMjU1LDI1NSwyNTUsMC4xKSIvPjwvcGF0dGVybj48cmVjdCB3aWR0aD0iNDAiIGhlaWdodD0iNDAiIGZpbGw9InVybCgjYikiLz48L3BhdHRlcm4+PC9kZWZzPjxyZWN0IHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjYSkiLz48L3N2Zz4=')] opacity-20"></div>
|
<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>
|
||||||
<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">
|
<span class="text-[9px] font-mono text-brand-accent uppercase tracking-widest block mb-1">/// Role</span>
|
||||||
<div class="max-w-2xl transform translate-y-6 group-hover:translate-y-0 transition-transform duration-700 ease-out">
|
<span class="text-xl md:text-2xl font-bold text-white uppercase tracking-tight">VFX Sup</span>
|
||||||
<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>
|
|
||||||
</div>
|
</div>
|
||||||
|
<div>
|
||||||
<div class="hidden md:block text-right opacity-80 group-hover:opacity-100 transition-opacity duration-500">
|
<span class="text-[9px] font-mono text-brand-accent uppercase tracking-widest block mb-1">/// Client</span>
|
||||||
<span class="block text-[10px] uppercase text-slate-500 tracking-widest mb-2">Year</span>
|
<span class="text-xl md:text-2xl font-bold text-white uppercase tracking-tight">Stink</span>
|
||||||
<span class="block text-2xl font-bold text-white mb-6 tracking-tight">2024</span>
|
</div>
|
||||||
<span class="block text-[10px] uppercase text-slate-500 tracking-widest mb-2">Client</span>
|
<div>
|
||||||
<span class="block text-xl font-bold text-white tracking-tight">Stinkfilms</span>
|
<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>
|
||||||
</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>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|||||||
@ -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">
|
<section id="hero" class="relative w-full h-screen overflow-hidden bg-brand-dark">
|
||||||
<div class="grid grid-cols-1 md:grid-cols-12 gap-8 lg:gap-12">
|
<!-- Background Image (Portrait) -->
|
||||||
<div class="col-span-12">
|
<div class="absolute top-0 right-0 w-full md:w-1/2 h-full z-0">
|
||||||
<p class="font-mono text-brand-accent text-sm mb-6 tracking-wide animate-on-scroll fade-in">
|
<div class="relative w-full h-full">
|
||||||
/// TECHNICAL GENERALIST & VFX SUPERVISOR
|
<img
|
||||||
</p>
|
src="/media/nicholai-closeup-portrait.JPEG"
|
||||||
<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">
|
alt="Nicholai Portrait"
|
||||||
<span class="animate-on-scroll slide-up block stagger-1">Visual</span>
|
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"
|
||||||
<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>
|
id="hero-portrait"
|
||||||
</h1>
|
/>
|
||||||
</div>
|
<div class="absolute inset-0 bg-gradient-to-l from-transparent via-brand-dark/50 to-brand-dark"></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">
|
<div class="absolute inset-0 bg-gradient-to-t from-brand-dark via-transparent to-transparent"></div>
|
||||||
<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>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Hero Footer -->
|
<!-- The 100 Squares Grid Overlay -->
|
||||||
<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 id="grid-container" class="absolute inset-0 z-10 w-full h-full grid grid-cols-10 grid-rows-10 pointer-events-none">
|
||||||
<div class="font-mono text-xs text-slate-500 tracking-wide opacity-60">
|
{Array.from({ length: 100 }).map((_, i) => (
|
||||||
<span class="block text-slate-600 mb-1">LOCATION</span>
|
<div class="grid-cell w-full h-full border border-white/5 opacity-0 transition-all duration-500 ease-out" data-index={i}></div>
|
||||||
COLORADO SPRINGS, CO<br>
|
))}
|
||||||
<span id="clock" class="text-slate-400">00:00:00</span>
|
</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>
|
</div>
|
||||||
|
|
||||||
<!-- Scroll Indicator with animation -->
|
<!-- Main Heading & Description -->
|
||||||
<div id="scroll-indicator" class="font-mono text-xs text-slate-500 text-right tracking-wide transition-all duration-500">
|
<div class="max-w-5xl">
|
||||||
<span class="block text-slate-600 mb-1">EXPLORE</span>
|
<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="inline-flex flex-col items-center">
|
<span class="block intro-element opacity-0 translate-y-10 transition-all duration-1000 ease-out delay-100">VISUAL</span>
|
||||||
SCROLL
|
<span class="block text-brand-accent opacity-0 translate-y-10 transition-all duration-1000 ease-out delay-200 intro-element">ALCHEMIST</span>
|
||||||
<span class="scroll-arrow block mt-2 w-[1px] h-8 bg-gradient-to-b from-brand-accent to-transparent"></span>
|
</h1>
|
||||||
</span>
|
|
||||||
|
<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>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
/* Scroll arrow bounce animation */
|
.grid-cell.active {
|
||||||
.scroll-arrow {
|
background-color: var(--color-brand-accent);
|
||||||
animation: scrollBounce 2s ease-in-out infinite;
|
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 {
|
/* Initial Loaded State Classes */
|
||||||
0%, 100% {
|
.intro-visible {
|
||||||
transform: translateY(0);
|
opacity: 1 !important;
|
||||||
opacity: 1;
|
transform: translateY(0) !important;
|
||||||
}
|
|
||||||
50% {
|
|
||||||
transform: translateY(8px);
|
|
||||||
opacity: 0.6;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Fade out on scroll */
|
/* Portrait Loaded State */
|
||||||
#scroll-indicator.scrolled {
|
.portrait-visible {
|
||||||
opacity: 0;
|
opacity: 0.4 !important; /* Mobile default */
|
||||||
transform: translateY(10px);
|
}
|
||||||
pointer-events: none;
|
@media (min-width: 768px) {
|
||||||
|
.portrait-visible {
|
||||||
|
opacity: 0.6 !important; /* Desktop default */
|
||||||
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
// Clock
|
||||||
function updateClock() {
|
function updateClock() {
|
||||||
const clock = document.getElementById('clock');
|
const clock = document.getElementById('clock');
|
||||||
if (clock) {
|
if (clock) {
|
||||||
@ -83,27 +106,104 @@
|
|||||||
setInterval(updateClock, 1000);
|
setInterval(updateClock, 1000);
|
||||||
updateClock();
|
updateClock();
|
||||||
|
|
||||||
// Scroll-driven fade for scroll indicator
|
// Intro Animation Sequence
|
||||||
const scrollIndicator = document.getElementById('scroll-indicator');
|
window.addEventListener('load', () => {
|
||||||
|
// Trigger Intro Elements
|
||||||
|
const introElements = document.querySelectorAll('.intro-element');
|
||||||
|
introElements.forEach(el => {
|
||||||
|
el.classList.add('intro-visible');
|
||||||
|
});
|
||||||
|
|
||||||
function handleScroll() {
|
// Trigger Portrait
|
||||||
if (scrollIndicator) {
|
const portrait = document.getElementById('hero-portrait');
|
||||||
const scrollY = window.scrollY;
|
if (portrait) {
|
||||||
// Start fading at 50px, fully hidden at 200px
|
portrait.classList.add('portrait-visible');
|
||||||
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 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 });
|
// Random pulse for liveliness
|
||||||
handleScroll(); // Initial check
|
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>
|
</script>
|
||||||
|
|||||||
@ -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 -->
|
<section id="skills" class="bg-brand-dark py-32 lg:py-48 overflow-hidden relative cursor-default">
|
||||||
<div class="animate-on-scroll slide-up stagger-1">
|
<div class="container mx-auto px-6 lg:px-12 relative z-10">
|
||||||
<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>
|
<!-- Header Section -->
|
||||||
Compositing
|
<div class="mb-24 lg:mb-32 grid grid-cols-1 lg:grid-cols-12 gap-12">
|
||||||
</h3>
|
<div class="lg:col-span-8">
|
||||||
<div class="flex flex-wrap gap-2">
|
<h2 class="text-6xl md:text-8xl lg:text-9xl font-bold uppercase tracking-tighter leading-[0.85] text-white">
|
||||||
<span class="skill-tag">Nuke/NukeX</span>
|
<span class="block relative overflow-hidden">
|
||||||
<span class="skill-tag">ComfyUI</span>
|
<span class="animate-on-scroll slide-up block">Technical</span>
|
||||||
<span class="skill-tag">After Effects</span>
|
</span>
|
||||||
<span class="skill-tag">Photoshop</span>
|
<span class="block relative overflow-hidden">
|
||||||
<span class="skill-tag">Deep Compositing</span>
|
<span class="animate-on-scroll slide-up stagger-1 block text-stroke text-transparent">Arsenal</span>
|
||||||
<span class="skill-tag">Live Action VFX</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>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- 3D -->
|
<!-- Skills Data Grid -->
|
||||||
<div class="animate-on-scroll slide-up stagger-2">
|
<div class="w-full border-t border-white/10" id="skills-table">
|
||||||
<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>
|
|
||||||
|
|
||||||
<!-- AI/ML -->
|
<!-- Table Header -->
|
||||||
<div class="animate-on-scroll slide-up stagger-3">
|
<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">
|
||||||
<h3 class="text-base font-bold text-white uppercase mb-6 flex items-center gap-3 tracking-wide">
|
<div class="col-span-2 md:col-span-1">/// ID</div>
|
||||||
<i data-lucide="cpu" class="w-4 h-4 text-brand-accent"></i>
|
<div class="col-span-10 md:col-span-4">Domain</div>
|
||||||
AI/ML Integration
|
<div class="col-span-12 md:col-span-5 hidden md:block">Stack</div>
|
||||||
</h3>
|
<div class="col-span-6 md:col-span-2 hidden md:block text-right">Proficiency</div>
|
||||||
<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>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Dev -->
|
<!-- Row 1: Compositing -->
|
||||||
<div class="animate-on-scroll slide-up stagger-4">
|
<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">
|
||||||
<h3 class="text-base font-bold text-white uppercase mb-6 flex items-center gap-3 tracking-wide">
|
<div class="col-span-2 md:col-span-1 text-brand-accent font-mono text-sm relative overflow-hidden">
|
||||||
<i data-lucide="code" class="w-4 h-4 text-brand-accent"></i>
|
<span class="block group-hover:-translate-y-full transition-transform duration-500">01</span>
|
||||||
Development
|
<span class="absolute top-0 left-0 translate-y-full group-hover:translate-y-0 transition-transform duration-500">01</span>
|
||||||
</h3>
|
</div>
|
||||||
<div class="flex flex-wrap gap-2">
|
<div class="col-span-10 md:col-span-4 relative overflow-hidden">
|
||||||
<span class="skill-tag">Python</span>
|
<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>
|
||||||
<span class="skill-tag">JavaScript</span>
|
<!-- Reveal Swipe Effect -->
|
||||||
<span class="skill-tag">React</span>
|
<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>
|
||||||
<span class="skill-tag">Docker</span>
|
</div>
|
||||||
<span class="skill-tag">Linux</span>
|
<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">
|
||||||
<span class="skill-tag">Pipeline Dev</span>
|
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>
|
</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>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</section>
|
</section>
|
||||||
|
|||||||
@ -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.
|
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 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.
|
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.
|
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.*
|
*This project exemplifies the direction we're taking at Biohazard VFX: embracing new technology while never compromising on quality or artistic vision.*
|
||||||
|
|||||||
@ -9,9 +9,10 @@ import { SITE_TITLE, SITE_DESCRIPTION } from '../consts';
|
|||||||
interface Props {
|
interface Props {
|
||||||
title?: string;
|
title?: string;
|
||||||
description?: 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>
|
<!DOCTYPE html>
|
||||||
@ -24,7 +25,7 @@ const { title = SITE_TITLE, description = SITE_DESCRIPTION } = Astro.props;
|
|||||||
<GridOverlay />
|
<GridOverlay />
|
||||||
<Navigation />
|
<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 />
|
<slot />
|
||||||
</main>
|
</main>
|
||||||
|
|
||||||
|
|||||||
@ -1,112 +1,287 @@
|
|||||||
---
|
---
|
||||||
import BaseLayout from '../layouts/BaseLayout.astro';
|
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.">
|
<BaseLayout title={pageTitle} description="Get in touch for collaboration or inquiries." usePadding={false}>
|
||||||
<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>
|
|
||||||
|
|
||||||
<div class="grid grid-cols-1 lg:grid-cols-12 gap-12 lg:gap-20">
|
<!-- Background Grid (Optional, low opacity) -->
|
||||||
<!-- Contact Form -->
|
<div class="fixed inset-0 z-0 pointer-events-none">
|
||||||
<div class="lg:col-span-7 animate-on-scroll slide-up stagger-1">
|
<div class="w-full h-full grid grid-cols-12 gap-4 opacity-[0.03]">
|
||||||
<form class="space-y-8" action="#" method="POST">
|
{Array.from({ length: 12 }).map((_) => (
|
||||||
<div class="grid grid-cols-1 md:grid-cols-2 gap-6">
|
<div class="h-full border-r border-white"></div>
|
||||||
<div class="space-y-3">
|
))}
|
||||||
<label for="name" class="text-xs font-bold uppercase tracking-widest text-slate-500 block">Name</label>
|
</div>
|
||||||
<input
|
</div>
|
||||||
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>
|
|
||||||
|
|
||||||
<div class="space-y-3">
|
<section class="relative z-10 min-h-screen flex flex-col pt-32 lg:pt-48 pb-20 px-6 lg:px-12">
|
||||||
<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>
|
|
||||||
|
|
||||||
<div class="space-y-3">
|
<!-- Page Header -->
|
||||||
<label for="message" class="text-xs font-bold uppercase tracking-widest text-slate-500 block">Message</label>
|
<div class="grid grid-cols-1 lg:grid-cols-12 gap-12 mb-20 lg:mb-32 border-b border-white/10 pb-12">
|
||||||
<textarea
|
<div class="lg:col-span-8">
|
||||||
id="message"
|
<h1 class="text-6xl md:text-8xl lg:text-9xl font-bold uppercase tracking-tighter leading-[0.85] text-white mb-8">
|
||||||
name="message"
|
<span class="block animate-on-scroll slide-up">Project</span>
|
||||||
rows="6"
|
<span class="block text-brand-accent animate-on-scroll slide-up stagger-1">Inquiry</span>
|
||||||
placeholder="Tell me about your project..."
|
</h1>
|
||||||
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"
|
</div>
|
||||||
required
|
<div class="lg:col-span-4 flex flex-col justify-end">
|
||||||
></textarea>
|
<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">
|
||||||
</div>
|
Available for freelance commissions and studio collaborations.
|
||||||
|
Currently booking Q3 2026.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="pt-6">
|
<div class="grid grid-cols-1 lg:grid-cols-12 gap-12 lg:gap-24 flex-grow">
|
||||||
<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>
|
|
||||||
|
|
||||||
<!-- Sidebar Info -->
|
<!-- Left Column: Contact Form -->
|
||||||
<div class="lg:col-span-5 space-y-12 animate-on-scroll slide-left stagger-2">
|
<div class="lg:col-span-7 animate-on-scroll slide-up stagger-3">
|
||||||
<div>
|
<div class="mb-8 flex items-center gap-3">
|
||||||
<h3 class="text-xs font-bold uppercase tracking-widest text-slate-500 mb-6">Contact Info</h3>
|
<span class="w-2 h-2 bg-brand-accent rounded-full animate-pulse"></span>
|
||||||
<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">
|
<span class="font-mono text-xs text-brand-accent uppercase tracking-widest">Transmission Uplink</span>
|
||||||
nicholai@nicholai.work
|
</div>
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div>
|
<form class="space-y-12" action="#" method="POST">
|
||||||
<h3 class="text-xs font-bold uppercase tracking-widest text-slate-500 mb-6">Location</h3>
|
<div class="group relative">
|
||||||
<p class="text-base lg:text-lg text-slate-300 leading-relaxed font-light">
|
<input
|
||||||
Colorado Springs, CO<br/>
|
type="text"
|
||||||
Mountain Standard Time (MST)
|
id="name"
|
||||||
</p>
|
name="name"
|
||||||
</div>
|
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">
|
<div class="group relative">
|
||||||
<h3 class="text-xs font-bold uppercase tracking-widest text-slate-500 mb-6">Availability</h3>
|
<input
|
||||||
<div class="flex items-center gap-3 mb-4">
|
type="email"
|
||||||
<span class="relative flex h-2.5 w-2.5">
|
id="email"
|
||||||
<span class="animate-ping absolute inline-flex h-full w-full rounded-full bg-brand-accent opacity-75"></span>
|
name="email"
|
||||||
<span class="relative inline-flex rounded-full h-2.5 w-2.5 bg-brand-accent"></span>
|
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"
|
||||||
</span>
|
placeholder="Email"
|
||||||
<span class="text-sm font-bold text-brand-accent uppercase tracking-wide">Open to opportunities</span>
|
required
|
||||||
</div>
|
/>
|
||||||
<p class="text-slate-400 text-sm leading-relaxed font-light">
|
<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">
|
||||||
Currently accepting new projects for Q3 2026. Reach out to schedule a discovery call.
|
/// Return Address
|
||||||
</p>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
</div>
|
<!-- Custom Dropdown -->
|
||||||
</section>
|
<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>
|
</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>
|
||||||
|
|||||||
@ -6,7 +6,7 @@ import FeaturedProject from '../components/sections/FeaturedProject.astro';
|
|||||||
import Skills from '../components/sections/Skills.astro';
|
import Skills from '../components/sections/Skills.astro';
|
||||||
---
|
---
|
||||||
|
|
||||||
<BaseLayout>
|
<BaseLayout usePadding={false}>
|
||||||
<Hero />
|
<Hero />
|
||||||
|
|
||||||
<!-- Gradient Divider -->
|
<!-- Gradient Divider -->
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user