diff --git a/.agents/skills/nanobanana-skill/SKILL.md b/.agents/skills/nanobanana-skill/SKILL.md new file mode 100644 index 0000000..ba6abe9 --- /dev/null +++ b/.agents/skills/nanobanana-skill/SKILL.md @@ -0,0 +1,141 @@ +--- +name: nanobanana-skill +description: 'Generate or edit images using Google Gemini API via nanobanana. Triggers: "nanobanana", "generate image", "create image", "edit image", "AI drawing", "图片生成", "AI绘图", "图片编辑", "生成图片".' +allowed-tools: Read, Write, Glob, Grep, Task, Bash(cat:*), Bash(ls:*), Bash(tree:*), Bash(python3:*) +--- + +# Nanobanana Image Generation Skill + +Generate or edit images using Google Gemini API through the nanobanana tool. + +## Requirements + +1. **GEMINI_API_KEY**: Must be configured in `~/.nanobanana.env` or `export GEMINI_API_KEY=` +2. **Python3 with dependent packages installed**: google-genai, Pillow, python-dotenv. They could be installed via `python3 -m pip install -r ./requirements.txt` if not installed yet. +3. **Executable**: `./nanobanana.py` + +## Instructions + +### For image generation + +1. Ask the user for: + - What they want to create (the prompt) + - Desired aspect ratio/size (optional, defaults to 9:16 portrait) + - Output filename (optional, auto-generates UUID if not specified) + - Model preference (optional, defaults to gemini-3.1-flash-image-preview) + - Resolution (optional, defaults to 1K) + +2. Run the nanobanana script with appropriate parameters: + + ```bash + python3 ./nanobanana.py --prompt "description of image" --output "filename.png" + ``` + +3. Show the user the saved image path when complete + +### For image editing + +1. Ask the user for: + - Input image file(s) to edit + - What changes they want (the prompt) + - Output filename (optional) + +2. Run with input images: + + ```bash + python3 ./nanobanana.py --prompt "editing instructions" --input image1.png image2.png --output "edited.png" + ``` + +## Available Options + +### Aspect Ratios (--size) + +- `1024x1024` (1:1) - Square +- `832x1248` (2:3) - Portrait +- `1248x832` (3:2) - Landscape +- `864x1184` (3:4) - Portrait +- `1184x864` (4:3) - Landscape +- `896x1152` (4:5) - Portrait +- `1152x896` (5:4) - Landscape +- `768x1344` (9:16) - Portrait (default) +- `1344x768` (16:9) - Landscape +- `1536x672` (21:9) - Ultra-wide + +### Models (--model) + +- `gemini-3.1-flash-image-preview` (default) - Latest, fast generation +- `gemini-3-pro-image-preview` - Higher quality, supports thinking/reasoning + +### Resolution (--resolution) + +- `1K` (default) +- `2K` +- `4K` + +### Other Options + +- `--no-search` - Disable Google Search grounding (enabled by default) +- `--no-think` - Disable thinking/reasoning mode + +## Examples + +### Generate a simple image + +```bash +python3 ./nanobanana.py --prompt "A serene mountain landscape at sunset with a lake" +``` + +### Generate with specific size and output + +```bash +python3 ./nanobanana.py \ + --prompt "Modern minimalist logo for a tech startup" \ + --size 1024x1024 \ + --output "logo.png" +``` + +### Generate landscape image with high resolution + +```bash +python3 ./nanobanana.py \ + --prompt "Futuristic cityscape with flying cars" \ + --size 1344x768 \ + --resolution 2K \ + --output "cityscape.png" +``` + +### Edit existing images + +```bash +python3 ./nanobanana.py \ + --prompt "Add a rainbow in the sky" \ + --input photo.png \ + --output "photo-with-rainbow.png" +``` + +### Use pro model for higher quality + +```bash +python3 ./nanobanana.py \ + --prompt "Detailed portrait of a cat in watercolor style" \ + --model gemini-3-pro-image-preview \ + --output "cat-portrait.png" +``` + +## Error Handling + +If the script fails: + +- Check that `GEMINI_API_KEY` is exported or set in ~/.nanobanana.env +- Verify input image files exist and are readable +- Ensure the output directory is writable +- If no image is generated, try making the prompt more specific about wanting an image + +## Best Practices + +1. Be descriptive in prompts - include style, mood, colors, composition +2. For logos/graphics, use square aspect ratio (1024x1024) +3. For social media posts, use 9:16 for stories or 1:1 for posts +4. For wallpapers, use 16:9 or 21:9 +5. Start with 1K resolution for testing, upgrade to 2K/4K for final output +6. Use gemini-3-pro-image-preview for best quality, gemini-3.1-flash-image-preview (default) for speed diff --git a/.agents/skills/nanobanana-skill/nanobanana.py b/.agents/skills/nanobanana-skill/nanobanana.py new file mode 100755 index 0000000..33e1e13 --- /dev/null +++ b/.agents/skills/nanobanana-skill/nanobanana.py @@ -0,0 +1,167 @@ +#!/usr/bin/env python3 +# Generate or edit images using Google Gemini API +import os +import argparse +import uuid +from dotenv import load_dotenv +from google import genai +from google.genai import types +from PIL import Image +from io import BytesIO + +# Load environment variables +load_dotenv(os.path.expanduser("~") + "/.nanobanana.env") + +# Google API configuration from environment variables +api_key = os.getenv("GEMINI_API_KEY") or "" + +if not api_key: + raise ValueError( + "Missing GEMINI_API_KEY environment variable. Please check your .env file." + ) + +# Initialize Gemini client +client = genai.Client(api_key=api_key) + +# Aspect ratio to resolution mapping +ASPECT_RATIO_MAP = { + "1024x1024": "1:1", # 1:1 + "832x1248": "2:3", # 2:3 + "1248x832": "3:2", # 3:2 + "864x1184": "3:4", # 3:4 + "1184x864": "4:3", # 4:3 + "896x1152": "4:5", # 4:5 + "1152x896": "5:4", # 5:4 + "768x1344": "9:16", # 9:16 + "1344x768": "16:9", # 16:9 + "1536x672": "21:9", # 21:9 +} + + +def main(): + # Parse command-line arguments + parser = argparse.ArgumentParser( + description="Generate or edit images using Google Gemini API" + ) + parser.add_argument( + "--prompt", + type=str, + required=True, + help="Prompt for image generation or editing", + ) + parser.add_argument( + "--output", + type=str, + default=f"nanobanana-{uuid.uuid4()}.png", + help="Output image filename (default: nanobanana-.png)", + ) + parser.add_argument( + "--input", type=str, nargs="*", help="Input image files for editing (optional)" + ) + parser.add_argument( + "--size", + type=str, + default="768x1344", + choices=list(ASPECT_RATIO_MAP.keys()), + help="Size/aspect ratio of the generated image (default: 768x1344 / 9:16)", + ) + parser.add_argument( + "--model", + type=str, + default="gemini-3.1-flash-image-preview", + help="Model to use for image generation (default: gemini-3.1-flash-image-preview)", + ) + parser.add_argument( + "--resolution", + type=str, + default="1K", + choices=["1K", "2K", "4K"], + help="Resolution of the generated image (default: 1K)", + ) + parser.add_argument( + "--no-search", + action="store_true", + default=False, + help="Disable Google Search grounding (enabled by default)", + ) + parser.add_argument( + "--no-think", + action="store_true", + default=False, + help="Disable thinking/reasoning (useful for models that don't support it)", + ) + + args = parser.parse_args() + + # Get aspect ratio from size + aspect_ratio = ASPECT_RATIO_MAP.get(args.size, "16:9") + + # Build contents list for the API call + contents = [] + + # Check if input images are provided + if args.input and len(args.input) > 0: + # Use images.generate_content() with images for editing + print(f"Editing images with prompt: {args.prompt}") + print(f"Input images: {args.input}") + print(f"Aspect ratio: {aspect_ratio} ({args.size})") + + # Add prompt first + contents.append(args.prompt) + + # Add all input images + for img_path in args.input: + image = Image.open(img_path) + contents.append(image) + else: + print(f"Generating image (size: {args.size}) with prompt: {args.prompt}") + contents.append(args.prompt) + + # Build generation config + config_kwargs = { + "response_modalities": ["TEXT", "IMAGE"], + "image_config": types.ImageConfig( + aspect_ratio=aspect_ratio, + image_size=args.resolution, + ), + } + if not getattr(args, "no_search", False): + config_kwargs["tools"] = [types.Tool(google_search=types.GoogleSearch())] + if not getattr(args, "no_think", False): + config_kwargs["thinking_config"] = types.ThinkingConfig(include_thoughts=True) + + # Generate or edit image + response = client.models.generate_content( + model=args.model, + contents=contents, + config=types.GenerateContentConfig(**config_kwargs), + ) + + if ( + response.candidates is None + or len(response.candidates) == 0 + or response.candidates[0].content is None + or response.candidates[0].content.parts is None + ): + raise ValueError("No data received from the API.") + + # Extract image from response + image_saved = False + for part in response.candidates[0].content.parts: + if part.text is not None: + print(f"{part.text}", end="") + elif part.inline_data is not None and part.inline_data.data is not None: + image = Image.open(BytesIO(part.inline_data.data)) + + image.save(args.output) + image_saved = True + print(f"\n\nImage saved to: {args.output}") + + if not image_saved: + print( + "\n\nWarning: No image data found in the API response. This usually means the model returned only text. Please try again with a different prompt to make image generation more clear." + ) + + +if __name__ == "__main__": + main() diff --git a/.agents/skills/nanobanana-skill/requirements.txt b/.agents/skills/nanobanana-skill/requirements.txt new file mode 100644 index 0000000..94675c9 --- /dev/null +++ b/.agents/skills/nanobanana-skill/requirements.txt @@ -0,0 +1,4 @@ +python-dotenv +httpx[socks] +google-genai +Pillow diff --git a/.gitignore b/.gitignore index d677d43..9287bd4 100644 --- a/.gitignore +++ b/.gitignore @@ -3,4 +3,12 @@ node_modules .worktrees/ dist/ .opencode/ + +# Stitch reference files (solo para desarrollo local) +docs/stitch_mnq_premium_landing_page/ docs/stitch_mnq_premium_landing_page.zip +docs/stitch_mnq_premium_landing_pag3e.zip +docs/plans/ + +# Nanobanana generated images temp +public/images/generated/test.jpg diff --git a/docs/3.png b/docs/3.png new file mode 100644 index 0000000..99ee077 Binary files /dev/null and b/docs/3.png differ diff --git a/docs/ChatGPT Image 8 may 2026, 00_33_39.png b/docs/ChatGPT Image 8 may 2026, 00_33_39.png new file mode 100644 index 0000000..4c8bd4e Binary files /dev/null and b/docs/ChatGPT Image 8 may 2026, 00_33_39.png differ diff --git a/docs/ChatGPT Image 8 may 2026, 00_35_58.png b/docs/ChatGPT Image 8 may 2026, 00_35_58.png new file mode 100644 index 0000000..cba5f07 Binary files /dev/null and b/docs/ChatGPT Image 8 may 2026, 00_35_58.png differ diff --git a/docs/ChatGPT Image 8 may 2026, 00_37_39.png b/docs/ChatGPT Image 8 may 2026, 00_37_39.png new file mode 100644 index 0000000..c34e06f Binary files /dev/null and b/docs/ChatGPT Image 8 may 2026, 00_37_39.png differ diff --git a/docs/ChatGPT Image 8 may 2026, 00_42_51.png b/docs/ChatGPT Image 8 may 2026, 00_42_51.png new file mode 100644 index 0000000..d3c7b17 Binary files /dev/null and b/docs/ChatGPT Image 8 may 2026, 00_42_51.png differ diff --git a/docs/scr2een.png b/docs/scr2een.png new file mode 100644 index 0000000..209fe33 Binary files /dev/null and b/docs/scr2een.png differ diff --git a/docs/screen.png b/docs/screen.png new file mode 100644 index 0000000..6276423 Binary files /dev/null and b/docs/screen.png differ diff --git a/docs/screen2.png b/docs/screen2.png new file mode 100644 index 0000000..514405e Binary files /dev/null and b/docs/screen2.png differ diff --git a/public/images/bodas-hero.png b/public/images/bodas-hero.png new file mode 100644 index 0000000..daf2ef6 Binary files /dev/null and b/public/images/bodas-hero.png differ diff --git a/public/images/catering-premium.png b/public/images/catering-premium.png new file mode 100644 index 0000000..ee75204 Binary files /dev/null and b/public/images/catering-premium.png differ diff --git a/public/images/foto-bodas.png b/public/images/foto-bodas.png new file mode 100644 index 0000000..209fe33 Binary files /dev/null and b/public/images/foto-bodas.png differ diff --git a/public/images/foto-canapes.png b/public/images/foto-canapes.png new file mode 100644 index 0000000..514405e Binary files /dev/null and b/public/images/foto-canapes.png differ diff --git a/public/images/foto-corporativo.png b/public/images/foto-corporativo.png new file mode 100644 index 0000000..6276423 Binary files /dev/null and b/public/images/foto-corporativo.png differ diff --git a/public/images/foto-plato-mnq.png b/public/images/foto-plato-mnq.png new file mode 100644 index 0000000..99ee077 Binary files /dev/null and b/public/images/foto-plato-mnq.png differ diff --git a/public/images/generated/gallery-1.jpg b/public/images/generated/gallery-1.jpg new file mode 100644 index 0000000..cc27bbd Binary files /dev/null and b/public/images/generated/gallery-1.jpg differ diff --git a/public/images/generated/gallery-2.jpg b/public/images/generated/gallery-2.jpg new file mode 100644 index 0000000..4f7dbe3 Binary files /dev/null and b/public/images/generated/gallery-2.jpg differ diff --git a/public/images/generated/gallery-3.jpg b/public/images/generated/gallery-3.jpg new file mode 100644 index 0000000..9298c8c Binary files /dev/null and b/public/images/generated/gallery-3.jpg differ diff --git a/public/images/generated/gallery-4.jpg b/public/images/generated/gallery-4.jpg new file mode 100644 index 0000000..4f1592f Binary files /dev/null and b/public/images/generated/gallery-4.jpg differ diff --git a/public/images/generated/hero-bodas-gen.jpg b/public/images/generated/hero-bodas-gen.jpg new file mode 100644 index 0000000..bbfb68e Binary files /dev/null and b/public/images/generated/hero-bodas-gen.jpg differ diff --git a/public/images/generated/hero-familiares-gen.jpg b/public/images/generated/hero-familiares-gen.jpg new file mode 100644 index 0000000..8b075df Binary files /dev/null and b/public/images/generated/hero-familiares-gen.jpg differ diff --git a/public/images/generated/hero-home.jpg b/public/images/generated/hero-home.jpg new file mode 100644 index 0000000..ce4ccbc Binary files /dev/null and b/public/images/generated/hero-home.jpg differ diff --git a/public/images/generated/hero-nosotros-gen.jpg b/public/images/generated/hero-nosotros-gen.jpg new file mode 100644 index 0000000..c8c9f6d Binary files /dev/null and b/public/images/generated/hero-nosotros-gen.jpg differ diff --git a/public/images/hero-bodas.png b/public/images/hero-bodas.png new file mode 100644 index 0000000..bfb30c2 Binary files /dev/null and b/public/images/hero-bodas.png differ diff --git a/public/images/hero-contacto.png b/public/images/hero-contacto.png new file mode 100644 index 0000000..f20f930 Binary files /dev/null and b/public/images/hero-contacto.png differ diff --git a/public/images/hero-corporativo.png b/public/images/hero-corporativo.png new file mode 100644 index 0000000..f0fbaf3 Binary files /dev/null and b/public/images/hero-corporativo.png differ diff --git a/public/images/hero-familiares.png b/public/images/hero-familiares.png new file mode 100644 index 0000000..21d9d8f Binary files /dev/null and b/public/images/hero-familiares.png differ diff --git a/public/images/hero-home.png b/public/images/hero-home.png new file mode 100644 index 0000000..15fbc77 Binary files /dev/null and b/public/images/hero-home.png differ diff --git a/public/images/hero-nosotros.png b/public/images/hero-nosotros.png new file mode 100644 index 0000000..1b406b8 Binary files /dev/null and b/public/images/hero-nosotros.png differ diff --git a/public/images/logo-banner.png b/public/images/logo-banner.png new file mode 100644 index 0000000..7e90aae Binary files /dev/null and b/public/images/logo-banner.png differ diff --git a/public/images/logo-horizontal.png b/public/images/logo-horizontal.png new file mode 100644 index 0000000..d3c7b17 Binary files /dev/null and b/public/images/logo-horizontal.png differ diff --git a/public/images/logo-main.png b/public/images/logo-main.png new file mode 100644 index 0000000..4cf8025 Binary files /dev/null and b/public/images/logo-main.png differ diff --git a/public/images/logo-mnq.jpeg b/public/images/logo-mnq.jpeg new file mode 100644 index 0000000..7783d1f Binary files /dev/null and b/public/images/logo-mnq.jpeg differ diff --git a/public/images/logo-monograma.png b/public/images/logo-monograma.png new file mode 100644 index 0000000..c34e06f Binary files /dev/null and b/public/images/logo-monograma.png differ diff --git a/public/images/logo-nav-dark.png b/public/images/logo-nav-dark.png new file mode 100644 index 0000000..881e436 Binary files /dev/null and b/public/images/logo-nav-dark.png differ diff --git a/public/images/logo-ojo-transparent.png b/public/images/logo-ojo-transparent.png new file mode 100644 index 0000000..8b58325 Binary files /dev/null and b/public/images/logo-ojo-transparent.png differ diff --git a/public/images/logo-ojo.png b/public/images/logo-ojo.png new file mode 100644 index 0000000..cba5f07 Binary files /dev/null and b/public/images/logo-ojo.png differ diff --git a/public/images/logo-secondary.png b/public/images/logo-secondary.png new file mode 100644 index 0000000..ab37fa1 Binary files /dev/null and b/public/images/logo-secondary.png differ diff --git a/skills-lock.json b/skills-lock.json new file mode 100644 index 0000000..8bd4c2b --- /dev/null +++ b/skills-lock.json @@ -0,0 +1,11 @@ +{ + "version": 1, + "skills": { + "nanobanana-skill": { + "source": "feiskyer/claude-code-settings", + "sourceType": "github", + "skillPath": "skills/nanobanana-skill/SKILL.md", + "computedHash": "ace04861b1410614a3922b61186907cb59336398714b15bfc8964d9dea2f9daa" + } + } +} diff --git a/src/components/SiteFooter.astro b/src/components/SiteFooter.astro index a9388b3..729ab22 100644 --- a/src/components/SiteFooter.astro +++ b/src/components/SiteFooter.astro @@ -1,12 +1,45 @@
-
diff --git a/src/components/SiteHeader.astro b/src/components/SiteHeader.astro index 066541e..f865193 100644 --- a/src/components/SiteHeader.astro +++ b/src/components/SiteHeader.astro @@ -1,14 +1,64 @@ +--- +interface Props { + activeNav?: string; +} +const { activeNav } = Astro.props; + +const links = [ + { href: '/bodas-reales', label: 'Bodas', key: 'bodas' }, + { href: '/corporativo-business', label: 'Corporativo', key: 'corporativo' }, + { href: '/reuniones-familiares', label: 'Social', key: 'social' }, + { href: '/nosotros', label: 'Nosotros', key: 'nosotros' }, + { href: '/contacto', label: 'Contacto', key: 'contacto' }, +]; +--- + + + diff --git a/src/components/WhatsAppButton.astro b/src/components/WhatsAppButton.astro index ab43d0d..994c2fb 100644 --- a/src/components/WhatsAppButton.astro +++ b/src/components/WhatsAppButton.astro @@ -1,9 +1,12 @@ - WhatsApp + Consultar via WhatsApp + diff --git a/src/layouts/MainLayout.astro b/src/layouts/MainLayout.astro index 3564dda..8902d6d 100644 --- a/src/layouts/MainLayout.astro +++ b/src/layouts/MainLayout.astro @@ -11,9 +11,14 @@ import '../styles/utilities.css'; interface Props { title: string; description?: string; + activeNav?: string; } -const { title, description = 'MNQ Catering y Evento · Experiencias premium para momentos inolvidables.' } = Astro.props; +const { + title, + description = 'MNQ Catering y Evento · Experiencias gastronómicas premium para bodas, eventos corporativos y celebraciones familiares.', + activeNav, +} = Astro.props; --- @@ -23,10 +28,21 @@ const { title, description = 'MNQ Catering y Evento · Experiencias premium para {title} + + + + + - -
+ +
diff --git a/src/pages/bodas-reales.astro b/src/pages/bodas-reales.astro index 31fead0..b0cb36d 100644 --- a/src/pages/bodas-reales.astro +++ b/src/pages/bodas-reales.astro @@ -2,11 +2,212 @@ import MainLayout from '../layouts/MainLayout.astro'; --- - -
-

Servicio · Bodas Reales

-

Bodas con identidad propia y ejecución impecable.

-

Diseñamos menú, ambientación gastronómica y experiencia de servicio para que cada boda se sienta única, elegante y personal.

- Cotizar boda por WhatsApp + + + +
+ Bodas Reales — MNQ Catering +
+
+
+ Portafolio Exclusivo +

Bodas Reales

+
+
+ + +
+
+
+
+

+ Donde cada detalle cuenta una historia de amor. +

+

+ En MNQ Catering, entendemos que una boda no es solo un evento, sino el reflejo de una promesa. Nuestra narrativa visual se construye a través de texturas, aromas y sabores que trascienden lo ordinario para crear memorias eternas. +

+
+
+
+

Excelencia Culinaria

+

Sinfonía de sabores diseñada para el paladar más exigente.

+
+
+
+
+
+ + +
+
+
+ + +
+ Salón de bodas dorado — MNQ +
+
+

Sofía & Mateo

+

Gran Salón Imperial · 2024

+
+
+ + +
+ Mesa de boda con flores +
+
Detalles Florales
+
+ +
+ Postre de autor +
+
Pastelería de Autor
+
+ +
+
+
+ + +
+
+
+

El Arte de la Mesa

+

+ Mantelería de lino fino, cristalería de bohemia y una curaduría floral que respira vida en cada rincón. +

+
+ +
+
+
+ Texturas nobles +
+

Texturas Nobles

+

Linos y sedas seleccionados por su caída y tacto excepcional.

+
+ +
+
+ Canapés premium +
+

Cristal & Oro

+

Detalles metálicos que aportan un brillo atemporal a su celebración.

+
+ +
+
+ Platos de autor +
+

Platos de Autor

+

Cada ingrediente es una nota en nuestra composición gastronómica.

+
+
+
+
+ + +
+
+
+
+ Testimonios +

Palabras que nos inspiran.

+
+
+
+
"
+

"Superaron cualquier expectativa. No solo fue la comida, que fue espectacular, sino la tranquilidad que nos dieron durante todo el proceso. Fue un sueño hecho realidad."

+
+
+
+

Elena & Carlos

+

Finca La Montaña, Junio 2023

+
+
+
+
+
"
+

"Nuestros invitados todavía hablan del cóctel. La elegancia de cada bocado y la atención del personal fue impecable. MNQ es, sin duda, la mejor elección para una boda premium."

+
+
+
+

Patricia & Javier

+

Castillo de Viñuelas, Septiembre 2023

+
+
+
+
+
+
+
+ + +
+
+
+
+
+
+

¿Comenzamos a planear su gran día?

+

Solicite una asesoría personalizada y reciba un presupuesto a medida para su boda exclusiva.

+ + chat + Consultar por WhatsApp + +
+
+
+
+
+ + diff --git a/src/pages/contacto.astro b/src/pages/contacto.astro index 96b344b..5f78f2e 100644 --- a/src/pages/contacto.astro +++ b/src/pages/contacto.astro @@ -2,27 +2,185 @@ import MainLayout from '../layouts/MainLayout.astro'; --- - -
-

Contacto

-

Coordinemos tu evento por WhatsApp.

-

Canal principal de atención para asesorarte rápido y enviarte una propuesta personalizada.

- Iniciar conversación por WhatsApp + -
- - - - -
+ +
+
+
+ +
+ Contacto +

+ Hablemos de su próximo evento. +

+

+ Diseñamos experiencias gastronómicas a medida. Permítanos conocer sus necesidades para crear una propuesta única y exclusiva. +

+
+ +
+ MNQ Catering — salón de eventos premium +
+ +
+
+ + +
+
+
+ + + + + +
+
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ +
+ +
+
+ +
+
+
+
+ + diff --git a/src/pages/corporativo-business.astro b/src/pages/corporativo-business.astro index 9e0fb55..590eb7f 100644 --- a/src/pages/corporativo-business.astro +++ b/src/pages/corporativo-business.astro @@ -2,11 +2,159 @@ import MainLayout from '../layouts/MainLayout.astro'; --- - -
-

Servicio · Corporativo & Business

-

Eventos empresariales con timing, imagen y calidad premium.

-

Ofrecemos propuestas ejecutivas para lanzamientos, directorios y jornadas corporativas con foco en puntualidad y presentación profesional.

- Solicitar propuesta por WhatsApp + + + +
+
+
+ +
+

Excelencia en Eventos

+

Corporativo
& Business

+

+ Elevamos la imagen de su empresa a través de experiencias gastronómicas impecables. Desde lanzamientos de marca disruptivos hasta galas institucionales de alto nivel. +

+ +
+ +
+ Eventos corporativos premium — MNQ +
+ +
+
+
+ + +
+
+
+

Servicios Especializados

+
+
+ +
+ +
+ Lanzamientos de marca +
+
+

Lanzamientos de Marca

+

Impacto visual y conceptual para presentaciones que trascienden.

+
+
+ +
+ Coffee Breaks Premium +
+
+

Coffee Breaks Premium

+

Pausas que inspiran productividad y networking de calidad.

+
+
+ +
+ Galas y Cenas Anuales +
+
+

Galas & Cenas Anuales

+

Protocolo impecable para los momentos más solemnes de su organización.

+
+
+ +
+
+ + +
+
+

Empresas que confían en nuestra visión

+
+ LUMINA + Vanguard + Ethereal. + Nordic Corp + Apex Sol. +
+
+
+ + +
+
+
+
+

Cotización Corporativa

+

Diseñamos una propuesta a la medida de sus objetivos empresariales.

+
+
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ +
+
+
+
+
+
+
+ + diff --git a/src/pages/index.astro b/src/pages/index.astro index acdd063..db297fe 100644 --- a/src/pages/index.astro +++ b/src/pages/index.astro @@ -2,11 +2,222 @@ import MainLayout from '../layouts/MainLayout.astro'; --- - -
-

Catering premium para eventos memorables

-

Diseñamos experiencias gastronómicas a la altura de tu celebración.

-

Con enfoque editorial, servicio impecable y ejecución personalizada para cada ocasión.

- Cotizar por WhatsApp + + + +
+ MNQ Catering — salón de bodas premium +
+
+
+

+ Catering premium para eventos memorables +

+

+ MNQ: donde la tradición
se encuentra con la exclusividad +

+ + Explorar Servicios + +
+
+ + +
+
+
+ Nuestra Propuesta +

Experiencias Gastronómicas a Medida

+
+ +
+ + +
+
+ Bodas Reales — MNQ Catering +
+
+

Bodas

+

El arte de celebrar el amor con un banquete inolvidable diseñado hasta el último detalle.

+ Saber más +
+
+ + +
+
+ Corporativo — MNQ Catering +
+
+

Eventos Corporativos

+

Reforzamos la identidad de su empresa a través de una propuesta culinaria de primer nivel.

+ Saber más +
+
+ + +
+
+ Reuniones Familiares — MNQ Catering +
+
+

Reuniones Familiares

+

La calidez del hogar elevada por la excelencia de nuestra cocina de autor.

+ Saber más +
+
+ +
+
+
+ + +
+
+
+
+ Galería +

Momentos MNQ

+
+ +
+ +
+ Postre de autor con oro + Canapés premium + Vieiras con azafrán + Mesa de boda + Plato MNQ Catering + Bartender de coctelería +
+
+
+ + +
+
+
+
+ ★★★ + ★★ +
+

+ Lo que nuestros clientes dicen sobre nosotros +

+
+ +
+
+

+ "MNQ transformó nuestra boda en un sueño gastronómico. La atención al detalle y la calidad de los ingredientes superaron cualquier expectativa." +

+
+
+
+

Isabel & Marcos

+

Boda en Hacienda del Sol

+
+
+
+
+

+ "Para nuestro evento corporativo anual necesitábamos algo que reflejara nuestra marca. MNQ fue la elección perfecta: sobriedad y sabor excepcional." +

+
+
+
+

Javier Ruiz

+

Director Ejecutivo, TechCorp

+
+
+
+
+
+
+ + +
+
+
+
+
+
+ MNQ +
+
+

+ ¿Comenzamos a planear su próximo evento? +

+

+ Solicite una asesoría personalizada y reciba una propuesta a medida. +

+ + chat + Consultar por WhatsApp + +
+
+
+
+
+ + diff --git a/src/pages/nosotros.astro b/src/pages/nosotros.astro index f11ad89..6228497 100644 --- a/src/pages/nosotros.astro +++ b/src/pages/nosotros.astro @@ -2,11 +2,149 @@ import MainLayout from '../layouts/MainLayout.astro'; --- - -
-

Nosotros

-

Hospitalidad, estética y excelencia operativa.

-

MNQ nace para elevar celebraciones con una propuesta premium que combina gastronomía, diseño y coordinación integral del evento.

- Hablar por WhatsApp + + + +
+
+
+ +
+ Nuestra Esencia +

El arte de la hospitalidad elevada.

+

+ Desde nuestra fundación, MNQ Catering ha redefinido el concepto de exclusividad culinaria. No solo servimos comida; curamos momentos que perduran en la memoria de los paladares más exigentes. +

+
+ +
+
+ Chef ejecutiva MNQ — el arte de la hospitalidad +
+ +
+ +
+
+ + +
+
+
+

Filosofía de Exclusividad

+
+

Creemos que cada evento tiene su propia alma. Nuestra filosofía se basa en la escucha activa y la personalización radical. En un mundo de producciones en serie, MNQ apuesta por lo artesanal, lo local y lo extraordinario.

+

Cada ingrediente es seleccionado por su trazabilidad y calidad superior, trabajando codo a codo con productores que comparten nuestra pasión por la excelencia.

+ +
+
+
+
+ + +
+
+
+ Pilares de Marca +

Valores que nos definen

+
+
+
+ verified +

Calidad

+

Innegociable. Desde la frescura del producto hasta el último detalle del servicio de sala.

+
+
+ history_edu +

Tradición

+

Honramos las técnicas clásicas que han forjado la gran cocina, aplicándolas con respeto.

+
+
+ architecture +

Vanguardia

+

Innovamos en presentaciones y texturas para sorprender a los paladares contemporáneos.

+
+
+
+
+ + +
+
+
+
+ El Capital Humano +

Mentes tras el menú

+
+

Un equipo multidisciplinar de chefs, sommeliers y diseñadores de eventos unidos por un propósito común.

+
+ +
+ {[ + { nombre: 'Mateo Navarro', rol: 'Director Ejecutivo', src: '/images/generated/gallery-2.jpg', pos: 'center top' }, + { nombre: 'Lucía Quintana', rol: 'Chef Creativa', src: '/images/generated/hero-nosotros-gen.jpg', pos: 'center top' }, + { nombre: 'Julián Marín', rol: 'Head Sommelier', src: '/images/foto-canapes.png', pos: 'center 30%' }, + { nombre: 'Elena Soler', rol: 'Diseño de Experiencias', src: '/images/foto-plato-mnq.png', pos: 'center top' }, + ].map(({ nombre, rol, src, pos }) => ( +
+
+ {nombre} +
+
+

{nombre}

+

{rol}

+
+
+ ))} +
+
+
+ + +
+
+
+

¿Planeamos algo extraordinario?

+

Estamos listos para transformar su visión en una realidad gastronómica sin precedentes.

+ Solicitar Dosier Exclusivo +
+
+
+
+ + diff --git a/src/pages/reuniones-familiares.astro b/src/pages/reuniones-familiares.astro index e3bff2e..7067d8d 100644 --- a/src/pages/reuniones-familiares.astro +++ b/src/pages/reuniones-familiares.astro @@ -2,11 +2,275 @@ import MainLayout from '../layouts/MainLayout.astro'; --- - -
-

Servicio · Reuniones Familiares

-

Celebraciones íntimas con calidez y refinamiento.

-

Desde aniversarios hasta cenas privadas, creamos experiencias cuidadas para disfrutar en familia sin resignar elegancia.

- Consultar por WhatsApp + + + +
+ Reuniones familiares — MNQ Catering +
+ +
+
+
+ Eventos Sociales +

Reuniones Familiares con Alma

+

+ Creamos experiencias culinarias íntimas donde cada detalle cuenta. Desde bautizos hasta aniversarios dorados, transformamos su mesa en un escenario de recuerdos inolvidables. +

+ Reservar una Cita +
+
+
+ + +
+
+ +
+

Momentos que Merecen Excelencia

+

+ "La familia es el corazón de todo lo que hacemos. Nuestra misión es permitirle ser el anfitrión perfecto sin las preocupaciones de la cocina." +

+
+ +
+ + +
+
+ Bautizos — mesa de celebración +
+
+

Bautizos

+

Cenas y Brunch Temáticos

+
+
+ + +
+
+ Aniversarios — celebración familiar +
+
+

Aniversarios

+

Menús Degustación Privados

+
+
+ + +
+
+ Cenas privadas — chef ejecutiva +
+
+

Cenas Privadas

+

Chef en Casa & Servicio Premium

+
+
+ +
+
+
+ + +
+
+
+ Culinaria de Autor +

Platos que Cuentan Historias

+
+ +
+ +
+
+ Vieiras de la Costa con Azafrán +
+
+

Vieiras de la Costa con Azafrán

+ Entrante de Firma +
+
+ + +
+
+
+ Postre de autor MNQ +
+

Postre de Autor

+

Elaboración artesanal con flor de azahar y crema de vainilla.

+
+
+
+ Postre con láminas de oro +
+

Repostería Dorada

+

Láminas de oro comestible sobre crema pastelera de temporada.

+
+
+
+
+
+ + +
+
+
+ +
+ Canapés premium para reuniones familiares +
+ +
+

+ Menús Diseñados Exclusivamente para Usted +

+

+ En MNQ Catering, entendemos que no hay dos familias iguales. Por ello, nuestro proceso de creación comienza con una conversación personal. Adaptamos cada plato a sus preferencias dietéticas, gustos personales y al tono del evento. +

+
    +
  • + auto_awesome +
    +
    Consultoría Privada
    +

    Reunión con nuestro Chef Ejecutivo para definir el concepto gastronómico.

    +
    +
  • +
  • + restaurant_menu +
    +
    Prueba de Degustación
    +

    Sesión íntima para refinar sabores y presentaciones antes del gran día.

    +
    +
  • +
  • + local_florist +
    +
    Armonía Visual
    +

    Coordinación de mantelería, vajilla y cristalería con el menú seleccionado.

    +
    +
  • +
+ Consultar Disponibilidad +
+ +
+
+
+ + +
+
+

¿Comenzamos a planear su próximo encuentro?

+

+ Nuestro equipo está disponible para asesorarle de forma inmediata y personalizada a través de nuestro canal exclusivo de WhatsApp. +

+ + chat + Contactar por WhatsApp + +
+
+
+ + diff --git a/src/styles/base.css b/src/styles/base.css index c1760df..2cb1a67 100644 --- a/src/styles/base.css +++ b/src/styles/base.css @@ -1,9 +1,8 @@ -* { +*, *::before, *::after { box-sizing: border-box; } -html, -body { +html, body { margin: 0; padding: 0; } @@ -16,12 +15,16 @@ body { background: var(--color-surface); } -h1, -h2, -h3 { +::selection { + background: var(--color-primary-container); + color: var(--color-on-surface); +} + +h1, h2, h3, h4, h5, h6 { font-family: var(--font-serif); line-height: 1.2; margin: 0; + font-weight: 400; } p { @@ -30,4 +33,24 @@ p { a { color: inherit; + text-decoration: none; +} + +img { + max-width: 100%; + height: auto; + display: block; +} + +ul, ol { + margin: 0; + padding: 0; + list-style: none; +} + +.material-symbols-outlined { + font-variation-settings: 'FILL' 0, 'wght' 300, 'GRAD' 0, 'opsz' 24; + display: inline-block; + line-height: 1; + vertical-align: middle; } diff --git a/src/styles/components.css b/src/styles/components.css index 23808f2..b1f40a1 100644 --- a/src/styles/components.css +++ b/src/styles/components.css @@ -1,107 +1,687 @@ +/* ───────────────────────────────────────────── + SITE HEADER / NAV + ───────────────────────────────────────────── */ + .site-header { - border-bottom: 1px solid rgb(31 26 23 / 10%); + position: fixed; + top: 0; + width: 100%; + z-index: 50; + height: var(--nav-h); + background: rgb(255 248 240 / 85%); + backdrop-filter: blur(12px); + -webkit-backdrop-filter: blur(12px); + border-bottom: 1px solid rgb(127 118 99 / 10%); +} + +.site-header .page-wrap { + height: 100%; + display: flex; + align-items: center; + justify-content: space-between; +} + +.site-brand { + font-family: var(--font-serif); + font-size: var(--text-headline-md); + color: var(--color-primary); + letter-spacing: -0.02em; + font-weight: 400; + white-space: nowrap; +} + +.site-nav { + display: none; + align-items: center; + gap: var(--space-8); +} + +.nav-link { + font-family: var(--font-sans); + font-size: var(--text-label-caps); + font-weight: 600; + letter-spacing: 0.15em; + text-transform: uppercase; + color: var(--color-on-surface); + transition: color 200ms; + padding-bottom: 0.25rem; +} + +.nav-link:hover { + color: var(--color-primary); +} + +.nav-link.active { + color: var(--color-primary); + border-bottom: 2px solid var(--color-primary); +} + +.nav-actions { + display: flex; + align-items: center; + gap: var(--space-4); +} + +@media (min-width: 48rem) { + .site-nav { + display: flex; + } +} + +/* ───────────────────────────────────────────── + BUTTONS + ───────────────────────────────────────────── */ + +.btn { + display: inline-flex; + align-items: center; + justify-content: center; + gap: var(--space-3); + min-height: 44px; + padding: 0.75rem 1.75rem; + font-family: var(--font-sans); + font-size: var(--text-label-caps); + font-weight: 600; + letter-spacing: 0.15em; + text-transform: uppercase; + text-decoration: none; + border: none; + cursor: pointer; + transition: opacity 200ms, transform 100ms, background 200ms; +} + +.btn:active { + transform: scale(0.96); +} + +.btn-primary { + background: var(--color-primary); + color: var(--color-on-primary); + border-radius: var(--radius-md); +} + +.btn-primary:hover { + background: var(--color-primary-container); + color: var(--color-on-surface); +} + +.btn-pill { + background: var(--color-primary); + color: var(--color-on-primary); + border-radius: var(--radius-full); +} + +.btn-pill:hover { + opacity: 0.85; +} + +.btn-outline { + background: transparent; + color: var(--color-primary); + border: 1px solid var(--color-primary-container); + border-radius: var(--radius-md); +} + +.btn-outline:hover { + background: var(--color-primary-container); + color: var(--color-on-surface); +} + +.btn-ghost { + background: transparent; + color: var(--color-on-primary); + border: 2px solid var(--color-primary-container); + border-radius: var(--radius-full); + padding: 1rem 2.5rem; +} + +.btn-ghost:hover { + background: var(--color-primary-container); + color: var(--color-on-surface); +} + +.btn-underline { + display: inline-flex; + align-items: center; + gap: var(--space-3); + font-family: var(--font-sans); + font-size: var(--text-label-caps); + font-weight: 600; + letter-spacing: 0.2em; + text-transform: uppercase; + color: var(--color-primary); + border-bottom: 2px solid var(--color-primary); + padding-bottom: 0.375rem; + transition: opacity 200ms; + cursor: pointer; + background: none; + border-top: none; + border-left: none; + border-right: none; +} + +.btn-underline:hover { + opacity: 0.65; +} + +.btn-dark { + background: var(--color-primary-container); + color: var(--color-on-surface); + border-radius: var(--radius-full); + padding: 1.25rem 2.5rem; +} + +.btn-dark:hover { + background: var(--color-primary-fixed); + transform: scale(1.03); +} + +/* ───────────────────────────────────────────── + TYPOGRAPHY CLASSES + ───────────────────────────────────────────── */ + +.text-display { + font-family: var(--font-serif); + font-size: var(--text-display); + line-height: 1.1; + letter-spacing: -0.02em; + font-weight: 400; +} + +.text-headline-lg { + font-family: var(--font-serif); + font-size: var(--text-headline-lg); + line-height: 1.2; + letter-spacing: 0.02em; + font-weight: 400; +} + +.text-headline-md { + font-family: var(--font-serif); + font-size: var(--text-headline-md); + line-height: 1.3; + letter-spacing: 0.03em; + font-weight: 400; +} + +.label-caps { + font-family: var(--font-sans); + font-size: var(--text-label-caps); + font-weight: 600; + letter-spacing: 0.15em; + text-transform: uppercase; +} + +.label-caps-wide { + font-family: var(--font-sans); + font-size: var(--text-label-caps); + font-weight: 600; + letter-spacing: 0.3em; + text-transform: uppercase; +} + +.text-body-sm { + font-size: var(--text-sm); + line-height: 1.5; + letter-spacing: 0.01em; +} + +/* ───────────────────────────────────────────── + COLOR UTILITIES + ───────────────────────────────────────────── */ + +.text-primary { color: var(--color-primary); } +.text-muted { color: var(--color-on-surface-variant); } +.text-white { color: #fff; } +.text-inverse { color: var(--color-inverse-on-surface); } + +.bg-surface { background: var(--color-surface); } +.bg-container { background: var(--color-surface-container); } +.bg-container-low { background: var(--color-surface-container-low); } +.bg-container-high { background: var(--color-surface-container-high); } +.bg-inverse { background: var(--color-inverse-surface); } +.bg-primary { background: var(--color-primary); } +.bg-primary-container { background: var(--color-primary-container); } + +/* ───────────────────────────────────────────── + HERO SECTIONS + ───────────────────────────────────────────── */ + +.hero-full { + position: relative; + height: 100svh; + min-height: 540px; + display: flex; + align-items: center; + justify-content: center; + overflow: hidden; +} + +.hero-tall { + position: relative; + height: 80svh; + min-height: 500px; + display: flex; + align-items: flex-end; + overflow: hidden; +} + +.hero-bg { + position: absolute; + inset: 0; + width: 100%; + height: 100%; + object-fit: cover; + object-position: center; +} + +.hero-gradient-placeholder { + position: absolute; + inset: 0; + background: linear-gradient(135deg, var(--color-inverse-surface) 0%, var(--color-primary) 50%, var(--color-primary-container) 100%); +} + +.hero-overlay { + position: absolute; + inset: 0; + background: rgb(31 27 19 / 35%); +} + +.hero-overlay-bottom { + position: absolute; + inset: 0; + background: linear-gradient(to bottom, transparent 0%, rgb(31 27 19 / 50%) 100%); +} + +.hero-content { + position: relative; + z-index: 10; + width: 100%; +} + +/* ───────────────────────────────────────────── + CARDS + ───────────────────────────────────────────── */ + +.card-border { + border: 1px solid rgb(208 197 175 / 30%); + border-radius: var(--radius-lg); background: var(--color-surface); } -.brand { - font-weight: 600; - text-decoration: none; +.card-image { + overflow: hidden; + border-radius: var(--radius-lg); + border: 1px solid rgb(208 197 175 / 10%); } -.site-footer { - border-top: 1px solid rgb(31 26 23 / 10%); - padding-block: var(--space-6); -} - -.footer-title, -.eyebrow { - font-size: var(--text-sm); - letter-spacing: 0.08em; - text-transform: uppercase; - color: var(--color-secondary); -} - -.card { - background: #fff; - border: 1px solid rgb(31 26 23 / 8%); - border-radius: var(--radius-md); - padding: var(--space-6); - box-shadow: var(--shadow-soft); - display: grid; - gap: var(--space-4); -} - -.button-primary, -.button-secondary { - width: fit-content; - display: inline-flex; - align-items: center; - justify-content: center; - min-height: 44px; - padding: 0.75rem 1rem; - border-radius: var(--radius-sm); - text-decoration: none; - border: 1px solid transparent; - font-weight: 600; -} - -.button-primary { - background: var(--color-primary); - color: #201a14; -} - -.button-primary:hover { - background: var(--color-secondary); - color: #fff; -} - -.button-secondary { - background: transparent; - color: var(--color-on-surface); - border-color: rgb(31 26 23 / 25%); -} - -.contact-form { - display: grid; - gap: var(--space-4); -} - -.contact-form label { - display: grid; - gap: var(--space-2); - font-weight: 500; -} - -.contact-form input, -.contact-form textarea { +.card-image img { width: 100%; - border-radius: var(--radius-sm); - border: 1px solid rgb(31 26 23 / 20%); - padding: 0.75rem; - font: inherit; - background: #fff; + height: 100%; + object-fit: cover; + transition: transform 700ms ease; } -.contact-form input:focus, -.contact-form textarea:focus { - outline: 2px solid var(--color-primary); - outline-offset: 2px; +.card-image:hover img { + transform: scale(1.05); } +/* Portfolio/bento cards */ +.bento-card { + position: relative; + overflow: hidden; + border-radius: var(--radius-lg); + border: 1px solid rgb(208 197 175 / 10%); +} + +.bento-card img { + position: absolute; + inset: 0; + width: 100%; + height: 100%; + object-fit: cover; + transition: transform 700ms ease; +} + +.bento-card:hover img { + transform: scale(1.05); +} + +.bento-card-overlay { + position: absolute; + inset: 0; + background: linear-gradient(to top, rgb(31 27 19 / 70%), transparent); +} + +.bento-card-body { + position: absolute; + bottom: 0; + left: 0; + right: 0; + padding: var(--space-8); + z-index: 10; +} + +/* Testimonial card */ +.testimonial-card { + padding: var(--space-10); + border: 1px solid rgb(208 197 175 / 30%); + border-radius: var(--radius-lg); + background: rgb(255 255 255 / 50%); + backdrop-filter: blur(4px); + display: flex; + flex-direction: column; + gap: var(--space-6); +} + +.testimonial-quote { + font-style: italic; + line-height: 1.6; + color: var(--color-on-surface); + flex: 1; +} + +.testimonial-author { + display: flex; + align-items: center; + gap: var(--space-4); + padding-top: var(--space-6); + border-top: 1px solid rgb(208 197 175 / 30%); +} + +.testimonial-avatar { + width: 3rem; + height: 3rem; + border-radius: var(--radius-full); + background: var(--color-surface-container-high); + border: 1px solid rgb(212 175 55 / 20%); + flex-shrink: 0; +} + +/* Value card */ +.value-card { + padding: var(--space-10); + border: 1px solid rgb(208 197 175 / 30%); + display: flex; + flex-direction: column; + align-items: center; + text-align: center; + gap: var(--space-4); + transition: background 300ms; +} + +.value-card:hover { + background: var(--color-surface-container); +} + +/* ───────────────────────────────────────────── + DIVIDERS / ACCENTS + ───────────────────────────────────────────── */ + +.gold-line { + width: 3rem; + height: 2px; + background: var(--color-primary-container); +} + +.border-left-gold { + border-left: 2px solid rgb(212 175 55 / 20%); + padding-left: var(--space-8); +} + +/* ───────────────────────────────────────────── + FORMS + ───────────────────────────────────────────── */ + +.form-field { + display: flex; + flex-direction: column; + gap: var(--space-2); +} + +.form-label { + font-family: var(--font-sans); + font-size: 0.625rem; + font-weight: 600; + letter-spacing: 0.2em; + text-transform: uppercase; + color: var(--color-primary); +} + +.form-input, +.form-select, +.form-textarea { + background: transparent; + border: none; + border-bottom: 1px solid var(--color-outline-variant); + padding: var(--space-4) 0; + font-family: var(--font-sans); + font-size: var(--text-base); + color: var(--color-on-surface); + width: 100%; + transition: border-color 200ms; + outline: none; + appearance: none; +} + +.form-input:focus, +.form-select:focus, +.form-textarea:focus { + border-bottom-color: var(--color-primary-container); +} + +.form-input::placeholder, +.form-textarea::placeholder { + color: var(--color-on-surface-variant); + opacity: 0.6; +} + +.form-textarea { + resize: none; +} + +.form-grid { + display: grid; + gap: var(--space-12); +} + +@media (min-width: 48rem) { + .form-grid { + grid-template-columns: 1fr 1fr; + } + + .form-span-full { + grid-column: 1 / -1; + } +} + +/* ───────────────────────────────────────────── + FLOATING WHATSAPP CTA + ───────────────────────────────────────────── */ + .whatsapp-float { position: fixed; - right: var(--space-4); - bottom: var(--space-4); - z-index: 50; - background: #25d366; - color: #fff; - text-decoration: none; - min-height: 48px; - padding: 0.75rem 1rem; - border-radius: 999px; + right: var(--space-8); + bottom: var(--space-8); + z-index: 60; display: inline-flex; align-items: center; - justify-content: center; - font-weight: 700; - box-shadow: var(--shadow-soft); + gap: var(--space-4); + background: var(--color-primary); + color: var(--color-on-primary); + padding: var(--space-4) var(--space-6); + padding-left: var(--space-8); + border-radius: var(--radius-full); + box-shadow: var(--shadow-lg); + font-family: var(--font-sans); + font-size: var(--text-label-caps); + font-weight: 600; + letter-spacing: 0.15em; + text-transform: uppercase; + text-decoration: none; + transition: transform 200ms, box-shadow 200ms; +} + +.whatsapp-float:hover { + transform: scale(1.04); + box-shadow: 0 30px 60px -15px rgb(115 92 0 / 35%); +} + +.whatsapp-float:active { + transform: scale(0.97); +} + +.whatsapp-float-icon { + width: 2.5rem; + height: 2.5rem; + border-radius: var(--radius-full); + background: rgb(255 255 255 / 15%); + display: flex; + align-items: center; + justify-content: center; +} + +/* ───────────────────────────────────────────── + SITE FOOTER + ───────────────────────────────────────────── */ + +.site-footer { + background: var(--color-surface-container); + border-top: 1px solid rgb(208 197 175 / 20%); +} + +.footer-inner { + display: flex; + flex-direction: column; + gap: var(--space-8); + padding-block: var(--space-section); +} + +.footer-brand h3 { + font-family: var(--font-serif); + font-size: var(--text-headline-lg); + color: var(--color-on-surface); + margin-bottom: var(--space-4); +} + +.footer-brand p { + font-size: var(--text-sm); + color: var(--color-on-surface-variant); + max-width: 20rem; +} + +.footer-links { + display: flex; + flex-wrap: wrap; + gap: var(--space-16); +} + +.footer-col { + display: flex; + flex-direction: column; + gap: var(--space-4); +} + +.footer-col-title { + font-family: var(--font-sans); + font-size: var(--text-label-caps); + font-weight: 600; + letter-spacing: 0.15em; + text-transform: uppercase; + color: var(--color-primary); + margin-bottom: var(--space-2); +} + +.footer-link { + font-size: var(--text-sm); + color: var(--color-on-surface-variant); + transition: color 200ms; +} + +.footer-link:hover { + color: var(--color-primary); +} + +.footer-bottom { + padding-block: var(--space-6); + border-top: 1px solid rgb(208 197 175 / 10%); + display: flex; + flex-direction: column; + gap: var(--space-4); + align-items: flex-start; +} + +@media (min-width: 48rem) { + .footer-inner { + flex-direction: row; + justify-content: space-between; + align-items: flex-start; + } + + .footer-bottom { + flex-direction: row; + justify-content: space-between; + align-items: center; + } +} + +/* ───────────────────────────────────────────── + DARK CTA SECTION + ───────────────────────────────────────────── */ + +.cta-dark { + background: var(--color-inverse-surface); + color: var(--color-inverse-on-surface); + border-radius: var(--radius-lg); + padding: var(--space-16) var(--space-8); + position: relative; + overflow: hidden; + text-align: center; +} + +@media (min-width: 48rem) { + .cta-dark { + padding: var(--space-24) var(--space-20); + } +} + +.cta-dark-ring { + position: absolute; + border: 2px solid rgb(255 224 136 / 10%); + border-radius: var(--radius-full); + pointer-events: none; +} + +.cta-gold { + background: var(--color-primary); + color: var(--color-on-primary); + padding: var(--space-16) var(--space-8); + text-align: center; +} + +/* ───────────────────────────────────────────── + BORDER UTILITIES + ───────────────────────────────────────────── */ + +.border-outline-soft { + border: 1px solid rgb(208 197 175 / 30%); +} + +.rounded-sm { border-radius: var(--radius-sm); } +.rounded-md { border-radius: var(--radius-md); } +.rounded-lg { border-radius: var(--radius-lg); } +.rounded-full { border-radius: var(--radius-full); } + +/* ───────────────────────────────────────────── + IMAGE PLACEHOLDERS (no photo yet) + ───────────────────────────────────────────── */ + +.img-placeholder { + background: linear-gradient(135deg, var(--color-surface-container-high) 0%, var(--color-surface-container) 100%); + width: 100%; + height: 100%; +} + +.img-placeholder-hero { + background: linear-gradient(160deg, var(--color-inverse-surface) 0%, #3d3020 40%, var(--color-primary) 100%); } diff --git a/src/styles/layout.css b/src/styles/layout.css index ca7336c..03949e6 100644 --- a/src/styles/layout.css +++ b/src/styles/layout.css @@ -1,47 +1,145 @@ -.container { - width: min(100% - 2rem, 72rem); +/* Container */ +.page-wrap { + max-width: var(--max-w-content); margin-inline: auto; + padding-inline: var(--space-page); } -.section-stack { - padding-block: var(--space-8) var(--space-12); +/* Section spacing */ +.section-pad { + padding-block: var(--space-section); } -.section-stack-sm { +.section-pad-sm { + padding-block: var(--space-12); +} + +/* Grids */ +.grid-2 { display: grid; - gap: var(--space-4); + gap: var(--space-8); } -.nav-wrap { - display: flex; - flex-direction: column; - gap: var(--space-4); - padding-block: var(--space-4); -} - -.nav-list { - display: flex; - flex-wrap: wrap; - gap: var(--space-3); - list-style: none; - margin: 0; - padding: 0; -} - -.footer-grid { +.grid-3 { display: grid; - gap: var(--space-4); + gap: var(--space-8); +} + +.grid-4 { + display: grid; + gap: var(--space-8); +} + +.grid-12 { + display: grid; + grid-template-columns: repeat(12, 1fr); + gap: var(--space-8); } @media (min-width: 48rem) { - .nav-wrap { - flex-direction: row; - justify-content: space-between; - align-items: center; - } - - .footer-grid { - grid-template-columns: 1fr auto; - align-items: center; - } + .grid-2 { grid-template-columns: repeat(2, 1fr); } + .grid-3 { grid-template-columns: repeat(3, 1fr); } + .grid-4 { grid-template-columns: repeat(4, 1fr); } } + +/* Column spans (for use inside .grid-12) */ +.col-5 { grid-column: span 12; } +.col-6 { grid-column: span 12; } +.col-7 { grid-column: span 12; } +.col-8 { grid-column: span 12; } + +@media (min-width: 48rem) { + .col-5 { grid-column: span 5; } + .col-6 { grid-column: span 6; } + .col-7 { grid-column: span 7; } + .col-8 { grid-column: span 8; } +} + +/* Flex utilities */ +.flex-between { + display: flex; + justify-content: space-between; + align-items: center; +} + +.flex-center { + display: flex; + justify-content: center; + align-items: center; +} + +.flex-col { + display: flex; + flex-direction: column; +} + +.gap-4 { gap: var(--space-4); } +.gap-6 { gap: var(--space-6); } +.gap-8 { gap: var(--space-8); } +.gap-12 { gap: var(--space-12); } + +/* Stack (vertical flex with gap) */ +.stack-4 { display: flex; flex-direction: column; gap: var(--space-4); } +.stack-6 { display: flex; flex-direction: column; gap: var(--space-6); } +.stack-8 { display: flex; flex-direction: column; gap: var(--space-8); } +.stack-12 { display: flex; flex-direction: column; gap: var(--space-12); } + +/* Mosaic gallery (CSS columns) */ +.mosaic { + columns: 1; + gap: var(--space-8); +} + +@media (min-width: 40rem) { + .mosaic { columns: 2; } +} + +@media (min-width: 64rem) { + .mosaic { columns: 3; } +} + +.mosaic > * { + break-inside: avoid; + margin-bottom: var(--space-8); +} + +/* Aspect ratios */ +.aspect-portrait { + aspect-ratio: 3/4; +} + +.aspect-square { + aspect-ratio: 1/1; +} + +.aspect-video { + aspect-ratio: 16/9; +} + +.aspect-wide { + aspect-ratio: 4/3; +} + +.object-cover { + width: 100%; + height: 100%; + object-fit: cover; + object-position: center; +} + +/* Overflow hidden for hover effects */ +.overflow-hidden { + overflow: hidden; +} + +/* Text alignment */ +.text-center { text-align: center; } +.text-right { text-align: right; } + +/* Max width utilities */ +.max-w-sm { max-width: 24rem; } +.max-w-md { max-width: 32rem; } +.max-w-lg { max-width: 40rem; } +.max-w-xl { max-width: 48rem; } +.max-w-2xl { max-width: 56rem; } +.mx-auto { margin-inline: auto; } diff --git a/src/styles/tokens.css b/src/styles/tokens.css index f2ba611..c6f2bec 100644 --- a/src/styles/tokens.css +++ b/src/styles/tokens.css @@ -1,28 +1,61 @@ :root { - --color-primary: #d4af37; - --color-secondary: #a67c1b; - --color-surface: #fffdf8; - --color-on-surface: #1f1a17; + /* Brand colors */ + --color-primary: #735c00; + --color-primary-container: #d4af37; + --color-primary-fixed: #ffe088; + --color-on-primary: #ffffff; + --color-secondary: #7b5900; + --color-surface: #fff8f0; + --color-surface-container: #f5eddf; + --color-surface-container-low: #fbf3e5; + --color-surface-container-high: #efe7da; + --color-on-surface: #1f1b13; + --color-on-surface-variant: #4d4635; + --color-outline: #7f7663; + --color-outline-variant: #d0c5af; + --color-inverse-surface: #343027; + --color-inverse-on-surface: #f8f0e2; --color-error: #b3261e; + /* Fonts */ --font-sans: 'Inter', system-ui, -apple-system, sans-serif; - --font-serif: 'Playfair Display', Georgia, serif; + --font-serif: 'Noto Serif', Georgia, serif; - --text-sm: 0.875rem; + /* Type scale */ + --text-display: clamp(2.5rem, 6vw, 4rem); + --text-headline-lg: clamp(1.75rem, 4vw, 2.5rem); + --text-headline-md: 2rem; + --text-label-caps: 0.75rem; --text-base: 1rem; - --text-lg: 1.125rem; - --text-xl: clamp(1.5rem, 5vw, 2.25rem); + --text-sm: 0.875rem; + /* Spacing */ + --space-1: 0.25rem; --space-2: 0.5rem; --space-3: 0.75rem; --space-4: 1rem; --space-6: 1.5rem; --space-8: 2rem; + --space-10: 2.5rem; --space-12: 3rem; + --space-16: 4rem; + --space-20: 5rem; + --space-24: 6rem; + --space-section: clamp(4rem, 10vw, 7.5rem); + --space-page: clamp(1.5rem, 5vw, 4rem); + --max-w-content: 80rem; + /* Border radius */ --radius-sm: 6px; --radius-md: 12px; --radius-lg: 20px; + --radius-full: 9999px; + /* Shadows */ --shadow-soft: 0 8px 24px rgb(31 26 23 / 8%); + --shadow-editorial: 0 10px 30px -10px rgb(115 92 0 / 5%); + --shadow-lg: 0 25px 50px -12px rgb(31 26 23 / 15%); + + /* Nav height */ + --nav-h: 5rem; } diff --git a/src/styles/utilities.css b/src/styles/utilities.css index b7c8dfb..7f4820b 100644 --- a/src/styles/utilities.css +++ b/src/styles/utilities.css @@ -1,9 +1,121 @@ -.text-muted { - color: rgb(31 26 23 / 72%); +/* Margin utilities */ +.mt-4 { margin-top: var(--space-4); } +.mt-6 { margin-top: var(--space-6); } +.mt-8 { margin-top: var(--space-8); } +.mt-12 { margin-top: var(--space-12); } +.mt-16 { margin-top: var(--space-16); } +.mt-20 { margin-top: var(--space-20); } +.mt-24 { margin-top: var(--space-24); } +.mb-4 { margin-bottom: var(--space-4); } +.mb-6 { margin-bottom: var(--space-6); } +.mb-8 { margin-bottom: var(--space-8); } +.mb-12 { margin-bottom: var(--space-12); } +.mb-16 { margin-bottom: var(--space-16); } + +/* Padding utilities */ +.pt-nav { padding-top: var(--nav-h); } +.p-10 { padding: var(--space-10); } +.p-12 { padding: var(--space-12); } + +/* Display */ +.hidden { display: none; } +.block { display: block; } +.flex { display: flex; } +.grid { display: grid; } + +@media (min-width: 48rem) { + .md-block { display: block; } + .md-flex { display: flex; } + .md-hidden { display: none; } } -.link-accent { - color: var(--color-secondary); - text-decoration: underline; - text-underline-offset: 0.2em; +/* Width */ +.w-full { width: 100%; } + +/* Overflow */ +.overflow-hidden { overflow: hidden; } + +/* Position */ +.relative { position: relative; } +.absolute { position: absolute; } +.sticky-top { position: sticky; top: 0; } + +/* Z-index */ +.z-10 { z-index: 10; } + +/* Opacity */ +.opacity-30 { opacity: 0.3; } +.opacity-60 { opacity: 0.6; } +.opacity-80 { opacity: 0.8; } + +/* Grayscale */ +.grayscale { filter: grayscale(1); } +.grayscale-hover:hover { filter: none; } + +/* Transition */ +.transition { transition: all 300ms ease; } + +/* Italic */ +.italic { font-style: italic; } + +/* Weight */ +.font-bold { font-weight: 700; } +.font-medium { font-weight: 500; } + +/* Leading */ +.leading-relaxed { line-height: 1.7; } +.leading-tight { line-height: 1.15; } + +/* Stars rating */ +.stars { + display: flex; + gap: var(--space-1); + justify-content: center; +} + +.star { + color: var(--color-primary-container); + font-size: 1.25rem; +} + +/* Section label */ +.section-eyebrow { + display: block; + font-family: var(--font-sans); + font-size: var(--text-label-caps); + font-weight: 600; + letter-spacing: 0.3em; + text-transform: uppercase; + color: var(--color-primary); + margin-bottom: var(--space-4); +} + +/* Editorial quote accent */ +.quote-mark { + font-family: var(--font-serif); + font-size: 4rem; + line-height: 0.8; + color: var(--color-primary-container); + margin-bottom: var(--space-4); +} + +/* Hover scale on cards */ +.hover-scale { + transition: transform 500ms ease; +} +.hover-scale:hover { + transform: scale(1.02); +} + +/* Image hover zoom (applied to parent that clips) */ +.img-zoom img { + transition: transform 700ms ease; +} +.img-zoom:hover img { + transform: scale(1.08); +} + +/* Icon size */ +.icon-lg { + font-size: 2.5rem; }