Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 28 additions & 0 deletions BRAND_GUIDELINES.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# Brand Guidelines

## Visual Language: "Modern Blueprint"
The website follows a "Modern Blueprint" aesthetic, characterized by:
- **Grid-based layouts**: Consistent use of 60px grids.
- **Sharp Corners**: All containers, input fields, and buttons MUST have square corners (`rounded-none`).
- **Precision Borders**: Use 2px borders (`border-2`) for primary elements.
- **High Contrast**: Dark backgrounds with vibrant accent colors (Brilliant Blue).

## Components

### Buttons
All buttons must follow these rules:
1. **Square Corners**: Always use `rounded-none`.
2. **Outlined by Default**: Buttons should have a 2px border and transparent background.
3. **Filled on Hover**: On hover, the button should fill with the accent color and text should change color for contrast.
4. **Typography**: Bold, often uppercase with wide tracking for a technical look.

### Input Fields
- **Corners**: Always `rounded-none`.
- **Borders**: 2px border (`border-2`).
- **Interaction**: Highlight border color on focus.

## Color Palette
Defined in `src/index.css`.
- **Primary**: Brilliant Blue (#0b5ef3) - `hsl(221 91% 50%)`
- **Background**: Off-white (#edeceb) - `hsl(30 14% 93%)`
- **Foreground**: Dark Navy (#161B24) - `hsl(217 57% 13%)`
4 changes: 1 addition & 3 deletions public/locales/en/common.json
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,7 @@
"line1": "Transform Your",
"line2": "Digital Presence",
"description": "I create innovative and cutting-edge digital products, developing personalized solutions, websites, and extraordinary applications that offer unique experiences and maximize success in the market.",
"ctaPrimary": "Start Your Project",
"ctaSecondary": "Learn More"
"ctaPrimary": "Start Your Project"
},
"services": {
"title": "What I can do ",
Expand Down Expand Up @@ -126,7 +125,6 @@
"line2": "Ordosgoitty",
"description": "Frontend Developer, Full Stack Engineer, and passionate about software engineering.",
"ctaPrimary": "Start Your Project",
"ctaSecondary": "Learn More",
"intro": "Hi, I'm Jesus Ordosgoitty. I design and build fast, accessible, and scalable digital products. This page is coming soon."
},
"experience": {
Expand Down
4 changes: 1 addition & 3 deletions public/locales/es/common.json
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,7 @@
"line1": "Transforma tu",
"line2": "presencia Digital",
"description": "Creo productos digitales innovadores y de vanguardia, desarrollando soluciones personalizadas, sitios web y aplicaciones extraordinarias que ofrecen experiencias únicas y maximizan el éxito en el mercado.",
"ctaPrimary": "Comenzar tu Proyecto",
"ctaSecondary": "Saber Más"
"ctaPrimary": "Comenzar tu Proyecto"
},
"services": {
"title": "Lo que puedo hacer ",
Expand Down Expand Up @@ -126,7 +125,6 @@
"line2": "Ordosgoitty",
"description": "Desarrollador Frontend, Ingeniero Full Stack y apasionado por la ingeniería de software.",
"ctaPrimary": "Comenzar tu Proyecto",
"ctaSecondary": "Saber Más",
"intro": "Hola, soy Jesús Ordosgoitty. Diseño y desarrollo productos digitales rápidos, accesibles y escalables. Esta página estará disponible pronto."
},
"experience": {
Expand Down
2 changes: 1 addition & 1 deletion src/components/AvailabilityBadge.astro
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ const labels = {
const currentLabels = lang === 'es' ? labels.es : labels.en;
---

<div class="flex items-center gap-3 px-4 py-2 bg-white border-2 border-border rounded-none w-fit animate-fade-in shadow-sm">
<div class="flex items-center gap-3 p-3 bg-white border-2 border-border rounded-none w-fit animate-fade-in shadow-sm">
<span class={`relative flex h-2.5 w-2.5`}>
{isAvailable && (
<span class="animate-ping absolute inline-flex h-full w-full rounded-full bg-green-400 opacity-75"></span>
Expand Down
43 changes: 33 additions & 10 deletions src/components/ContactActions.astro
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,13 @@ const config = {

const labels = {
en: {
whatsapp: "Chat on WhatsApp",
telegram: "Message on Telegram",
whatsapp: "WhatsApp",
telegram: "Telegram",
fastResponse: "Fast response (under 2h)"
},
es: {
whatsapp: "Hablar por WhatsApp",
telegram: "Mensaje por Telegram",
whatsapp: "WhatsApp",
telegram: "Telegram",
fastResponse: "Respuesta rápida (menos de 2h)"
}
};
Expand All @@ -28,10 +28,21 @@ const t = lang === 'es' ? labels.es : labels.en;
href={config.whatsapp}
target="_blank"
rel="noopener noreferrer"
class="flex-1 flex items-center justify-center gap-2 px-6 py-3 bg-[#25D366] hover:bg-[#20ba56] text-white rounded-xl font-bold transition-all shadow-elegant hover:scale-[1.02] active:scale-[0.98]"
class="flex-1 flex items-center justify-center gap-2 p-3 border-2 border-[#25D366] text-[#25D366] hover:bg-[#25D366] hover:text-white rounded-none font-bold transition-all shadow-elegant hover:scale-[1.02] active:scale-[0.98]"
>
<svg class="w-5 h-5" fill="currentColor" viewBox="0 0 24 24">
<path d="M17.472 14.382c-.297-.149-1.758-.867-2.03-.967-.273-.099-.471-.148-.67.15-.197.297-.767.966-.94 1.164-.173.199-.347.223-.644.075-.297-.15-1.255-.463-2.39-1.328-.883-.788-1.48-1.761-1.653-2.059-.173-.297-.018-.458.13-.606.134-.133.298-.347.446-.52.149-.174.198-.298.298-.497.099-.198.05-.371-.025-.52-.05-.149-.471-1.137-.645-1.545-.17-.407-.344-.352-.471-.352-.126 0-.272-.012-.418-.012-.146 0-.384.055-.585.273-.201.218-.767.75-.767 1.83 0 1.08.787 2.123.897 2.272.11.149 1.548 2.363 3.75 3.313.524.226.933.361 1.253.463.526.167 1.004.144 1.383.081.578-.088 1.758-.719 2.006-1.413.248-.694.248-1.289.173-1.413-.074-.124-.272-.198-.57-.347m-5.421 7.403h-.004a9.87 9.87 0 01-5.031-1.378l-.361-.214-3.741.982.998-3.648-.235-.374a9.86 9.87 0 01-1.51-5.26c.001-5.45 4.436-9.884 9.888-9.884 2.64 0 5.122 1.03 6.988 2.898a9.825 9.825 0 012.893 6.994c-.003 5.45-4.437 9.884-9.885 9.884m8.413-18.297A11.815 11.815 0 0012.05 0C5.414 0 .015 5.398.015 12.03c0 2.123.553 4.197 1.602 6.06L0 24l6.149-1.613a11.77 11.77 0 005.912 1.594h.005c6.625 0 12.025-5.401 12.025-12.03a11.85 11.82 0 01-3.481-8.257z"/>
<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="w-6 h-6"
>
<path d="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z" />
</svg>
{t.whatsapp}
</a>
Expand All @@ -40,10 +51,22 @@ const t = lang === 'es' ? labels.es : labels.en;
href={config.telegram}
target="_blank"
rel="noopener noreferrer"
class="flex-1 flex items-center justify-center gap-2 px-6 py-3 bg-[#0088cc] hover:bg-[#0077b5] text-white rounded-xl font-bold transition-all shadow-elegant hover:scale-[1.02] active:scale-[0.98]"
class="flex-1 flex items-center justify-center gap-2 p-3 border-2 border-[#0088cc] text-[#0088cc] hover:bg-[#0088cc] hover:text-white rounded-none font-bold transition-all shadow-elegant hover:scale-[1.02] active:scale-[0.98]"
>
<svg class="w-5 h-5" fill="currentColor" viewBox="0 0 24 24">
<path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm4.64 6.8c-.15 1.58-.8 5.42-1.13 7.56-.14.91-.46 1.21-.78 1.24-.71.06-1.25-.47-1.94-.92-1.08-.71-1.69-1.15-2.74-1.86-1.21-.82-.42-1.27.26-1.98.18-.18 3.27-2.99 3.33-3.24.01-.03.01-.15-.06-.21-.07-.06-.17-.04-.24-.02-.1.02-1.67 1.06-4.73 3.14-.45.31-.85.46-1.21.45-.39-.01-1.15-.22-1.71-.41-.69-.23-1.24-.35-1.19-.74.03-.2.37-.41 1.03-.63 4.02-1.75 6.7-2.9 8.04-3.46 3.83-1.58 4.63-1.85 5.15-1.86.11 0 .37.03.54.17.14.12.18.3.2.43 0 .05.01.1.01.12z"/>
<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="w-6 h-6"
>
<path d="m22 2-7 20-4-9-9-4Z" />
<path d="M22 2 11 13" />
</svg>
{t.telegram}
</a>
Expand Down
40 changes: 23 additions & 17 deletions src/components/ContactForm.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import React, { useState } from 'react';
import { Send } from 'lucide-react';

interface ContactFormProps {
lang?: string;
Expand Down Expand Up @@ -55,56 +56,61 @@ const ContactForm: React.FC<ContactFormProps> = ({ lang = 'en' }) => {
};

return (
<form onSubmit={handleSubmit} class="space-y-4 w-full">
<div class="grid grid-cols-1 md:grid-cols-2 gap-4">
<div class="space-y-2">
<label class="text-sm font-medium text-foreground/80 ml-1">{t.name}</label>
<form onSubmit={handleSubmit} className="space-y-4 w-full">
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
<div className="space-y-2">
<label className="text-sm font-medium text-foreground/80 ml-1">{t.name}</label>
<input
required
type="text"
name="name"
placeholder="John Doe"
class="w-full px-4 py-3 bg-white border-2 border-border rounded-none focus:ring-0 focus:border-primary outline-none transition-all placeholder:text-muted-foreground/50"
className="w-full px-4 py-3 bg-white border-2 border-border rounded-none focus:ring-0 focus:border-primary outline-none transition-all placeholder:text-muted-foreground/50"
/>
</div>
<div class="space-y-2">
<label class="text-sm font-medium text-foreground/80 ml-1">{t.email}</label>
<div className="space-y-2">
<label className="text-sm font-medium text-foreground/80 ml-1">{t.email}</label>
<input
required
type="email"
name="email"
placeholder="john@example.com"
class="w-full px-4 py-3 bg-white border-2 border-border rounded-none focus:ring-0 focus:border-primary outline-none transition-all placeholder:text-muted-foreground/50"
className="w-full px-4 py-3 bg-white border-2 border-border rounded-none focus:ring-0 focus:border-primary outline-none transition-all placeholder:text-muted-foreground/50"
/>
</div>
</div>

<div class="space-y-2">
<label class="text-sm font-medium text-foreground/80 ml-1">{t.message}</label>
<div className="space-y-2">
<label className="text-sm font-medium text-foreground/80 ml-1">{t.message}</label>
<textarea
required
name="message"
rows={4}
placeholder="..."
class="w-full px-4 py-3 bg-white border-2 border-border rounded-none focus:ring-0 focus:border-primary outline-none transition-all resize-none placeholder:text-muted-foreground/50"
className="w-full px-4 py-3 bg-white border-2 border-border rounded-none focus:ring-0 focus:border-primary outline-none transition-all resize-none placeholder:text-muted-foreground/50"
></textarea>
</div>

<button
disabled={status === 'sending'}
type="submit"
class={`w-full py-4 rounded-none font-bold transition-all shadow-glow ${
status === 'sending' ? 'bg-primary/50' : 'bg-primary hover:bg-primary/90'
} text-white uppercase tracking-widest`}
className={`w-full rounded-none font-bold transition-all shadow-glow border-2 border-primary ${
status === 'sending'
? 'bg-primary/50 border-primary/50 text-white'
: 'bg-transparent text-primary hover:bg-primary hover:text-white'
} uppercase tracking-widest`}
>
{status === 'sending' ? t.sending : t.submit}
<span className="flex items-center justify-center gap-2">
{status === 'sending' ? t.sending : t.submit}
{status !== 'sending' && <Send className="w-5 h-5" />}
</span>
</button>

{status === 'success' && (
<p class="text-green-500 text-sm font-medium text-center animate-fade-in">{t.success}</p>
<p className="text-green-500 text-sm font-medium text-center animate-fade-in">{t.success}</p>
)}
{status === 'error' && (
<p class="text-destructive text-sm font-medium text-center animate-fade-in">{t.error}</p>
<p className="text-destructive text-sm font-medium text-center animate-fade-in">{t.error}</p>
)}
</form>
);
Expand Down
8 changes: 4 additions & 4 deletions src/components/HeaderInteractive.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -105,10 +105,10 @@ const HeaderInteractive = ({ navItems, logoSrc, lang, altLangHref, isOpaque = fa
<a
href={altLangHref}
onClick={handleLangSwitch}
className={`text-sm px-3 py-1 rounded-full border transition-all duration-300 font-bold ${
className={`text-sm px-3 py-1 rounded-none border-2 transition-all duration-300 font-bold ${
isScrolled || isMenuOpen || isOpaque
? 'text-white border-white/20 hover:border-brand-bright hover:text-brand-bright'
: 'text-blue-50 border-blue-50/30 hover:border-white hover:text-white'
? 'text-white border-white/20 hover:border-brand-bright hover:bg-white hover:text-brand-dark'
: 'text-blue-50 border-blue-50/30 hover:border-white hover:bg-white hover:text-brand-dark'
}`}
aria-label={`Switch to ${altLang}`}
>
Expand Down Expand Up @@ -161,7 +161,7 @@ const HeaderInteractive = ({ navItems, logoSrc, lang, altLangHref, isOpaque = fa
aria-label={`Switch to ${altLang}`}
>
<span className="mr-2">Language:</span>
<span className="px-3 py-1 bg-brand-dark/50 rounded-full text-brand-bright">{altLang}</span>
<span className="px-3 py-1 border-2 border-brand-bright rounded-none text-brand-bright">{altLang}</span>
</a>
</div>
</nav>
Expand Down
19 changes: 4 additions & 15 deletions src/components/islands/HeroIsland.tsx
Original file line number Diff line number Diff line change
@@ -1,18 +1,17 @@
// src/components/islands/HeroIsland.tsx
// React Island — scroll button interactivity + animations
import { ChevronDown } from 'lucide-react';
import { Button } from '@/components/ui/button';
import ScrollButton from '@/components/ui/ScrollButton';
import ColorBends from '@/components/ColorBends';

interface Props {
line1: string;
line2: string;
description: string;
ctaPrimary: string;
ctaSecondary: string;
}

const HeroIsland = ({ line1, line2, description, ctaPrimary, ctaSecondary }: Props) => {
const HeroIsland = ({ line1, line2, description, ctaPrimary }: Props) => {
const scrollToSection = (sectionId: string) => {
const element = document.getElementById(sectionId);
if (element) {
Expand All @@ -32,7 +31,7 @@ const HeroIsland = ({ line1, line2, description, ctaPrimary, ctaSecondary }: Pro
className="flex flex-col justify-center text-white space-y-8 animate-fade-in h-full"
id="scroll"
>
<h1 className="text-5xl md:text-6xl lg:text-7xl font-bold leading-tight bg-gradient-to-r from-blue-50 to-blue-400 bg-clip-text text-transparent">
<h1 className="text-4xl md:text-5xl lg:text-6xl font-bold leading-tight bg-gradient-to-r from-blue-50 to-blue-400 bg-clip-text text-transparent">
{line1}
<span className="block">{line2}</span>
</h1>
Expand All @@ -51,22 +50,12 @@ const HeroIsland = ({ line1, line2, description, ctaPrimary, ctaSecondary }: Pro
{ctaPrimary}
<span className="group-hover:translate-x-1 transition-transform">→</span>
</Button>

<Button variant="outline-hero" size="xl" onClick={() => scrollToSection('services')}>
{ctaSecondary}
</Button>
</div>
</div>
</div>
</div>
</div>
<div className="absolute bottom-1 w-full flex justify-center z-[3] h-20">
<div className="animate-float z-10">
<Button variant="scroll" size="icon-lg" onClick={() => scrollToSection('services')} aria-label="Scroll down">
<ChevronDown className="w-6 h-6" />
</Button>
</div>
</div>
<ScrollButton targetId="services" />
</section>
);
};
Expand Down
39 changes: 39 additions & 0 deletions src/components/ui/ScrollButton.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import React from 'react';
import { ChevronDown } from 'lucide-react';
import { Button } from './button';

interface ScrollButtonProps {
targetId: string;
className?: string;
ariaLabel?: string;
}

const ScrollButton: React.FC<ScrollButtonProps> = ({
targetId,
className = "",
ariaLabel = "Scroll down"
}) => {
const scrollToSection = () => {
const element = document.getElementById(targetId);
if (element) {
element.scrollIntoView({ behavior: 'smooth' });
}
};

return (
<div className={`absolute bottom-4 w-full flex justify-center z-[10] h-20 ${className}`}>
<div className="animate-float">
<Button
variant="scroll"
size="icon-lg"
onClick={scrollToSection}
aria-label={ariaLabel}
>
<ChevronDown className="w-6 h-6" />
</Button>
</div>
</div>
);
};

export default ScrollButton;
22 changes: 11 additions & 11 deletions src/components/ui/button.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,25 +5,25 @@ import { cva, type VariantProps } from "class-variance-authority";
import { cn } from "@/lib/utils";

const buttonVariants = cva(
"inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0",
"inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-none text-sm font-medium ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0",
{
variants: {
variant: {
default: "bg-primary text-primary-foreground hover:bg-primary/90",
destructive: "bg-destructive text-destructive-foreground hover:bg-destructive/90",
outline: "border border-input bg-background hover:bg-accent hover:text-accent-foreground",
secondary: "bg-secondary text-secondary-foreground hover:bg-secondary/80",
default: "border-2 border-primary bg-transparent text-primary hover:bg-primary hover:text-primary-foreground",
destructive: "border-2 border-destructive bg-transparent text-destructive hover:bg-destructive hover:text-destructive-foreground",
outline: "border-2 border-input bg-transparent hover:bg-accent hover:text-accent-foreground",
secondary: "border-2 border-secondary bg-transparent text-secondary hover:bg-secondary hover:text-secondary-foreground",
ghost: "hover:bg-accent hover:text-accent-foreground",
link: "text-primary underline-offset-4 hover:underline",
hero: "bg-primary text-primary-foreground shadow-glow hover:shadow-elegant hover:scale-105 transition-all duration-300 font-semibold",
hero: "bg-primary text-primary-foreground shadow-glow hover:bg-primary/90 hover:shadow-elegant hover:scale-105 transition-all duration-300 font-semibold border-2 border-primary",
"outline-hero": "border-2 border-white text-white bg-transparent hover:bg-white hover:text-accent transition-all duration-300 font-semibold",
scroll: "bg-white/10 text-white border border-white/20 hover:bg-white/20 rounded-full p-3 hover:scale-110 transition-all duration-300",
scroll: "bg-transparent text-white hover:bg-transparent focus:bg-transparent p-3 hover:scale-110 transition-all duration-300",
},
size: {
default: "h-10 px-4 py-2",
sm: "h-9 rounded-md px-3",
lg: "h-11 rounded-md px-8",
xl: "h-12 rounded-md px-10 text-base",
default: "p-3",
sm: "p-2",
lg: "p-4",
xl: "p-5 text-lg",
icon: "h-10 w-10",
"icon-lg": "h-12 w-12",
},
Expand Down
Loading
Loading