feat: sitio hostingdelsur.net v2 con Astro 5, Tailwind v4, soporte light/dark, i18n es/en, Keystatic CMS, reCAPTCHA v3

- Arista Pro Alternate Regular self-hosted (font corporativa)
- Toggle theme con CSS variables y @custom-variant dark
- 6 servicios en 3 categorías (Hosting & Correo / Diseño & Contenido / Infraestructura)
- 3 planes destacados (Básico USD 59, Institucional USD 129, E-commerce USD 219)
- Datacenters en 4 países (Canadá, USA, Alemania, Uruguay) sin ciudades en el sitio
- Sede operativa en Maldonado, Uruguay
- i18n es/en con contenido duplicado en Keystatic
- Endpoint PHP para form de contacto con PHPMailer + reCAPTCHA v3 + honeypot + rate limit
- WorldMap con animación SVG de los 4 países
- 29 páginas generadas, 0 JS por default
- Sitemap auto + robots.txt
- JSON-LD Organization + ProfessionalService con areaServed
This commit is contained in:
Mauri
2026-06-08 22:32:23 -03:00
commit 393f6b0dc3
73 changed files with 15399 additions and 0 deletions
+14
View File
@@ -0,0 +1,14 @@
node_modules
dist
.astro
.env
.env.local
.DS_Store
*.log
src/forms/_test_*
# Local artifacts (no versionar)
_screenshots/
_sketch/
playwright-report/
test-results/
+24
View File
@@ -0,0 +1,24 @@
import { defineConfig } from 'astro/config';
import tailwindcss from '@tailwindcss/vite';
import sitemap from '@astrojs/sitemap';
export default defineConfig({
site: 'https://hostingdelsur.net',
output: 'static',
i18n: {
defaultLocale: 'es',
locales: ['es', 'en'],
routing: {
prefixDefaultLocale: false,
},
},
integrations: [
sitemap(),
],
vite: {
plugins: [tailwindcss()],
},
build: {
inlineStylesheets: 'auto',
},
});
+8
View File
@@ -0,0 +1,8 @@
{
"name": "hostingdelsur-net-api",
"description": "PHPMailer for hostingdelsur.net contact form",
"type": "project",
"require": {
"phpmailer/phpmailer": "^6.9"
}
}
+97
View File
@@ -0,0 +1,97 @@
import { defineConfig, collection, fields, singleton } from '@keystatic/core';
export default defineConfig({
storage: {
kind: 'local',
},
collections: {
services: collection({
label: 'Servicios',
slugField: 'slug',
path: 'src/content/services/*',
schema: {
slug: fields.text({
label: 'Slug (URL)',
validation: { length: { min: 1, max: 80 } },
}),
category: fields.select({
label: 'Categoría',
options: [
{ label: 'Hosting & Correo', value: 'hosting' },
{ label: 'Diseño & Contenido', value: 'diseno' },
{ label: 'Infraestructura', value: 'infraestructura' },
],
defaultValue: 'hosting',
}),
icon: fields.text({
label: 'Ícono (MailIcon, WordpressIcon, CodeIcon, ShopIcon, TranslateIcon, ServerIcon)',
}),
order: fields.number({
label: 'Orden',
defaultValue: 0,
}),
name_es: fields.text({ label: 'Nombre (ES)' }),
name_en: fields.text({ label: 'Nombre (EN)' }),
shortDescription_es: fields.text({ label: 'Descripción corta (ES)', multiline: true }),
shortDescription_en: fields.text({ label: 'Descripción corta (EN)', multiline: true }),
body_es: fields.mdx({ label: 'Descripción completa (ES)' }),
body_en: fields.mdx({ label: 'Descripción completa (EN)' }),
features_es: fields.array(fields.text({ label: 'Feature' }), {
label: 'Features (ES)',
itemLabel: (props) => props.value,
}),
features_en: fields.array(fields.text({ label: 'Feature' }), {
label: 'Features (EN)',
itemLabel: (props) => props.value,
}),
},
}),
tutorials: collection({
label: 'Instructivos',
slugField: 'slug',
path: 'src/content/tutorials/*',
schema: {
slug: fields.text({
label: 'Slug (URL)',
validation: { length: { min: 1, max: 80 } },
}),
category: fields.select({
label: 'Categoría',
options: [
{ label: 'Correo', value: 'correo' },
{ label: 'WordPress', value: 'wordpress' },
{ label: 'Dominios', value: 'dominios' },
{ label: 'cPanel', value: 'cpanel' },
{ label: 'SSL', value: 'ssl' },
{ label: 'Backups', value: 'backups' },
],
}),
updatedAt: fields.date({
label: 'Última actualización',
}),
title_es: fields.text({ label: 'Título (ES)' }),
title_en: fields.text({ label: 'Título (EN)' }),
summary_es: fields.text({ label: 'Resumen (ES)', multiline: true }),
summary_en: fields.text({ label: 'Resumen (EN)', multiline: true }),
content_es: fields.mdx({ label: 'Contenido (ES)' }),
content_en: fields.mdx({ label: 'Contenido (EN)' }),
},
}),
},
singletons: {
siteSettings: singleton({
label: 'Configuración del sitio',
path: 'src/content/settings/site',
schema: {
contactEmail: fields.text({ label: 'Email de contacto' }),
whatsappNumber: fields.text({ label: 'WhatsApp (con código país, sin +)' }),
whatsappDefaultMessage_es: fields.text({ label: 'Mensaje inicial WhatsApp (ES)' }),
whatsappDefaultMessage_en: fields.text({ label: 'Mensaje inicial WhatsApp (EN)' }),
addressLine: fields.text({ label: 'Dirección (línea corta)' }),
socialLinkedin: fields.url({ label: 'LinkedIn URL' }),
socialGithub: fields.url({ label: 'GitHub URL' }),
},
}),
},
});
+10762
View File
File diff suppressed because it is too large Load Diff
+28
View File
@@ -0,0 +1,28 @@
{
"name": "hostingdelsur.net",
"type": "module",
"version": "1.0.0",
"private": true,
"scripts": {
"dev": "astro dev",
"start": "astro dev",
"build": "astro build",
"preview": "astro preview",
"astro": "astro",
"check": "astro check"
},
"dependencies": {
"@astrojs/sitemap": "^3.2.1",
"@fontsource/cormorant-garamond": "^5.1.0",
"@fontsource/mulish": "^5.1.0",
"@keystatic/core": "^0.5.0",
"@tailwindcss/vite": "^4.0.0",
"astro": "^5.0.0",
"sharp": "^0.33.5",
"tailwindcss": "^4.0.0"
},
"devDependencies": {
"playwright": "^1.60.0",
"typescript": "^5.6.0"
}
}
+73
View File
@@ -0,0 +1,73 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg viewBox="600 700 3300 4500" xmlns="http://www.w3.org/2000/svg">
<path fill="rgb(238,118,35)" stroke="none" d="M 3122,1125 L 2956,1125 C 2934,1125 2916,1107 2916,1085 L 2916,919 C 2916,897 2934,879 2956,879 L 3122,879 C 3144,879 3162,897 3162,919 L 3162,1085 C 3162,1107 3144,1125 3122,1125 L 3122,1125 Z"/>
<path fill="rgb(255,193,155)" stroke="none" d="M 3122,1432 L 2956,1432 C 2934,1432 2916,1414 2916,1393 L 2916,1226 C 2916,1204 2934,1186 2956,1186 L 3122,1186 C 3144,1186 3162,1204 3162,1226 L 3162,1393 C 3162,1414 3144,1432 3122,1432 L 3122,1432 Z"/>
<path fill="rgb(255,186,144)" stroke="none" d="M 3122,1740 L 2956,1740 C 2934,1740 2916,1722 2916,1700 L 2916,1534 C 2916,1512 2934,1494 2956,1494 L 3122,1494 C 3144,1494 3162,1512 3162,1534 L 3162,1700 C 3162,1722 3144,1740 3122,1740 L 3122,1740 Z"/>
<path fill="rgb(254,180,134)" stroke="none" d="M 3122,2047 L 2956,2047 C 2934,2047 2916,2029 2916,2007 L 2916,1841 C 2916,1819 2934,1801 2956,1801 L 3122,1801 C 3144,1801 3162,1819 3162,1841 L 3162,2007 C 3162,2029 3144,2047 3122,2047 L 3122,2047 Z"/>
<path fill="rgb(255,200,166)" stroke="none" d="M 2815,1432 L 2649,1432 C 2627,1432 2609,1414 2609,1393 L 2609,1226 C 2609,1204 2627,1186 2649,1186 L 2815,1186 C 2837,1186 2855,1204 2855,1226 L 2855,1393 C 2855,1414 2837,1432 2815,1432 L 2815,1432 Z"/>
<path fill="rgb(255,193,155)" stroke="none" d="M 2815,1740 L 2649,1740 C 2627,1740 2609,1722 2609,1700 L 2609,1534 C 2609,1512 2627,1494 2649,1494 L 2815,1494 C 2837,1494 2855,1512 2855,1534 L 2855,1700 C 2855,1722 2837,1740 2815,1740 L 2815,1740 Z"/>
<path fill="rgb(255,186,144)" stroke="none" d="M 2815,2047 L 2649,2047 C 2627,2047 2609,2029 2609,2007 L 2609,1841 C 2609,1819 2627,1801 2649,1801 L 2815,1801 C 2837,1801 2855,1819 2855,1841 L 2855,2007 C 2855,2029 2837,2047 2815,2047 L 2815,2047 Z"/>
<path fill="rgb(254,180,134)" stroke="none" d="M 2815,2354 L 2649,2354 C 2627,2354 2609,2337 2609,2315 L 2609,2148 C 2609,2126 2627,2109 2649,2109 L 2815,2109 C 2837,2109 2855,2126 2855,2148 L 2855,2315 C 2855,2337 2837,2354 2815,2354 L 2815,2354 Z"/>
<path fill="rgb(255,200,166)" stroke="none" d="M 2508,1740 L 2341,1740 C 2319,1740 2302,1722 2302,1700 L 2302,1534 C 2309,1512 2319,1494 2341,1494 L 2508,1494 C 2530,1494 2547,1512 2547,1534 L 2547,1700 C 2547,1722 2529,1740 2508,1740 L 2508,1740 Z"/>
<path fill="rgb(255,193,155)" stroke="none" d="M 2508,2047 L 2341,2047 C 2319,2047 2302,2029 2302,2007 L 2302,1841 C 2302,1819 2319,1801 2341,1801 L 2508,1801 C 2530,1801 2547,1819 2547,1841 L 2547,2007 C 2547,2029 2529,2047 2508,2047 L 2508,2047 Z"/>
<path fill="rgb(255,186,144)" stroke="none" d="M 2508,2354 L 2341,2354 C 2319,2354 2302,2337 2302,2315 L 2302,2148 C 2302,2126 2319,2109 2341,2109 L 2508,2109 C 2530,2109 2547,2126 2547,2148 L 2547,2315 C 2547,2337 2529,2354 2508,2354 L 2508,2354 Z"/>
<path fill="rgb(253,173,123)" stroke="none" d="M 2815,2662 L 2649,2662 C 2627,2662 2609,2644 2609,2622 L 2609,2456 C 2609,2434 2627,2416 2649,2416 L 2815,2416 C 2837,2416 2855,2434 2855,2456 L 2855,2622 C 2855,2644 2837,2662 2815,2662 L 2815,2662 Z"/>
<path fill="rgb(251,166,113)" stroke="none" d="M 2815,2969 L 2649,2969 C 2627,2969 2609,2952 2609,2930 L 2609,2763 C 2609,2741 2627,2724 2649,2724 L 2815,2724 C 2837,2724 2855,2741 2855,2763 L 2855,2930 C 2855,2952 2837,2969 2815,2969 L 2815,2969 Z"/>
<path fill="rgb(250,159,103)" stroke="none" d="M 2815,3277 L 2649,3277 C 2627,3277 2609,3259 2609,3237 L 2609,3071 C 2609,3049 2627,3031 2649,3031 L 2815,3031 C 2837,3031 2855,3049 2855,3071 L 2855,3237 C 2855,3259 2837,3277 2815,3277 L 2815,3277 Z"/>
<path fill="rgb(254,180,134)" stroke="none" d="M 2508,2662 L 2341,2662 C 2319,2662 2302,2644 2302,2622 L 2302,2456 C 2302,2434 2319,2416 2341,2416 L 2508,2416 C 2530,2416 2547,2434 2547,2456 L 2547,2622 C 2547,2644 2529,2662 2508,2662 L 2508,2662 Z"/>
<path fill="rgb(253,173,123)" stroke="none" d="M 2508,2969 L 2341,2969 C 2319,2969 2302,2952 2302,2930 L 2302,2763 C 2302,2741 2319,2724 2341,2724 L 2508,2724 C 2530,2724 2547,2741 2547,2763 L 2547,2930 C 2547,2952 2529,2969 2508,2969 L 2508,2969 Z"/>
<path fill="rgb(251,166,113)" stroke="none" d="M 2508,3277 L 2341,3277 C 2319,3277 2302,3259 2302,3237 L 2302,3071 C 2302,3049 2319,3031 2341,3031 L 2508,3031 C 2530,3031 2547,3049 2547,3071 L 2547,3237 C 2547,3259 2529,3277 2508,3277 L 2508,3277 Z"/>
<path fill="rgb(246,146,81)" stroke="none" d="M 3122,3584 L 2956,3584 C 2934,3584 2916,3566 2916,3544 L 2916,3378 C 2916,3356 2934,3338 2956,3338 L 3122,3338 C 3144,3338 3162,3356 3162,3378 L 3162,3544 C 3162,3566 3144,3584 3122,3584 L 3122,3584 Z"/>
<path fill="rgb(244,139,70)" stroke="none" d="M 3122,3891 L 2956,3891 C 2934,3891 2916,3874 2916,3852 L 2916,3685 C 2916,3663 2934,3646 2956,3646 L 3122,3646 C 3144,3646 3162,3663 3162,3685 L 3162,3852 C 3162,3874 3144,3891 3122,3891 L 3122,3891 Z"/>
<path fill="rgb(242,132,60)" stroke="none" d="M 3122,4199 L 2956,4199 C 2934,4199 2916,4181 2916,4159 L 2916,3993 C 2916,3971 2934,3953 2956,3953 L 3122,3953 C 3144,3953 3162,3971 3162,3993 L 3162,4159 C 3162,4181 3144,4199 3122,4199 L 3122,4199 Z"/>
<path fill="rgb(248,153,92)" stroke="none" d="M 2815,3584 L 2649,3584 C 2627,3584 2609,3566 2609,3544 L 2609,3378 C 2609,3356 2627,3338 2649,3338 L 2815,3338 C 2837,3338 2855,3356 2855,3378 L 2855,3544 C 2855,3566 2837,3584 2815,3584 L 2815,3584 Z"/>
<path fill="rgb(246,146,81)" stroke="none" d="M 2815,3891 L 2649,3891 C 2627,3891 2609,3874 2609,3852 L 2609,3685 C 2609,3663 2627,3646 2649,3646 L 2815,3646 C 2837,3646 2855,3663 2855,3685 L 2855,3852 C 2855,3874 2837,3891 2815,3891 L 2815,3891 Z"/>
<path fill="rgb(244,139,70)" stroke="none" d="M 2815,4199 L 2649,4199 C 2627,4199 2609,4181 2609,4159 L 2609,3993 C 2609,3971 2627,3953 2649,3953 L 2815,3953 C 2837,3953 2855,3971 2855,3993 L 2855,4159 C 2855,4181 2837,4199 2815,4199 L 2815,4199 Z"/>
<path fill="rgb(250,159,103)" stroke="none" d="M 2508,3584 L 2341,3584 C 2319,3584 2302,3566 2302,3544 L 2302,3378 C 2302,3356 2319,3338 2341,3338 L 2508,3338 C 2530,3338 2547,3356 2547,3378 L 2547,3544 C 2547,3566 2529,3584 2508,3584 L 2508,3584 Z"/>
<path fill="rgb(248,153,92)" stroke="none" d="M 2508,3891 L 2341,3891 C 2319,3891 2302,3874 2302,3852 L 2302,3685 C 2302,3663 2319,3646 2341,3646 L 2508,3646 C 2530,3646 2547,3663 2547,3685 L 2547,3852 C 2547,3874 2529,3891 2508,3891 L 2508,3891 Z"/>
<path fill="rgb(246,146,81)" stroke="none" d="M 2508,4199 L 2341,4199 C 2319,4199 2302,4181 2302,4159 L 2302,3993 C 2302,3971 2319,3953 2341,3953 L 2508,3953 C 2530,3953 2547,3971 2547,3993 L 2547,4159 C 2547,4181 2529,4199 2508,4199 L 2508,4199 Z"/>
<path fill="rgb(240,125,48)" stroke="none" d="M 3122,4506 L 2956,4506 C 2934,4506 2916,4488 2916,4466 L 2916,4300 C 2916,4278 2934,4260 2956,4260 L 3122,4260 C 3144,4260 3162,4278 3162,4300 L 3162,4466 C 3162,4488 3144,4506 3122,4506 L 3122,4506 Z"/>
<path fill="rgb(238,118,35)" stroke="none" d="M 3122,4814 L 2956,4814 C 2934,4814 2916,4796 2916,4774 L 2916,4607 C 2916,4586 2934,4568 2956,4568 L 3122,4568 C 3144,4568 3162,4586 3162,4607 L 3162,4774 C 3162,4796 3144,4814 3122,4814 L 3122,4814 Z"/>
<path fill="rgb(242,132,60)" stroke="none" d="M 3430,3891 L 3263,3891 C 3241,3891 3224,3874 3224,3852 L 3224,3685 C 3224,3663 3241,3646 3263,3646 L 3430,3646 C 3452,3646 3469,3663 3469,3685 L 3469,3852 C 3469,3874 3452,3891 3430,3891 L 3430,3891 Z"/>
<path fill="rgb(240,125,48)" stroke="none" d="M 3430,4199 L 3263,4199 C 3241,4199 3224,4181 3224,4159 L 3224,3993 C 3224,3971 3241,3953 3263,3953 L 3430,3953 C 3452,3953 3469,3971 3469,3993 L 3469,4159 C 3469,4181 3452,4199 3430,4199 L 3430,4199 Z"/>
<path fill="rgb(238,118,35)" stroke="none" d="M 3737,4199 L 3571,4199 C 3549,4199 3531,4181 3531,4159 L 3531,3993 C 3531,3971 3549,3953 3571,3953 L 3737,3953 C 3759,3953 3777,3971 3777,3993 L 3777,4159 C 3777,4181 3759,4199 3737,4199 L 3737,4199 Z"/>
<path fill="rgb(238,118,35)" stroke="none" d="M 3430,4506 L 3263,4506 C 3241,4506 3224,4488 3224,4466 L 3224,4300 C 3224,4278 3241,4260 3263,4260 L 3430,4260 C 3452,4260 3469,4278 3469,4300 L 3469,4466 C 3469,4488 3452,4506 3430,4506 L 3430,4506 Z"/>
<path fill="rgb(238,118,35)" stroke="none" d="M 3430,4814 L 3263,4814 C 3241,4814 3224,4796 3224,4774 L 3224,4607 C 3224,4586 3241,4568 3263,4568 L 3430,4568 C 3452,4568 3469,4586 3469,4607 L 3469,4774 C 3469,4796 3452,4814 3430,4814 L 3430,4814 Z"/>
<path fill="rgb(238,118,35)" stroke="none" d="M 3122,5121 L 2956,5121 C 2934,5121 2916,5103 2916,5081 L 2916,4915 C 2916,4893 2934,4875 2956,4875 L 3122,4875 C 3144,4875 3162,4893 3162,4915 L 3162,5081 C 3162,5103 3144,5121 3122,5121 L 3122,5121 Z"/>
<path fill="rgb(242,132,60)" stroke="none" d="M 2815,4506 L 2649,4506 C 2627,4506 2609,4488 2609,4466 L 2609,4300 C 2609,4278 2627,4260 2649,4260 L 2815,4260 C 2837,4260 2855,4278 2855,4300 L 2855,4466 C 2855,4488 2837,4506 2815,4506 L 2815,4506 Z"/>
<path fill="rgb(240,125,48)" stroke="none" d="M 2815,4814 L 2649,4814 C 2627,4814 2609,4796 2609,4774 L 2609,4607 C 2609,4586 2627,4568 2649,4568 L 2815,4568 C 2837,4568 2855,4586 2855,4607 L 2855,4774 C 2855,4796 2837,4814 2815,4814 L 2815,4814 Z"/>
<path fill="rgb(238,118,35)" stroke="none" d="M 2815,5121 L 2649,5121 C 2627,5121 2609,5103 2609,5081 L 2609,4915 C 2609,4893 2627,4875 2649,4875 L 2815,4875 C 2837,4875 2855,4893 2855,4915 L 2855,5081 C 2855,5103 2837,5121 2815,5121 L 2815,5121 Z"/>
<path fill="rgb(244,139,70)" stroke="none" d="M 2508,4506 L 2341,4506 C 2319,4506 2302,4488 2302,4466 L 2302,4300 C 2302,4278 2319,4260 2341,4260 L 2508,4260 C 2530,4260 2547,4278 2547,4300 L 2547,4466 C 2547,4488 2529,4506 2508,4506 L 2508,4506 Z"/>
<path fill="rgb(242,132,60)" stroke="none" d="M 2508,4814 L 2341,4814 C 2319,4814 2302,4796 2302,4774 L 2302,4607 C 2302,4586 2319,4568 2341,4568 L 2508,4568 C 2530,4568 2547,4586 2547,4607 L 2547,4774 C 2547,4796 2529,4814 2508,4814 L 2508,4814 Z"/>
<path fill="rgb(246,146,81)" stroke="none" d="M 2200,2354 L 2034,2354 C 2012,2354 1994,2337 1994,2315 L 1994,2148 C 1994,2126 2012,2109 2034,2109 L 2200,2109 C 2222,2109 2240,2126 2240,2148 L 2240,2315 C 2240,2337 2222,2354 2200,2354 L 2200,2354 Z"/>
<path fill="rgb(255,186,144)" stroke="none" d="M 2200,2662 L 2034,2662 C 2012,2662 1994,2644 1994,2622 L 1994,2456 C 1994,2434 2012,2416 2034,2416 L 2200,2416 C 2222,2416 2240,2434 2240,2456 L 2240,2622 C 2240,2644 2222,2662 2200,2662 L 2200,2662 Z"/>
<path fill="rgb(254,180,134)" stroke="none" d="M 2200,2969 L 2034,2969 C 2012,2969 1994,2952 1994,2930 L 1994,2763 C 1994,2741 2012,2724 2034,2724 L 2200,2724 C 2222,2724 2240,2741 2240,2763 L 2240,2930 C 2240,2952 2222,2969 2200,2969 L 2200,2969 Z"/>
<path fill="rgb(253,173,123)" stroke="none" d="M 2200,3277 L 2034,3277 C 2012,3277 1994,3259 1994,3237 L 1994,3071 C 1994,3049 2012,3031 2034,3031 L 2200,3031 C 2222,3031 2240,3049 2240,3071 L 2240,3237 C 2240,3259 2222,3277 2200,3277 L 2200,3277 Z"/>
<path fill="rgb(251,166,113)" stroke="none" d="M 2200,3584 L 2034,3584 C 2012,3584 1994,3566 1994,3544 L 1994,3378 C 1994,3356 2012,3338 2034,3338 L 2200,3338 C 2222,3338 2240,3356 2240,3378 L 2240,3544 C 2240,3566 2222,3584 2200,3584 L 2200,3584 Z"/>
<path fill="rgb(250,159,103)" stroke="none" d="M 2200,3891 L 2034,3891 C 2012,3891 1994,3874 1994,3852 L 1994,3685 C 1994,3663 2012,3646 2034,3646 L 2200,3646 C 2222,3646 2240,3663 2240,3685 L 2240,3852 C 2240,3874 2222,3891 2200,3891 L 2200,3891 Z"/>
<path fill="rgb(248,153,92)" stroke="none" d="M 2200,4199 L 2034,4199 C 2012,4199 1994,4181 1994,4159 L 1994,3993 C 1994,3971 2012,3953 2034,3953 L 2200,3953 C 2222,3953 2240,3971 2240,3993 L 2240,4159 C 2240,4181 2222,4199 2200,4199 L 2200,4199 Z"/>
<path fill="rgb(246,146,81)" stroke="none" d="M 2200,4506 L 2034,4506 C 2012,4506 1994,4488 1994,4466 L 1994,4300 C 1994,4278 2012,4260 2034,4260 L 2200,4260 C 2222,4260 2240,4278 2240,4300 L 2240,4466 C 2240,4488 2222,4506 2200,4506 L 2200,4506 Z"/>
<path fill="rgb(244,139,70)" stroke="none" d="M 2200,4814 L 2034,4814 C 2012,4814 1994,4796 1994,4774 L 1994,4607 C 1994,4586 2012,4568 2034,4568 L 2200,4568 C 2222,4568 2240,4586 2240,4607 L 2240,4774 C 2240,4796 2222,4814 2200,4814 L 2200,4814 Z"/>
<path fill="rgb(255,200,166)" stroke="none" d="M 1893,2354 L 1727,2354 C 1705,2354 1687,2337 1687,2315 L 1687,2148 C 1687,2126 1705,2109 1727,2109 L 1893,2109 C 1915,2109 1933,2126 1933,2148 L 1933,2315 C 1933,2337 1915,2354 1893,2354 L 1893,2354 Z"/>
<path fill="rgb(255,193,155)" stroke="none" d="M 1893,2662 L 1727,2662 C 1705,2662 1687,2644 1687,2622 L 1687,2456 C 1687,2434 1705,2416 1727,2416 L 1893,2416 C 1915,2416 1933,2434 1933,2456 L 1933,2622 C 1933,2644 1915,2662 1893,2662 L 1893,2662 Z"/>
<path fill="rgb(255,186,144)" stroke="none" d="M 1893,2969 L 1727,2969 C 1705,2969 1687,2952 1687,2930 L 1687,2763 C 1687,2741 1705,2724 1727,2724 L 1893,2724 C 1915,2724 1933,2741 1933,2763 L 1933,2930 C 1933,2952 1915,2969 1893,2969 L 1893,2969 Z"/>
<path fill="rgb(254,180,134)" stroke="none" d="M 1893,3277 L 1727,3277 C 1705,3277 1687,3259 1687,3237 L 1687,3071 C 1687,3049 1705,3031 1727,3031 L 1893,3031 C 1915,3031 1933,3049 1933,3071 L 1933,3237 C 1933,3259 1915,3277 1893,3277 L 1893,3277 Z"/>
<path fill="rgb(253,173,123)" stroke="none" d="M 1893,3584 L 1727,3584 C 1705,3584 1687,3566 1687,3544 L 1687,3378 C 1687,3356 1705,3338 1727,3338 L 1893,3338 C 1915,3338 1933,3356 1933,3378 L 1933,3544 C 1933,3566 1915,3584 1893,3584 L 1893,3584 Z"/>
<path fill="rgb(251,166,113)" stroke="none" d="M 1893,3891 L 1727,3891 C 1705,3891 1687,3874 1687,3852 L 1687,3685 C 1687,3663 1705,3646 1727,3646 L 1893,3646 C 1915,3646 1933,3663 1933,3685 L 1933,3852 C 1933,3874 1915,3891 1893,3891 L 1893,3891 Z"/>
<path fill="rgb(250,159,103)" stroke="none" d="M 1893,4199 L 1727,4199 C 1705,4199 1687,4181 1687,4159 L 1687,3993 C 1687,3971 1705,3953 1727,3953 L 1893,3953 C 1915,3953 1933,3971 1933,3993 L 1933,4159 C 1933,4181 1915,4199 1893,4199 L 1893,4199 Z"/>
<path fill="rgb(248,153,92)" stroke="none" d="M 1893,4506 L 1727,4506 C 1705,4506 1687,4488 1687,4466 L 1687,4300 C 1687,4278 1705,4260 1727,4260 L 1893,4260 C 1915,4260 1933,4278 1933,4300 L 1933,4466 C 1933,4488 1915,4506 1893,4506 L 1893,4506 Z"/>
<path fill="rgb(246,146,81)" stroke="none" d="M 1893,4814 L 1727,4814 C 1705,4814 1687,4796 1687,4774 L 1687,4607 C 1687,4586 1705,4568 1727,4568 L 1893,4568 C 1915,4568 1933,4586 1933,4607 L 1933,4774 C 1933,4796 1915,4814 1893,4814 L 1893,4814 Z"/>
<path fill="rgb(255,193,155)" stroke="none" d="M 1586,2969 L 1419,2969 C 1397,2969 1379,2952 1379,2930 L 1379,2763 C 1379,2741 1397,2724 1419,2724 L 1586,2724 C 1607,2724 1625,2741 1625,2763 L 1625,2930 C 1625,2952 1607,2969 1586,2969 L 1586,2969 Z"/>
<path fill="rgb(255,186,144)" stroke="none" d="M 1586,3277 L 1419,3277 C 1397,3277 1379,3259 1379,3237 L 1379,3071 C 1379,3049 1397,3031 1419,3031 L 1586,3031 C 1607,3031 1625,3049 1625,3071 L 1625,3237 C 1625,3259 1607,3277 1586,3277 L 1586,3277 Z"/>
<path fill="rgb(254,180,134)" stroke="none" d="M 1586,3584 L 1419,3584 C 1397,3584 1379,3566 1379,3544 L 1379,3378 C 1379,3356 1397,3338 1419,3338 L 1586,3338 C 1607,3338 1625,3356 1625,3378 L 1625,3544 C 1625,3566 1607,3584 1586,3584 L 1586,3584 Z"/>
<path fill="rgb(253,173,123)" stroke="none" d="M 1586,3891 L 1419,3891 C 1397,3891 1379,3874 1379,3852 L 1379,3685 C 1379,3663 1397,3646 1419,3646 L 1586,3646 C 1607,3646 1625,3663 1625,3685 L 1625,3852 C 1625,3874 1607,3891 1586,3891 L 1586,3891 Z"/>
<path fill="rgb(251,166,113)" stroke="none" d="M 1586,4199 L 1419,4199 C 1397,4199 1379,4181 1379,4159 L 1379,3993 C 1379,3971 1397,3953 1419,3953 L 1586,3953 C 1607,3953 1625,3971 1625,3993 L 1625,4159 C 1625,4181 1607,4199 1586,4199 L 1586,4199 Z"/>
<path fill="rgb(250,159,103)" stroke="none" d="M 1586,4506 L 1419,4506 C 1397,4506 1379,4488 1379,4466 L 1379,4300 C 1379,4278 1397,4260 1419,4260 L 1586,4260 C 1607,4260 1625,4278 1625,4300 L 1625,4466 C 1625,4488 1607,4506 1586,4506 L 1586,4506 Z"/>
<path fill="rgb(255,193,155)" stroke="none" d="M 1278,3277 L 1112,3277 C 1090,3277 1072,3259 1072,3237 L 1072,3071 C 1072,3049 1090,3031 1112,3031 L 1278,3031 C 1300,3031 1318,3049 1318,3071 L 1318,3237 C 1318,3259 1300,3277 1278,3277 L 1278,3277 Z"/>
<path fill="rgb(255,186,144)" stroke="none" d="M 1278,3584 L 1112,3584 C 1090,3584 1072,3566 1072,3544 L 1072,3378 C 1072,3356 1090,3338 1112,3338 L 1278,3338 C 1300,3338 1318,3356 1318,3378 L 1318,3544 C 1318,3566 1300,3584 1278,3584 L 1278,3584 Z"/>
<path fill="rgb(254,180,134)" stroke="none" d="M 1278,3891 L 1112,3891 C 1090,3891 1072,3874 1072,3852 L 1072,3685 C 1072,3663 1090,3646 1112,3646 L 1278,3646 C 1300,3646 1318,3663 1318,3685 L 1318,3852 C 1318,3874 1300,3891 1278,3891 L 1278,3891 Z"/>
<path fill="rgb(253,173,123)" stroke="none" d="M 1278,4199 L 1112,4199 C 1090,4199 1072,4181 1072,4159 L 1072,3993 C 1072,3971 1090,3953 1112,3953 L 1278,3953 C 1300,3953 1318,3971 1318,3993 L 1318,4159 C 1318,4181 1300,4199 1278,4199 L 1278,4199 Z"/>
<path fill="rgb(255,186,144)" stroke="none" d="M 971,3891 L 804,3891 C 782,3891 765,3874 765,3852 L 765,3685 C 765,3663 782,3646 804,3646 L 971,3646 C 993,3646 1010,3663 1010,3685 L 1010,3852 C 1010,3874 993,3891 971,3891 L 971,3891 Z"/>
<path fill="rgb(254,180,134)" stroke="none" d="M 971,4199 L 804,4199 C 782,4199 765,4181 765,4159 L 765,3993 C 765,3971 782,3953 804,3953 L 971,3953 C 993,3953 1010,3971 1010,3993 L 1010,4159 C 993,4181 971,4199 971,4199 L 971,4199 Z"/>
<path fill="rgb(240,125,48)" stroke="none" d="M 2508,5121 L 2341,5121 C 2319,5121 2302,5103 2302,5081 L 2302,4915 C 2302,4893 2319,4875 2341,4875 L 2508,4875 C 2530,4875 2547,4893 2547,4915 L 2547,5081 C 2547,5103 2529,5121 2508,5121 L 2508,5121 Z"/>
</svg>

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.
Binary file not shown.
+98
View File
@@ -0,0 +1,98 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg version="1.2" width="159mm" height="60mm" viewBox="0 0 15900 6000" preserveAspectRatio="xMidYMid" fill-rule="evenodd" stroke-width="28.222" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" xmlns:ooo="http://xml.openoffice.org/svg/export" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:presentation="http://sun.com/xmlns/staroffice/presentation" xmlns:smil="http://www.w3.org/2001/SMIL20/" xmlns:anim="urn:oasis:names:tc:opendocument:xmlns:animation:1.0" xml:space="preserve">
<defs class="ClipPathGroup">
<clipPath id="presentation_clip_path" clipPathUnits="userSpaceOnUse">
<rect x="0" y="0" width="15900" height="6000"/>
</clipPath>
<clipPath id="presentation_clip_path_shrink" clipPathUnits="userSpaceOnUse">
<rect x="15" y="6" width="15869" height="5988"/>
</clipPath>
</defs>
<g clip-path="url(#presentation_clip_path_shrink)">
<g id="id3">
<path fill="rgb(255,200,166)" stroke="none" d="M 3122,1125 L 2956,1125 C 2934,1125 2916,1107 2916,1085 L 2916,919 C 2916,897 2934,879 2956,879 L 3122,879 C 3144,879 3162,897 3162,919 L 3162,1085 C 3162,1107 3144,1125 3122,1125 L 3122,1125 Z"/>
<path fill="rgb(255,193,155)" stroke="none" d="M 3122,1432 L 2956,1432 C 2934,1432 2916,1414 2916,1393 L 2916,1226 C 2916,1204 2934,1186 2956,1186 L 3122,1186 C 3144,1186 3162,1204 3162,1226 L 3162,1393 C 3162,1414 3144,1432 3122,1432 L 3122,1432 Z"/>
<path fill="rgb(255,186,144)" stroke="none" d="M 3122,1740 L 2956,1740 C 2934,1740 2916,1722 2916,1700 L 2916,1534 C 2916,1512 2934,1494 2956,1494 L 3122,1494 C 3144,1494 3162,1512 3162,1534 L 3162,1700 C 3162,1722 3144,1740 3122,1740 L 3122,1740 Z"/>
<path fill="rgb(254,180,134)" stroke="none" d="M 3122,2047 L 2956,2047 C 2934,2047 2916,2029 2916,2007 L 2916,1841 C 2916,1819 2934,1801 2956,1801 L 3122,1801 C 3144,1801 3162,1819 3162,1841 L 3162,2007 C 3162,2029 3144,2047 3122,2047 L 3122,2047 Z"/>
<path fill="rgb(255,200,166)" stroke="none" d="M 2815,1432 L 2649,1432 C 2627,1432 2609,1414 2609,1393 L 2609,1226 C 2609,1204 2627,1186 2649,1186 L 2815,1186 C 2837,1186 2855,1204 2855,1226 L 2855,1393 C 2855,1414 2837,1432 2815,1432 L 2815,1432 Z"/>
<path fill="rgb(255,193,155)" stroke="none" d="M 2815,1740 L 2649,1740 C 2627,1740 2609,1722 2609,1700 L 2609,1534 C 2609,1512 2627,1494 2649,1494 L 2815,1494 C 2837,1494 2855,1512 2855,1534 L 2855,1700 C 2855,1722 2837,1740 2815,1740 L 2815,1740 Z"/>
<path fill="rgb(255,186,144)" stroke="none" d="M 2815,2047 L 2649,2047 C 2627,2047 2609,2029 2609,2007 L 2609,1841 C 2609,1819 2627,1801 2649,1801 L 2815,1801 C 2837,1801 2855,1819 2855,1841 L 2855,2007 C 2855,2029 2837,2047 2815,2047 L 2815,2047 Z"/>
<path fill="rgb(254,180,134)" stroke="none" d="M 2815,2354 L 2649,2354 C 2627,2354 2609,2337 2609,2315 L 2609,2148 C 2609,2126 2627,2109 2649,2109 L 2815,2109 C 2837,2109 2855,2126 2855,2148 L 2855,2315 C 2855,2337 2837,2354 2815,2354 L 2815,2354 Z"/>
<path fill="rgb(255,200,166)" stroke="none" d="M 2508,1740 L 2341,1740 C 2319,1740 2302,1722 2302,1700 L 2302,1534 C 2302,1512 2319,1494 2341,1494 L 2508,1494 C 2530,1494 2547,1512 2547,1534 L 2547,1700 C 2547,1722 2529,1740 2508,1740 L 2508,1740 Z"/>
<path fill="rgb(255,193,155)" stroke="none" d="M 2508,2047 L 2341,2047 C 2319,2047 2302,2029 2302,2007 L 2302,1841 C 2302,1819 2319,1801 2341,1801 L 2508,1801 C 2530,1801 2547,1819 2547,1841 L 2547,2007 C 2547,2029 2529,2047 2508,2047 L 2508,2047 Z"/>
<path fill="rgb(255,186,144)" stroke="none" d="M 2508,2354 L 2341,2354 C 2319,2354 2302,2337 2302,2315 L 2302,2148 C 2302,2126 2319,2109 2341,2109 L 2508,2109 C 2530,2109 2547,2126 2547,2148 L 2547,2315 C 2547,2337 2529,2354 2508,2354 L 2508,2354 Z"/>
<path fill="rgb(253,173,123)" stroke="none" d="M 2815,2662 L 2649,2662 C 2627,2662 2609,2644 2609,2622 L 2609,2456 C 2609,2434 2627,2416 2649,2416 L 2815,2416 C 2837,2416 2855,2434 2855,2456 L 2855,2622 C 2855,2644 2837,2662 2815,2662 L 2815,2662 Z"/>
<path fill="rgb(251,166,113)" stroke="none" d="M 2815,2969 L 2649,2969 C 2627,2969 2609,2952 2609,2930 L 2609,2763 C 2609,2741 2627,2724 2649,2724 L 2815,2724 C 2837,2724 2855,2741 2855,2763 L 2855,2930 C 2855,2952 2837,2969 2815,2969 L 2815,2969 Z"/>
<path fill="rgb(250,159,103)" stroke="none" d="M 2815,3277 L 2649,3277 C 2627,3277 2609,3259 2609,3237 L 2609,3071 C 2609,3049 2627,3031 2649,3031 L 2815,3031 C 2837,3031 2855,3049 2855,3071 L 2855,3237 C 2855,3259 2837,3277 2815,3277 L 2815,3277 Z"/>
<path fill="rgb(254,180,134)" stroke="none" d="M 2508,2662 L 2341,2662 C 2319,2662 2302,2644 2302,2622 L 2302,2456 C 2302,2434 2319,2416 2341,2416 L 2508,2416 C 2530,2416 2547,2434 2547,2456 L 2547,2622 C 2547,2644 2529,2662 2508,2662 L 2508,2662 Z"/>
<path fill="rgb(253,173,123)" stroke="none" d="M 2508,2969 L 2341,2969 C 2319,2969 2302,2952 2302,2930 L 2302,2763 C 2302,2741 2319,2724 2341,2724 L 2508,2724 C 2530,2724 2547,2741 2547,2763 L 2547,2930 C 2547,2952 2529,2969 2508,2969 L 2508,2969 Z"/>
<path fill="rgb(251,166,113)" stroke="none" d="M 2508,3277 L 2341,3277 C 2319,3277 2302,3259 2302,3237 L 2302,3071 C 2302,3049 2319,3031 2341,3031 L 2508,3031 C 2530,3031 2547,3049 2547,3071 L 2547,3237 C 2547,3259 2529,3277 2508,3277 L 2508,3277 Z"/>
<path fill="rgb(246,146,81)" stroke="none" d="M 3122,3584 L 2956,3584 C 2934,3584 2916,3566 2916,3544 L 2916,3378 C 2916,3356 2934,3338 2956,3338 L 3122,3338 C 3144,3338 3162,3356 3162,3378 L 3162,3544 C 3162,3566 3144,3584 3122,3584 L 3122,3584 Z"/>
<path fill="rgb(244,139,70)" stroke="none" d="M 3122,3891 L 2956,3891 C 2934,3891 2916,3874 2916,3852 L 2916,3685 C 2916,3663 2934,3646 2956,3646 L 3122,3646 C 3144,3646 3162,3663 3162,3685 L 3162,3852 C 3162,3874 3144,3891 3122,3891 L 3122,3891 Z"/>
<path fill="rgb(242,132,60)" stroke="none" d="M 3122,4199 L 2956,4199 C 2934,4199 2916,4181 2916,4159 L 2916,3993 C 2916,3971 2934,3953 2956,3953 L 3122,3953 C 3144,3953 3162,3971 3162,3993 L 3162,4159 C 3162,4181 3144,4199 3122,4199 L 3122,4199 Z"/>
<path fill="rgb(248,153,92)" stroke="none" d="M 2815,3584 L 2649,3584 C 2627,3584 2609,3566 2609,3544 L 2609,3378 C 2609,3356 2627,3338 2649,3338 L 2815,3338 C 2837,3338 2855,3356 2855,3378 L 2855,3544 C 2855,3566 2837,3584 2815,3584 L 2815,3584 Z"/>
<path fill="rgb(246,146,81)" stroke="none" d="M 2815,3891 L 2649,3891 C 2627,3891 2609,3874 2609,3852 L 2609,3685 C 2609,3663 2627,3646 2649,3646 L 2815,3646 C 2837,3646 2855,3663 2855,3685 L 2855,3852 C 2855,3874 2837,3891 2815,3891 L 2815,3891 Z"/>
<path fill="rgb(244,139,70)" stroke="none" d="M 2815,4199 L 2649,4199 C 2627,4199 2609,4181 2609,4159 L 2609,3993 C 2609,3971 2627,3953 2649,3953 L 2815,3953 C 2855,3953 2855,3971 2855,3993 L 2855,4159 C 2855,4181 2837,4199 2815,4199 L 2815,4199 Z"/>
<path fill="rgb(250,159,103)" stroke="none" d="M 2508,3584 L 2341,3584 C 2319,3584 2302,3566 2302,3544 L 2302,3378 C 2302,3556 2319,3338 2341,3338 L 2508,3338 C 2530,3338 2547,3356 2547,3378 L 2547,3544 C 2547,3566 2529,3584 2508,3584 L 2508,3584 Z"/>
<path fill="rgb(248,153,92)" stroke="none" d="M 2508,3891 L 2341,3891 C 2319,3891 2302,3874 2302,3852 L 2302,3685 C 2302,3663 2319,3646 2341,3646 L 2508,3646 C 2530,3646 2547,3663 2547,3685 L 2547,3852 C 2547,3874 2529,3891 2508,3891 L 2508,3891 Z"/>
<path fill="rgb(246,146,81)" stroke="none" d="M 2508,4199 L 2341,4199 C 2319,4199 2302,4181 2302,4159 L 2302,3993 C 2302,3971 2319,3951 2341,3953 L 2508,3953 C 2530,3953 2547,3971 2547,3993 L 2547,4159 C 2547,4181 2529,4199 2508,4199 L 2508,4199 Z"/>
<path fill="rgb(240,125,48)" stroke="none" d="M 3122,4506 L 2956,4506 C 2934,4506 2916,4488 2916,4466 L 2916,4300 C 2916,4278 2934,4260 2956,4260 L 3122,4260 C 3144,4260 3162,4278 3162,4300 L 3162,4466 C 3162,4488 3144,4506 3122,4506 L 3122,4506 Z"/>
<path fill="rgb(238,118,35)" stroke="none" d="M 3122,4814 L 2956,4814 C 2934,4814 2916,4796 2916,4774 L 2916,4607 C 2916,4586 2934,4568 2956,4568 L 3122,4568 C 3144,4568 3162,4586 3162,4607 L 3162,4774 C 3162,4796 3144,4814 3122,4814 L 3122,4814 Z"/>
<path fill="rgb(242,132,60)" stroke="none" d="M 3430,3891 L 3263,3891 C 3241,3891 3224,3874 3224,3852 L 3224,3685 C 3224,3663 3241,3646 3263,3646 L 3430,3646 C 3452,3646 3469,3663 3469,3685 L 3469,3852 C 3469,3874 3452,3891 3430,3891 L 3430,3891 Z"/>
<path fill="rgb(240,125,48)" stroke="none" d="M 3430,4199 L 3263,4199 C 3241,4199 3224,4181 3224,4159 L 3224,3993 C 3224,3971 3241,3953 3263,3953 L 3430,3953 C 3452,3953 3469,3971 3469,3993 L 3469,4159 C 3469,4181 3452,4199 3430,4199 L 3430,4199 Z"/>
<path fill="rgb(238,118,35)" stroke="none" d="M 3737,4199 L 3571,4199 C 3549,4199 3531,4181 3531,4159 L 3531,3993 C 3531,3971 3549,3953 3571,3953 L 3737,3953 C 3759,3953 3777,3971 3777,3993 L 3777,4159 C 3777,4181 3759,4199 3737,4199 L 3737,4199 Z"/>
<path fill="rgb(238,118,35)" stroke="none" d="M 3430,4506 L 3263,4506 C 3241,4506 3224,4488 3224,4466 L 3224,4300 C 3224,4278 3241,4260 3263,4260 L 3430,4260 C 3452,4260 3469,4278 3469,4300 L 3469,4466 C 3469,4488 3452,4506 3430,4506 L 3430,4506 Z"/>
<path fill="rgb(238,118,35)" stroke="none" d="M 3430,4814 L 3263,4814 C 3241,4814 3224,4796 3224,4774 L 3224,4607 C 3224,4586 3241,4568 3263,4568 L 3430,4568 C 3452,4568 3469,4586 3469,4607 L 3469,4774 C 3469,4796 3452,4814 3430,4814 L 3430,4814 Z"/>
<path fill="rgb(238,118,35)" stroke="none" d="M 3122,5121 L 2956,5121 C 2934,5121 2916,5103 2916,5081 L 2916,4915 C 2916,4893 2934,4875 2956,4875 L 3122,4875 C 3144,4875 3162,4893 3162,4915 L 3162,5081 C 3162,5103 3144,5121 3122,5121 L 3122,5121 Z"/>
<path fill="rgb(242,132,60)" stroke="none" d="M 2815,4506 L 2649,4506 C 2627,4506 2609,4488 2609,4466 L 2609,4300 C 2609,4278 2627,4260 2649,4260 L 2815,4260 C 2837,4260 2855,4278 2855,4300 L 2855,4466 C 2855,4488 2837,4506 2815,4506 L 2815,4506 Z"/>
<path fill="rgb(240,125,48)" stroke="none" d="M 2815,4814 L 2649,4814 C 2627,4814 2609,4796 2609,4774 L 2609,4607 C 2609,4586 2627,4568 2649,4568 L 2815,4568 C 2837,4568 2855,4586 2855,4607 L 2855,4774 C 2855,4796 2837,4814 2815,4814 L 2815,4814 Z"/>
<path fill="rgb(238,118,35)" stroke="none" d="M 2815,5121 L 2649,5121 C 2627,5121 2609,5103 2609,5081 L 2609,4915 C 2609,4893 2627,4875 2649,4875 L 2815,4875 C 2837,4875 2855,4893 2855,4915 L 2855,5081 C 2855,5103 2837,5121 2815,5121 L 2815,5121 Z"/>
<path fill="rgb(244,139,70)" stroke="none" d="M 2508,4506 L 2341,4506 C 2319,4506 2302,4488 2302,4466 L 2302,4300 C 2302,4278 2319,4260 2341,4260 L 2508,4260 C 2530,4260 2547,4278 2547,4300 L 2547,4466 C 2547,4488 2529,4506 2508,4506 L 2508,4506 Z"/>
<path fill="rgb(242,132,60)" stroke="none" d="M 2508,4814 L 2341,4814 C 2319,4814 2302,4796 2302,4774 L 2302,4607 C 2302,4586 2319,4568 2341,4568 L 2508,4568 C 2530,4568 2547,4586 2547,4607 L 2547,4774 C 2547,4796 2529,4814 2508,4814 L 2508,4814 Z"/>
<path fill="rgb(246,146,81)" stroke="none" d="M 2200,2354 L 2034,2354 C 2012,2354 1994,2337 1994,2315 L 1994,2148 C 1994,2126 2012,2109 2034,2109 L 2200,2109 C 2222,2109 2240,2126 2240,2148 L 2240,2315 C 2240,2337 2222,2354 2200,2354 L 2200,2354 Z"/>
<path fill="rgb(255,186,144)" stroke="none" d="M 2200,2662 L 2034,2662 C 2012,2662 1994,2644 1994,2622 L 1994,2456 C 1994,2434 2012,2416 2034,2416 L 2200,2416 C 2222,2416 2240,2434 2240,2456 L 2240,2622 C 2240,2644 2222,2662 2200,2662 L 2200,2662 Z"/>
<path fill="rgb(254,180,134)" stroke="none" d="M 2200,2969 L 2034,2969 C 2012,2969 1994,2952 1994,2930 L 1994,2763 C 1994,2741 2012,2724 2034,2724 L 2200,2724 C 2222,2724 2240,2741 2240,2763 L 2240,2930 C 2240,2952 2222,2969 2200,2969 L 2200,2969 Z"/>
<path fill="rgb(253,173,123)" stroke="none" d="M 2200,3277 L 2034,3277 C 2012,3277 1994,3259 1994,3237 L 1994,3071 C 1994,3049 2012,3031 2034,3031 L 2200,3031 C 2222,3031 2240,3049 2240,3071 L 2240,3237 C 2240,3259 2222,3277 2200,3277 L 2200,3277 Z"/>
<path fill="rgb(251,166,113)" stroke="none" d="M 2200,3584 L 2034,3584 C 2012,3584 1994,3566 1994,3544 L 1994,3378 C 1994,3356 2012,3338 2034,3338 L 2200,3338 C 2222,3338 2240,3356 2240,3378 L 2240,3544 C 2240,3566 2222,3584 2200,3584 L 2200,3584 Z"/>
<path fill="rgb(250,159,103)" stroke="none" d="M 2200,3891 L 2034,3891 C 2012,3891 1994,3874 1994,3852 L 1994,3685 C 1994,3663 2012,3646 2034,3646 L 2200,3646 C 2222,3646 2240,3663 2240,3685 L 2240,3852 C 2240,3874 2222,3891 2200,3891 L 2200,3891 Z"/>
<path fill="rgb(248,153,92)" stroke="none" d="M 2200,4199 L 2034,4199 C 2012,4199 1994,4181 1994,4159 L 1994,3993 C 1994,3971 2012,3953 2034,3953 L 2200,3953 C 2222,3953 2240,3971 2240,3993 L 2240,4159 C 2240,4181 2222,4199 2200,4199 L 2200,4199 Z"/>
<path fill="rgb(246,146,81)" stroke="none" d="M 2200,4506 L 2034,4506 C 2012,4506 1994,4488 1994,4466 L 1994,4300 C 1994,4278 2012,4260 2034,4260 L 2200,4260 C 2222,4260 2240,4278 2240,4300 L 2240,4466 C 2240,4488 2222,4506 2200,4506 L 2200,4506 Z"/>
<path fill="rgb(244,139,70)" stroke="none" d="M 2200,4814 L 2034,4814 C 2012,4814 1994,4796 1994,4774 L 1994,4607 C 1994,4586 2012,4568 2034,4568 L 2200,4568 C 2222,4568 2240,4586 2240,4607 L 2240,4774 C 2240,4796 2222,4814 2200,4814 L 2200,4814 Z"/>
<path fill="rgb(255,200,166)" stroke="none" d="M 1893,2354 L 1727,2354 C 1705,2354 1687,2337 1687,2315 L 1687,2148 C 1687,2126 1705,2109 1727,2109 L 1893,2109 C 1915,2109 1933,2126 1933,2148 L 1933,2315 C 1933,2337 1915,2354 1893,2354 L 1893,2354 Z"/>
<path fill="rgb(255,193,155)" stroke="none" d="M 1893,2662 L 1727,2662 C 1705,2662 1687,2644 1687,2622 L 1687,2456 C 1687,2434 1705,2416 1727,2416 L 1893,2416 C 1915,2416 1933,2434 1933,2456 L 1933,2622 C 1933,2644 1915,2662 1893,2662 L 1893,2662 Z"/>
<path fill="rgb(255,186,144)" stroke="none" d="M 1893,2969 L 1727,2969 C 1705,2969 1687,2952 1687,2930 L 1687,2763 C 1687,2741 1705,2724 1727,2724 L 1893,2724 C 1915,2724 1933,2741 1933,2763 L 1933,2930 C 1915,2952 1893,2969 1893,2969 L 1893,2969 Z"/>
<path fill="rgb(254,180,134)" stroke="none" d="M 1893,3277 L 1727,3277 C 1705,3277 1687,3259 1687,3237 L 1687,3071 C 1687,3049 1705,3031 1727,3031 L 1893,3031 C 1915,3031 1933,3049 1933,3071 L 1933,3237 C 1933,3259 1915,3277 1893,3277 L 1893,3277 Z"/>
<path fill="rgb(253,173,123)" stroke="none" d="M 1893,3584 L 1727,3584 C 1705,3584 1687,3566 1687,3544 L 1687,3378 C 1687,3356 1705,3338 1727,3338 L 1893,3338 C 1915,3338 1933,3356 1933,3378 L 1933,3544 C 1933,3566 1915,3584 1893,3584 L 1893,3584 Z"/>
<path fill="rgb(251,166,113)" stroke="none" d="M 1893,3891 L 1727,3891 C 1705,3891 1687,3874 1687,3852 L 1687,3685 C 1687,3663 1705,3646 1727,3646 L 1893,3646 C 1915,3646 1933,3663 1933,3685 L 1933,3852 C 1933,3874 1915,3891 1893,3891 L 1893,3891 Z"/>
<path fill="rgb(250,159,103)" stroke="none" d="M 1893,4199 L 1727,4199 C 1705,4199 1687,4181 1687,4159 L 1687,3993 C 1687,3971 1705,3953 1727,3953 L 1893,3953 C 1915,3953 1933,3971 1933,3993 L 1933,4159 C 1933,4181 1915,4199 1893,4199 L 1893,4199 Z"/>
<path fill="rgb(248,153,92)" stroke="none" d="M 1893,4506 L 1727,4506 C 1705,4506 1687,4488 1687,4466 L 1687,4300 C 1685,4278 1705,4260 1727,4260 L 1893,4260 C 1915,4260 1933,4278 1933,4300 L 1933,4466 C 1933,4488 1915,4506 1893,4506 L 1893,4506 Z"/>
<path fill="rgb(246,146,81)" stroke="none" d="M 1893,4814 L 1727,4814 C 1705,4814 1687,4796 1687,4774 L 1687,4607 C 1687,4586 1705,4568 1727,4568 L 1893,4568 C 1915,4568 1933,4586 1933,4607 L 1933,4774 C 1933,4596 1915,4814 1893,4814 L 1893,4814 Z"/>
<path fill="rgb(255,193,155)" stroke="none" d="M 1586,2969 L 1419,2969 C 1397,2969 1379,2952 1379,2930 L 1379,2763 C 1379,2741 1397,2724 1419,2724 L 1586,2724 C 1607,2724 1625,2741 1625,2763 L 1625,2930 C 1627,2952 1607,2969 1586,2969 L 1586,2969 Z"/>
<path fill="rgb(255,186,144)" stroke="none" d="M 1586,3277 L 1419,3277 C 1397,3277 1379,3259 1379,3237 L 1379,3071 C 1379,3049 1397,3031 1419,3031 L 1586,3031 C 1607,3031 1625,3049 1625,3071 L 1625,3237 C 1625,3259 1607,3277 1586,3277 L 1586,3277 Z"/>
<path fill="rgb(254,180,134)" stroke="none" d="M 1586,3584 L 1419,3584 C 1397,3584 1379,3566 1379,3544 L 1379,3378 C 1379,3356 1397,3338 1419,3338 L 1586,3338 C 1607,3338 1625,3356 1625,3378 L 1625,3544 C 1627,3584 1607,3584 1586,3584 L 1586,3584 Z"/>
<path fill="rgb(253,173,123)" stroke="none" d="M 1586,3891 L 1419,3891 C 1397,3891 1379,3874 1379,3852 L 1379,3685 C 1379,3663 1397,3646 1419,3646 L 1586,3646 C 1607,3646 1625,3663 1625,3685 L 1625,3852 C 1607,3874 1586,3891 1586,3891 L 1586,3891 Z"/>
<path fill="rgb(251,166,113)" stroke="none" d="M 1586,4199 L 1419,4199 C 1397,4199 1379,4181 1379,4159 L 1379,3993 C 1379,3971 1397,3953 1419,3953 L 1586,3953 C 1607,3953 1625,3971 1625,3993 L 1625,4159 C 1607,4181 1586,4199 1586,4199 L 1586,4199 Z"/>
<path fill="rgb(250,159,103)" stroke="none" d="M 1586,4506 L 1419,4506 C 1397,4506 1379,4488 1379,4466 L 1379,4300 C 1379,4278 1397,4260 1419,4260 L 1586,4260 C 1607,4260 1625,4278 1625,4300 L 1625,4466 C 1627,4488 1607,4506 1586,4506 L 1586,4506 Z"/>
<path fill="rgb(255,193,155)" stroke="none" d="M 1278,3277 L 1112,3277 C 1090,3277 1072,3259 1072,3237 L 1072,3071 C 1072,3049 1090,3031 1112,3031 L 1278,3031 C 1300,3031 1318,3049 1318,3071 L 1318,3237 C 1318,3259 1300,3277 1278,3277 L 1278,3277 Z"/>
<path fill="rgb(255,186,144)" stroke="none" d="M 1278,3584 L 1112,3584 C 1090,3584 1072,3566 1072,3544 L 1072,3378 C 1072,3356 1090,3338 1112,3338 L 1278,3338 C 1300,3338 1318,3356 1318,3378 L 1318,3544 C 1300,3566 1278,3584 1278,3584 L 1278,3584 Z"/>
<path fill="rgb(254,180,134)" stroke="none" d="M 1278,3891 L 1112,3891 C 1090,3891 1072,3874 1072,3852 L 1072,3685 C 1072,3663 1090,3646 1112,3646 L 1278,3646 C 1300,3646 1318,3663 1318,3685 L 1318,3852 C 1318,3874 1300,3891 1278,3891 L 1278,3891 Z"/>
<path fill="rgb(253,173,123)" stroke="none" d="M 1278,4199 L 1112,4199 C 1090,4199 1072,4181 1072,4159 L 1072,3993 C 1072,3971 1090,3953 1112,3953 L 1278,3953 C 1300,3953 1318,3971 1318,3993 L 1318,4159 C 1318,4181 1300,4199 1278,4199 L 1278,4199 Z"/>
<path fill="rgb(255,186,144)" stroke="none" d="M 971,3891 L 804,3891 C 782,3891 765,3874 765,3852 L 765,3685 C 765,3663 782,3646 804,3646 L 971,3646 C 993,3646 1010,3663 1010,3685 L 1010,3852 C 1010,3874 993,3891 971,3891 L 971,3891 Z"/>
<path fill="rgb(254,180,134)" stroke="none" d="M 971,4199 L 804,4199 C 782,4199 765,4181 765,4159 L 765,3993 C 765,3971 782,3953 804,3953 L 971,3953 C 993,3953 1010,3971 1010,3993 L 1010,4159 C 993,4181 971,4199 971,4199 L 971,4199 Z"/>
<path fill="rgb(240,125,48)" stroke="none" d="M 2508,5121 L 2341,5121 C 2319,5121 2302,5103 2302,5081 L 2302,4915 C 2302,4893 2319,4875 2341,4875 L 2508,4875 C 2530,4875 2547,4893 2547,4915 L 2547,5081 C 2547,5103 2529,5121 2508,5121 L 2508,5121 Z"/>
<path fill="rgb(34,34,34)" stroke="none" d="M 10036,2981 C 10036,2923 10047,2868 10069,2816 10092,2765 10122,2720 10160,2681 10199,2643 10244,2613 10295,2590 10346,2568 10401,2557 10459,2557 10519,2557 10567,2567 10603,2586 10639,2606 10668,2634 10690,2670 L 10690,2351 C 10690,2337 10692,2324 10697,2312 10701,2299 10708,2289 10716,2280 10725,2271 10735,2264 10747,2259 10759,2253 10771,2251 10785,2251 10799,2251 10812,2254 10824,2259 10836,2264 10846,2271 10854,2280 10863,2289 10870,2299 10875,2312 10880,2324 10882,2337 10882,2351 L 10882,2986 C 10882,3044 10870,3098 10847,3148 10825,3199 10795,3243 10756,3281 10718,3319 10674,3349 10623,3371 10572,3393 10517,3404 10459,3404 10401,3404 10346,3393 10295,3371 10244,3348 10199,3318 10160,3280 10122,3242 10092,3197 10069,3146 10047,3094 10036,3040 10036,2981 L 10036,2981 Z M 10229,2981 C 10229,3013 10235,3043 10247,3071 10259,3098 10275,3123 10296,3143 10317,3164 10342,3181 10369,3193 10397,3205 10427,3211 10459,3211 10491,3211 10522,3205 10550,3193 10578,3181 10602,3164 10623,3143 10644,3122 10660,3098 10672,3071 10684,3043 10690,3013 10690,2981 10690,2949 10684,2920 10672,2892 10660,2864 10643,2840 10622,2819 10601,2798 10577,2782 10549,2770 10521,2758 10491,2752 10459,2752 10428,2752 10398,2758 10370,2770 10342,2782 10317,2798 10296,2819 10275,2840 10259,2864 10247,2892 10235,2920 10229,2949 10229,2981 L 10229,2981 Z"/>
<path fill="rgb(34,34,34)" stroke="none" d="M 11213,3068 C 11220,3090 11231,3110 11245,3129 11259,3147 11275,3163 11293,3176 11311,3189 11332,3200 11354,3207 11376,3215 11399,3219 11424,3219 11450,3219 11471,3217 11488,3212 11505,3208 11520,3201 11536,3192 11556,3180 11575,3174 11592,3174 11605,3174 11618,3176 11629,3182 11641,3187 11651,3195 11659,3204 11668,3213 11674,3224 11679,3236 11684,3248 11686,3261 11686,3273 11686,3293 11680,3311 11667,3327 11655,3343 11637,3357 11614,3368 11591,3380 11563,3388 11530,3394 11498,3400 11462,3403 11424,3403 11365,3403 11310,3392 11258,3370 11206,3348 11161,3317 11123,3279 11084,3241 11053,3196 11031,3145 11009,3094 10998,3039 10998,2981 10998,2922 11009,2866 11031,2815 11053,2763 11084,2719 11123,2681 11161,2643 11206,2612 11258,2590 11310,2568 11365,2557 11424,2557 11482,2557 11536,2568 11587,2590 11638,2612 11683,2642 11722,2679 11760,2717 11791,2761 11814,2812 11836,2863 11849,2918 11850,2976 11850,3003 11841,3026 11823,3042 11805,3059 11783,3067 11755,3067 L 11213,3067 11213,3068 Z M 11652,2907 C 11645,2882 11635,2860 11620,2840 11606,2820 11589,2802 11570,2788 11551,2773 11529,2761 11504,2753 11480,2745 11454,2741 11427,2741 11400,2741 11374,2745 11350,2754 11326,2763 11305,2775 11286,2789 11267,2804 11250,2822 11237,2842 11223,2862 11213,2884 11207,2907 L 11652,2907 11652,2907 Z"/>
<path fill="rgb(34,34,34)" stroke="none" d="M 12291,3394 C 12250,3394 12212,3387 12176,3374 12141,3360 12110,3341 12083,3316 12057,3290 12036,3260 12021,3225 12006,3190 11998,3152 11998,3109 L 11998,2354 C 11998,2340 12000,2327 12005,2316 12010,2304 12017,2293 12025,2285 12033,2276 12043,2270 12054,2265 12065,2259 12078,2257 12091,2257 12104,2257 12117,2259 12129,2265 12141,2270 12152,2276 12161,2285 12170,2294 12177,2304 12182,2316 12188,2327 12191,2340 12191,2354 L 12191,3113 C 12192,3143 12201,3165 12218,3181 12234,3197 12258,3205 12287,3205 L 12291,3205 C 12305,3205 12318,3208 12329,3213 12341,3218 12351,3224 12360,3233 12368,3242 12375,3252 12380,3264 12384,3275 12386,3288 12386,3301 12386,3329 12377,3351 12359,3369 12342,3385 12319,3394 12291,3394 L 12291,3394 Z"/>
<path fill="rgb(34,34,34)" stroke="none" d="M 4724,2958 C 4724,2917 4718,2879 4705,2844 4693,2808 4675,2777 4652,2750 4629,2724 4601,2702 4568,2687 4536,2672 4499,2664 4459,2664 4419,2664 4380,2671 4344,2686 4307,2701 4275,2721 4248,2748 4221,2774 4199,2805 4182,2840 4166,2876 4158,2914 4158,2955 L 4158,3333 C 4158,3349 4152,3363 4141,3374 4130,3385 4116,3391 4100,3391 4083,3391 4070,3385 4058,3374 4047,3363 4041,3349 4041,3333 L 4041,2301 C 4041,2284 4047,2270 4059,2258 4071,2246 4084,2240 4100,2240 4116,2240 4130,2246 4141,2258 4152,2270 4158,2284 4158,2301 L 4158,2711 C 4176,2686 4195,2664 4217,2644 4239,2624 4263,2607 4288,2592 4314,2578 4341,2567 4369,2559 4398,2551 4428,2547 4459,2547 4515,2547 4566,2558 4613,2579 4660,2601 4700,2630 4734,2667 4768,2704 4794,2747 4812,2797 4831,2847 4840,2900 4840,2957 L 4840,3334 C 4840,3351 4835,3365 4824,3376 4813,3387 4799,3392 4782,3392 4766,3392 4752,3387 4741,3376 4730,3365 4724,3351 4724,3334 L 4724,2958 4724,2958 Z"/>
<path fill="rgb(34,34,34)" stroke="none" d="M 4971,2976 C 4971,2916 4982,2861 5004,2808 5027,2756 5057,2711 5096,2672 5135,2634 5180,2603 5232,2581 5283,2559 5339,2548 5397,2548 5457,2548 5512,2559 5564,2581 5616,2604 5661,2634 5700,2673 5738,2712 5768,2757 5791,2809 5813,2861 5824,2916 5824,2976 5824,3035 5813,3090 5791,3142 5768,3193 5738,3238 5700,3277 5661,3315 5616,3346 5564,3368 5512,3390 5457,3402 5397,3402 5338,3402 5283,3390 5232,3368 5180,3346 5135,3315 5096,3277 5057,3238 5027,3193 5004,3142 4982,3090 4971,3035 4971,2976 L 4971,2976 Z M 5087,2976 C 5087,3018 5095,3058 5112,3095 5128,3133 5150,3166 5178,3194 5206,3222 5239,3244 5276,3261 5314,3277 5354,3285 5398,3285 5441,3285 5482,3277 5520,3261 5558,3244 5591,3222 5618,3194 5646,3166 5668,3133 5684,3095 5700,3058 5708,3018 5708,2976 5708,2933 5700,2893 5684,2855 5668,2817 5646,2784 5618,2757 5591,2729 5558,2707 5520,2690 5482,2674 5441,2666 5398,2666 5354,2666 5314,2674 5276,2690 5239,2707 5206,2729 5178,2757 5150,2785 5128,2817 5112,2855 5095,2893 5087,2933 5087,2976 L 5087,2976 Z"/>
<path fill="rgb(34,34,34)" stroke="none" d="M 6336,3275 C 6353,3275 6369,3272 6385,3266 6401,3260 6415,3251 6428,3239 6441,3227 6452,3213 6459,3197 6467,3181 6471,3163 6471,3143 6471,3123 6467,3105 6460,3090 6452,3075 6442,3062 6430,3052 6417,3041 6403,3033 6386,3028 6370,3022 6353,3019 6335,3019 L 6163,3019 C 6130,3019 6099,3012 6070,2999 6041,2987 6016,2969 5995,2947 5974,2925 5958,2900 5946,2871 5934,2843 5928,2812 5928,2779 5928,2747 5934,2717 5946,2689 5958,2661 5975,2637 5996,2616 6017,2595 6043,2579 6071,2566 6100,2554 6130,2548 6163,2548 L 6482,2548 C 6498,2548 6512,2553 6523,2563 6535,2573 6540,2587 6540,2604 6540,2623 6535,2638 6523,2648 6512,2659 6498,2665 6482,2665 L 6162,2665 C 6145,2665 6129,2668 6115,2675 6101,2681 6088,2690 6078,2701 6067,2712 6059,2724 6053,2739 6047,2753 6044,2768 6044,2783 6044,2800 6047,2815 6053,2829 6059,2844 6068,2856 6079,2867 6089,2878 6102,2887 6116,2893 6130,2899 6146,2903 6162,2903 L 6345,2903 C 6379,2903 6411,2909 6440,2922 6470,2935 6495,2952 6517,2975 6539,2997 6556,3023 6568,3053 6581,3082 6587,3113 6587,3147 6587,3180 6581,3211 6568,3241 6556,3270 6539,3297 6518,3319 6497,3341 6472,3359 6442,3372 6413,3385 6381,3392 6346,3392 L 5966,3392 C 5950,3392 5937,3386 5927,3375 5917,3364 5912,3349 5912,3332 5912,3315 5917,3301 5927,3291 5937,3280 5950,3275 5966,3275 L 6336,3275 6336,3275 Z"/>
<path fill="rgb(34,34,34)" stroke="none" d="M 6711,2355 C 6711,2339 6716,2325 6728,2313 6740,2302 6753,2296 6769,2296 6785,2296 6799,2301 6811,2313 6823,2324 6829,2338 6829,2355 L 6829,2554 7215,2554 C 7231,2554 7245,2560 7257,2572 7268,2584 7274,2598 7274,2615 7274,2630 7269,2643 7257,2654 7246,2665 7232,2671 7215,2671 L 6830,2671 6830,2985 C 6830,3027 6838,3067 6854,3103 6870,3140 6892,3172 6920,3199 6948,3226 6981,3248 7018,3263 7056,3278 7097,3286 7140,3286 7179,3286 7215,3280 7248,3269 7281,3257 7312,3238 7342,3212 7348,3207 7355,3202 7362,3198 7369,3195 7377,3193 7388,3193 7401,3193 7413,3198 7423,3209 7434,3220 7439,3233 7439,3248 7439,3257 7437,3265 7433,3274 7430,3283 7424,3290 7417,3297 7380,3332 7339,3358 7292,3376 7245,3394 7194,3403 7140,3403 7081,3403 7025,3392 6973,3371 6921,3349 6875,3320 6836,3282 6797,3245 6767,3200 6744,3149 6722,3098 6711,3043 6711,2984 L 6711,2355 6711,2355 Z"/>
<path fill="rgb(34,34,34)" stroke="none" d="M 7537,2359 C 7537,2339 7543,2322 7557,2309 7570,2295 7587,2289 7607,2289 7626,2289 7643,2295 7657,2309 7671,2322 7678,2339 7678,2359 7678,2378 7671,2394 7657,2408 7643,2422 7626,2429 7607,2429 7587,2429 7570,2422 7557,2408 7544,2394 7537,2378 7537,2359 L 7537,2359 Z M 7547,2607 C 7547,2590 7553,2576 7565,2565 7576,2553 7590,2548 7606,2548 7623,2548 7637,2553 7648,2565 7658,2576 7664,2590 7664,2607 L 7664,3337 C 7664,3353 7658,3367 7647,3379 7635,3390 7622,3396 7607,3396 7590,3396 7576,3390 7565,3379 7553,3367 7548,3353 7548,3337 L 7548,2607 7547,2607 Z"/>
<path fill="rgb(34,34,34)" stroke="none" d="M 7819,2958 C 7819,2901 7829,2848 7849,2798 7870,2748 7897,2705 7933,2668 7969,2631 8011,2602 8059,2580 8107,2558 8160,2548 8216,2548 8273,2548 8325,2558 8373,2580 8421,2601 8463,2630 8498,2667 8534,2704 8561,2748 8581,2797 8601,2847 8611,2900 8611,2957 L 8611,3334 C 8611,3351 8605,3364 8594,3375 8584,3386 8570,3391 8553,3391 8537,3391 8523,3386 8511,3375 8500,3364 8494,3351 8494,3334 L 8494,2961 C 8494,2920 8488,2882 8474,2846 8460,2810 8441,2779 8416,2752 8391,2725 8362,2704 8328,2689 8294,2673 8256,2665 8216,2665 8176,2665 8139,2673 8105,2688 8070,2703 8041,2724 8016,2750 7990,2776 7971,2807 7957,2843 7943,2879 7936,2917 7936,2958 L 7936,3334 C 7936,3351 7931,3364 7920,3375 7910,3386 7896,3391 7880,3391 7864,3391 7850,3386 7838,3375 7826,3364 7820,3351 7820,3334 L 7820,2958 7819,2958 Z"/>
<path fill="rgb(34,34,34)" stroke="none" d="M 8736,2976 C 8736,2916 8747,2861 8770,2808 8792,2756 8823,2711 8862,2672 8901,2634 8946,2603 8997,2581 9049,2559 9104,2548 9163,2548 9223,2548 9279,2559 9330,2581 9382,2604 9428,2634 9466,2673 9505,2712 9535,2757 9557,2809 9579,2861 9591,2916 9591,2976 9591,3021 9584,3065 9570,3105 9557,3146 9538,3184 9514,3219 9538,3245 9556,3275 9566,3307 9577,3340 9582,3376 9582,3417 9582,3466 9573,3510 9556,3548 9540,3586 9517,3618 9489,3644 9461,3670 9429,3690 9393,3704 9357,3718 9319,3725 9281,3725 9255,3725 9227,3723 9197,3718 9166,3713 9137,3711 9109,3711 9101,3711 9091,3711 9081,3712 9070,3713 9059,3715 9048,3718 9037,3720 9025,3724 9014,3729 9003,3733 8993,3739 8984,3746 8972,3755 8960,3759 8949,3759 8933,3759 8919,3754 8906,3742 8893,3731 8887,3717 8887,3702 8887,3682 8895,3666 8912,3654 8929,3641 8950,3631 8973,3624 8996,3616 9020,3611 9044,3608 9068,3605 9087,3604 9101,3604 9125,3604 9148,3605 9172,3607 9195,3608 9219,3609 9243,3609 9312,3609 9367,3593 9407,3560 9446,3527 9466,3479 9466,3417 9466,3402 9465,3389 9462,3378 9460,3367 9458,3357 9455,3348 9451,3340 9448,3333 9444,3326 9440,3320 9436,3314 9432,3308 9395,3338 9354,3361 9308,3378 9262,3394 9214,3402 9163,3402 9104,3402 9049,3391 8997,3369 8946,3346 8900,3316 8862,3278 8823,3239 8792,3194 8770,3142 8748,3090 8736,3035 8736,2976 L 8736,2976 Z M 8853,2976 C 8853,3018 8861,3058 8877,3095 8894,3133 8916,3166 8944,3194 8972,3222 9005,3244 9042,3261 9080,3277 9120,3285 9163,3285 9207,3285 9248,3277 9286,3261 9324,3244 9357,3222 9384,3194 9412,3166 9434,3133 9451,3095 9467,3058 9475,3018 9475,2976 9475,2933 9467,2893 9451,2855 9434,2817 9412,2784 9384,2757 9356,2729 9324,2707 9286,2690 9248,2674 9207,2666 9163,2666 9120,2666 9080,2674 9042,2690 9005,2707 8972,2729 8944,2757 8916,2785 8893,2817 8877,2855 8861,2893 8853,2933 8853,2976 L 8853,2976 Z"/>
<path fill="rgb(238,118,35)" stroke="none" d="M 13244,3167 C 13249,3167 13254,3166 13260,3165 13266,3164 13271,3162 13276,3160 13280,3157 13284,3153 13287,3148 13290,3143 13292,3136 13292,3128 13292,3120 13290,3113 13287,3108 13284,3103 13280,3100 13275,3098 13270,3096 13264,3094 13258,3093 13251,3093 13245,3093 13240,3093 L 13103,3093 C 13066,3093 13032,3085 13000,3070 12969,3056 12942,3035 12919,3010 12897,2985 12879,2956 12866,2924 12853,2891 12847,2857 12847,2821 12847,2787 12854,2754 12867,2724 12881,2693 12899,2666 12922,2643 12945,2620 12972,2602 13003,2588 13035,2575 13068,2568 13103,2568 L 13369,2568 C 13385,2568 13399,2571 13413,2576 13427,2580 13439,2588 13449,2597 13459,2606 13467,2618 13473,2632 13479,2646 13482,2662 13482,2679 13482,2696 13479,2711 13474,2726 13468,2740 13461,2753 13451,2763 13441,2774 13430,2783 13417,2788 13404,2794 13390,2797 13376,2797 L 13369,2797 13107,2797 C 13099,2797 13092,2800 13085,2806 13078,2812 13075,2820 13075,2831 13075,2844 13078,2853 13086,2857 13093,2862 13099,2864 13106,2864 L 13262,2864 C 13300,2864 13334,2871 13366,2886 13398,2901 13425,2921 13448,2946 13471,2971 13489,2999 13501,3032 13514,3065 13520,3099 13520,3134 13520,3170 13514,3203 13502,3234 13489,3265 13472,3293 13450,3316 13428,3340 13402,3359 13371,3374 13340,3388 13306,3396 13270,3397 L 12937,3397 C 12922,3397 12908,3394 12895,3388 12882,3382 12871,3374 12862,3364 12852,3354 12845,3341 12840,3327 12835,3313 12832,3297 12832,3280 12832,3245 12842,3218 12861,3198 12881,3178 12906,3168 12937,3168 L 13244,3168 13244,3167 Z"/>
<path fill="rgb(238,118,35)" stroke="none" d="M 13627,2682 C 13627,2666 13630,2652 13636,2638 13642,2624 13650,2612 13661,2602 13671,2592 13683,2584 13696,2578 13710,2572 13725,2569 13740,2569 13755,2569 13770,2572 13784,2578 13798,2584 13811,2592 13821,2602 13832,2612 13840,2624 13846,2638 13852,2652 13855,2666 13855,2682 L 13855,3001 C 13855,3026 13859,3049 13869,3071 13878,3092 13891,3111 13907,3126 13923,3142 13942,3155 13964,3163 13986,3172 14010,3176 14035,3176 14060,3176 14082,3172 14103,3163 14123,3153 14139,3141 14153,3125 14167,3109 14177,3090 14185,3069 14192,3047 14196,3023 14196,2998 L 14196,2681 C 14196,2666 14199,2652 14205,2638 14212,2624 14220,2612 14231,2602 14241,2592 14254,2583 14268,2577 14282,2571 14297,2569 14313,2569 14328,2569 14343,2571 14357,2577 14370,2584 14382,2592 14392,2602 14402,2612 14410,2624 14416,2638 14422,2652 14424,2666 14424,2681 L 14424,2999 C 14424,3055 14415,3107 14395,3156 14376,3206 14349,3248 14314,3285 14279,3322 14238,3352 14190,3373 14143,3394 14091,3405 14035,3405 13979,3405 13926,3394 13876,3373 13826,3352 13783,3322 13746,3285 13709,3248 13680,3206 13659,3156 13637,3107 13626,3054 13626,2999 L 13626,2682 13627,2682 Z"/>
<path fill="rgb(238,118,35)" stroke="none" d="M 14577,2996 C 14579,2937 14591,2882 14615,2831 14639,2780 14670,2734 14709,2696 14748,2657 14794,2627 14845,2604 14897,2581 14952,2570 15010,2568 L 15018,2568 C 15056,2569 15085,2580 15105,2601 15125,2622 15135,2649 15135,2681 15135,2698 15132,2713 15126,2727 15120,2741 15111,2753 15101,2763 15090,2773 15077,2781 15063,2787 15048,2793 15033,2795 15017,2795 14988,2795 14961,2801 14936,2812 14911,2823 14888,2838 14869,2857 14850,2875 14835,2898 14823,2923 14812,2948 14806,2976 14805,3005 L 14805,3284 C 14805,3300 14802,3315 14797,3328 14791,3342 14783,3354 14773,3364 14762,3374 14750,3382 14737,3388 14724,3393 14709,3396 14694,3396 14678,3396 14663,3393 14649,3388 14635,3382 14622,3374 14612,3364 14601,3354 14593,3342 14586,3328 14580,3315 14577,3300 14577,3284 L 14577,2996 14577,2996 Z"/>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 33 KiB

+73
View File
@@ -0,0 +1,73 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg viewBox="600 700 3300 4500" xmlns="http://www.w3.org/2000/svg">
<path fill="rgb(238,118,35)" stroke="none" d="M 3122,1125 L 2956,1125 C 2934,1125 2916,1107 2916,1085 L 2916,919 C 2916,897 2934,879 2956,879 L 3122,879 C 3144,879 3162,897 3162,919 L 3162,1085 C 3162,1107 3144,1125 3122,1125 L 3122,1125 Z"/>
<path fill="rgb(255,193,155)" stroke="none" d="M 3122,1432 L 2956,1432 C 2934,1432 2916,1414 2916,1393 L 2916,1226 C 2916,1204 2934,1186 2956,1186 L 3122,1186 C 3144,1186 3162,1204 3162,1226 L 3162,1393 C 3162,1414 3144,1432 3122,1432 L 3122,1432 Z"/>
<path fill="rgb(255,186,144)" stroke="none" d="M 3122,1740 L 2956,1740 C 2934,1740 2916,1722 2916,1700 L 2916,1534 C 2916,1512 2934,1494 2956,1494 L 3122,1494 C 3144,1494 3162,1512 3162,1534 L 3162,1700 C 3162,1722 3144,1740 3122,1740 L 3122,1740 Z"/>
<path fill="rgb(254,180,134)" stroke="none" d="M 3122,2047 L 2956,2047 C 2934,2047 2916,2029 2916,2007 L 2916,1841 C 2916,1819 2934,1801 2956,1801 L 3122,1801 C 3144,1801 3162,1819 3162,1841 L 3162,2007 C 3162,2029 3144,2047 3122,2047 L 3122,2047 Z"/>
<path fill="rgb(255,200,166)" stroke="none" d="M 2815,1432 L 2649,1432 C 2627,1432 2609,1414 2609,1393 L 2609,1226 C 2609,1204 2627,1186 2649,1186 L 2815,1186 C 2837,1186 2855,1204 2855,1226 L 2855,1393 C 2855,1414 2837,1432 2815,1432 L 2815,1432 Z"/>
<path fill="rgb(255,193,155)" stroke="none" d="M 2815,1740 L 2649,1740 C 2627,1740 2609,1722 2609,1700 L 2609,1534 C 2609,1512 2627,1494 2649,1494 L 2815,1494 C 2837,1494 2855,1512 2855,1534 L 2855,1700 C 2855,1722 2837,1740 2815,1740 L 2815,1740 Z"/>
<path fill="rgb(255,186,144)" stroke="none" d="M 2815,2047 L 2649,2047 C 2627,2047 2609,2029 2609,2007 L 2609,1841 C 2609,1819 2627,1801 2649,1801 L 2815,1801 C 2837,1801 2855,1819 2855,1841 L 2855,2007 C 2855,2029 2837,2047 2815,2047 L 2815,2047 Z"/>
<path fill="rgb(254,180,134)" stroke="none" d="M 2815,2354 L 2649,2354 C 2627,2354 2609,2337 2609,2315 L 2609,2148 C 2609,2126 2627,2109 2649,2109 L 2815,2109 C 2837,2109 2855,2126 2855,2148 L 2855,2315 C 2855,2337 2837,2354 2815,2354 L 2815,2354 Z"/>
<path fill="rgb(255,200,166)" stroke="none" d="M 2508,1740 L 2341,1740 C 2319,1740 2302,1722 2302,1700 L 2302,1534 C 2309,1512 2319,1494 2341,1494 L 2508,1494 C 2530,1494 2547,1512 2547,1534 L 2547,1700 C 2547,1722 2529,1740 2508,1740 L 2508,1740 Z"/>
<path fill="rgb(255,193,155)" stroke="none" d="M 2508,2047 L 2341,2047 C 2319,2047 2302,2029 2302,2007 L 2302,1841 C 2302,1819 2319,1801 2341,1801 L 2508,1801 C 2530,1801 2547,1819 2547,1841 L 2547,2007 C 2547,2029 2529,2047 2508,2047 L 2508,2047 Z"/>
<path fill="rgb(255,186,144)" stroke="none" d="M 2508,2354 L 2341,2354 C 2319,2354 2302,2337 2302,2315 L 2302,2148 C 2302,2126 2319,2109 2341,2109 L 2508,2109 C 2530,2109 2547,2126 2547,2148 L 2547,2315 C 2547,2337 2529,2354 2508,2354 L 2508,2354 Z"/>
<path fill="rgb(253,173,123)" stroke="none" d="M 2815,2662 L 2649,2662 C 2627,2662 2609,2644 2609,2622 L 2609,2456 C 2609,2434 2627,2416 2649,2416 L 2815,2416 C 2837,2416 2855,2434 2855,2456 L 2855,2622 C 2855,2644 2837,2662 2815,2662 L 2815,2662 Z"/>
<path fill="rgb(251,166,113)" stroke="none" d="M 2815,2969 L 2649,2969 C 2627,2969 2609,2952 2609,2930 L 2609,2763 C 2609,2741 2627,2724 2649,2724 L 2815,2724 C 2837,2724 2855,2741 2855,2763 L 2855,2930 C 2855,2952 2837,2969 2815,2969 L 2815,2969 Z"/>
<path fill="rgb(250,159,103)" stroke="none" d="M 2815,3277 L 2649,3277 C 2627,3277 2609,3259 2609,3237 L 2609,3071 C 2609,3049 2627,3031 2649,3031 L 2815,3031 C 2837,3031 2855,3049 2855,3071 L 2855,3237 C 2855,3259 2837,3277 2815,3277 L 2815,3277 Z"/>
<path fill="rgb(254,180,134)" stroke="none" d="M 2508,2662 L 2341,2662 C 2319,2662 2302,2644 2302,2622 L 2302,2456 C 2302,2434 2319,2416 2341,2416 L 2508,2416 C 2530,2416 2547,2434 2547,2456 L 2547,2622 C 2547,2644 2529,2662 2508,2662 L 2508,2662 Z"/>
<path fill="rgb(253,173,123)" stroke="none" d="M 2508,2969 L 2341,2969 C 2319,2969 2302,2952 2302,2930 L 2302,2763 C 2302,2741 2319,2724 2341,2724 L 2508,2724 C 2530,2724 2547,2741 2547,2763 L 2547,2930 C 2547,2952 2529,2969 2508,2969 L 2508,2969 Z"/>
<path fill="rgb(251,166,113)" stroke="none" d="M 2508,3277 L 2341,3277 C 2319,3277 2302,3259 2302,3237 L 2302,3071 C 2302,3049 2319,3031 2341,3031 L 2508,3031 C 2530,3031 2547,3049 2547,3071 L 2547,3237 C 2547,3259 2529,3277 2508,3277 L 2508,3277 Z"/>
<path fill="rgb(246,146,81)" stroke="none" d="M 3122,3584 L 2956,3584 C 2934,3584 2916,3566 2916,3544 L 2916,3378 C 2916,3356 2934,3338 2956,3338 L 3122,3338 C 3144,3338 3162,3356 3162,3378 L 3162,3544 C 3162,3566 3144,3584 3122,3584 L 3122,3584 Z"/>
<path fill="rgb(244,139,70)" stroke="none" d="M 3122,3891 L 2956,3891 C 2934,3891 2916,3874 2916,3852 L 2916,3685 C 2916,3663 2934,3646 2956,3646 L 3122,3646 C 3144,3646 3162,3663 3162,3685 L 3162,3852 C 3162,3874 3144,3891 3122,3891 L 3122,3891 Z"/>
<path fill="rgb(242,132,60)" stroke="none" d="M 3122,4199 L 2956,4199 C 2934,4199 2916,4181 2916,4159 L 2916,3993 C 2916,3971 2934,3953 2956,3953 L 3122,3953 C 3144,3953 3162,3971 3162,3993 L 3162,4159 C 3162,4181 3144,4199 3122,4199 L 3122,4199 Z"/>
<path fill="rgb(248,153,92)" stroke="none" d="M 2815,3584 L 2649,3584 C 2627,3584 2609,3566 2609,3544 L 2609,3378 C 2609,3356 2627,3338 2649,3338 L 2815,3338 C 2837,3338 2855,3356 2855,3378 L 2855,3544 C 2855,3566 2837,3584 2815,3584 L 2815,3584 Z"/>
<path fill="rgb(246,146,81)" stroke="none" d="M 2815,3891 L 2649,3891 C 2627,3891 2609,3874 2609,3852 L 2609,3685 C 2609,3663 2627,3646 2649,3646 L 2815,3646 C 2837,3646 2855,3663 2855,3685 L 2855,3852 C 2855,3874 2837,3891 2815,3891 L 2815,3891 Z"/>
<path fill="rgb(244,139,70)" stroke="none" d="M 2815,4199 L 2649,4199 C 2627,4199 2609,4181 2609,4159 L 2609,3993 C 2609,3971 2627,3953 2649,3953 L 2815,3953 C 2837,3953 2855,3971 2855,3993 L 2855,4159 C 2855,4181 2837,4199 2815,4199 L 2815,4199 Z"/>
<path fill="rgb(250,159,103)" stroke="none" d="M 2508,3584 L 2341,3584 C 2319,3584 2302,3566 2302,3544 L 2302,3378 C 2302,3356 2319,3338 2341,3338 L 2508,3338 C 2530,3338 2547,3356 2547,3378 L 2547,3544 C 2547,3566 2529,3584 2508,3584 L 2508,3584 Z"/>
<path fill="rgb(248,153,92)" stroke="none" d="M 2508,3891 L 2341,3891 C 2319,3891 2302,3874 2302,3852 L 2302,3685 C 2302,3663 2319,3646 2341,3646 L 2508,3646 C 2530,3646 2547,3663 2547,3685 L 2547,3852 C 2547,3874 2529,3891 2508,3891 L 2508,3891 Z"/>
<path fill="rgb(246,146,81)" stroke="none" d="M 2508,4199 L 2341,4199 C 2319,4199 2302,4181 2302,4159 L 2302,3993 C 2302,3971 2319,3953 2341,3953 L 2508,3953 C 2530,3953 2547,3971 2547,3993 L 2547,4159 C 2547,4181 2529,4199 2508,4199 L 2508,4199 Z"/>
<path fill="rgb(240,125,48)" stroke="none" d="M 3122,4506 L 2956,4506 C 2934,4506 2916,4488 2916,4466 L 2916,4300 C 2916,4278 2934,4260 2956,4260 L 3122,4260 C 3144,4260 3162,4278 3162,4300 L 3162,4466 C 3162,4488 3144,4506 3122,4506 L 3122,4506 Z"/>
<path fill="rgb(238,118,35)" stroke="none" d="M 3122,4814 L 2956,4814 C 2934,4814 2916,4796 2916,4774 L 2916,4607 C 2916,4586 2934,4568 2956,4568 L 3122,4568 C 3144,4568 3162,4586 3162,4607 L 3162,4774 C 3162,4796 3144,4814 3122,4814 L 3122,4814 Z"/>
<path fill="rgb(242,132,60)" stroke="none" d="M 3430,3891 L 3263,3891 C 3241,3891 3224,3874 3224,3852 L 3224,3685 C 3224,3663 3241,3646 3263,3646 L 3430,3646 C 3452,3646 3469,3663 3469,3685 L 3469,3852 C 3469,3874 3452,3891 3430,3891 L 3430,3891 Z"/>
<path fill="rgb(240,125,48)" stroke="none" d="M 3430,4199 L 3263,4199 C 3241,4199 3224,4181 3224,4159 L 3224,3993 C 3224,3971 3241,3953 3263,3953 L 3430,3953 C 3452,3953 3469,3971 3469,3993 L 3469,4159 C 3469,4181 3452,4199 3430,4199 L 3430,4199 Z"/>
<path fill="rgb(238,118,35)" stroke="none" d="M 3737,4199 L 3571,4199 C 3549,4199 3531,4181 3531,4159 L 3531,3993 C 3531,3971 3549,3953 3571,3953 L 3737,3953 C 3759,3953 3777,3971 3777,3993 L 3777,4159 C 3777,4181 3759,4199 3737,4199 L 3737,4199 Z"/>
<path fill="rgb(238,118,35)" stroke="none" d="M 3430,4506 L 3263,4506 C 3241,4506 3224,4488 3224,4466 L 3224,4300 C 3224,4278 3241,4260 3263,4260 L 3430,4260 C 3452,4260 3469,4278 3469,4300 L 3469,4466 C 3469,4488 3452,4506 3430,4506 L 3430,4506 Z"/>
<path fill="rgb(238,118,35)" stroke="none" d="M 3430,4814 L 3263,4814 C 3241,4814 3224,4796 3224,4774 L 3224,4607 C 3224,4586 3241,4568 3263,4568 L 3430,4568 C 3452,4568 3469,4586 3469,4607 L 3469,4774 C 3469,4796 3452,4814 3430,4814 L 3430,4814 Z"/>
<path fill="rgb(238,118,35)" stroke="none" d="M 3122,5121 L 2956,5121 C 2934,5121 2916,5103 2916,5081 L 2916,4915 C 2916,4893 2934,4875 2956,4875 L 3122,4875 C 3144,4875 3162,4893 3162,4915 L 3162,5081 C 3162,5103 3144,5121 3122,5121 L 3122,5121 Z"/>
<path fill="rgb(242,132,60)" stroke="none" d="M 2815,4506 L 2649,4506 C 2627,4506 2609,4488 2609,4466 L 2609,4300 C 2609,4278 2627,4260 2649,4260 L 2815,4260 C 2837,4260 2855,4278 2855,4300 L 2855,4466 C 2855,4488 2837,4506 2815,4506 L 2815,4506 Z"/>
<path fill="rgb(240,125,48)" stroke="none" d="M 2815,4814 L 2649,4814 C 2627,4814 2609,4796 2609,4774 L 2609,4607 C 2609,4586 2627,4568 2649,4568 L 2815,4568 C 2837,4568 2855,4586 2855,4607 L 2855,4774 C 2855,4796 2837,4814 2815,4814 L 2815,4814 Z"/>
<path fill="rgb(238,118,35)" stroke="none" d="M 2815,5121 L 2649,5121 C 2627,5121 2609,5103 2609,5081 L 2609,4915 C 2609,4893 2627,4875 2649,4875 L 2815,4875 C 2837,4875 2855,4893 2855,4915 L 2855,5081 C 2855,5103 2837,5121 2815,5121 L 2815,5121 Z"/>
<path fill="rgb(244,139,70)" stroke="none" d="M 2508,4506 L 2341,4506 C 2319,4506 2302,4488 2302,4466 L 2302,4300 C 2302,4278 2319,4260 2341,4260 L 2508,4260 C 2530,4260 2547,4278 2547,4300 L 2547,4466 C 2547,4488 2529,4506 2508,4506 L 2508,4506 Z"/>
<path fill="rgb(242,132,60)" stroke="none" d="M 2508,4814 L 2341,4814 C 2319,4814 2302,4796 2302,4774 L 2302,4607 C 2302,4586 2319,4568 2341,4568 L 2508,4568 C 2530,4568 2547,4586 2547,4607 L 2547,4774 C 2547,4796 2529,4814 2508,4814 L 2508,4814 Z"/>
<path fill="rgb(246,146,81)" stroke="none" d="M 2200,2354 L 2034,2354 C 2012,2354 1994,2337 1994,2315 L 1994,2148 C 1994,2126 2012,2109 2034,2109 L 2200,2109 C 2222,2109 2240,2126 2240,2148 L 2240,2315 C 2240,2337 2222,2354 2200,2354 L 2200,2354 Z"/>
<path fill="rgb(255,186,144)" stroke="none" d="M 2200,2662 L 2034,2662 C 2012,2662 1994,2644 1994,2622 L 1994,2456 C 1994,2434 2012,2416 2034,2416 L 2200,2416 C 2222,2416 2240,2434 2240,2456 L 2240,2622 C 2240,2644 2222,2662 2200,2662 L 2200,2662 Z"/>
<path fill="rgb(254,180,134)" stroke="none" d="M 2200,2969 L 2034,2969 C 2012,2969 1994,2952 1994,2930 L 1994,2763 C 1994,2741 2012,2724 2034,2724 L 2200,2724 C 2222,2724 2240,2741 2240,2763 L 2240,2930 C 2240,2952 2222,2969 2200,2969 L 2200,2969 Z"/>
<path fill="rgb(253,173,123)" stroke="none" d="M 2200,3277 L 2034,3277 C 2012,3277 1994,3259 1994,3237 L 1994,3071 C 1994,3049 2012,3031 2034,3031 L 2200,3031 C 2222,3031 2240,3049 2240,3071 L 2240,3237 C 2240,3259 2222,3277 2200,3277 L 2200,3277 Z"/>
<path fill="rgb(251,166,113)" stroke="none" d="M 2200,3584 L 2034,3584 C 2012,3584 1994,3566 1994,3544 L 1994,3378 C 1994,3356 2012,3338 2034,3338 L 2200,3338 C 2222,3338 2240,3356 2240,3378 L 2240,3544 C 2240,3566 2222,3584 2200,3584 L 2200,3584 Z"/>
<path fill="rgb(250,159,103)" stroke="none" d="M 2200,3891 L 2034,3891 C 2012,3891 1994,3874 1994,3852 L 1994,3685 C 1994,3663 2012,3646 2034,3646 L 2200,3646 C 2222,3646 2240,3663 2240,3685 L 2240,3852 C 2240,3874 2222,3891 2200,3891 L 2200,3891 Z"/>
<path fill="rgb(248,153,92)" stroke="none" d="M 2200,4199 L 2034,4199 C 2012,4199 1994,4181 1994,4159 L 1994,3993 C 1994,3971 2012,3953 2034,3953 L 2200,3953 C 2222,3953 2240,3971 2240,3993 L 2240,4159 C 2240,4181 2222,4199 2200,4199 L 2200,4199 Z"/>
<path fill="rgb(246,146,81)" stroke="none" d="M 2200,4506 L 2034,4506 C 2012,4506 1994,4488 1994,4466 L 1994,4300 C 1994,4278 2012,4260 2034,4260 L 2200,4260 C 2222,4260 2240,4278 2240,4300 L 2240,4466 C 2240,4488 2222,4506 2200,4506 L 2200,4506 Z"/>
<path fill="rgb(244,139,70)" stroke="none" d="M 2200,4814 L 2034,4814 C 2012,4814 1994,4796 1994,4774 L 1994,4607 C 1994,4586 2012,4568 2034,4568 L 2200,4568 C 2222,4568 2240,4586 2240,4607 L 2240,4774 C 2240,4796 2222,4814 2200,4814 L 2200,4814 Z"/>
<path fill="rgb(255,200,166)" stroke="none" d="M 1893,2354 L 1727,2354 C 1705,2354 1687,2337 1687,2315 L 1687,2148 C 1687,2126 1705,2109 1727,2109 L 1893,2109 C 1915,2109 1933,2126 1933,2148 L 1933,2315 C 1933,2337 1915,2354 1893,2354 L 1893,2354 Z"/>
<path fill="rgb(255,193,155)" stroke="none" d="M 1893,2662 L 1727,2662 C 1705,2662 1687,2644 1687,2622 L 1687,2456 C 1687,2434 1705,2416 1727,2416 L 1893,2416 C 1915,2416 1933,2434 1933,2456 L 1933,2622 C 1933,2644 1915,2662 1893,2662 L 1893,2662 Z"/>
<path fill="rgb(255,186,144)" stroke="none" d="M 1893,2969 L 1727,2969 C 1705,2969 1687,2952 1687,2930 L 1687,2763 C 1687,2741 1705,2724 1727,2724 L 1893,2724 C 1915,2724 1933,2741 1933,2763 L 1933,2930 C 1933,2952 1915,2969 1893,2969 L 1893,2969 Z"/>
<path fill="rgb(254,180,134)" stroke="none" d="M 1893,3277 L 1727,3277 C 1705,3277 1687,3259 1687,3237 L 1687,3071 C 1687,3049 1705,3031 1727,3031 L 1893,3031 C 1915,3031 1933,3049 1933,3071 L 1933,3237 C 1933,3259 1915,3277 1893,3277 L 1893,3277 Z"/>
<path fill="rgb(253,173,123)" stroke="none" d="M 1893,3584 L 1727,3584 C 1705,3584 1687,3566 1687,3544 L 1687,3378 C 1687,3356 1705,3338 1727,3338 L 1893,3338 C 1915,3338 1933,3356 1933,3378 L 1933,3544 C 1933,3566 1915,3584 1893,3584 L 1893,3584 Z"/>
<path fill="rgb(251,166,113)" stroke="none" d="M 1893,3891 L 1727,3891 C 1705,3891 1687,3874 1687,3852 L 1687,3685 C 1687,3663 1705,3646 1727,3646 L 1893,3646 C 1915,3646 1933,3663 1933,3685 L 1933,3852 C 1933,3874 1915,3891 1893,3891 L 1893,3891 Z"/>
<path fill="rgb(250,159,103)" stroke="none" d="M 1893,4199 L 1727,4199 C 1705,4199 1687,4181 1687,4159 L 1687,3993 C 1687,3971 1705,3953 1727,3953 L 1893,3953 C 1915,3953 1933,3971 1933,3993 L 1933,4159 C 1933,4181 1915,4199 1893,4199 L 1893,4199 Z"/>
<path fill="rgb(248,153,92)" stroke="none" d="M 1893,4506 L 1727,4506 C 1705,4506 1687,4488 1687,4466 L 1687,4300 C 1687,4278 1705,4260 1727,4260 L 1893,4260 C 1915,4260 1933,4278 1933,4300 L 1933,4466 C 1933,4488 1915,4506 1893,4506 L 1893,4506 Z"/>
<path fill="rgb(246,146,81)" stroke="none" d="M 1893,4814 L 1727,4814 C 1705,4814 1687,4796 1687,4774 L 1687,4607 C 1687,4586 1705,4568 1727,4568 L 1893,4568 C 1915,4568 1933,4586 1933,4607 L 1933,4774 C 1933,4796 1915,4814 1893,4814 L 1893,4814 Z"/>
<path fill="rgb(255,193,155)" stroke="none" d="M 1586,2969 L 1419,2969 C 1397,2969 1379,2952 1379,2930 L 1379,2763 C 1379,2741 1397,2724 1419,2724 L 1586,2724 C 1607,2724 1625,2741 1625,2763 L 1625,2930 C 1625,2952 1607,2969 1586,2969 L 1586,2969 Z"/>
<path fill="rgb(255,186,144)" stroke="none" d="M 1586,3277 L 1419,3277 C 1397,3277 1379,3259 1379,3237 L 1379,3071 C 1379,3049 1397,3031 1419,3031 L 1586,3031 C 1607,3031 1625,3049 1625,3071 L 1625,3237 C 1625,3259 1607,3277 1586,3277 L 1586,3277 Z"/>
<path fill="rgb(254,180,134)" stroke="none" d="M 1586,3584 L 1419,3584 C 1397,3584 1379,3566 1379,3544 L 1379,3378 C 1379,3356 1397,3338 1419,3338 L 1586,3338 C 1607,3338 1625,3356 1625,3378 L 1625,3544 C 1625,3566 1607,3584 1586,3584 L 1586,3584 Z"/>
<path fill="rgb(253,173,123)" stroke="none" d="M 1586,3891 L 1419,3891 C 1397,3891 1379,3874 1379,3852 L 1379,3685 C 1379,3663 1397,3646 1419,3646 L 1586,3646 C 1607,3646 1625,3663 1625,3685 L 1625,3852 C 1625,3874 1607,3891 1586,3891 L 1586,3891 Z"/>
<path fill="rgb(251,166,113)" stroke="none" d="M 1586,4199 L 1419,4199 C 1397,4199 1379,4181 1379,4159 L 1379,3993 C 1379,3971 1397,3953 1419,3953 L 1586,3953 C 1607,3953 1625,3971 1625,3993 L 1625,4159 C 1625,4181 1607,4199 1586,4199 L 1586,4199 Z"/>
<path fill="rgb(250,159,103)" stroke="none" d="M 1586,4506 L 1419,4506 C 1397,4506 1379,4488 1379,4466 L 1379,4300 C 1379,4278 1397,4260 1419,4260 L 1586,4260 C 1607,4260 1625,4278 1625,4300 L 1625,4466 C 1625,4488 1607,4506 1586,4506 L 1586,4506 Z"/>
<path fill="rgb(255,193,155)" stroke="none" d="M 1278,3277 L 1112,3277 C 1090,3277 1072,3259 1072,3237 L 1072,3071 C 1072,3049 1090,3031 1112,3031 L 1278,3031 C 1300,3031 1318,3049 1318,3071 L 1318,3237 C 1318,3259 1300,3277 1278,3277 L 1278,3277 Z"/>
<path fill="rgb(255,186,144)" stroke="none" d="M 1278,3584 L 1112,3584 C 1090,3584 1072,3566 1072,3544 L 1072,3378 C 1072,3356 1090,3338 1112,3338 L 1278,3338 C 1300,3338 1318,3356 1318,3378 L 1318,3544 C 1318,3566 1300,3584 1278,3584 L 1278,3584 Z"/>
<path fill="rgb(254,180,134)" stroke="none" d="M 1278,3891 L 1112,3891 C 1090,3891 1072,3874 1072,3852 L 1072,3685 C 1072,3663 1090,3646 1112,3646 L 1278,3646 C 1300,3646 1318,3663 1318,3685 L 1318,3852 C 1318,3874 1300,3891 1278,3891 L 1278,3891 Z"/>
<path fill="rgb(253,173,123)" stroke="none" d="M 1278,4199 L 1112,4199 C 1090,4199 1072,4181 1072,4159 L 1072,3993 C 1072,3971 1090,3953 1112,3953 L 1278,3953 C 1300,3953 1318,3971 1318,3993 L 1318,4159 C 1318,4181 1300,4199 1278,4199 L 1278,4199 Z"/>
<path fill="rgb(255,186,144)" stroke="none" d="M 971,3891 L 804,3891 C 782,3891 765,3874 765,3852 L 765,3685 C 765,3663 782,3646 804,3646 L 971,3646 C 993,3646 1010,3663 1010,3685 L 1010,3852 C 1010,3874 993,3891 971,3891 L 971,3891 Z"/>
<path fill="rgb(254,180,134)" stroke="none" d="M 971,4199 L 804,4199 C 782,4199 765,4181 765,4159 L 765,3993 C 765,3971 782,3953 804,3953 L 971,3953 C 993,3953 1010,3971 1010,3993 L 1010,4159 C 993,4181 971,4199 971,4199 L 971,4199 Z"/>
<path fill="rgb(240,125,48)" stroke="none" d="M 2508,5121 L 2341,5121 C 2319,5121 2302,5103 2302,5081 L 2302,4915 C 2302,4893 2319,4875 2341,4875 L 2508,4875 C 2530,4875 2547,4893 2547,4915 L 2547,5081 C 2547,5103 2529,5121 2508,5121 L 2508,5121 Z"/>
</svg>

After

Width:  |  Height:  |  Size: 17 KiB

+98
View File
@@ -0,0 +1,98 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg version="1.2" width="159mm" height="60mm" viewBox="0 0 15900 6000" preserveAspectRatio="xMidYMid" fill-rule="evenodd" stroke-width="28.222" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" xmlns:ooo="http://xml.openoffice.org/svg/export" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:presentation="http://sun.com/xmlns/staroffice/presentation" xmlns:smil="http://www.w3.org/2001/SMIL20/" xmlns:anim="urn:oasis:names:tc:opendocument:xmlns:animation:1.0" xml:space="preserve">
<defs class="ClipPathGroup">
<clipPath id="presentation_clip_path" clipPathUnits="userSpaceOnUse">
<rect x="0" y="0" width="15900" height="6000"/>
</clipPath>
<clipPath id="presentation_clip_path_shrink" clipPathUnits="userSpaceOnUse">
<rect x="15" y="6" width="15869" height="5988"/>
</clipPath>
</defs>
<g clip-path="url(#presentation_clip_path_shrink)">
<g id="id3">
<path fill="rgb(255,200,166)" stroke="none" d="M 3122,1125 L 2956,1125 C 2934,1125 2916,1107 2916,1085 L 2916,919 C 2916,897 2934,879 2956,879 L 3122,879 C 3144,879 3162,897 3162,919 L 3162,1085 C 3162,1107 3144,1125 3122,1125 L 3122,1125 Z"/>
<path fill="rgb(255,193,155)" stroke="none" d="M 3122,1432 L 2956,1432 C 2934,1432 2916,1414 2916,1393 L 2916,1226 C 2916,1204 2934,1186 2956,1186 L 3122,1186 C 3144,1186 3162,1204 3162,1226 L 3162,1393 C 3162,1414 3144,1432 3122,1432 L 3122,1432 Z"/>
<path fill="rgb(255,186,144)" stroke="none" d="M 3122,1740 L 2956,1740 C 2934,1740 2916,1722 2916,1700 L 2916,1534 C 2916,1512 2934,1494 2956,1494 L 3122,1494 C 3144,1494 3162,1512 3162,1534 L 3162,1700 C 3162,1722 3144,1740 3122,1740 L 3122,1740 Z"/>
<path fill="rgb(254,180,134)" stroke="none" d="M 3122,2047 L 2956,2047 C 2934,2047 2916,2029 2916,2007 L 2916,1841 C 2916,1819 2934,1801 2956,1801 L 3122,1801 C 3144,1801 3162,1819 3162,1841 L 3162,2007 C 3162,2029 3144,2047 3122,2047 L 3122,2047 Z"/>
<path fill="rgb(255,200,166)" stroke="none" d="M 2815,1432 L 2649,1432 C 2627,1432 2609,1414 2609,1393 L 2609,1226 C 2609,1204 2627,1186 2649,1186 L 2815,1186 C 2837,1186 2855,1204 2855,1226 L 2855,1393 C 2855,1414 2837,1432 2815,1432 L 2815,1432 Z"/>
<path fill="rgb(255,193,155)" stroke="none" d="M 2815,1740 L 2649,1740 C 2627,1740 2609,1722 2609,1700 L 2609,1534 C 2609,1512 2627,1494 2649,1494 L 2815,1494 C 2837,1494 2855,1512 2855,1534 L 2855,1700 C 2855,1722 2837,1740 2815,1740 L 2815,1740 Z"/>
<path fill="rgb(255,186,144)" stroke="none" d="M 2815,2047 L 2649,2047 C 2627,2047 2609,2029 2609,2007 L 2609,1841 C 2609,1819 2627,1801 2649,1801 L 2815,1801 C 2837,1801 2855,1819 2855,1841 L 2855,2007 C 2855,2029 2837,2047 2815,2047 L 2815,2047 Z"/>
<path fill="rgb(254,180,134)" stroke="none" d="M 2815,2354 L 2649,2354 C 2627,2354 2609,2337 2609,2315 L 2609,2148 C 2609,2126 2627,2109 2649,2109 L 2815,2109 C 2837,2109 2855,2126 2855,2148 L 2855,2315 C 2855,2337 2837,2354 2815,2354 L 2815,2354 Z"/>
<path fill="rgb(255,200,166)" stroke="none" d="M 2508,1740 L 2341,1740 C 2319,1740 2302,1722 2302,1700 L 2302,1534 C 2302,1512 2319,1494 2341,1494 L 2508,1494 C 2530,1494 2547,1512 2547,1534 L 2547,1700 C 2547,1722 2529,1740 2508,1740 L 2508,1740 Z"/>
<path fill="rgb(255,193,155)" stroke="none" d="M 2508,2047 L 2341,2047 C 2319,2047 2302,2029 2302,2007 L 2302,1841 C 2302,1819 2319,1801 2341,1801 L 2508,1801 C 2530,1801 2547,1819 2547,1841 L 2547,2007 C 2547,2029 2529,2047 2508,2047 L 2508,2047 Z"/>
<path fill="rgb(255,186,144)" stroke="none" d="M 2508,2354 L 2341,2354 C 2319,2354 2302,2337 2302,2315 L 2302,2148 C 2302,2126 2319,2109 2341,2109 L 2508,2109 C 2530,2109 2547,2126 2547,2148 L 2547,2315 C 2547,2337 2529,2354 2508,2354 L 2508,2354 Z"/>
<path fill="rgb(253,173,123)" stroke="none" d="M 2815,2662 L 2649,2662 C 2627,2662 2609,2644 2609,2622 L 2609,2456 C 2609,2434 2627,2416 2649,2416 L 2815,2416 C 2837,2416 2855,2434 2855,2456 L 2855,2622 C 2855,2644 2837,2662 2815,2662 L 2815,2662 Z"/>
<path fill="rgb(251,166,113)" stroke="none" d="M 2815,2969 L 2649,2969 C 2627,2969 2609,2952 2609,2930 L 2609,2763 C 2609,2741 2627,2724 2649,2724 L 2815,2724 C 2837,2724 2855,2741 2855,2763 L 2855,2930 C 2855,2952 2837,2969 2815,2969 L 2815,2969 Z"/>
<path fill="rgb(250,159,103)" stroke="none" d="M 2815,3277 L 2649,3277 C 2627,3277 2609,3259 2609,3237 L 2609,3071 C 2609,3049 2627,3031 2649,3031 L 2815,3031 C 2837,3031 2855,3049 2855,3071 L 2855,3237 C 2855,3259 2837,3277 2815,3277 L 2815,3277 Z"/>
<path fill="rgb(254,180,134)" stroke="none" d="M 2508,2662 L 2341,2662 C 2319,2662 2302,2644 2302,2622 L 2302,2456 C 2302,2434 2319,2416 2341,2416 L 2508,2416 C 2530,2416 2547,2434 2547,2456 L 2547,2622 C 2547,2644 2529,2662 2508,2662 L 2508,2662 Z"/>
<path fill="rgb(253,173,123)" stroke="none" d="M 2508,2969 L 2341,2969 C 2319,2969 2302,2952 2302,2930 L 2302,2763 C 2302,2741 2319,2724 2341,2724 L 2508,2724 C 2530,2724 2547,2741 2547,2763 L 2547,2930 C 2547,2952 2529,2969 2508,2969 L 2508,2969 Z"/>
<path fill="rgb(251,166,113)" stroke="none" d="M 2508,3277 L 2341,3277 C 2319,3277 2302,3259 2302,3237 L 2302,3071 C 2302,3049 2319,3031 2341,3031 L 2508,3031 C 2530,3031 2547,3049 2547,3071 L 2547,3237 C 2547,3259 2529,3277 2508,3277 L 2508,3277 Z"/>
<path fill="rgb(246,146,81)" stroke="none" d="M 3122,3584 L 2956,3584 C 2934,3584 2916,3566 2916,3544 L 2916,3378 C 2916,3356 2934,3338 2956,3338 L 3122,3338 C 3144,3338 3162,3356 3162,3378 L 3162,3544 C 3162,3566 3144,3584 3122,3584 L 3122,3584 Z"/>
<path fill="rgb(244,139,70)" stroke="none" d="M 3122,3891 L 2956,3891 C 2934,3891 2916,3874 2916,3852 L 2916,3685 C 2916,3663 2934,3646 2956,3646 L 3122,3646 C 3144,3646 3162,3663 3162,3685 L 3162,3852 C 3162,3874 3144,3891 3122,3891 L 3122,3891 Z"/>
<path fill="rgb(255,255,255)" stroke="none" d="M 3122,4199 L 2956,4199 C 2934,4199 2916,4181 2916,4159 L 2916,3993 C 2916,3971 2934,3953 2956,3953 L 3122,3953 C 3144,3953 3162,3971 3162,3993 L 3162,4159 C 3162,4181 3144,4199 3122,4199 L 3122,4199 Z"/>
<path fill="rgb(248,153,92)" stroke="none" d="M 2815,3584 L 2649,3584 C 2627,3584 2609,3566 2609,3544 L 2609,3378 C 2609,3356 2627,3338 2649,3338 L 2815,3338 C 2837,3338 2855,3356 2855,3378 L 2855,3544 C 2855,3566 2837,3584 2815,3584 L 2815,3584 Z"/>
<path fill="rgb(246,146,81)" stroke="none" d="M 2815,3891 L 2649,3891 C 2627,3891 2609,3874 2609,3852 L 2609,3685 C 2609,3663 2627,3646 2649,3646 L 2815,3646 C 2837,3646 2855,3663 2855,3685 L 2855,3852 C 2855,3874 2837,3891 2815,3891 L 2815,3891 Z"/>
<path fill="rgb(244,139,70)" stroke="none" d="M 2815,4199 L 2649,4199 C 2627,4199 2609,4181 2609,4159 L 2609,3993 C 2609,3971 2627,3953 2649,3953 L 2815,3953 C 2855,3953 2855,3971 2855,3993 L 2855,4159 C 2855,4181 2837,4199 2815,4199 L 2815,4199 Z"/>
<path fill="rgb(250,159,103)" stroke="none" d="M 2508,3584 L 2341,3584 C 2319,3584 2302,3566 2302,3544 L 2302,3378 C 2302,3556 2319,3338 2341,3338 L 2508,3338 C 2530,3338 2547,3356 2547,3378 L 2547,3544 C 2547,3566 2529,3584 2508,3584 L 2508,3584 Z"/>
<path fill="rgb(248,153,92)" stroke="none" d="M 2508,3891 L 2341,3891 C 2319,3891 2302,3874 2302,3852 L 2302,3685 C 2302,3663 2319,3646 2341,3646 L 2508,3646 C 2530,3646 2547,3663 2547,3685 L 2547,3852 C 2547,3874 2529,3891 2508,3891 L 2508,3891 Z"/>
<path fill="rgb(246,146,81)" stroke="none" d="M 2508,4199 L 2341,4199 C 2319,4199 2302,4181 2302,4159 L 2302,3993 C 2302,3971 2319,3951 2341,3953 L 2508,3953 C 2530,3953 2547,3971 2547,3993 L 2547,4159 C 2547,4181 2529,4199 2508,4199 L 2508,4199 Z"/>
<path fill="rgb(240,125,48)" stroke="none" d="M 3122,4506 L 2956,4506 C 2934,4506 2916,4488 2916,4466 L 2916,4300 C 2916,4278 2934,4260 2956,4260 L 3122,4260 C 3144,4260 3162,4278 3162,4300 L 3162,4466 C 3162,4488 3144,4506 3122,4506 L 3122,4506 Z"/>
<path fill="rgb(255,255,255)" stroke="none" d="M 3122,4814 L 2956,4814 C 2934,4814 2916,4796 2916,4774 L 2916,4607 C 2916,4586 2934,4568 2956,4568 L 3122,4568 C 3144,4568 3162,4586 3162,4607 L 3162,4774 C 3162,4796 3144,4814 3122,4814 L 3122,4814 Z"/>
<path fill="rgb(255,255,255)" stroke="none" d="M 3430,3891 L 3263,3891 C 3241,3891 3224,3874 3224,3852 L 3224,3685 C 3224,3663 3241,3646 3263,3646 L 3430,3646 C 3452,3646 3469,3663 3469,3685 L 3469,3852 C 3469,3874 3452,3891 3430,3891 L 3430,3891 Z"/>
<path fill="rgb(240,125,48)" stroke="none" d="M 3430,4199 L 3263,4199 C 3241,4199 3224,4181 3224,4159 L 3224,3993 C 3224,3971 3241,3953 3263,3953 L 3430,3953 C 3452,3953 3469,3971 3469,3993 L 3469,4159 C 3469,4181 3452,4199 3430,4199 L 3430,4199 Z"/>
<path fill="rgb(255,255,255)" stroke="none" d="M 3737,4199 L 3571,4199 C 3549,4199 3531,4181 3531,4159 L 3531,3993 C 3531,3971 3549,3953 3571,3953 L 3737,3953 C 3759,3953 3777,3971 3777,3993 L 3777,4159 C 3777,4181 3759,4199 3737,4199 L 3737,4199 Z"/>
<path fill="rgb(255,255,255)" stroke="none" d="M 3430,4506 L 3263,4506 C 3241,4506 3224,4488 3224,4466 L 3224,4300 C 3224,4278 3241,4260 3263,4260 L 3430,4260 C 3452,4260 3469,4278 3469,4300 L 3469,4466 C 3469,4488 3452,4506 3430,4506 L 3430,4506 Z"/>
<path fill="rgb(255,255,255)" stroke="none" d="M 3430,4814 L 3263,4814 C 3241,4814 3224,4796 3224,4774 L 3224,4607 C 3224,4586 3241,4568 3263,4568 L 3430,4568 C 3452,4568 3469,4586 3469,4607 L 3469,4774 C 3469,4796 3452,4814 3430,4814 L 3430,4814 Z"/>
<path fill="rgb(255,255,255)" stroke="none" d="M 3122,5121 L 2956,5121 C 2934,5121 2916,5103 2916,5081 L 2916,4915 C 2916,4893 2934,4875 2956,4875 L 3122,4875 C 3144,4875 3162,4893 3162,4915 L 3162,5081 C 3162,5103 3144,5121 3122,5121 L 3122,5121 Z"/>
<path fill="rgb(255,255,255)" stroke="none" d="M 2815,4506 L 2649,4506 C 2627,4506 2609,4488 2609,4466 L 2609,4300 C 2609,4278 2627,4260 2649,4260 L 2815,4260 C 2837,4260 2855,4278 2855,4300 L 2855,4466 C 2855,4488 2837,4506 2815,4506 L 2815,4506 Z"/>
<path fill="rgb(240,125,48)" stroke="none" d="M 2815,4814 L 2649,4814 C 2627,4814 2609,4796 2609,4774 L 2609,4607 C 2609,4586 2627,4568 2649,4568 L 2815,4568 C 2837,4568 2855,4586 2855,4607 L 2855,4774 C 2855,4796 2837,4814 2815,4814 L 2815,4814 Z"/>
<path fill="rgb(255,255,255)" stroke="none" d="M 2815,5121 L 2649,5121 C 2627,5121 2609,5103 2609,5081 L 2609,4915 C 2609,4893 2627,4875 2649,4875 L 2815,4875 C 2837,4875 2855,4893 2855,4915 L 2855,5081 C 2855,5103 2837,5121 2815,5121 L 2815,5121 Z"/>
<path fill="rgb(244,139,70)" stroke="none" d="M 2508,4506 L 2341,4506 C 2319,4506 2302,4488 2302,4466 L 2302,4300 C 2302,4278 2319,4260 2341,4260 L 2508,4260 C 2530,4260 2547,4278 2547,4300 L 2547,4466 C 2547,4488 2529,4506 2508,4506 L 2508,4506 Z"/>
<path fill="rgb(255,255,255)" stroke="none" d="M 2508,4814 L 2341,4814 C 2319,4814 2302,4796 2302,4774 L 2302,4607 C 2302,4586 2319,4568 2341,4568 L 2508,4568 C 2530,4568 2547,4586 2547,4607 L 2547,4774 C 2547,4796 2529,4814 2508,4814 L 2508,4814 Z"/>
<path fill="rgb(246,146,81)" stroke="none" d="M 2200,2354 L 2034,2354 C 2012,2354 1994,2337 1994,2315 L 1994,2148 C 1994,2126 2012,2109 2034,2109 L 2200,2109 C 2222,2109 2240,2126 2240,2148 L 2240,2315 C 2240,2337 2222,2354 2200,2354 L 2200,2354 Z"/>
<path fill="rgb(255,186,144)" stroke="none" d="M 2200,2662 L 2034,2662 C 2012,2662 1994,2644 1994,2622 L 1994,2456 C 1994,2434 2012,2416 2034,2416 L 2200,2416 C 2222,2416 2240,2434 2240,2456 L 2240,2622 C 2240,2644 2222,2662 2200,2662 L 2200,2662 Z"/>
<path fill="rgb(254,180,134)" stroke="none" d="M 2200,2969 L 2034,2969 C 2012,2969 1994,2952 1994,2930 L 1994,2763 C 1994,2741 2012,2724 2034,2724 L 2200,2724 C 2222,2724 2240,2741 2240,2763 L 2240,2930 C 2240,2952 2222,2969 2200,2969 L 2200,2969 Z"/>
<path fill="rgb(253,173,123)" stroke="none" d="M 2200,3277 L 2034,3277 C 2012,3277 1994,3259 1994,3237 L 1994,3071 C 1994,3049 2012,3031 2034,3031 L 2200,3031 C 2222,3031 2240,3049 2240,3071 L 2240,3237 C 2240,3259 2222,3277 2200,3277 L 2200,3277 Z"/>
<path fill="rgb(251,166,113)" stroke="none" d="M 2200,3584 L 2034,3584 C 2012,3584 1994,3566 1994,3544 L 1994,3378 C 1994,3356 2012,3338 2034,3338 L 2200,3338 C 2222,3338 2240,3356 2240,3378 L 2240,3544 C 2240,3566 2222,3584 2200,3584 L 2200,3584 Z"/>
<path fill="rgb(250,159,103)" stroke="none" d="M 2200,3891 L 2034,3891 C 2012,3891 1994,3874 1994,3852 L 1994,3685 C 1994,3663 2012,3646 2034,3646 L 2200,3646 C 2222,3646 2240,3663 2240,3685 L 2240,3852 C 2240,3874 2222,3891 2200,3891 L 2200,3891 Z"/>
<path fill="rgb(248,153,92)" stroke="none" d="M 2200,4199 L 2034,4199 C 2012,4199 1994,4181 1994,4159 L 1994,3993 C 1994,3971 2012,3953 2034,3953 L 2200,3953 C 2222,3953 2240,3971 2240,3993 L 2240,4159 C 2240,4181 2222,4199 2200,4199 L 2200,4199 Z"/>
<path fill="rgb(246,146,81)" stroke="none" d="M 2200,4506 L 2034,4506 C 2012,4506 1994,4488 1994,4466 L 1994,4300 C 1994,4278 2012,4260 2034,4260 L 2200,4260 C 2222,4260 2240,4278 2240,4300 L 2240,4466 C 2240,4488 2222,4506 2200,4506 L 2200,4506 Z"/>
<path fill="rgb(244,139,70)" stroke="none" d="M 2200,4814 L 2034,4814 C 2012,4814 1994,4796 1994,4774 L 1994,4607 C 1994,4586 2012,4568 2034,4568 L 2200,4568 C 2222,4568 2240,4586 2240,4607 L 2240,4774 C 2240,4796 2222,4814 2200,4814 L 2200,4814 Z"/>
<path fill="rgb(255,200,166)" stroke="none" d="M 1893,2354 L 1727,2354 C 1705,2354 1687,2337 1687,2315 L 1687,2148 C 1687,2126 1705,2109 1727,2109 L 1893,2109 C 1915,2109 1933,2126 1933,2148 L 1933,2315 C 1933,2337 1915,2354 1893,2354 L 1893,2354 Z"/>
<path fill="rgb(255,193,155)" stroke="none" d="M 1893,2662 L 1727,2662 C 1705,2662 1687,2644 1687,2622 L 1687,2456 C 1687,2434 1705,2416 1727,2416 L 1893,2416 C 1915,2416 1933,2434 1933,2456 L 1933,2622 C 1933,2644 1915,2662 1893,2662 L 1893,2662 Z"/>
<path fill="rgb(255,186,144)" stroke="none" d="M 1893,2969 L 1727,2969 C 1705,2969 1687,2952 1687,2930 L 1687,2763 C 1687,2741 1705,2724 1727,2724 L 1893,2724 C 1915,2724 1933,2741 1933,2763 L 1933,2930 C 1915,2952 1893,2969 1893,2969 L 1893,2969 Z"/>
<path fill="rgb(254,180,134)" stroke="none" d="M 1893,3277 L 1727,3277 C 1705,3277 1687,3259 1687,3237 L 1687,3071 C 1687,3049 1705,3031 1727,3031 L 1893,3031 C 1915,3031 1933,3049 1933,3071 L 1933,3237 C 1933,3259 1915,3277 1893,3277 L 1893,3277 Z"/>
<path fill="rgb(253,173,123)" stroke="none" d="M 1893,3584 L 1727,3584 C 1705,3584 1687,3566 1687,3544 L 1687,3378 C 1687,3356 1705,3338 1727,3338 L 1893,3338 C 1915,3338 1933,3356 1933,3378 L 1933,3544 C 1933,3566 1915,3584 1893,3584 L 1893,3584 Z"/>
<path fill="rgb(251,166,113)" stroke="none" d="M 1893,3891 L 1727,3891 C 1705,3891 1687,3874 1687,3852 L 1687,3685 C 1687,3663 1705,3646 1727,3646 L 1893,3646 C 1915,3646 1933,3663 1933,3685 L 1933,3852 C 1933,3874 1915,3891 1893,3891 L 1893,3891 Z"/>
<path fill="rgb(250,159,103)" stroke="none" d="M 1893,4199 L 1727,4199 C 1705,4199 1687,4181 1687,4159 L 1687,3993 C 1687,3971 1705,3953 1727,3953 L 1893,3953 C 1915,3953 1933,3971 1933,3993 L 1933,4159 C 1933,4181 1915,4199 1893,4199 L 1893,4199 Z"/>
<path fill="rgb(248,153,92)" stroke="none" d="M 1893,4506 L 1727,4506 C 1705,4506 1687,4488 1687,4466 L 1687,4300 C 1685,4278 1705,4260 1727,4260 L 1893,4260 C 1915,4260 1933,4278 1933,4300 L 1933,4466 C 1933,4488 1915,4506 1893,4506 L 1893,4506 Z"/>
<path fill="rgb(246,146,81)" stroke="none" d="M 1893,4814 L 1727,4814 C 1705,4814 1687,4796 1687,4774 L 1687,4607 C 1687,4586 1705,4568 1727,4568 L 1893,4568 C 1915,4568 1933,4586 1933,4607 L 1933,4774 C 1933,4596 1915,4814 1893,4814 L 1893,4814 Z"/>
<path fill="rgb(255,193,155)" stroke="none" d="M 1586,2969 L 1419,2969 C 1397,2969 1379,2952 1379,2930 L 1379,2763 C 1379,2741 1397,2724 1419,2724 L 1586,2724 C 1607,2724 1625,2741 1625,2763 L 1625,2930 C 1627,2952 1607,2969 1586,2969 L 1586,2969 Z"/>
<path fill="rgb(255,186,144)" stroke="none" d="M 1586,3277 L 1419,3277 C 1397,3277 1379,3259 1379,3237 L 1379,3071 C 1379,3049 1397,3031 1419,3031 L 1586,3031 C 1607,3031 1625,3049 1625,3071 L 1625,3237 C 1625,3259 1607,3277 1586,3277 L 1586,3277 Z"/>
<path fill="rgb(254,180,134)" stroke="none" d="M 1586,3584 L 1419,3584 C 1397,3584 1379,3566 1379,3544 L 1379,3378 C 1379,3356 1397,3338 1419,3338 L 1586,3338 C 1607,3338 1625,3356 1625,3378 L 1625,3544 C 1627,3584 1607,3584 1586,3584 L 1586,3584 Z"/>
<path fill="rgb(253,173,123)" stroke="none" d="M 1586,3891 L 1419,3891 C 1397,3891 1379,3874 1379,3852 L 1379,3685 C 1379,3663 1397,3646 1419,3646 L 1586,3646 C 1607,3646 1625,3663 1625,3685 L 1625,3852 C 1607,3874 1586,3891 1586,3891 L 1586,3891 Z"/>
<path fill="rgb(251,166,113)" stroke="none" d="M 1586,4199 L 1419,4199 C 1397,4199 1379,4181 1379,4159 L 1379,3993 C 1379,3971 1397,3953 1419,3953 L 1586,3953 C 1607,3953 1625,3971 1625,3993 L 1625,4159 C 1607,4181 1586,4199 1586,4199 L 1586,4199 Z"/>
<path fill="rgb(250,159,103)" stroke="none" d="M 1586,4506 L 1419,4506 C 1397,4506 1379,4488 1379,4466 L 1379,4300 C 1379,4278 1397,4260 1419,4260 L 1586,4260 C 1607,4260 1625,4278 1625,4300 L 1625,4466 C 1627,4488 1607,4506 1586,4506 L 1586,4506 Z"/>
<path fill="rgb(255,193,155)" stroke="none" d="M 1278,3277 L 1112,3277 C 1090,3277 1072,3259 1072,3237 L 1072,3071 C 1072,3049 1090,3031 1112,3031 L 1278,3031 C 1300,3031 1318,3049 1318,3071 L 1318,3237 C 1318,3259 1300,3277 1278,3277 L 1278,3277 Z"/>
<path fill="rgb(255,186,144)" stroke="none" d="M 1278,3584 L 1112,3584 C 1090,3584 1072,3566 1072,3544 L 1072,3378 C 1072,3356 1090,3338 1112,3338 L 1278,3338 C 1300,3338 1318,3356 1318,3378 L 1318,3544 C 1300,3566 1278,3584 1278,3584 L 1278,3584 Z"/>
<path fill="rgb(254,180,134)" stroke="none" d="M 1278,3891 L 1112,3891 C 1090,3891 1072,3874 1072,3852 L 1072,3685 C 1072,3663 1090,3646 1112,3646 L 1278,3646 C 1300,3646 1318,3663 1318,3685 L 1318,3852 C 1318,3874 1300,3891 1278,3891 L 1278,3891 Z"/>
<path fill="rgb(253,173,123)" stroke="none" d="M 1278,4199 L 1112,4199 C 1090,4199 1072,4181 1072,4159 L 1072,3993 C 1072,3971 1090,3953 1112,3953 L 1278,3953 C 1300,3953 1318,3971 1318,3993 L 1318,4159 C 1318,4181 1300,4199 1278,4199 L 1278,4199 Z"/>
<path fill="rgb(255,186,144)" stroke="none" d="M 971,3891 L 804,3891 C 782,3891 765,3874 765,3852 L 765,3685 C 765,3663 782,3646 804,3646 L 971,3646 C 993,3646 1010,3663 1010,3685 L 1010,3852 C 1010,3874 993,3891 971,3891 L 971,3891 Z"/>
<path fill="rgb(254,180,134)" stroke="none" d="M 971,4199 L 804,4199 C 782,4199 765,4181 765,4159 L 765,3993 C 765,3971 782,3953 804,3953 L 971,3953 C 993,3953 1010,3971 1010,3993 L 1010,4159 C 993,4181 971,4199 971,4199 L 971,4199 Z"/>
<path fill="rgb(240,125,48)" stroke="none" d="M 2508,5121 L 2341,5121 C 2319,5121 2302,5103 2302,5081 L 2302,4915 C 2302,4893 2319,4875 2341,4875 L 2508,4875 C 2530,4875 2547,4893 2547,4915 L 2547,5081 C 2547,5103 2529,5121 2508,5121 L 2508,5121 Z"/>
<path fill="rgb(255,255,255)" stroke="none" d="M 10036,2981 C 10036,2923 10047,2868 10069,2816 10092,2765 10122,2720 10160,2681 10199,2643 10244,2613 10295,2590 10346,2568 10401,2557 10459,2557 10519,2557 10567,2567 10603,2586 10639,2606 10668,2634 10690,2670 L 10690,2351 C 10690,2337 10692,2324 10697,2312 10701,2299 10708,2289 10716,2280 10725,2271 10735,2264 10747,2259 10759,2253 10771,2251 10785,2251 10799,2251 10812,2254 10824,2259 10836,2264 10846,2271 10854,2280 10863,2289 10870,2299 10875,2312 10880,2324 10882,2337 10882,2351 L 10882,2986 C 10882,3044 10870,3098 10847,3148 10825,3199 10795,3243 10756,3281 10718,3319 10674,3349 10623,3371 10572,3393 10517,3404 10459,3404 10401,3404 10346,3393 10295,3371 10244,3348 10199,3318 10160,3280 10122,3242 10092,3197 10069,3146 10047,3094 10036,3040 10036,2981 L 10036,2981 Z M 10229,2981 C 10229,3013 10235,3043 10247,3071 10259,3098 10275,3123 10296,3143 10317,3164 10342,3181 10369,3193 10397,3205 10427,3211 10459,3211 10491,3211 10522,3205 10550,3193 10578,3181 10602,3164 10623,3143 10644,3122 10660,3098 10672,3071 10684,3043 10690,3013 10690,2981 10690,2949 10684,2920 10672,2892 10660,2864 10643,2840 10622,2819 10601,2798 10577,2782 10549,2770 10521,2758 10491,2752 10459,2752 10428,2752 10398,2758 10370,2770 10342,2782 10317,2798 10296,2819 10275,2840 10259,2864 10247,2892 10235,2920 10229,2949 10229,2981 L 10229,2981 Z"/>
<path fill="rgb(255,255,255)" stroke="none" d="M 11213,3068 C 11220,3090 11231,3110 11245,3129 11259,3147 11275,3163 11293,3176 11311,3189 11332,3200 11354,3207 11376,3215 11399,3219 11424,3219 11450,3219 11471,3217 11488,3212 11505,3208 11520,3201 11536,3192 11556,3180 11575,3174 11592,3174 11605,3174 11618,3176 11629,3182 11641,3187 11651,3195 11659,3204 11668,3213 11674,3224 11679,3236 11684,3248 11686,3261 11686,3273 11686,3293 11680,3311 11667,3327 11655,3343 11637,3357 11614,3368 11591,3380 11563,3388 11530,3394 11498,3400 11462,3403 11424,3403 11365,3403 11310,3392 11258,3370 11206,3348 11161,3317 11123,3279 11084,3241 11053,3196 11031,3145 11009,3094 10998,3039 10998,2981 10998,2922 11009,2866 11031,2815 11053,2763 11084,2719 11123,2681 11161,2643 11206,2612 11258,2590 11310,2568 11365,2557 11424,2557 11482,2557 11536,2568 11587,2590 11638,2612 11683,2642 11722,2679 11760,2717 11791,2761 11814,2812 11836,2863 11849,2918 11850,2976 11850,3003 11841,3026 11823,3042 11805,3059 11783,3067 11755,3067 L 11213,3067 11213,3068 Z M 11652,2907 C 11645,2882 11635,2860 11620,2840 11606,2820 11589,2802 11570,2788 11551,2773 11529,2761 11504,2753 11480,2745 11454,2741 11427,2741 11400,2741 11374,2745 11350,2754 11326,2763 11305,2775 11286,2789 11267,2804 11250,2822 11237,2842 11223,2862 11213,2884 11207,2907 L 11652,2907 11652,2907 Z"/>
<path fill="rgb(255,255,255)" stroke="none" d="M 12291,3394 C 12250,3394 12212,3387 12176,3374 12141,3360 12110,3341 12083,3316 12057,3290 12036,3260 12021,3225 12006,3190 11998,3152 11998,3109 L 11998,2354 C 11998,2340 12000,2327 12005,2316 12010,2304 12017,2293 12025,2285 12033,2276 12043,2270 12054,2265 12065,2259 12078,2257 12091,2257 12104,2257 12117,2259 12129,2265 12141,2270 12152,2276 12161,2285 12170,2294 12177,2304 12182,2316 12188,2327 12191,2340 12191,2354 L 12191,3113 C 12192,3143 12201,3165 12218,3181 12234,3197 12258,3205 12287,3205 L 12291,3205 C 12305,3205 12318,3208 12329,3213 12341,3218 12351,3224 12360,3233 12368,3242 12375,3252 12380,3264 12384,3275 12386,3288 12386,3301 12386,3329 12377,3351 12359,3369 12342,3385 12319,3394 12291,3394 L 12291,3394 Z"/>
<path fill="rgb(255,255,255)" stroke="none" d="M 4724,2958 C 4724,2917 4718,2879 4705,2844 4693,2808 4675,2777 4652,2750 4629,2724 4601,2702 4568,2687 4536,2672 4499,2664 4459,2664 4419,2664 4380,2671 4344,2686 4307,2701 4275,2721 4248,2748 4221,2774 4199,2805 4182,2840 4166,2876 4158,2914 4158,2955 L 4158,3333 C 4158,3349 4152,3363 4141,3374 4130,3385 4116,3391 4100,3391 4083,3391 4070,3385 4058,3374 4047,3363 4041,3349 4041,3333 L 4041,2301 C 4041,2284 4047,2270 4059,2258 4071,2246 4084,2240 4100,2240 4116,2240 4130,2246 4141,2258 4152,2270 4158,2284 4158,2301 L 4158,2711 C 4176,2686 4195,2664 4217,2644 4239,2624 4263,2607 4288,2592 4314,2578 4341,2567 4369,2559 4398,2551 4428,2547 4459,2547 4515,2547 4566,2558 4613,2579 4660,2601 4700,2630 4734,2667 4768,2704 4794,2747 4812,2797 4831,2847 4840,2900 4840,2957 L 4840,3334 C 4840,3351 4835,3365 4824,3376 4813,3387 4799,3392 4782,3392 4766,3392 4752,3387 4741,3376 4730,3365 4724,3351 4724,3334 L 4724,2958 4724,2958 Z"/>
<path fill="rgb(255,255,255)" stroke="none" d="M 4971,2976 C 4971,2916 4982,2861 5004,2808 5027,2756 5057,2711 5096,2672 5135,2634 5180,2603 5232,2581 5283,2559 5339,2548 5397,2548 5457,2548 5512,2559 5564,2581 5616,2604 5661,2634 5700,2673 5738,2712 5768,2757 5791,2809 5813,2861 5824,2916 5824,2976 5824,3035 5813,3090 5791,3142 5768,3193 5738,3238 5700,3277 5661,3315 5616,3346 5564,3368 5512,3390 5457,3402 5397,3402 5338,3402 5283,3390 5232,3368 5180,3346 5135,3315 5096,3277 5057,3238 5027,3193 5004,3142 4982,3090 4971,3035 4971,2976 L 4971,2976 Z M 5087,2976 C 5087,3018 5095,3058 5112,3095 5128,3133 5150,3166 5178,3194 5206,3222 5239,3244 5276,3261 5314,3277 5354,3285 5398,3285 5441,3285 5482,3277 5520,3261 5558,3244 5591,3222 5618,3194 5646,3166 5668,3133 5684,3095 5700,3058 5708,3018 5708,2976 5708,2933 5700,2893 5684,2855 5668,2817 5646,2784 5618,2757 5591,2729 5558,2707 5520,2690 5482,2674 5441,2666 5398,2666 5354,2666 5314,2674 5276,2690 5239,2707 5206,2729 5178,2757 5150,2785 5128,2817 5112,2855 5095,2893 5087,2933 5087,2976 L 5087,2976 Z"/>
<path fill="rgb(255,255,255)" stroke="none" d="M 6336,3275 C 6353,3275 6369,3272 6385,3266 6401,3260 6415,3251 6428,3239 6441,3227 6452,3213 6459,3197 6467,3181 6471,3163 6471,3143 6471,3123 6467,3105 6460,3090 6452,3075 6442,3062 6430,3052 6417,3041 6403,3033 6386,3028 6370,3022 6353,3019 6335,3019 L 6163,3019 C 6130,3019 6099,3012 6070,2999 6041,2987 6016,2969 5995,2947 5974,2925 5958,2900 5946,2871 5934,2843 5928,2812 5928,2779 5928,2747 5934,2717 5946,2689 5958,2661 5975,2637 5996,2616 6017,2595 6043,2579 6071,2566 6100,2554 6130,2548 6163,2548 L 6482,2548 C 6498,2548 6512,2553 6523,2563 6535,2573 6540,2587 6540,2604 6540,2623 6535,2638 6523,2648 6512,2659 6498,2665 6482,2665 L 6162,2665 C 6145,2665 6129,2668 6115,2675 6101,2681 6088,2690 6078,2701 6067,2712 6059,2724 6053,2739 6047,2753 6044,2768 6044,2783 6044,2800 6047,2815 6053,2829 6059,2844 6068,2856 6079,2867 6089,2878 6102,2887 6116,2893 6130,2899 6146,2903 6162,2903 L 6345,2903 C 6379,2903 6411,2909 6440,2922 6470,2935 6495,2952 6517,2975 6539,2997 6556,3023 6568,3053 6581,3082 6587,3113 6587,3147 6587,3180 6581,3211 6568,3241 6556,3270 6539,3297 6518,3319 6497,3341 6472,3359 6442,3372 6413,3385 6381,3392 6346,3392 L 5966,3392 C 5950,3392 5937,3386 5927,3375 5917,3364 5912,3349 5912,3332 5912,3315 5917,3301 5927,3291 5937,3280 5950,3275 5966,3275 L 6336,3275 6336,3275 Z"/>
<path fill="rgb(255,255,255)" stroke="none" d="M 6711,2355 C 6711,2339 6716,2325 6728,2313 6740,2302 6753,2296 6769,2296 6785,2296 6799,2301 6811,2313 6823,2324 6829,2338 6829,2355 L 6829,2554 7215,2554 C 7231,2554 7245,2560 7257,2572 7268,2584 7274,2598 7274,2615 7274,2630 7269,2643 7257,2654 7246,2665 7232,2671 7215,2671 L 6830,2671 6830,2985 C 6830,3027 6838,3067 6854,3103 6870,3140 6892,3172 6920,3199 6948,3226 6981,3248 7018,3263 7056,3278 7097,3286 7140,3286 7179,3286 7215,3280 7248,3269 7281,3257 7312,3238 7342,3212 7348,3207 7355,3202 7362,3198 7369,3195 7377,3193 7388,3193 7401,3193 7413,3198 7423,3209 7434,3220 7439,3233 7439,3248 7439,3257 7437,3265 7433,3274 7430,3283 7424,3290 7417,3297 7380,3332 7339,3358 7292,3376 7245,3394 7194,3403 7140,3403 7081,3403 7025,3392 6973,3371 6921,3349 6875,3320 6836,3282 6797,3245 6767,3200 6744,3149 6722,3098 6711,3043 6711,2984 L 6711,2355 6711,2355 Z"/>
<path fill="rgb(255,255,255)" stroke="none" d="M 7537,2359 C 7537,2339 7543,2322 7557,2309 7570,2295 7587,2289 7607,2289 7626,2289 7643,2295 7657,2309 7671,2322 7678,2339 7678,2359 7678,2378 7671,2394 7657,2408 7643,2422 7626,2429 7607,2429 7587,2429 7570,2422 7557,2408 7544,2394 7537,2378 7537,2359 L 7537,2359 Z M 7547,2607 C 7547,2590 7553,2576 7565,2565 7576,2553 7590,2548 7606,2548 7623,2548 7637,2553 7648,2565 7658,2576 7664,2590 7664,2607 L 7664,3337 C 7664,3353 7658,3367 7647,3379 7635,3390 7622,3396 7607,3396 7590,3396 7576,3390 7565,3379 7553,3367 7548,3353 7548,3337 L 7548,2607 7547,2607 Z"/>
<path fill="rgb(255,255,255)" stroke="none" d="M 7819,2958 C 7819,2901 7829,2848 7849,2798 7870,2748 7897,2705 7933,2668 7969,2631 8011,2602 8059,2580 8107,2558 8160,2548 8216,2548 8273,2548 8325,2558 8373,2580 8421,2601 8463,2630 8498,2667 8534,2704 8561,2748 8581,2797 8601,2847 8611,2900 8611,2957 L 8611,3334 C 8611,3351 8605,3364 8594,3375 8584,3386 8570,3391 8553,3391 8537,3391 8523,3386 8511,3375 8500,3364 8494,3351 8494,3334 L 8494,2961 C 8494,2920 8488,2882 8474,2846 8460,2810 8441,2779 8416,2752 8391,2725 8362,2704 8328,2689 8294,2673 8256,2665 8216,2665 8176,2665 8139,2673 8105,2688 8070,2703 8041,2724 8016,2750 7990,2776 7971,2807 7957,2843 7943,2879 7936,2917 7936,2958 L 7936,3334 C 7936,3351 7931,3364 7920,3375 7910,3386 7896,3391 7880,3391 7864,3391 7850,3386 7838,3375 7826,3364 7820,3351 7820,3334 L 7820,2958 7819,2958 Z"/>
<path fill="rgb(255,255,255)" stroke="none" d="M 8736,2976 C 8736,2916 8747,2861 8770,2808 8792,2756 8823,2711 8862,2672 8901,2634 8946,2603 8997,2581 9049,2559 9104,2548 9163,2548 9223,2548 9279,2559 9330,2581 9382,2604 9428,2634 9466,2673 9505,2712 9535,2757 9557,2809 9579,2861 9591,2916 9591,2976 9591,3021 9584,3065 9570,3105 9557,3146 9538,3184 9514,3219 9538,3245 9556,3275 9566,3307 9577,3340 9582,3376 9582,3417 9582,3466 9573,3510 9556,3548 9540,3586 9517,3618 9489,3644 9461,3670 9429,3690 9393,3704 9357,3718 9319,3725 9281,3725 9255,3725 9227,3723 9197,3718 9166,3713 9137,3711 9109,3711 9101,3711 9091,3711 9081,3712 9070,3713 9059,3715 9048,3718 9037,3720 9025,3724 9014,3729 9003,3733 8993,3739 8984,3746 8972,3755 8960,3759 8949,3759 8933,3759 8919,3754 8906,3742 8893,3731 8887,3717 8887,3702 8887,3682 8895,3666 8912,3654 8929,3641 8950,3631 8973,3624 8996,3616 9020,3611 9044,3608 9068,3605 9087,3604 9101,3604 9125,3604 9148,3605 9172,3607 9195,3608 9219,3609 9243,3609 9312,3609 9367,3593 9407,3560 9446,3527 9466,3479 9466,3417 9466,3402 9465,3389 9462,3378 9460,3367 9458,3357 9455,3348 9451,3340 9448,3333 9444,3326 9440,3320 9436,3314 9432,3308 9395,3338 9354,3361 9308,3378 9262,3394 9214,3402 9163,3402 9104,3402 9049,3391 8997,3369 8946,3346 8900,3316 8862,3278 8823,3239 8792,3194 8770,3142 8748,3090 8736,3035 8736,2976 L 8736,2976 Z M 8853,2976 C 8853,3018 8861,3058 8877,3095 8894,3133 8916,3166 8944,3194 8972,3222 9005,3244 9042,3261 9080,3277 9120,3285 9163,3285 9207,3285 9248,3277 9286,3261 9324,3244 9357,3222 9384,3194 9412,3166 9434,3133 9451,3095 9467,3058 9475,3018 9475,2976 9475,2933 9467,2893 9451,2855 9434,2817 9412,2784 9384,2757 9356,2729 9324,2707 9286,2690 9248,2674 9207,2666 9163,2666 9120,2666 9080,2674 9042,2690 9005,2707 8972,2729 8944,2757 8916,2785 8893,2817 8877,2855 8861,2893 8853,2933 8853,2976 L 8853,2976 Z"/>
<path fill="rgb(255,255,255)" stroke="none" d="M 13244,3167 C 13249,3167 13254,3166 13260,3165 13266,3164 13271,3162 13276,3160 13280,3157 13284,3153 13287,3148 13290,3143 13292,3136 13292,3128 13292,3120 13290,3113 13287,3108 13284,3103 13280,3100 13275,3098 13270,3096 13264,3094 13258,3093 13251,3093 13245,3093 13240,3093 L 13103,3093 C 13066,3093 13032,3085 13000,3070 12969,3056 12942,3035 12919,3010 12897,2985 12879,2956 12866,2924 12853,2891 12847,2857 12847,2821 12847,2787 12854,2754 12867,2724 12881,2693 12899,2666 12922,2643 12945,2620 12972,2602 13003,2588 13035,2575 13068,2568 13103,2568 L 13369,2568 C 13385,2568 13399,2571 13413,2576 13427,2580 13439,2588 13449,2597 13459,2606 13467,2618 13473,2632 13479,2646 13482,2662 13482,2679 13482,2696 13479,2711 13474,2726 13468,2740 13461,2753 13451,2763 13441,2774 13430,2783 13417,2788 13404,2794 13390,2797 13376,2797 L 13369,2797 13107,2797 C 13099,2797 13092,2800 13085,2806 13078,2812 13075,2820 13075,2831 13075,2844 13078,2853 13086,2857 13093,2862 13099,2864 13106,2864 L 13262,2864 C 13300,2864 13334,2871 13366,2886 13398,2901 13425,2921 13448,2946 13471,2971 13489,2999 13501,3032 13514,3065 13520,3099 13520,3134 13520,3170 13514,3203 13502,3234 13489,3265 13472,3293 13450,3316 13428,3340 13402,3359 13371,3374 13340,3388 13306,3396 13270,3397 L 12937,3397 C 12922,3397 12908,3394 12895,3388 12882,3382 12871,3374 12862,3364 12852,3354 12845,3341 12840,3327 12835,3313 12832,3297 12832,3280 12832,3245 12842,3218 12861,3198 12881,3178 12906,3168 12937,3168 L 13244,3168 13244,3167 Z"/>
<path fill="rgb(255,255,255)" stroke="none" d="M 13627,2682 C 13627,2666 13630,2652 13636,2638 13642,2624 13650,2612 13661,2602 13671,2592 13683,2584 13696,2578 13710,2572 13725,2569 13740,2569 13755,2569 13770,2572 13784,2578 13798,2584 13811,2592 13821,2602 13832,2612 13840,2624 13846,2638 13852,2652 13855,2666 13855,2682 L 13855,3001 C 13855,3026 13859,3049 13869,3071 13878,3092 13891,3111 13907,3126 13923,3142 13942,3155 13964,3163 13986,3172 14010,3176 14035,3176 14060,3176 14082,3172 14103,3163 14123,3153 14139,3141 14153,3125 14167,3109 14177,3090 14185,3069 14192,3047 14196,3023 14196,2998 L 14196,2681 C 14196,2666 14199,2652 14205,2638 14212,2624 14220,2612 14231,2602 14241,2592 14254,2583 14268,2577 14282,2571 14297,2569 14313,2569 14328,2569 14343,2571 14357,2577 14370,2584 14382,2592 14392,2602 14402,2612 14410,2624 14416,2638 14422,2652 14424,2666 14424,2681 L 14424,2999 C 14424,3055 14415,3107 14395,3156 14376,3206 14349,3248 14314,3285 14279,3322 14238,3352 14190,3373 14143,3394 14091,3405 14035,3405 13979,3405 13926,3394 13876,3373 13826,3352 13783,3322 13746,3285 13709,3248 13680,3206 13659,3156 13637,3107 13626,3054 13626,2999 L 13626,2682 13627,2682 Z"/>
<path fill="rgb(255,255,255)" stroke="none" d="M 14577,2996 C 14579,2937 14591,2882 14615,2831 14639,2780 14670,2734 14709,2696 14748,2657 14794,2627 14845,2604 14897,2581 14952,2570 15010,2568 L 15018,2568 C 15056,2569 15085,2580 15105,2601 15125,2622 15135,2649 15135,2681 15135,2698 15132,2713 15126,2727 15120,2741 15111,2753 15101,2763 15090,2773 15077,2781 15063,2787 15048,2793 15033,2795 15017,2795 14988,2795 14961,2801 14936,2812 14911,2823 14888,2838 14869,2857 14850,2875 14835,2898 14823,2923 14812,2948 14806,2976 14805,3005 L 14805,3284 C 14805,3300 14802,3315 14797,3328 14791,3342 14783,3354 14773,3364 14762,3374 14750,3382 14737,3388 14724,3393 14709,3396 14694,3396 14678,3396 14663,3393 14649,3388 14635,3382 14622,3374 14612,3364 14601,3354 14593,3342 14586,3328 14580,3315 14577,3300 14577,3284 L 14577,2996 14577,2996 Z"/>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 33 KiB

+4
View File
@@ -0,0 +1,4 @@
User-agent: *
Allow: /
Sitemap: https://hostingdelsur.net/sitemap-index.xml
+48
View File
@@ -0,0 +1,48 @@
#!/bin/bash
set -e
DIST="/root/opencode/development/hostingdelsur.net/dist"
REMOTE="server1"
REMOTE_PATH="/home/hostingd/public_html"
LOCAL_USER="root"
echo "=== Deploy hostingdelsur.net ==="
echo "Local dist: $DIST"
echo "Remote: $REMOTE:$REMOTE_PATH"
echo "Preserving: mwp/, .well-known/, .smtp-credentials.json (initially)"
echo ""
# lftp sync: borra archivos del remote que no estén en local,
# sube los nuevos, NO toca mwp/ ni .well-known/
lftp -c "
set sftp:auto-confirm yes
set ssl:verify-certificate no
open -u $LOCAL_USER sftp://$REMOTE
cd $REMOTE_PATH
# 1. Backup de archivos críticos a tmp antes de limpiar
mkdir -p /tmp/hds-deploy-backup
mv .smtp-credentials.json /tmp/hds-deploy-backup/ 2>/dev/null || true
# 2. Limpiar lo que va a ser reemplazado
# (NO borra mwp/ ni .well-known/)
glob rm -rf '!(mwp|.well-known)'
echo '=== Archivos restantes tras limpieza ==='
ls -la
# 3. Subir dist
mirror --reverse --delete --verbose=1 $DIST/ ./
# 4. Restaurar credenciales (se moverán después a /home/hostingd/)
mv /tmp/hds-deploy-backup/.smtp-credentials.json ./ 2>/dev/null || true
echo ''
echo '=== Resultado ==='
ls -la
"
echo ""
echo "=== Verificación mwp intacto ==="
ssh $REMOTE "ls /home/hostingd/public_html/mwp/ | head -5" 2>&1
echo ""
echo "=== Files deployed ==="
ssh $REMOTE "find /home/hostingd/public_html -maxdepth 1 -type d" 2>&1
+60
View File
@@ -0,0 +1,60 @@
# Hosting del Sur — .htaccess
# Generado para el sitio estático Astro
<IfModule mod_rewrite.c>
RewriteEngine On
# HTTPS forzado
RewriteCond %{HTTPS} off
RewriteRule ^(.*)$ https://%{HTTP_HOST}/$1 [R=301,L]
# www → no-www
RewriteCond %{HTTP_HOST} ^www\.(.+)$ [NC]
RewriteRule ^(.*)$ https://%1/$1 [R=301,L]
# Quitar .html de la URL (limpieza opcional)
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI} ^(.+)\.html$ [NC]
RewriteRule ^(.+)\.html$ /$1 [R=301,L]
</IfModule>
# Compresión gzip
<IfModule mod_deflate.c>
AddOutputFilterByType DEFLATE text/html text/css text/javascript application/javascript application/json image/svg+xml application/xml font/woff2
</IfModule>
# Cache-control
<IfModule mod_expires.c>
ExpiresActive On
ExpiresByType image/avif "access plus 1 year"
ExpiresByType image/webp "access plus 1 year"
ExpiresByType image/svg+xml "access plus 1 year"
ExpiresByType image/jpeg "access plus 1 year"
ExpiresByType image/png "access plus 1 year"
ExpiresByType text/css "access plus 1 year"
ExpiresByType application/javascript "access plus 1 year"
ExpiresByType font/woff2 "access plus 1 year"
ExpiresByType text/html "access plus 1 hour"
</IfModule>
# Security headers
<IfModule mod_headers.c>
Header set X-Content-Type-Options "nosniff"
Header set X-Frame-Options "SAMEORIGIN"
Header set Referrer-Policy "strict-origin-when-cross-origin"
Header set Permissions-Policy "geolocation=(), microphone=(), camera=()"
Header set Strict-Transport-Security "max-age=31536000; includeSubDomains" env=HTTPS
</IfModule>
# Proteger archivos sensibles
<FilesMatch "^\.htaccess$">
Require all denied
</FilesMatch>
<FilesMatch "\.(env|json|lock|md|yaml|yml)$">
Require all denied
</FilesMatch>
# No listado de directorios
Options -Indexes
+39
View File
@@ -0,0 +1,39 @@
---
const label = 'Volver arriba';
---
<button
type="button"
id="back-to-top"
class="fixed bottom-24 right-6 z-30 inline-flex items-center justify-center w-11 h-11 rounded-full text-white shadow-md opacity-0 invisible transition-all"
style="background: var(--hds-fg);"
aria-label={label}
>
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
<polyline points="18 15 12 9 6 15"/>
</svg>
</button>
<script is:inline>
(function() {
const btn = document.getElementById('back-to-top');
if (!btn) return;
let visible = false;
function update() {
const should = window.scrollY > 400;
if (should !== visible) {
visible = should;
if (should) {
btn.classList.remove('opacity-0', 'invisible');
btn.classList.add('opacity-100', 'visible');
} else {
btn.classList.remove('opacity-100', 'visible');
btn.classList.add('opacity-0', 'invisible');
}
}
}
window.addEventListener('scroll', update, { passive: true });
btn.addEventListener('click', () => {
window.scrollTo({ top: 0, behavior: 'smooth' });
});
})();
</script>
+21
View File
@@ -0,0 +1,21 @@
---
interface Props {
variant?: 'wave' | 'cloud';
flip?: boolean;
fillClass?: string;
}
const { variant = 'wave', flip = false, fillClass = 'fill-hds-bg' } = Astro.props;
---
{variant === 'wave' ? (
<div class={`w-full overflow-hidden leading-none ${flip ? 'rotate-180' : ''}`} aria-hidden="true">
<svg class="w-full h-12 md:h-16" viewBox="0 0 1440 80" preserveAspectRatio="none" xmlns="http://www.w3.org/2000/svg">
<path class={fillClass} d="M0,32 C240,80 480,0 720,32 C960,64 1200,16 1440,48 L1440,80 L0,80 Z" />
</svg>
</div>
) : (
<div class={`w-full overflow-hidden leading-none ${flip ? 'rotate-180' : ''}`} aria-hidden="true">
<svg class="w-full h-16 md:h-24" viewBox="0 0 1440 120" preserveAspectRatio="none" xmlns="http://www.w3.org/2000/svg">
<path class={fillClass} d="M0,60 C120,100 240,20 360,50 C480,80 600,30 720,55 C840,80 960,40 1080,60 C1200,80 1320,45 1440,65 L1440,120 L0,120 Z" />
</svg>
</div>
)}
+41
View File
@@ -0,0 +1,41 @@
---
import SectionEyebrow from './SectionEyebrow.astro';
import type { TranslationKey } from '@/i18n/ui';
interface Props {
t: (key: TranslationKey) => string;
whatsappUrl: string;
}
const { t, whatsappUrl } = Astro.props;
---
<section class="relative overflow-hidden py-20 md:py-32" style="background: #0F0E0C; color: #FAF6EE;">
<div class="absolute inset-0 particle-grid" aria-hidden="true" style="opacity: 0.7;"></div>
<div class="relative max-w-4xl mx-auto px-4 sm:px-6 lg:px-8 text-center">
<div class="inline-block">
<span class="inline-flex items-center gap-3 text-xs font-semibold tracking-[0.25em] uppercase" style="color: #FA9F5C;">
<span class="inline-block w-10 h-px" style="background: #FA9F5C;"></span>
{t('ctaFinal.eyebrow') || 'Hablemos'}
</span>
</div>
<h2 class="font-display leading-tight mt-5 mb-5" style="font-size: clamp(2.25rem, 5vw, 4rem); color: #FAF6EE;">
{t('ctaFinal.title')}
</h2>
<p class="text-lg md:text-xl max-w-2xl mx-auto mb-10" style="color: #C8C2B8;">
{t('ctaFinal.body')}
</p>
<div class="flex flex-col sm:flex-row gap-4 justify-center">
<a href={whatsappUrl} target="_blank" rel="noopener noreferrer" class="btn-primary text-base">
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="currentColor" aria-hidden="true">
<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.475-.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-.075-.149-.669-1.612-.916-2.207-.242-.579-.487-.5-.669-.51-.173-.008-.371-.01-.57-.01-.198 0-.52.074-.792.372-.272.297-1.04 1.016-1.04 2.479 0 1.462 1.065 2.875 1.213 3.074.149.198 2.096 3.2 5.077 4.487.709.306 1.262.489 1.694.625.712.227 1.36.195 1.871.118.571-.085 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.86 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.495 0 .16 5.335.157 11.892c0 2.096.547 4.142 1.588 5.945L.057 24l6.305-1.654a11.882 11.882 0 005.683 1.448h.005c6.554 0 11.89-5.335 11.893-11.893a11.821 11.821 0 00-3.48-8.413Z"/>
</svg>
{t('ctaFinal.button')}
</a>
<a href="mailto:contacto@hostingdelsur.net" class="inline-flex items-center justify-center gap-2 px-7 py-3.5 rounded-md text-base font-semibold transition-colors" style="border: 2px solid #FAF6EE; color: #FAF6EE; background: transparent;" onmouseover="this.style.background='#FAF6EE'; this.style.color='#0F0E0C';" onmouseout="this.style.background='transparent'; this.style.color='#FAF6EE';">
contacto@hostingdelsur.net
</a>
</div>
</div>
</section>
+47
View File
@@ -0,0 +1,47 @@
---
import SectionEyebrow from './SectionEyebrow.astro';
import type { TranslationKey } from '@/i18n/ui';
import MateIcon from './icons/MateIcon.astro';
import SovereigntyIcon from './icons/SovereigntyIcon.astro';
import GlobeIcon from './icons/GlobeIcon.astro';
interface Props {
t: (key: TranslationKey) => string;
}
const { t } = Astro.props;
const items = [
{ Icon: MateIcon, titleKey: 'diff.support.title' as TranslationKey, bodyKey: 'diff.support.body' as TranslationKey },
{ Icon: SovereigntyIcon, titleKey: 'diff.sovereignty.title' as TranslationKey, bodyKey: 'diff.sovereignty.body' as TranslationKey },
{ Icon: GlobeIcon, titleKey: 'diff.infra.title' as TranslationKey, bodyKey: 'diff.infra.body' as TranslationKey },
];
---
<section class="py-20 md:py-28" style="background: var(--hds-bg-soft);">
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
<div class="max-w-3xl mb-14 md:mb-20">
<SectionEyebrow text={t('diff.eyebrow')} />
<h2 class="font-display leading-tight mt-5" style="font-size: clamp(2rem, 5vw, 3.5rem); color: var(--hds-fg);">
{t('diff.title')}
</h2>
<p class="text-lg mt-5 max-w-2xl" style="color: var(--hds-fg-soft);">
{t('diff.subtitle')}
</p>
</div>
<div class="grid grid-cols-1 md:grid-cols-3 gap-6">
{items.map((item) => (
<article class="service-card">
<div class="icon-circle mb-6">
<item.Icon class="w-7 h-7" />
</div>
<h3 class="text-xl md:text-2xl font-semibold mb-3" style="color: var(--hds-fg);">
{t(item.titleKey)}
</h3>
<p class="text-[15px] leading-relaxed" style="color: var(--hds-fg-soft);">
{t(item.bodyKey)}
</p>
</article>
))}
</div>
</div>
</section>
+37
View File
@@ -0,0 +1,37 @@
---
interface FaqItem {
q: string;
a: string;
}
interface Props {
items: FaqItem[];
}
const { items } = Astro.props;
const groupId = `faq-${Math.random().toString(36).slice(2, 8)}`;
---
<div class="divide-y" style="border-color: var(--hds-line);">
{items.map((item, idx) => {
const inputId = `${groupId}-${idx}`;
return (
<details class="group" style="border-color: var(--hds-line);">
<summary
class="flex items-start justify-between gap-4 py-5 cursor-pointer list-none transition-colors"
style="color: var(--hds-fg);"
>
<h3 class="text-base md:text-lg font-semibold pr-4">{item.q}</h3>
<span class="flex-shrink-0 mt-1 icon-circle transition-transform group-open:rotate-45" style="width: 28px; height: 28px;">
<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" aria-hidden="true">
<line x1="12" y1="5" x2="12" y2="19"/>
<line x1="5" y1="12" x2="19" y2="12"/>
</svg>
</span>
</summary>
<div class="pb-5 pr-12 text-[15px] leading-relaxed" style="color: var(--hds-fg-soft);">
{item.a}
</div>
</details>
);
})}
</div>
+109
View File
@@ -0,0 +1,109 @@
---
import type { Lang } from '@/i18n/utils';
import type { TranslationKey } from '@/i18n/ui';
interface Props {
t: (key: TranslationKey) => string;
lang: Lang;
}
const { t, lang } = Astro.props;
const year = new Date().getFullYear();
const base = lang === 'en' ? '/en' : '';
const navLinks: { href: string; key: TranslationKey }[] = [
{ href: `${base}/`, key: 'nav.home' },
{ href: `${base}/servicios/`, key: 'nav.services' },
{ href: `${base}/planes/`, key: 'nav.plans' },
{ href: `${base}/nosotros/`, key: 'nav.about' },
{ href: `${base}/instructivos/`, key: 'nav.tutorials' },
{ href: `${base}/contacto/`, key: 'nav.contact' },
];
const legalLinks = [
{ href: `${base}/legal/privacidad/`, key: 'footer.privacy' as TranslationKey },
{ href: `${base}/legal/terminos/`, key: 'footer.terms' as TranslationKey },
];
---
<footer class="py-14 md:py-20" style="background: #0F0E0C; color: #FAF6EE;">
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
<div class="grid grid-cols-1 md:grid-cols-12 gap-10 md:gap-8">
<div class="md:col-span-4">
<a href={lang === 'en' ? '/en/' : '/'} class="inline-flex items-center gap-2.5 mb-4" aria-label="Hosting del Sur">
<img src="/logo/hds-mark.svg" alt="" width="36" height="36" class="h-9 w-9" aria-hidden="true" style="filter: brightness(0) invert(1);" />
<span class="text-lg font-display tracking-tight">
<span style="color: #EE7623;">hosting</span> del <span style="color: #EE7623;">sur</span>
</span>
</a>
<p class="text-sm leading-relaxed max-w-sm" style="color: #C8C2B8;">
{t('footer.tagline')}
</p>
<p class="text-xs mt-4" style="color: #8A8580;">
{lang === 'en' ? 'Web, email, infrastructure and human support in Uruguay.' : 'Web, correo, infraestructura y soporte humano en Uruguay.'}
</p>
</div>
<div class="md:col-span-2">
<h2 class="text-xs font-semibold tracking-[0.25em] uppercase mb-4" style="color: #FA9F5C;">
{t('footer.nav')}
</h2>
<ul class="space-y-2.5">
{navLinks.map((link) => (
<li>
<a
href={link.href}
class="text-sm transition-colors hover:text-white"
style="color: #C8C2B8;"
>
{t(link.key)}
</a>
</li>
))}
</ul>
</div>
<div class="md:col-span-3">
<h2 class="text-xs font-semibold tracking-[0.25em] uppercase mb-4" style="color: #FA9F5C;">
{t('footer.contact')}
</h2>
<ul class="space-y-2.5 text-sm" style="color: #C8C2B8;">
<li>
<a href="https://wa.me/59899812487" target="_blank" rel="noopener noreferrer" class="hover:text-white transition-colors">
+598 99 812 487
</a>
</li>
<li>
<a href="mailto:contacto@hostingdelsur.net" class="hover:text-white transition-colors break-all">
contacto@hostingdelsur.net
</a>
</li>
<li>Maldonado, Uruguay</li>
</ul>
</div>
<div class="md:col-span-3">
<h2 class="text-xs font-semibold tracking-[0.25em] uppercase mb-4" style="color: #FA9F5C;">
{t('footer.legal')}
</h2>
<ul class="space-y-2.5">
{legalLinks.map((link) => (
<li>
<a
href={link.href}
class="text-sm transition-colors hover:text-white"
style="color: #C8C2B8;"
>
{t(link.key)}
</a>
</li>
))}
</ul>
</div>
</div>
<div class="mt-12 pt-6 border-t flex flex-col sm:flex-row sm:justify-between gap-3 text-xs" style="border-color: #2A2520; color: #8A8580;">
<p>© {year} Hosting del Sur. {t('footer.copyright')}</p>
<p>Maldonado, Uruguay</p>
</div>
</div>
</footer>
+59
View File
@@ -0,0 +1,59 @@
---
import type { TranslationKey } from '@/i18n/ui';
interface Props {
t: (key: TranslationKey) => string;
whatsappUrl: string;
}
const { t, whatsappUrl } = Astro.props;
---
<section class="relative overflow-hidden pt-24 pb-32 md:pt-32 md:pb-40">
<div class="absolute inset-0 particle-grid" aria-hidden="true"></div>
<div class="absolute inset-0" style="background: linear-gradient(180deg, transparent 0%, var(--hds-bg) 100%);" aria-hidden="true"></div>
<div class="relative max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
<div class="max-w-4xl">
<div class="eyebrow mb-7">
<span>Premium hosting · Desde 2000</span>
</div>
<h1 class="font-display leading-[0.98] mb-8" style="font-size: clamp(2.75rem, 7vw, 5.5rem); color: var(--hds-fg); letter-spacing: -0.025em; font-weight: 400;">
Alojamiento en la nube<br/>
que te <span style="color: var(--color-hds-naranja); font-style: italic;">conoce</span>.
</h1>
<p class="text-lg md:text-xl leading-relaxed mb-10 max-w-2xl" style="color: var(--hds-fg-soft);">
{t('hero.body')}
</p>
<div class="flex flex-col sm:flex-row gap-4 mb-14">
<a href="#planes" class="btn-primary">
{t('hero.ctaPrimary')}
</a>
<a href={whatsappUrl} target="_blank" rel="noopener noreferrer" class="btn-secondary">
{t('hero.ctaSecondary')}
</a>
</div>
<div class="flex flex-wrap items-center gap-x-8 gap-y-3 text-sm" style="color: var(--hds-fg-muted);">
<span class="flex items-center gap-2">
<span style="color: var(--color-hds-naranja);">●</span>
26+ años
</span>
<span class="flex items-center gap-2">
<span style="color: var(--color-hds-naranja);">●</span>
Uptime 99.9%
</span>
<span class="flex items-center gap-2">
<span style="color: var(--color-hds-naranja);">●</span>
{t('diff.support.title')}
</span>
<span class="flex items-center gap-2">
<span style="color: var(--color-hds-naranja);">●</span>
Maldonado, Uruguay
</span>
</div>
</div>
</div>
</section>
+31
View File
@@ -0,0 +1,31 @@
---
import { LANGUAGES, DEFAULT_LANG, type Lang } from '@/i18n/utils';
interface Props {
lang: Lang;
}
const { lang } = Astro.props;
const path = Astro.url.pathname;
function otherLangUrl(): string {
const cleanPath = path.replace(/^\/(en|es)/, '') || '/';
if (lang === DEFAULT_LANG) {
return `/en${cleanPath === '/' ? '' : cleanPath}`;
}
return cleanPath;
}
const other = LANGUAGES.find((l) => l.code !== lang);
const isEn = lang === 'en';
---
<a
href={otherLangUrl()}
hreflang={other?.code}
class="text-xs font-semibold tracking-wider px-2.5 py-1.5 rounded border transition-colors"
style="border-color: var(--hds-line); color: var(--hds-fg-soft);"
aria-label={isEn ? 'Switch language to Spanish' : 'Cambiar idioma a inglés'}
onmouseover="this.style.borderColor='var(--color-hds-naranja)';this.style.color='var(--color-hds-naranja)';"
onmouseout="this.style.borderColor='var(--hds-line)';this.style.color='var(--hds-fg-soft)';"
>
{other?.label}
</a>
+143
View File
@@ -0,0 +1,143 @@
---
import ThemeToggle from './ThemeToggle.astro';
import LangToggle from './LangToggle.astro';
import { type Lang } from '@/i18n/utils';
import type { TranslationKey } from '@/i18n/ui';
interface Props {
t: (key: TranslationKey) => string;
lang: Lang;
currentPath?: string;
}
const { t, lang, currentPath } = Astro.props;
const path = currentPath || Astro.url.pathname;
const navItems: { label: string; href: string; key: TranslationKey }[] = [
{ label: t('nav.home'), href: lang === 'en' ? '/en/' : '/', key: 'nav.home' },
{ label: t('nav.services'), href: lang === 'en' ? '/en/servicios/' : '/servicios/', key: 'nav.services' },
{ label: t('nav.plans'), href: lang === 'en' ? '/en/planes/' : '/planes/', key: 'nav.plans' },
{ label: t('nav.about'), href: lang === 'en' ? '/en/nosotros/' : '/nosotros/', key: 'nav.about' },
{ label: t('nav.tutorials'), href: lang === 'en' ? '/en/instructivos/' : '/instructivos/', key: 'nav.tutorials' },
{ label: t('nav.contact'), href: lang === 'en' ? '/en/contacto/' : '/contacto/', key: 'nav.contact' },
];
const whatsappUrl = 'https://wa.me/59899812487';
const isActive = (href: string) => {
const normalized = path.replace(/\/$/, '') || '/';
const target = href.replace(/\/$/, '') || '/';
return normalized === target;
};
---
<header id="navbar" class="sticky top-0 z-40 backdrop-blur-md border-b transition-colors" style="background: rgba(250,246,238,0.85); border-color: var(--hds-line);">
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
<div class="flex items-center justify-between h-16 md:h-20">
<a href={lang === 'en' ? '/en/' : '/'} class="flex items-center gap-2.5 flex-shrink-0" aria-label="Hosting del Sur - Inicio">
<img
src="/logo/hds-mark.svg"
alt=""
width="32"
height="32"
class="h-8 w-8"
aria-hidden="true"
/>
<span class="text-base font-display tracking-tight" style="color: var(--hds-fg);">
<span style="color: var(--color-hds-naranja);">hosting</span> del <span style="color: var(--color-hds-naranja);">sur</span>
</span>
</a>
<nav class="hidden lg:flex items-center gap-7" aria-label="Principal">
{navItems.map((item) => (
<a
href={item.href}
class:list={[
"text-sm font-medium transition-colors",
isActive(item.href) ? "text-hds-naranja" : ""
]}
style={isActive(item.href) ? 'color: var(--color-hds-naranja);' : 'color: var(--hds-fg-soft);'}
>
{item.label}
</a>
))}
</nav>
<div class="flex items-center gap-2">
<LangToggle lang={lang} />
<ThemeToggle lang={lang} />
<a
href={whatsappUrl}
target="_blank"
rel="noopener noreferrer"
class="hidden md:inline-flex btn-primary text-sm"
>
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="currentColor" aria-hidden="true">
<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.475-.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-.075-.149-.669-1.612-.916-2.207-.242-.579-.487-.5-.669-.51-.173-.008-.371-.01-.57-.01-.198 0-.52.074-.792.372-.272.297-1.04 1.016-1.04 2.479 0 1.462 1.065 2.875 1.213 3.074.149.198 2.096 3.2 5.077 4.487.709.306 1.262.489 1.694.625.712.227 1.36.195 1.871.118.571-.085 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.86 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.495 0 .16 5.335.157 11.892c0 2.096.547 4.142 1.588 5.945L.057 24l6.305-1.654a11.882 11.882 0 005.683 1.448h.005c6.554 0 11.89-5.335 11.893-11.893a11.821 11.821 0 00-3.48-8.413Z"/>
</svg>
<span>{t('nav.cta')}</span>
</a>
<button
type="button"
class="lg:hidden p-2 -mr-2"
aria-label="Abrir menú"
aria-expanded="false"
aria-controls="mobile-menu"
id="mobile-menu-button"
style="color: var(--hds-fg);"
>
<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" aria-hidden="true">
<line x1="3" y1="6" x2="21" y2="6"/>
<line x1="3" y1="12" x2="21" y2="12"/>
<line x1="3" y1="18" x2="21" y2="18"/>
</svg>
</button>
</div>
</div>
<div id="mobile-menu" class="lg:hidden hidden border-t py-4" style="border-color: var(--hds-line);">
<nav class="flex flex-col gap-3" aria-label="Móvil">
{navItems.map((item) => (
<a
href={item.href}
class="text-base font-medium py-2"
style={isActive(item.href) ? 'color: var(--color-hds-naranja);' : 'color: var(--hds-fg-soft);'}
>
{item.label}
</a>
))}
<a
href={whatsappUrl}
target="_blank"
rel="noopener noreferrer"
class="md:hidden inline-flex items-center justify-center gap-2 btn-primary text-sm mt-2"
>
<span>{t('nav.cta')}</span>
</a>
</nav>
</div>
</div>
</header>
<script is:inline>
(function() {
const btn = document.getElementById('mobile-menu-button');
const menu = document.getElementById('mobile-menu');
if (!btn || !menu) return;
btn.addEventListener('click', () => {
const isOpen = !menu.classList.contains('hidden');
if (isOpen) {
menu.classList.add('hidden');
btn.setAttribute('aria-expanded', 'false');
} else {
menu.classList.remove('hidden');
btn.setAttribute('aria-expanded', 'true');
}
});
})();
</script>
<style>
:global(:root.dark) #navbar {
background: rgba(26,22,18,0.85) !important;
}
</style>
+19
View File
@@ -0,0 +1,19 @@
---
interface Props {
size?: 'sm' | 'md' | 'lg';
opacity?: number;
}
const { size = 'md', opacity = 0.10 } = Astro.props;
const sizes = {
sm: 40,
md: 56,
lg: 72,
};
const cell = sizes[size];
---
<div
class="absolute inset-0 pointer-events-none"
aria-hidden="true"
style={`background-image: linear-gradient(to right, rgba(238,118,35,${opacity}) 1px, transparent 1px), linear-gradient(to bottom, rgba(238,118,35,${opacity}) 1px, transparent 1px); background-size: ${cell}px ${cell}px;`}
></div>
+76
View File
@@ -0,0 +1,76 @@
---
interface Props {
plans: Array<{
slug: string;
name: string;
priceUsdYear: number;
recommended?: boolean;
features: string[];
}>;
whatsappUrl: string;
additionalNote?: string;
}
const { plans, whatsappUrl, additionalNote } = Astro.props;
function monthlyEquivalent(annual: number): string {
return (annual / 12).toFixed(2);
}
---
<div class="grid grid-cols-1 md:grid-cols-3 gap-6">
{plans.map((plan) => (
<div
class="relative rounded-2xl p-8 transition-all flex flex-col h-full"
style={plan.recommended
? `background: var(--hds-card); border: 2px solid var(--color-hds-naranja); box-shadow: 0 16px 40px rgba(238,118,35,0.15);`
: `background: var(--hds-card); border: 1px solid var(--hds-line);`}
>
{plan.recommended && (
<div class="absolute -top-3.5 left-1/2 -translate-x-1/2 text-[11px] font-bold tracking-[0.2em] uppercase px-4 py-1.5 rounded-full whitespace-nowrap" style="background: var(--color-hds-naranja); color: white; box-shadow: 0 4px 12px rgba(238,118,35,0.3);">
⭐ Recomendado
</div>
)}
<div class="mb-5">
<div class="text-xs font-semibold tracking-[0.25em] uppercase mb-3" style={`color: ${plan.recommended ? 'var(--color-hds-naranja)' : 'var(--hds-fg-muted)'};`}>
{plan.name}
</div>
<div class="flex items-baseline gap-1">
<span class="text-2xl font-semibold" style="color: var(--hds-fg);">USD</span>
<span class="font-display leading-none" style="font-size: 4rem; color: var(--hds-fg); font-weight: 500; letter-spacing: -0.02em;">{plan.priceUsdYear}</span>
</div>
<div class="text-sm mt-2" style="color: var(--hds-fg-muted);">
por año · ~USD {monthlyEquivalent(plan.priceUsdYear)}/mes
</div>
</div>
<div class="border-t pt-6 mb-6 flex-grow" style="border-color: var(--hds-line);">
<ul class="space-y-2.5 text-sm" style="color: var(--hds-fg-soft);">
{plan.features.map((feature) => (
<li class="flex items-start gap-2.5">
<svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" class="flex-shrink-0 mt-0.5" style="color: var(--color-hds-naranja);" aria-hidden="true">
<polyline points="20 6 9 17 4 12"/>
</svg>
<span>{feature}</span>
</li>
))}
</ul>
</div>
<a
href={whatsappUrl}
target="_blank"
rel="noopener noreferrer"
class={plan.recommended ? 'btn-primary justify-center' : 'btn-secondary justify-center'}
>
Elegir {plan.name}
</a>
</div>
))}
</div>
{additionalNote && (
<p class="text-center text-sm mt-6 italic" style="color: var(--hds-fg-muted);">
{additionalNote}
</p>
)}
+45
View File
@@ -0,0 +1,45 @@
---
import SectionEyebrow from './SectionEyebrow.astro';
import type { TranslationKey } from '@/i18n/ui';
interface Props {
t: (key: TranslationKey) => string;
}
const { t } = Astro.props;
const steps = [
{ num: '01', titleKey: 'process.step1.title' as TranslationKey, bodyKey: 'process.step1.body' as TranslationKey },
{ num: '02', titleKey: 'process.step2.title' as TranslationKey, bodyKey: 'process.step2.body' as TranslationKey },
{ num: '03', titleKey: 'process.step3.title' as TranslationKey, bodyKey: 'process.step3.body' as TranslationKey },
{ num: '04', titleKey: 'process.step4.title' as TranslationKey, bodyKey: 'process.step4.body' as TranslationKey },
];
---
<section class="py-20 md:py-28" style="background: var(--hds-bg-soft);">
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
<div class="max-w-3xl mb-14 md:mb-20">
<SectionEyebrow text={t('process.eyebrow')} />
<h2 class="font-display leading-tight mt-5" style="font-size: clamp(2rem, 5vw, 3.5rem); color: var(--hds-fg);">
{t('process.title')}
</h2>
</div>
<ol class="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-10 md:gap-8 relative">
<div class="hidden lg:block absolute top-12 left-[12.5%] right-[12.5%] h-px" style="background: linear-gradient(to right, transparent, var(--color-hds-naranja) 20%, var(--color-hds-naranja) 80%, transparent);" aria-hidden="true"></div>
{steps.map((step) => (
<li class="relative">
<div class="font-display leading-none mb-4 relative inline-block" style="font-size: 5rem; color: var(--color-hds-naranja); font-weight: 500; opacity: 0.85;" aria-hidden="true">
{step.num}
<span class="absolute -bottom-1 left-0 w-10 h-1" style="background: var(--color-hds-naranja);"></span>
</div>
<h3 class="text-xl md:text-2xl font-semibold mb-3" style="color: var(--hds-fg);">
{t(step.titleKey)}
</h3>
<p class="text-[15px] leading-relaxed" style="color: var(--hds-fg-soft);">
{t(step.bodyKey)}
</p>
</li>
))}
</ol>
</div>
</section>
+22
View File
@@ -0,0 +1,22 @@
---
interface Props {
text: string;
align?: 'left' | 'center';
light?: boolean;
}
const { text, align = 'left', light = false } = Astro.props;
---
{align === 'center' ? (
<div class="text-center">
<span class="inline-flex items-center gap-3 text-xs font-semibold tracking-[0.25em] uppercase" style={`color: ${light ? '#FA9F5C' : 'var(--color-hds-naranja)'}`}>
<span class="inline-block w-10 h-px" style={`background: ${light ? '#FA9F5C' : 'var(--color-hds-naranja)'}`}></span>
{text}
<span class="inline-block w-10 h-px" style={`background: ${light ? '#FA9F5C' : 'var(--color-hds-naranja)'}`}></span>
</span>
</div>
) : (
<div class="inline-flex items-center gap-3 text-xs font-semibold tracking-[0.25em] uppercase" style={`color: ${light ? '#FA9F5C' : 'var(--color-hds-naranja)'}`}>
{text}
<span class="inline-block w-12 h-px" style={`background: ${light ? '#FA9F5C' : 'var(--color-hds-naranja)'}`}></span>
</div>
)}
+35
View File
@@ -0,0 +1,35 @@
---
import type { TranslationKey } from '@/i18n/ui';
interface Props {
href: string;
title: string;
description: string;
Icon: any;
borderColor?: string;
}
const { href, title, description, Icon, borderColor = 'var(--color-hds-naranja)' } = Astro.props;
---
<a
href={href}
class="service-card group flex flex-col h-full"
style={`border-top: 4px solid ${borderColor}; padding-top: 1.5rem;`}
>
<div class="icon-circle mb-5" style="width: 48px; height: 48px;">
<Icon class="w-6 h-6" />
</div>
<h3 class="text-xl font-semibold mb-2 transition-colors" style="color: var(--hds-fg);">
{title}
</h3>
<p class="text-sm leading-relaxed mb-4 flex-grow" style="color: var(--hds-fg-soft);">
{description}
</p>
<span class="btn-ghost mt-auto">
Ver detalles
<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
<line x1="5" y1="12" x2="19" y2="12"/>
<polyline points="12 5 19 12 12 19"/>
</svg>
</span>
</a>
+41
View File
@@ -0,0 +1,41 @@
---
import ServiceCard from './ServiceCard.astro';
import type { TranslationKey } from '@/i18n/ui';
interface Service {
slug: string;
title: string;
description: string;
Icon: any;
}
interface Props {
categoryTitle: string;
categoryKey: TranslationKey;
services: Service[];
lang: 'es' | 'en';
}
const { categoryTitle, categoryKey, services, lang } = Astro.props;
const base = lang === 'en' ? '/en' : '';
---
<div class="mb-12 last:mb-0">
<div class="flex items-baseline justify-between mb-6">
<h3 class="text-2xl md:text-3xl text-hds-tinta">
{categoryTitle}
</h3>
<span class="text-xs font-semibold tracking-wider uppercase text-hds-coral">
{categoryKey}
</span>
</div>
<div class="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-4 md:gap-6">
{services.map((service) => (
<ServiceCard
href={`${base}/servicios/${service.slug}/`}
title={service.title}
description={service.description}
Icon={service.Icon}
/>
))}
</div>
</div>
+140
View File
@@ -0,0 +1,140 @@
---
import ServiceCard from './ServiceCard.astro';
import SectionEyebrow from './SectionEyebrow.astro';
import type { TranslationKey } from '@/i18n/ui';
import MailIcon from './icons/MailIcon.astro';
import WordpressIcon from './icons/WordpressIcon.astro';
import CodeIcon from './icons/CodeIcon.astro';
import ShopIcon from './icons/ShopIcon.astro';
import TranslateIcon from './icons/TranslateIcon.astro';
import ServerIcon from './icons/ServerIcon.astro';
interface Props {
t: (key: TranslationKey) => string;
lang: 'es' | 'en';
}
const { t, lang } = Astro.props;
const base = lang === 'en' ? '/en' : '';
const groups = [
{
title: t('services.cat.hosting'),
items: [
{
slug: 'hosting-correo-web',
title: lang === 'en' ? 'Hosting for email & web' : 'Hosting correo y web',
desc: lang === 'en'
? 'Optimized hosting with cPanel for WordPress, PHP and MySQL.'
: 'Alojamiento optimizado con cPanel para WordPress, PHP y MySQL.',
Icon: MailIcon,
border: 'var(--color-hds-naranja)',
},
{
slug: 'mantenimiento-wordpress',
title: lang === 'en' ? 'WordPress maintenance' : 'Mantenimiento WordPress',
desc: lang === 'en'
? 'Security patches and updates by official WordPress ecosystem experts.'
: 'Parches de seguridad y actualizaciones por expertos del ecosistema WP.',
Icon: WordpressIcon,
border: 'var(--color-hds-naranja)',
},
],
},
{
title: t('services.cat.design'),
items: [
{
slug: 'desarrollo-webs-institucionales',
title: lang === 'en' ? 'Institutional websites' : 'Desarrollo webs institucionales',
desc: lang === 'en'
? 'Corporate sites tailored to your business and identity.'
: 'Sitios corporativos a medida de tu negocio e identidad.',
Icon: CodeIcon,
border: 'var(--color-hds-coral)',
},
{
slug: 'e-commerce',
title: lang === 'en' ? 'E-commerce websites' : 'Sitios web con e-commerce',
desc: lang === 'en'
? 'WooCommerce stores with secure payments and inventory.'
: 'Tiendas WooCommerce con pagos seguros y gestión de stock.',
Icon: ShopIcon,
border: 'var(--color-hds-coral)',
},
{
slug: 'gestion-contenido-traducciones',
title: lang === 'en' ? 'Content & translations' : 'Gestión de contenido y traducciones',
desc: lang === 'en'
? 'Recurring editorial: copy, updates, blog and translations.'
: 'Servicio editorial recurrente: redacción, blog, traducciones.',
Icon: TranslateIcon,
border: 'var(--color-hds-coral)',
},
],
},
{
title: t('services.cat.infra'),
items: [
{
slug: 'servidores-linux-virtualizacion',
title: lang === 'en' ? 'Linux servers & virtualization' : 'Servidores Linux y virtualización',
desc: lang === 'en'
? 'Linux servers, KVM virtualization, private clouds.'
: 'Servidores Linux, virtualización KVM, nubes privadas.',
Icon: ServerIcon,
border: 'var(--color-hds-durazno)',
},
],
},
];
---
<section id="servicios" class="py-20 md:py-28" style="background: var(--hds-bg);">
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
<div class="max-w-3xl mb-14 md:mb-20">
<SectionEyebrow text={t('services.eyebrow')} />
<h2 class="font-display leading-tight mt-5" style="font-size: clamp(2rem, 5vw, 3.5rem); color: var(--hds-fg);">
{t('services.title')}
</h2>
<p class="text-lg mt-5 max-w-2xl" style="color: var(--hds-fg-soft);">
{t('services.subtitle')}
</p>
</div>
<div class="space-y-14">
{groups.map((group) => (
<div>
<div class="flex items-baseline gap-4 mb-6">
<h3 class="text-2xl md:text-3xl font-display" style="color: var(--hds-fg);">
{group.title}
</h3>
<span class="text-xs font-semibold tracking-[0.25em] uppercase" style="color: var(--color-hds-naranja);">
{group.items.length} {group.items.length === 1 ? 'servicio' : 'servicios'}
</span>
</div>
<div class="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-5">
{group.items.map((item) => (
<ServiceCard
href={`${base}/servicios/${item.slug}/`}
title={item.title}
description={item.desc}
Icon={item.Icon}
borderColor={item.border}
/>
))}
</div>
</div>
))}
</div>
<div class="text-center mt-14">
<a href={`${base}/servicios/`} class="btn-secondary">
Ver todos los servicios
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
<line x1="5" y1="12" x2="19" y2="12"/>
<polyline points="12 5 19 12 12 19"/>
</svg>
</a>
</div>
</div>
</section>
+26
View File
@@ -0,0 +1,26 @@
---
interface Props {
size?: number;
duration?: number;
suffix?: string;
label: string;
sublabel?: string;
light?: boolean;
}
const { size = 96, duration = 2000, suffix = '', label, sublabel, light = false } = Astro.props;
const numId = `stat-${Math.random().toString(36).slice(2, 9)}`;
---
<div class="text-center group">
<div class={`stat-number font-display leading-none ${light ? 'text-white' : ''}`} style={`font-size: ${size}px; color: var(--color-hds-naranja); font-weight: 500;`} data-target={typeof label === 'string' && /^\d+$/.test(label) ? label : '0'} data-suffix={suffix} data-duration={duration} id={numId}>
{label}{suffix}
</div>
<div class={`text-sm font-semibold mt-3 ${light ? 'text-hds-crema-soft' : ''}`} style={light ? 'color: #FAF6EE' : 'color: var(--hds-fg-soft)'}>
<slot name="label">{label}</slot>
</div>
{sublabel && (
<div class={`text-xs mt-1 ${light ? 'text-hds-line' : ''}`} style={light ? 'color: #C8C2B8' : 'color: var(--hds-fg-muted)'}>
{sublabel}
</div>
)}
</div>
+35
View File
@@ -0,0 +1,35 @@
---
import type { TranslationKey } from '@/i18n/ui';
import StatCounter from './StatCounter.astro';
interface Props {
t: (key: TranslationKey) => string;
}
const { t } = Astro.props;
const stats = [
{ value: '26+', label: 'Años de experiencia', sub: 'Desde el 2000' },
{ value: '100+', label: 'Proyectos hospedados', sub: 'Webs, e-commerce, infra' },
{ value: '4', label: 'Países', sub: 'Canadá, USA, Alemania, UY' },
{ value: 'Senior', label: 'Equipo senior', sub: 'SysAdmin / SRE' },
];
---
<section class="py-20 md:py-24" style="background: var(--hds-bg); border-top: 1px solid var(--hds-line); border-bottom: 1px solid var(--hds-line);">
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
<div class="grid grid-cols-2 md:grid-cols-4 gap-10 md:gap-8">
{stats.map((stat) => (
<div class="text-center">
<div class="font-display leading-none mb-3" style="font-size: clamp(3rem, 6vw, 4.5rem); color: var(--color-hds-naranja); font-weight: 500;">
{stat.value}
</div>
<div class="text-sm font-semibold" style="color: var(--hds-fg-soft);">
{stat.label}
</div>
<div class="text-xs mt-1" style="color: var(--hds-fg-muted);">
{stat.sub}
</div>
</div>
))}
</div>
</div>
</section>
+36
View File
@@ -0,0 +1,36 @@
---
import { DEFAULT_LANG, type Lang } from '@/i18n/utils';
interface Props {
lang: Lang;
}
const { lang } = Astro.props;
const isDark = lang === 'en' ? 'dark' : 'light';
---
<button
type="button"
id="theme-toggle"
aria-label={lang === 'en' ? 'Switch theme' : 'Cambiar tema'}
class="p-2 rounded-md hover:bg-hds-line transition-colors"
style="color: var(--hds-fg-soft);"
>
<svg class="theme-icon-sun w-5 h-5 hidden dark:block" 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" aria-hidden="true">
<circle cx="12" cy="12" r="4"/>
<path d="M12 2v2M12 20v2M4.93 4.93l1.41 1.41M17.66 17.66l1.41 1.41M2 12h2M20 12h2M4.93 19.07l1.41-1.41M17.66 6.34l1.41-1.41"/>
</svg>
<svg class="theme-icon-moon w-5 h-5 block dark:hidden" 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" aria-hidden="true">
<path d="M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79z"/>
</svg>
</button>
<script is:inline>
(function() {
const btn = document.getElementById('theme-toggle');
if (!btn) return;
btn.addEventListener('click', () => {
const isDark = document.documentElement.classList.toggle('dark');
try { localStorage.setItem('theme', isDark ? 'dark' : 'light'); } catch(e) {}
});
})();
</script>
+22
View File
@@ -0,0 +1,22 @@
---
import type { Lang } from '@/i18n/utils';
interface Props {
lang: Lang;
}
const { lang } = Astro.props;
const label = lang === 'en' ? 'Chat on WhatsApp' : 'Hablar por WhatsApp';
---
<a
href="https://wa.me/59899812487"
target="_blank"
rel="noopener noreferrer"
class="fixed bottom-6 right-6 z-30 inline-flex items-center justify-center w-14 h-14 rounded-full text-white shadow-xl hover:scale-105 transition-transform"
style="background: #25D366;"
aria-label={label}
>
<svg xmlns="http://www.w3.org/2000/svg" width="28" height="28" viewBox="0 0 24 24" fill="currentColor" aria-hidden="true">
<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.475-.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-.075-.149-.669-1.612-.916-2.207-.242-.579-.487-.5-.669-.51-.173-.008-.371-.01-.57-.01-.198 0-.52.074-.792.372-.272.297-1.04 1.016-1.04 2.479 0 1.462 1.065 2.875 1.213 3.074.149.198 2.096 3.2 5.077 4.487.709.306 1.262.489 1.694.625.712.227 1.36.195 1.871.118.571-.085 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.86 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.495 0 .16 5.335.157 11.892c0 2.096.547 4.142 1.588 5.945L.057 24l6.305-1.654a11.882 11.882 0 005.683 1.448h.005c6.554 0 11.89-5.335 11.893-11.893a11.821 11.821 0 00-3.48-8.413Z"/>
</svg>
</a>
+13
View File
@@ -0,0 +1,13 @@
---
interface Props {
class?: string;
}
const { class: className = 'w-12 h-12' } = Astro.props;
---
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 48 48" fill="none" class={className} aria-hidden="true">
<path d="M14 30 Q8 24 14 18" stroke="#EE7623" stroke-width="2.5" fill="none" stroke-linecap="round"/>
<path d="M34 30 Q40 24 34 18" stroke="#EE7623" stroke-width="2.5" fill="none" stroke-linecap="round"/>
<rect x="20" y="16" width="8" height="20" rx="2" fill="#FA9F5C"/>
<circle cx="24" cy="10" r="2" fill="#EE7623"/>
<path d="M22 12 Q22 14 24 16 M26 12 Q26 14 24 16" stroke="#EE7623" stroke-width="1.2" fill="none" stroke-linecap="round"/>
</svg>
+16
View File
@@ -0,0 +1,16 @@
---
interface Props {
class?: string;
}
const { class: className = 'w-12 h-12' } = Astro.props;
---
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 48 48" fill="none" class={className} aria-hidden="true">
<path d="M16 8 L8 24 L16 40" stroke="#EE7623" stroke-width="2.5" fill="none" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M32 8 L40 24 L32 40" stroke="#EE7623" stroke-width="2.5" fill="none" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M28 10 L20 38" stroke="#FA9F5C" stroke-width="2.5" fill="none" stroke-linecap="round"/>
<path d="M11 28 L37 28" stroke="#FA9F5C" stroke-width="2.5" fill="none" stroke-linecap="round"/>
<rect x="6" y="6" width="3" height="3" fill="#FFCBA1"/>
<rect x="39" y="6" width="3" height="3" fill="#FFCBA1"/>
<rect x="6" y="39" width="3" height="3" fill="#FFCBA1"/>
<rect x="39" y="39" width="3" height="3" fill="#FFCBA1"/>
</svg>
+14
View File
@@ -0,0 +1,14 @@
---
interface Props {
class?: string;
}
const { class: className = 'w-12 h-12' } = Astro.props;
---
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 48 48" fill="none" class={className} aria-hidden="true">
<circle cx="24" cy="24" r="18" fill="none" stroke="#EE7623" stroke-width="2"/>
<ellipse cx="24" cy="24" rx="8" ry="18" fill="none" stroke="#EE7623" stroke-width="1.5"/>
<path d="M6 24 L42 24" stroke="#EE7623" stroke-width="1.5"/>
<path d="M9 14 Q24 18 39 14" stroke="#FA9F5C" stroke-width="1.5" fill="none"/>
<path d="M9 34 Q24 30 39 34" stroke="#FA9F5C" stroke-width="1.5" fill="none"/>
<circle cx="24" cy="24" r="2" fill="#EE7623"/>
</svg>
+17
View File
@@ -0,0 +1,17 @@
---
interface Props {
class?: string;
}
const { class: className = 'w-12 h-12' } = Astro.props;
---
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 48 48" fill="none" class={className} aria-hidden="true">
<rect x="8" y="14" width="26" height="20" rx="2" fill="#EE7623"/>
<path d="M34 18 L38 18 Q42 18 42 22 Q42 26 38 26 L34 26" stroke="#EE7623" stroke-width="2.5" fill="none" stroke-linecap="round"/>
<path d="M34 22 L38 22 Q40 22 40 24" stroke="#FA9F5C" stroke-width="1.5" fill="none" stroke-linecap="round"/>
<path d="M21 8 L21 14" stroke="#FA9F5C" stroke-width="2" stroke-linecap="round"/>
<path d="M15 8 L15 14" stroke="#FA9F5C" stroke-width="2" stroke-linecap="round"/>
<path d="M27 8 L27 14" stroke="#FA9F5C" stroke-width="2" stroke-linecap="round"/>
<rect x="12" y="20" width="6" height="2" fill="#FAF6EE" rx="1"/>
<rect x="12" y="24" width="10" height="2" fill="#FAF6EE" rx="1" opacity="0.7"/>
<rect x="12" y="28" width="8" height="2" fill="#FAF6EE" rx="1" opacity="0.5"/>
</svg>
+20
View File
@@ -0,0 +1,20 @@
---
interface Props {
class?: string;
}
const { class: className = 'w-12 h-12' } = Astro.props;
---
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 48 48" fill="none" class={className} aria-hidden="true">
<circle cx="24" cy="32" r="6" fill="#EE7623"/>
<path d="M24 26 L24 18" stroke="#EE7623" stroke-width="2.5" stroke-linecap="round"/>
<path d="M16 8 L16 18" stroke="#FA9F5C" stroke-width="2.5" stroke-linecap="round"/>
<path d="M32 8 L32 18" stroke="#FA9F5C" stroke-width="2.5" stroke-linecap="round"/>
<path d="M14 18 Q24 12 34 18" stroke="#EE7623" stroke-width="2.5" fill="none" stroke-linecap="round"/>
<path d="M14 18 L34 18" stroke="#EE7623" stroke-width="2.5" stroke-linecap="round"/>
<rect x="11" y="6" width="4" height="4" fill="#FFCBA1" rx="0.5"/>
<rect x="17" y="6" width="4" height="4" fill="#FFCBA1" rx="0.5"/>
<rect x="27" y="6" width="4" height="4" fill="#FFCBA1" rx="0.5"/>
<rect x="33" y="6" width="4" height="4" fill="#FFCBA1" rx="0.5"/>
<path d="M19 32 Q19 36 22 38" stroke="#FA9F5C" stroke-width="1.5" fill="none" stroke-linecap="round"/>
<path d="M29 32 Q29 36 26 38" stroke="#FA9F5C" stroke-width="1.5" fill="none" stroke-linecap="round"/>
</svg>
+18
View File
@@ -0,0 +1,18 @@
---
interface Props {
class?: string;
}
const { class: className = 'w-12 h-12' } = Astro.props;
---
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 48 48" fill="none" class={className} aria-hidden="true">
<rect x="8" y="12" width="14" height="10" rx="1" fill="#EE7623"/>
<rect x="26" y="12" width="14" height="10" rx="1" fill="#EE7623"/>
<rect x="8" y="26" width="14" height="10" rx="1" fill="#FA9F5C"/>
<rect x="26" y="26" width="14" height="10" rx="1" fill="#FA9F5C"/>
<circle cx="15" cy="17" r="1.5" fill="#FAF6EE"/>
<circle cx="33" cy="17" r="1.5" fill="#FAF6EE"/>
<circle cx="15" cy="31" r="1.5" fill="#FAF6EE"/>
<circle cx="33" cy="31" r="1.5" fill="#FAF6EE"/>
<path d="M22 17 L22 31" stroke="#FFCBA1" stroke-width="2" stroke-linecap="round"/>
<path d="M15 22 L33 22" stroke="#FFCBA1" stroke-width="2" stroke-linecap="round"/>
</svg>
+15
View File
@@ -0,0 +1,15 @@
---
interface Props {
class?: string;
}
const { class: className = 'w-12 h-12' } = Astro.props;
---
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 48 48" fill="none" class={className} aria-hidden="true">
<path d="M10 14 L10 38 L38 38 L38 18 L30 10 L10 14 Z" fill="#EE7623" stroke="#EE7623" stroke-width="2" stroke-linejoin="round"/>
<path d="M30 10 L30 18 L38 18" fill="none" stroke="#FAF6EE" stroke-width="2" stroke-linejoin="round"/>
<rect x="14" y="22" width="20" height="2" fill="#FAF6EE" rx="1"/>
<rect x="14" y="26" width="14" height="2" fill="#FAF6EE" rx="1" opacity="0.7"/>
<rect x="14" y="30" width="10" height="2" fill="#FAF6EE" rx="1" opacity="0.5"/>
<path d="M32 28 L40 22 L40 32 L32 36 Z" fill="#FA9F5C" stroke="#FA9F5C" stroke-width="1.5" stroke-linejoin="round"/>
<circle cx="36" cy="29" r="1.2" fill="#FAF6EE"/>
</svg>
@@ -0,0 +1,13 @@
---
interface Props {
class?: string;
}
const { class: className = 'w-12 h-12' } = Astro.props;
---
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 48 48" fill="none" class={className} aria-hidden="true">
<rect x="10" y="20" width="28" height="20" rx="2" fill="none" stroke="#EE7623" stroke-width="2.5"/>
<path d="M18 20 L18 14 Q18 10 22 10 L26 10 Q30 10 30 14 L30 20" fill="none" stroke="#EE7623" stroke-width="2.5" stroke-linejoin="round"/>
<circle cx="24" cy="30" r="2.5" fill="#FA9F5C"/>
<path d="M24 32.5 L24 36" stroke="#FA9F5C" stroke-width="2" stroke-linecap="round"/>
<rect x="8" y="38" width="32" height="2" fill="#FFCBA1" rx="1"/>
</svg>
+16
View File
@@ -0,0 +1,16 @@
---
interface Props {
class?: string;
}
const { class: className = 'w-12 h-12' } = Astro.props;
---
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 48 48" fill="none" class={className} aria-hidden="true">
<rect x="8" y="14" width="22" height="20" rx="1" fill="#EE7623"/>
<path d="M30 14 L40 14 L40 34 L30 34" fill="none" stroke="#EE7623" stroke-width="2.5"/>
<path d="M30 14 L30 34" stroke="#EE7623" stroke-width="2.5"/>
<path d="M34 18 L40 18 M34 22 L40 22 M34 26 L40 26" stroke="#FA9F5C" stroke-width="1.5" stroke-linecap="round"/>
<path d="M12 20 L20 20 M12 24 L26 24 M12 28 L22 28" stroke="#FAF6EE" stroke-width="1.8" stroke-linecap="round"/>
<path d="M22 30 L26 26 M26 30 L22 26" stroke="#FFCBA1" stroke-width="1.8" stroke-linecap="round"/>
<circle cx="32" cy="10" r="3" fill="#FA9F5C"/>
<path d="M32 8 L32 12 M30 10 L34 10" stroke="#FAF6EE" stroke-width="1.2" stroke-linecap="round"/>
</svg>
+19
View File
@@ -0,0 +1,19 @@
---
interface Props {
class?: string;
}
const { class: className = 'w-12 h-12' } = Astro.props;
---
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 48 48" fill="none" class={className} aria-hidden="true">
<rect x="8" y="10" width="32" height="28" rx="3" fill="none" stroke="#EE7623" stroke-width="2.5"/>
<circle cx="24" cy="24" r="8" fill="none" stroke="#EE7623" stroke-width="2.5"/>
<path d="M16 14 L24 22 L32 14" stroke="#FA9F5C" stroke-width="2" fill="none" stroke-linecap="round" stroke-linejoin="round"/>
<rect x="11" y="6" width="3" height="3" fill="#FFCBA1" rx="0.5"/>
<rect x="14" y="6" width="3" height="3" fill="#FFCBA1" rx="0.5"/>
<rect x="31" y="6" width="3" height="3" fill="#FFCBA1" rx="0.5"/>
<rect x="34" y="6" width="3" height="3" fill="#FFCBA1" rx="0.5"/>
<rect x="6" y="11" width="3" height="3" fill="#FA9F5C" rx="0.5"/>
<rect x="6" y="14" width="3" height="3" fill="#FA9F5C" rx="0.5"/>
<rect x="39" y="31" width="3" height="3" fill="#FA9F5C" rx="0.5"/>
<rect x="39" y="34" width="3" height="3" fill="#FA9F5C" rx="0.5"/>
</svg>
+69
View File
@@ -0,0 +1,69 @@
---
interface Props {
class?: string;
}
const { class: className = '' } = Astro.props;
---
<svg viewBox="0 0 1000 500" xmlns="http://www.w3.org/2000/svg" class={className} aria-hidden="true">
<defs>
<linearGradient id="mapGrad" x1="0" x2="0" y1="0" y2="1">
<stop offset="0" stop-color="#EE7623" stop-opacity="0.05"/>
<stop offset="1" stop-color="#EE7623" stop-opacity="0.12"/>
</linearGradient>
</defs>
<path
d="M 130,140 Q 90,180 110,230 Q 90,290 140,330 Q 180,360 230,340 Q 280,330 290,290 Q 320,250 300,210 Q 280,160 230,140 Q 180,120 130,140 Z"
fill="url(#mapGrad)" stroke="var(--color-hds-naranja)" stroke-width="1.5" stroke-dasharray="4 3" opacity="0.5"
/>
<path
d="M 280,180 Q 320,150 380,160 Q 440,150 470,180 Q 480,210 460,240 Q 420,270 380,260 Q 330,250 300,230 Q 270,210 280,180 Z"
fill="url(#mapGrad)" stroke="var(--color-hds-naranja)" stroke-width="1.5" stroke-dasharray="4 3" opacity="0.5"
/>
<path
d="M 470,200 Q 510,180 560,190 Q 610,200 620,240 Q 600,280 550,290 Q 500,290 470,260 Q 450,230 470,200 Z"
fill="url(#mapGrad)" stroke="var(--color-hds-naranja)" stroke-width="1.5" stroke-dasharray="4 3" opacity="0.5"
/>
<path
d="M 620,290 Q 670,300 720,330 Q 770,360 800,400 Q 820,440 780,460 Q 730,470 680,440 Q 640,410 620,370 Q 600,330 620,290 Z"
fill="url(#mapGrad)" stroke="var(--color-hds-naranja)" stroke-width="1.5" stroke-dasharray="4 3" opacity="0.5"
/>
<g>
<circle cx="170" cy="240" r="8" fill="var(--color-hds-naranja)">
<animate attributeName="r" values="6;10;6" dur="2.5s" repeatCount="indefinite"/>
<animate attributeName="opacity" values="0.4;0;0.4" dur="2.5s" repeatCount="indefinite"/>
</circle>
<circle cx="170" cy="240" r="5" fill="var(--color-hds-naranja)"/>
<text x="170" y="220" text-anchor="middle" font-size="14" font-weight="600" fill="var(--hds-fg)">Canadá</text>
</g>
<g>
<circle cx="370" cy="210" r="8" fill="var(--color-hds-naranja)">
<animate attributeName="r" values="6;10;6" dur="2.5s" begin="0.4s" repeatCount="indefinite"/>
<animate attributeName="opacity" values="0.4;0;0.4" dur="2.5s" begin="0.4s" repeatCount="indefinite"/>
</circle>
<circle cx="370" cy="210" r="5" fill="var(--color-hds-naranja)"/>
<text x="370" y="190" text-anchor="middle" font-size="14" font-weight="600" fill="var(--hds-fg)">USA</text>
</g>
<g>
<circle cx="540" cy="230" r="8" fill="var(--color-hds-naranja)">
<animate attributeName="r" values="6;10;6" dur="2.5s" begin="0.8s" repeatCount="indefinite"/>
<animate attributeName="opacity" values="0.4;0;0.4" dur="2.5s" begin="0.8s" repeatCount="indefinite"/>
</circle>
<circle cx="540" cy="230" r="5" fill="var(--color-hds-naranja)"/>
<text x="540" y="210" text-anchor="middle" font-size="14" font-weight="600" fill="var(--hds-fg)">Alemania</text>
</g>
<g>
<circle cx="720" cy="390" r="10" fill="var(--color-hds-naranja)">
<animate attributeName="r" values="8;14;8" dur="2.5s" begin="1.2s" repeatCount="indefinite"/>
<animate attributeName="opacity" values="0.4;0;0.4" dur="2.5s" begin="1.2s" repeatCount="indefinite"/>
</circle>
<circle cx="720" cy="390" r="6" fill="var(--color-hds-naranja)"/>
<circle cx="720" cy="390" r="2.5" fill="white"/>
<text x="720" y="370" text-anchor="middle" font-size="14" font-weight="600" fill="var(--hds-fg)">Uruguay</text>
<text x="720" y="425" text-anchor="middle" font-size="10" fill="var(--hds-fg-muted)">Sede operativa</text>
</g>
</svg>
+103
View File
@@ -0,0 +1,103 @@
# Contact Form — PHP endpoint
Este endpoint vive en `server1` y procesa los envíos del formulario de `/contacto`.
## ⚠️ NO se deploya con Astro. Es solo template.
## Setup en server1 (Netcup, cPanel)
### 1. Crear cuenta de correo dedicada
En cPanel → Email Accounts, crear:
- **Email**: `no-reply@hostingdelsur.net` (Mauri confirma que ya existe)
- **Password**: contraseña fuerte (mínimo 16 caracteres, símbolos, números)
- **Quota**: 1 GB (solo se usa para SMTP, no recibe correo)
### 2. Crear archivo de credenciales
El archivo se crea en `/home/hostingdelsur/.smtp-credentials.json` (NO en `public_html/`, por seguridad).
Contenido (reemplazar PEGAR_AQUI con la password real):
```json
{
"host": "localhost",
"port": 465,
"username": "no-reply@hostingdelsur.net",
"password": "PEGAR_AQUI",
"encryption": "ssl",
"from": "no-reply@hostingdelsur.net",
"fromName": "Hosting del Sur - Web",
"to": "contacto@hostingdelsur.net"
}
```
Por SSH:
```bash
chmod 600 /home/hostingdelsur/.smtp-credentials.json
chown hostingdelsur:hostingdelsur /home/hostingdelsur/.smtp-credentials.json
```
### 3. Subir PHPMailer (ya subido en este deploy)
```bash
# Ya ejecutado durante el deploy:
mkdir -p /home/hostingd/private/PHPMailer
# 3 archivos copiados: Exception.php, PHPMailer.php, SMTP.php
chmod 640 /home/hostingd/private/PHPMailer/*.php
chown -R hostingdelsur:hostingdelsur /home/hostingd/private
```
### 4. Subir el endpoint (ya subido)
```
/home/hostingd/public_html/api/contact.php
/home/hostingd/public_html/api/.htaccess
```
El `.htaccess` deniega todo excepto POST al endpoint. Ya configurado.
### 5. Variables de entorno opcionales (reCAPTCHA secret)
Para activar validación reCAPTCHA v3 server-side, agregar en el `.htaccess` o php.ini del server:
```bash
# SetEnv RECAPTCHA_SECRET "6LeOxaEaAAAAAM5OODBE2p9bknosuxpW7Gg17fKG"
```
O en cPanel → MultiPHP INI Editor:
```ini
env[RECAPTCHA_SECRET] = "6LeOxaEaAAAAAM5OODBE2p9bknosuxpW7Gg17fKG"
```
### 6. Test
```bash
curl -X POST https://hostingdelsur.net/api/contact.php \
-d "name=Test&[email protected]&message=Hola&lang=es"
```
Debe devolver `{"ok":true}`. Sin reCAPTCHA token primero, con token después.
## Seguridad implementada
- ✅ Credenciales fuera de `public_html/` (en `~/`)
- ✅ Permisos `chmod 600` (solo el usuario puede leer)
- ✅ Honeypot (`website` field) anti-bot
- ✅ Validación y sanitización de inputs
-`Reply-To` con email del visitante para responder
-`From` con la cuenta dedicada (no spoofing)
- ✅ TLS obligatorio (puerto 465 + `ssl`)
- ✅ Rate limit básico por IP (3 envíos/hora) vía `apcu_fetch/store`
- ✅ Headers anti-cache y anti-sniff
- ✅ Mensaje de error genérico (no expone detalles internos)
- ✅ reCAPTCHA v3 invisible (con score ≥ 0.3) si se configura `RECAPTCHA_SECRET`
## Pendiente
- [ ] Mauri debe re-enviar la password de `no-reply@` (Mauri la puso en chat originalmente; el deploy la borró del servidor)
- [ ] Mauri debe crear el archivo `~/.smtp-credentials.json` con la password real
- [ ] (Opcional) Configurar `RECAPTCHA_SECRET` en el environment del server
+144
View File
@@ -0,0 +1,144 @@
<?php
/**
* hostingdelsur.net — Contact form endpoint
*
* Lee credenciales SMTP de ~/.smtp-credentials.json (fuera de public_html)
* y envía el mail vía PHPMailer. Valida reCAPTCHA v3 (opcional si no hay token).
*
* Setup: ver src/forms/README.md
*/
declare(strict_types=1);
header('Content-Type: application/json; charset=utf-8');
header('X-Content-Type-Options: nosniff');
header('Referrer-Policy: same-origin');
header('X-Frame-Options: DENY');
require_once __DIR__ . '/../../private/PHPMailer/Exception.php';
require_once __DIR__ . '/../../private/PHPMailer/PHPMailer.php';
require_once __DIR__ . '/../../private/PHPMailer/SMTP.php';
use PHPMailer\PHPMailer\PHPMailer;
use PHPMailer\PHPMailer\Exception;
if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
http_response_code(405);
header('Allow: POST');
echo json_encode(['ok' => false, 'error' => 'Método no permitido']);
exit;
}
$reCAPTCHA_secret = getenv('RECAPTCHA_SECRET') ?: ($_SERVER['RECAPTCHA_SECRET'] ?? '');
$credsPath = (($_SERVER['HOME'] ?? '') ?: '/home/hostingdelsur') . '/.smtp-credentials.json';
if (!is_readable($credsPath)) {
error_log('contact.php: credenciales no disponibles en ' . $credsPath);
http_response_code(500);
echo json_encode(['ok' => false, 'error' => 'Configuración no disponible']);
exit;
}
try {
$credsRaw = file_get_contents($credsPath);
if ($credsRaw === false) {
throw new RuntimeException('No se pudo leer el archivo de credenciales');
}
$creds = json_decode($credsRaw, true, 8, JSON_THROW_ON_ERROR);
} catch (Throwable $e) {
error_log('contact.php: credenciales inválidas — ' . $e->getMessage());
http_response_code(500);
echo json_encode(['ok' => false, 'error' => 'Configuración inválida']);
exit;
}
if (!empty($_POST['website'])) {
echo json_encode(['ok' => true]);
exit;
}
$name = trim((string) filter_input(INPUT_POST, 'name', FILTER_SANITIZE_SPECIAL_CHARS));
$email = trim((string) filter_input(INPUT_POST, 'email', FILTER_VALIDATE_EMAIL));
$message = trim((string) filter_input(INPUT_POST, 'message', FILTER_SANITIZE_SPECIAL_CHARS));
$lang = in_array($_POST['lang'] ?? '', ['es', 'en'], true) ? $_POST['lang'] : 'es';
$recaptchaToken = trim((string) ($_POST['g-recaptcha-response'] ?? ''));
if ($name === '' || !$email || $message === '' || mb_strlen($message) > 5000) {
http_response_code(400);
echo json_encode(['ok' => false, 'error' => 'Datos inválidos']);
exit;
}
if ($reCAPTCHA_secret !== '' && $recaptchaToken !== '') {
$verifyUrl = 'https://www.google.com/recaptcha/api/siteverify';
$ch = curl_init();
curl_setopt_array($ch, [
CURLOPT_URL => $verifyUrl,
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => http_build_query([
'secret' => $reCAPTCHA_secret,
'response' => $recaptchaToken,
'remoteip' => $_SERVER['REMOTE_ADDR'] ?? '',
]),
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 5,
CURLOPT_SSL_VERIFYPEER => true,
]);
$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
if ($response !== false && $httpCode === 200) {
$verification = json_decode($response, true);
if (!is_array($verification) || empty($verification['success']) || ($verification['score'] ?? 1) < 0.3) {
error_log('contact.php: reCAPTCHA failed — ' . json_encode($verification));
http_response_code(400);
echo json_encode(['ok' => false, 'error' => 'Verificación de seguridad falló']);
exit;
}
}
} elseif ($reCAPTCHA_secret !== '' && $recaptchaToken === '') {
error_log('contact.php: reCAPTCHA token missing');
}
$ip = $_SERVER['REMOTE_ADDR'] ?? 'unknown';
$rateKey = "contact_rl_{$ip}";
if (function_exists('apcu_fetch')) {
$hits = apcu_fetch($rateKey) ?: 0;
if ($hits >= 3) {
http_response_code(429);
header('Retry-After: 3600');
echo json_encode(['ok' => false, 'error' => 'Demasiados envíos. Probá más tarde.']);
exit;
}
apcu_store($rateKey, $hits + 1, 3600);
}
$mail = new PHPMailer(true);
try {
$mail->isSMTP();
$mail->Host = (string) $creds['host'];
$mail->SMTPAuth = true;
$mail->Username = (string) $creds['username'];
$mail->Password = (string) $creds['password'];
$mail->SMTPSecure = (string) ($creds['encryption'] ?? 'ssl');
$mail->Port = (int) ($creds['port'] ?? 465);
$mail->CharSet = 'UTF-8';
$mail->Timeout = 10;
$mail->setFrom((string) $creds['from'], (string) ($creds['fromName'] ?? 'Hosting del Sur'));
$mail->addAddress((string) $creds['to']);
$mail->addReplyTo($email, $name);
$mail->Subject = "Contacto desde hostingdelsur.net: {$name}";
$body = "Nombre: {$name}\nEmail: {$email}\nIdioma: {$lang}\nIP: {$ip}\n\nMensaje:\n{$message}";
$mail->Body = $body;
$mail->AltBody = $body;
$mail->send();
echo json_encode(['ok' => true]);
} catch (Exception $e) {
error_log('contact.php: PHPMailer error — ' . $e->getMessage());
http_response_code(500);
echo json_encode(['ok' => false, 'error' => 'No se pudo enviar el mensaje']);
}
+111
View File
@@ -0,0 +1,111 @@
export const ui = {
es: {
'nav.home': 'Inicio',
'nav.services': 'Servicios',
'nav.plans': 'Planes',
'nav.about': 'Nosotros',
'nav.tutorials': 'Instructivos',
'nav.contact': 'Contacto',
'nav.cta': 'Hablar por WhatsApp',
'hero.eyebrow': 'Tu proveedor de soluciones digitales',
'hero.title': 'Alojamiento en la nube, cerca y en tu idioma',
'hero.body': 'Olvidate de las complejidades técnicas. Nuestro equipo te brinda asesoramiento y soporte personalizado para que tu proyecto en la web funcione sin complicaciones. Te brindamos la misma tecnología que los gigantes tecnológicos, con una atención cercana y personalizada.',
'hero.ctaPrimary': 'Hablar con un humano',
'hero.ctaSecondary': 'Ver servicios',
'diff.eyebrow': 'La diferencia',
'diff.title': 'Por qué elegirnos',
'diff.subtitle': 'Tu proyecto merece un socio tecnológico, no solo un hosting.',
'diff.support.title': 'Soporte técnico real',
'diff.support.body': 'Olvidate de los intermediarios y los tickets infinitos. Hablás directamente con profesionales senior (SysAdmin/SRE) que entienden tu negocio y resuelven de verdad.',
'diff.sovereignty.title': 'Soberanía y privacidad de datos',
'diff.sovereignty.body': 'Ponemos el foco en que seas el único dueño de tu información. Sabemos exactamente dónde están tus datos y quién tiene acceso a ellos, garantizando una privacidad que las nubes masivas no ofrecen.',
'diff.infra.title': 'Infraestructura global y escalable',
'diff.infra.body': 'Con presencia internacional desde el año 2000 y tecnología Open Source (GNU/Linux), te brindamos una plataforma robusta que te permite crecer sin pagar costos excesivos de licenciamiento.',
'services.eyebrow': 'Lo que hacemos',
'services.title': 'Nuestros servicios',
'services.subtitle': 'Acompañamos a tu empresa en cada paso, desde el hosting hasta la infraestructura compleja.',
'services.cat.hosting': 'Hosting & Correo',
'services.cat.design': 'Diseño & Contenido',
'services.cat.infra': 'Infraestructura',
'services.viewDetail': 'Ver detalle',
'process.eyebrow': 'Cómo trabajamos',
'process.title': 'Del primer mate al proyecto en marcha',
'process.step1.title': 'Charlamos',
'process.step1.body': 'Nos contás tu proyecto. Te escuchamos sin tecnicismos ni promesas vacías.',
'process.step2.title': 'Diseñamos',
'process.step2.body': 'Te proponemos la mejor solución a tu medida, con costos claros.',
'process.step3.title': 'Desplegamos',
'process.step3.body': 'Implementamos todo sin que tengas que preocuparte por detalles técnicos.',
'process.step4.title': 'Te acompañamos',
'process.step4.body': 'Soporte humano continuo, no tickets automáticos ni respuestas genéricas.',
'ctaFinal.eyebrow': 'Hablemos',
'ctaFinal.title': '¿Listo para charlar?',
'ctaFinal.body': 'Escribinos por WhatsApp y te respondemos personas reales, no bots.',
'ctaFinal.button': 'Hablar por WhatsApp',
'footer.tagline': 'Alojamiento en la nube, cerca y en tu idioma.',
'footer.contact': 'Contacto',
'footer.nav': 'Navegación',
'footer.legal': 'Legal',
'footer.privacy': 'Privacidad',
'footer.terms': 'Términos',
'footer.copyright': 'Todos los derechos reservados.',
'lang.toggle': 'EN',
'lang.label': 'Cambiar idioma',
},
en: {
'nav.home': 'Home',
'nav.services': 'Services',
'nav.plans': 'Plans',
'nav.about': 'About',
'nav.tutorials': 'Tutorials',
'nav.contact': 'Contact',
'nav.cta': 'Chat on WhatsApp',
'hero.eyebrow': 'Your digital solutions provider',
'hero.title': 'Cloud hosting, close by and in your language',
'hero.body': 'Forget technical complexity. Our team gives you personalized advice and support so your web project runs smoothly. We offer the same technology as the tech giants, with a close, human touch.',
'hero.ctaPrimary': 'Talk to a human',
'hero.ctaSecondary': 'See services',
'diff.eyebrow': 'The difference',
'diff.title': 'Why choose us',
'diff.subtitle': 'Your project deserves a technology partner, not just a hosting provider.',
'diff.support.title': 'Real technical support',
'diff.support.body': 'Forget middlemen and endless tickets. You talk directly to senior professionals (SysAdmin/SRE) who understand your business and actually solve things.',
'diff.sovereignty.title': 'Data sovereignty and privacy',
'diff.sovereignty.body': 'We focus on you being the sole owner of your data. We know exactly where your data is and who has access, guaranteeing a privacy that massive clouds cannot offer.',
'diff.infra.title': 'Global, scalable infrastructure',
'diff.infra.body': 'With international presence since 2000 and Open Source technology (GNU/Linux), we offer a robust platform that lets you grow without paying excessive licensing fees.',
'services.eyebrow': 'What we do',
'services.title': 'Our services',
'services.subtitle': 'We support your business at every step, from hosting to complex infrastructure.',
'services.cat.hosting': 'Hosting & Email',
'services.cat.design': 'Design & Content',
'services.cat.infra': 'Infrastructure',
'services.viewDetail': 'View details',
'process.eyebrow': 'How we work',
'process.title': 'From the first chat to a live project',
'process.step1.title': 'We listen',
'process.step1.body': 'Tell us about your project. We listen without jargon or empty promises.',
'process.step2.title': 'We design',
'process.step2.body': 'We propose the best tailor-made solution, with clear costs.',
'process.step3.title': 'We deploy',
'process.step3.body': 'We handle all the implementation so you do not worry about technical details.',
'process.step4.title': 'We support',
'process.step4.body': 'Continuous human support, not automated tickets or generic answers.',
'ctaFinal.eyebrow': 'Let us talk',
'ctaFinal.title': 'Ready to chat?',
'ctaFinal.body': 'Message us on WhatsApp and real people will reply, not bots.',
'ctaFinal.button': 'Chat on WhatsApp',
'footer.tagline': 'Cloud hosting, close by and in your language.',
'footer.contact': 'Contact',
'footer.nav': 'Navigation',
'footer.legal': 'Legal',
'footer.privacy': 'Privacy',
'footer.terms': 'Terms',
'footer.copyright': 'All rights reserved.',
'lang.toggle': 'ES',
'lang.label': 'Switch language',
},
} as const;
export type Lang = keyof typeof ui;
export type TranslationKey = keyof typeof ui.es;
+25
View File
@@ -0,0 +1,25 @@
import { ui, type Lang, type TranslationKey } from './ui';
export const LANGUAGES: { code: Lang; label: string }[] = [
{ code: 'es', label: 'ES' },
{ code: 'en', label: 'EN' },
];
export const DEFAULT_LANG: Lang = 'es';
export function getLangFromUrl(url: URL): Lang {
const [, lang] = url.pathname.split('/');
return lang === 'en' ? 'en' : 'es';
}
export function useTranslations(lang: Lang) {
return function t(key: TranslationKey): string {
return ui[lang][key] ?? ui.es[key];
};
}
export function pathForLang(path: string, targetLang: Lang): string {
const cleanPath = path.replace(/^\/(en|es)/, '') || '/';
if (targetLang === DEFAULT_LANG) return cleanPath;
return `/${targetLang}${cleanPath === '/' ? '' : cleanPath}`;
}
+126
View File
@@ -0,0 +1,126 @@
---
import { getLangFromUrl, useTranslations, type Lang } from '@/i18n/utils';
interface Props {
title: string;
description: string;
ogImage?: string;
canonical?: string;
lang?: Lang;
pageType?: 'website' | 'article';
}
const { title, description, ogImage = '/og-image.jpg', canonical, lang, pageType = 'website' } = Astro.props;
const currentLang = lang ?? getLangFromUrl(Astro.url);
const t = useTranslations(currentLang);
const siteUrl = Astro.site?.toString().replace(/\/$/, '') ?? 'https://hostingdelsur.net';
const canonicalUrl = canonical ? `${siteUrl}${canonical}` : `${siteUrl}${Astro.url.pathname}`;
import '@/styles/global.css';
import Navbar from '@/components/Navbar.astro';
import Footer from '@/components/Footer.astro';
import WhatsappFab from '@/components/WhatsappFab.astro';
import BackToTop from '@/components/BackToTop.astro';
const orgJsonLd = {
'@context': 'https://schema.org',
'@type': 'Organization',
name: 'Hosting del Sur',
url: siteUrl,
logo: `${siteUrl}/logo/hds-color.svg`,
description: description,
telephone: '+59899812487',
email: 'contacto@hostingdelsur.net',
address: {
'@type': 'PostalAddress',
addressCountry: 'UY',
addressLocality: 'Maldonado',
},
areaServed: [
{ '@type': 'Country', name: 'Uruguay' },
{ '@type': 'Country', name: 'Canada' },
{ '@type': 'Country', name: 'United States' },
{ '@type': 'Country', name: 'Germany' },
],
};
const localBusinessJsonLd = {
'@context': 'https://schema.org',
'@type': 'ProfessionalService',
name: 'Hosting del Sur',
image: `${siteUrl}/og-image.jpg`,
'@id': siteUrl,
url: siteUrl,
telephone: '+59899812487',
email: 'contacto@hostingdelsur.net',
priceRange: '$$',
address: {
'@type': 'PostalAddress',
addressCountry: 'UY',
addressLocality: 'Maldonado',
},
areaServed: [
{ '@type': 'Country', name: 'Uruguay' },
{ '@type': 'Country', name: 'Canada' },
{ '@type': 'Country', name: 'United States' },
{ '@type': 'Country', name: 'Germany' },
],
};
---
<!doctype html>
<html lang={currentLang}>
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta name="theme-color" content="#FAF6EE" media="(prefers-color-scheme: light)" />
<meta name="theme-color" content="#1A1612" media="(prefers-color-scheme: dark)" />
<title>{title} | Hosting del Sur</title>
<meta name="description" content={description} />
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
<link rel="canonical" href={canonicalUrl} />
<meta property="og:type" content={pageType} />
<meta property="og:url" content={canonicalUrl} />
<meta property="og:title" content={`${title} | Hosting del Sur`} />
<meta property="og:description" content={description} />
<meta property="og:image" content={`${siteUrl}${ogImage}`} />
<meta property="og:locale" content={currentLang === 'en' ? 'en_US' : 'es_UY'} />
<meta property="og:site_name" content="Hosting del Sur" />
<meta name="twitter:card" content="summary_large_image" />
<meta name="twitter:title" content={`${title} | Hosting del Sur`} />
<meta name="twitter:description" content={description} />
<meta name="twitter:image" content={`${siteUrl}${ogImage}`} />
<link rel="alternate" hreflang="es" href={`${siteUrl}${currentLang === 'en' ? '/' : Astro.url.pathname.replace(/^\/en/, '')}`} />
<link rel="alternate" hreflang="en" href={`${siteUrl}/en${Astro.url.pathname.replace(/^\/en/, '') || ''}`} />
<script type="application/ld+json" set:html={JSON.stringify(orgJsonLd)} />
<script type="application/ld+json" set:html={JSON.stringify(localBusinessJsonLd)} />
<script is:inline>
(function() {
try {
var stored = localStorage.getItem('theme');
var prefersDark = window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches;
var theme = stored || (prefersDark ? 'dark' : 'light');
if (theme === 'dark') {
document.documentElement.classList.add('dark');
}
} catch(e) {}
})();
</script>
</head>
<body>
<a href="#main" class="skip-link">
{currentLang === 'en' ? 'Skip to content' : 'Saltar al contenido'}
</a>
<Navbar t={t} lang={currentLang} />
<main id="main">
<slot />
</main>
<Footer t={t} lang={currentLang} />
<WhatsappFab lang={currentLang} />
<BackToTop />
</body>
</html>
+69
View File
@@ -0,0 +1,69 @@
export interface Plan {
slug: string;
name: string;
priceUsdYear: number;
recommended?: boolean;
features: string[];
featuresEn?: string[];
}
export const PLANS: Plan[] = [
{
slug: 'basico',
name: 'Básico',
priceUsdYear: 59,
recommended: false,
features: [
'5 GB espacio en disco',
'10 cuentas de correo',
'SSL gratis (Let\'s Encrypt)',
'Backups automáticos diarios',
'cPanel incluido',
'Soporte técnico real',
],
},
{
slug: 'institucional',
name: 'Institucional',
priceUsdYear: 129,
recommended: true,
features: [
'15 GB espacio en disco',
'30 cuentas de correo',
'1 base de datos MySQL',
'1 dominio parqueado',
'250% CPU speed',
'2 GB RAM',
'Soporte prioritario',
],
},
{
slug: 'e-commerce',
name: 'E-commerce',
priceUsdYear: 219,
recommended: false,
features: [
'30 GB espacio en disco',
'50 cuentas de correo',
'3 bases de datos MySQL',
'3 dominios parkados',
'300% CPU speed',
'2.5 GB RAM',
'Soporte prioritario',
'Optimización para WooCommerce',
],
},
];
export const ADDITIONAL_PLANS = [
'WordPress',
'Empresarial',
'Avanzado',
'Avanzado HD',
'Corporativo',
'Corporativo HD',
];
export function monthlyEquivalent(annual: number): string {
return (annual / 12).toFixed(2);
}
+23
View File
@@ -0,0 +1,23 @@
---
import BaseLayout from '@/layouts/BaseLayout.astro';
---
<BaseLayout
title="404"
description="Página no encontrada"
>
<section class="py-32 bg-hds-marfil">
<div class="max-w-2xl mx-auto px-4 text-center">
<p class="text-6xl font-display text-hds-naranja mb-4">404</p>
<h1 class="text-3xl md:text-4xl text-hds-tinta mb-4">Página no encontrada</h1>
<p class="text-hds-grafito mb-8">
La página que buscás no existe o fue movida.
</p>
<a
href="/"
class="inline-flex items-center gap-2 bg-hds-naranja hover:bg-hds-naranja-hover text-white text-sm font-semibold px-5 py-2.5 rounded-md transition-colors"
>
Volver al inicio
</a>
</div>
</section>
</BaseLayout>
+205
View File
@@ -0,0 +1,205 @@
---
import BaseLayout from '@/layouts/BaseLayout.astro';
import SectionEyebrow from '@/components/SectionEyebrow.astro';
import { getLangFromUrl, useTranslations } from '@/i18n/utils';
const lang = getLangFromUrl(Astro.url);
const t = useTranslations(lang);
const whatsappUrl = 'https://wa.me/59899812487';
const reCAPTCHA_site_key = '6LeOxaEaAAAAAPD8rQQLqw4woxn1dMjvF_Ooy0BG';
---
<BaseLayout
title={lang === 'en' ? 'Contact' : 'Contacto'}
description={lang === 'en'
? 'Talk to a real person at Hosting del Sur. WhatsApp, email or form.'
: 'Hablá con una persona real en Hosting del Sur. WhatsApp, mail o formulario.'}
lang={lang}
>
<section class="pt-20 pb-12 md:pt-28 md:pb-16" style="background: var(--hds-bg-soft);">
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
<SectionEyebrow text={lang === 'en' ? 'Contact' : 'Contacto'} />
<h1 class="font-display leading-tight mt-5" style="font-size: clamp(2.5rem, 6vw, 4.5rem); color: var(--hds-fg);">
{lang === 'en'
? <>Talk to a <span style="color: var(--color-hds-naranja); font-style: italic;">real person</span>.</>
: <>Hablá con una <span style="color: var(--color-hds-naranja); font-style: italic;">persona real</span>.</>}
</h1>
<p class="text-lg mt-5 max-w-2xl" style="color: var(--hds-fg-soft);">
{lang === 'en'
? 'No bots, no tickets. Write to us on WhatsApp, email us, or fill out the form below.'
: 'Sin bots, sin tickets. Escribinos por WhatsApp, mandanos un mail o completá el formulario.'}
</p>
</div>
</section>
<section class="py-20 md:py-24" style="background: var(--hds-bg);">
<div class="max-w-6xl mx-auto px-4 sm:px-6 lg:px-8">
<div class="grid grid-cols-1 lg:grid-cols-3 gap-6">
<aside class="lg:col-span-1 space-y-4">
<div class="rounded-2xl p-6" style="background: var(--hds-card); border: 1px solid var(--hds-line);">
<h2 class="text-xs font-semibold tracking-[0.25em] uppercase mb-3" style="color: var(--color-hds-naranja);">WhatsApp</h2>
<a href={whatsappUrl} target="_blank" rel="noopener noreferrer" class="text-lg font-semibold hover:underline break-all" style="color: var(--color-hds-naranja);">+598 99 812 487</a>
<p class="text-sm mt-2" style="color: var(--hds-fg-soft);">
{lang === 'en' ? 'Monday to Friday, 9 to 18 hs UYT' : 'Lunes a viernes, 9 a 18 hs UYT'}
</p>
</div>
<div class="rounded-2xl p-6" style="background: var(--hds-card); border: 1px solid var(--hds-line);">
<h2 class="text-xs font-semibold tracking-[0.25em] uppercase mb-3" style="color: var(--color-hds-naranja);">Email</h2>
<a href="mailto:contacto@hostingdelsur.net" class="text-lg font-semibold hover:underline break-all" style="color: var(--color-hds-naranja);">contacto@hostingdelsur.net</a>
</div>
<div class="rounded-2xl p-6" style="background: var(--hds-card); border: 1px solid var(--hds-line);">
<h2 class="text-xs font-semibold tracking-[0.25em] uppercase mb-3" style="color: var(--color-hds-naranja);">{lang === 'en' ? 'Location' : 'Ubicación'}</h2>
<p style="color: var(--hds-fg-soft);">Maldonado, Uruguay</p>
</div>
</aside>
<div class="lg:col-span-2">
<form
action="/api/contact.php"
method="POST"
class="rounded-2xl p-8 md:p-10 space-y-5"
style="background: var(--hds-card); border: 1px solid var(--hds-line);"
id="contact-form"
novalidate
>
<input type="hidden" name="lang" value={lang} />
<input type="hidden" name="g-recaptcha-response" id="g-recaptcha-response" />
<div class="absolute -left-[9999px]" aria-hidden="true">
<label for="website">Website</label>
<input type="text" id="website" name="website" tabindex="-1" autocomplete="off" />
</div>
<div>
<label for="name" class="block text-sm font-medium mb-1.5" style="color: var(--hds-fg);">
{lang === 'en' ? 'Name' : 'Nombre'} <span style="color: var(--color-hds-error);">*</span>
</label>
<input
type="text"
id="name"
name="name"
required
autocomplete="name"
maxlength="100"
class="w-full px-3.5 py-2.5 rounded-md outline-none transition-colors"
style="background: var(--hds-bg); color: var(--hds-fg); border: 1px solid var(--hds-line);"
/>
</div>
<div>
<label for="email" class="block text-sm font-medium mb-1.5" style="color: var(--hds-fg);">
Email <span style="color: var(--color-hds-error);">*</span>
</label>
<input
type="email"
id="email"
name="email"
required
autocomplete="email"
maxlength="200"
class="w-full px-3.5 py-2.5 rounded-md outline-none transition-colors"
style="background: var(--hds-bg); color: var(--hds-fg); border: 1px solid var(--hds-line);"
/>
</div>
<div>
<label for="message" class="block text-sm font-medium mb-1.5" style="color: var(--hds-fg);">
{lang === 'en' ? 'Message' : 'Mensaje'} <span style="color: var(--color-hds-error);">*</span>
</label>
<textarea
id="message"
name="message"
required
rows="5"
maxlength="5000"
class="w-full px-3.5 py-2.5 rounded-md outline-none transition-colors resize-y"
style="background: var(--hds-bg); color: var(--hds-fg); border: 1px solid var(--hds-line);"
></textarea>
</div>
<div class="flex flex-col sm:flex-row sm:items-center sm:justify-between gap-4 pt-2">
<p class="text-xs" style="color: var(--hds-fg-muted);">
{lang === 'en' ? 'We typically reply within 24 business hours.' : 'Respondemos típicamente dentro de las 24 hs hábiles.'}
</p>
<button type="submit" class="btn-primary text-sm">
<span id="contact-submit-label">{lang === 'en' ? 'Send message' : 'Enviar mensaje'}</span>
</button>
</div>
<div id="contact-status" role="status" aria-live="polite" class="hidden text-sm"></div>
</form>
</div>
</div>
</div>
</section>
<script src={`https://www.google.com/recaptcha/api.js?render=${reCAPTCHA_site_key}`} async defer></script>
<noscript>
<p class="text-xs mt-2" style="color: var(--color-hds-error);">JavaScript is required for the form to work.</p>
</noscript>
<script is:inline define:vars={{ siteKey: reCAPTCHA_site_key }}>
(function() {
const form = document.getElementById('contact-form');
if (!form) return;
const status = document.getElementById('contact-status');
const submit = form.querySelector('button[type="submit"]');
const label = document.getElementById('contact-submit-label');
const langInput = form.querySelector('input[name="lang"]');
const isEn = langInput && langInput.value === 'en';
const sendingLabel = isEn ? 'Sending…' : 'Enviando…';
const successMsg = isEn ? 'Message sent. We will reply soon.' : 'Mensaje enviado. Te respondemos pronto.';
const errorMsg = isEn ? 'Could not send. Please try again or contact us via WhatsApp.' : 'No se pudo enviar. Probá de nuevo o contactanos por WhatsApp.';
window.addEventListener('load', () => {
if (window.grecaptcha && window.grecaptcha.ready) {
window.grecaptcha.ready();
}
});
form.addEventListener('submit', async (e) => {
e.preventDefault();
const originalLabel = label.textContent;
label.textContent = sendingLabel;
submit.disabled = true;
status.classList.remove('hidden');
status.className = 'text-sm';
status.textContent = '';
status.style.color = 'var(--hds-fg-soft)';
try {
let token = '';
if (window.grecaptcha && window.grecaptcha.execute) {
try {
token = await Promise.race([
window.grecaptcha.execute(siteKey, { action: 'contact' }),
new Promise((_, reject) => setTimeout(() => reject(new Error('recaptcha timeout')), 5000)),
]);
} catch (e) { /* fall through without token */ }
}
document.getElementById('g-recaptcha-response').value = token || '';
const formData = new FormData(form);
const res = await fetch(form.action, {
method: 'POST',
body: formData,
headers: { 'X-Requested-With': 'fetch' },
});
const data = await res.json().catch(() => ({}));
if (res.ok && data.ok) {
status.style.color = 'var(--color-hds-exito)';
status.textContent = successMsg;
form.reset();
} else {
throw new Error(data.error || 'error');
}
} catch (err) {
status.style.color = 'var(--color-hds-error)';
status.textContent = errorMsg;
} finally {
label.textContent = originalLabel;
submit.disabled = false;
}
});
})();
</script>
</BaseLayout>
+97
View File
@@ -0,0 +1,97 @@
---
import BaseLayout from '@/layouts/BaseLayout.astro';
import SectionEyebrow from '@/components/SectionEyebrow.astro';
import WorldMap from '@/components/icons/WorldMap.astro';
import CtaFinal from '@/components/CtaFinal.astro';
import { getLangFromUrl, useTranslations } from '@/i18n/utils';
const lang = getLangFromUrl(Astro.url);
const t = useTranslations(lang);
const whatsappUrl = 'https://wa.me/59899812487';
---
<BaseLayout
title={lang === 'en' ? 'About us' : 'Nosotros'}
description={lang === 'en'
? 'Since 2000, Hosting del Sur provides technology services with a human touch from Maldonado, Uruguay, across four countries.'
: 'Desde 2000, Hosting del Sur brinda servicios de tecnología con atención humana desde Maldonado, Uruguay, con alcance en cuatro países.'}
lang={lang}
>
<section class="pt-20 pb-12 md:pt-28 md:pb-16" style="background: var(--hds-bg-soft);">
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
<SectionEyebrow text={lang === 'en' ? 'About us' : 'Nosotros'} />
<h1 class="font-display leading-tight mt-5 max-w-4xl" style="font-size: clamp(2.5rem, 6vw, 4.5rem); color: var(--hds-fg);">
{lang === 'en'
? <>Technology with a <span style="color: var(--color-hds-naranja); font-style: italic;">human face</span> since 2000.</>
: <>Tecnología con <span style="color: var(--color-hds-naranja); font-style: italic;">cara de persona</span> desde 2000.</>}
</h1>
</div>
</section>
<section class="py-16 md:py-20" style="background: var(--hds-bg);">
<div class="max-w-4xl mx-auto px-4 sm:px-6 lg:px-8">
<div class="prose prose-lg max-w-none" style="color: var(--hds-fg-soft);">
<p class="text-lg leading-relaxed" style="color: var(--hds-fg-soft);">
{lang === 'en'
? 'We are a small team of senior SysAdmins and SREs based in Maldonado, Uruguay. We work with clients across Latin America and the world.'
: 'Somos un equipo chico de SysAdmins y SREs senior, radicados en Maldonado, Uruguay. Trabajamos con clientes de toda Latinoamérica y el mundo.'}
</p>
<h2 class="font-display mt-12 mb-4" style="color: var(--hds-fg); font-size: 2rem;">
{lang === 'en' ? 'Our story' : 'Nuestra historia'}
</h2>
<p>
{lang === 'en'
? 'Hosting del Sur was born in 2000 as a hosting services provider for Uruguayan businesses. From the beginning we were clear: we wanted to offer enterprise-level technology with the closeness of a small team. Twenty-six years later we are still the same — fewer tickets, real names, infrastructure we know by heart.'
: 'Hosting del Sur nació en el año 2000 como proveedor de servicios de hosting para empresas uruguayas. Desde el principio teníamos claro: queríamos ofrecer tecnología de nivel enterprise con la cercanía de un equipo chico. Veintiséis años después seguimos siendo lo mismo — menos tickets, nombres reales, infraestructura que conocemos de memoria.'}
</p>
<h2 class="font-display mt-12 mb-4" style="color: var(--hds-fg); font-size: 2rem;">
{lang === 'en' ? 'What we believe' : 'En qué creemos'}
</h2>
<ul class="space-y-2" style="color: var(--hds-fg-soft);">
<li><strong style="color: var(--hds-fg);">{lang === 'en' ? 'A real person answers.' : 'Una persona real te responde.'}</strong> {lang === 'en' ? 'Always.' : 'Siempre.'}</li>
<li><strong style="color: var(--hds-fg);">{lang === 'en' ? 'You own your data.' : 'Tus datos son tuyos.'}</strong> {lang === 'en' ? 'We just host it.' : 'Nosotros solo los hospedamos.'}</li>
<li><strong style="color: var(--hds-fg);">{lang === 'en' ? 'Open source first.' : 'Open source primero.'}</strong> {lang === 'en' ? 'Vendor lock-in never.' : 'Vendor lock-in nunca.'}</li>
<li><strong style="color: var(--hds-fg);">{lang === 'en' ? 'No magic, no jargon.' : 'Sin magia, sin jerga.'}</strong> {lang === 'en' ? 'We explain what we do.' : 'Explicamos lo que hacemos.'}</li>
</ul>
</div>
</div>
</section>
<section class="py-20 md:py-24" style="background: var(--hds-bg-soft);">
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
<div class="grid grid-cols-1 lg:grid-cols-2 gap-12 items-center">
<div>
<SectionEyebrow text={lang === 'en' ? 'Where we work' : 'Dónde trabajamos'} />
<h2 class="font-display leading-tight mt-5" style="font-size: clamp(2rem, 4.5vw, 3rem); color: var(--hds-fg);">
{lang === 'en'
? <>Four countries,<br/><span style="color: var(--color-hds-naranja); font-style: italic;">one team</span>.</>
: <>Cuatro países,<br/><span style="color: var(--color-hds-naranja); font-style: italic;">un equipo</span>.</>}
</h2>
<p class="text-lg mt-5" style="color: var(--hds-fg-soft);">
{lang === 'en'
? 'We operate from Maldonado, Uruguay, with infrastructure distributed across four countries: Canada, the United States, Germany and Uruguay. We combine providers in three regions with our own equipment in Uruguay to give you redundancy, low latency and data sovereignty.'
: 'Operamos desde Maldonado, Uruguay, con infraestructura distribuida en cuatro países: Canadá, Estados Unidos, Alemania y Uruguay. Combinamos proveedores en tres regiones con equipos propios en Uruguay para darte redundancia, baja latencia y soberanía de datos.'}
</p>
<ul class="mt-8 space-y-3 text-sm" style="color: var(--hds-fg-soft);">
<li class="flex items-start gap-3">
<span class="mt-1.5 w-2 h-2 rounded-full flex-shrink-0" style="background: var(--color-hds-naranja);"></span>
<span><strong style="color: var(--hds-fg);">{lang === 'en' ? 'Canada, USA, Germany:' : 'Canadá, USA, Alemania:'}</strong> {lang === 'en' ? 'provider infrastructure.' : 'infraestructura de proveedores.'}</span>
</li>
<li class="flex items-start gap-3">
<span class="mt-1.5 w-2 h-2 rounded-full flex-shrink-0" style="background: var(--color-hds-naranja);"></span>
<span><strong style="color: var(--hds-fg);">{lang === 'en' ? 'Uruguay:' : 'Uruguay:'}</strong> {lang === 'en' ? 'our own equipment and headquarters.' : 'equipos propios y sede operativa.'}</span>
</li>
</ul>
</div>
<div class="rounded-2xl p-6 lg:p-8" style="background: var(--hds-card); border: 1px solid var(--hds-line);">
<WorldMap class="w-full h-auto" />
</div>
</div>
</div>
</section>
<CtaFinal t={t} whatsappUrl={whatsappUrl} />
</BaseLayout>
+205
View File
@@ -0,0 +1,205 @@
---
import BaseLayout from '@/layouts/BaseLayout.astro';
import SectionEyebrow from '@/components/SectionEyebrow.astro';
import { getLangFromUrl, useTranslations } from '@/i18n/utils';
const lang = getLangFromUrl(Astro.url);
const t = useTranslations(lang);
const whatsappUrl = 'https://wa.me/59899812487';
const reCAPTCHA_site_key = '6LeOxaEaAAAAAPD8rQQLqw4woxn1dMjvF_Ooy0BG';
---
<BaseLayout
title={lang === 'en' ? 'Contact' : 'Contacto'}
description={lang === 'en'
? 'Talk to a real person at Hosting del Sur. WhatsApp, email or form.'
: 'Hablá con una persona real en Hosting del Sur. WhatsApp, mail o formulario.'}
lang={lang}
>
<section class="pt-20 pb-12 md:pt-28 md:pb-16" style="background: var(--hds-bg-soft);">
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
<SectionEyebrow text={lang === 'en' ? 'Contact' : 'Contacto'} />
<h1 class="font-display leading-tight mt-5" style="font-size: clamp(2.5rem, 6vw, 4.5rem); color: var(--hds-fg);">
{lang === 'en'
? <>Talk to a <span style="color: var(--color-hds-naranja); font-style: italic;">real person</span>.</>
: <>Hablá con una <span style="color: var(--color-hds-naranja); font-style: italic;">persona real</span>.</>}
</h1>
<p class="text-lg mt-5 max-w-2xl" style="color: var(--hds-fg-soft);">
{lang === 'en'
? 'No bots, no tickets. Write to us on WhatsApp, email us, or fill out the form below.'
: 'Sin bots, sin tickets. Escribinos por WhatsApp, mandanos un mail o completá el formulario.'}
</p>
</div>
</section>
<section class="py-20 md:py-24" style="background: var(--hds-bg);">
<div class="max-w-6xl mx-auto px-4 sm:px-6 lg:px-8">
<div class="grid grid-cols-1 lg:grid-cols-3 gap-6">
<aside class="lg:col-span-1 space-y-4">
<div class="rounded-2xl p-6" style="background: var(--hds-card); border: 1px solid var(--hds-line);">
<h2 class="text-xs font-semibold tracking-[0.25em] uppercase mb-3" style="color: var(--color-hds-naranja);">WhatsApp</h2>
<a href={whatsappUrl} target="_blank" rel="noopener noreferrer" class="text-lg font-semibold hover:underline break-all" style="color: var(--color-hds-naranja);">+598 99 812 487</a>
<p class="text-sm mt-2" style="color: var(--hds-fg-soft);">
{lang === 'en' ? 'Monday to Friday, 9 to 18 hs UYT' : 'Lunes a viernes, 9 a 18 hs UYT'}
</p>
</div>
<div class="rounded-2xl p-6" style="background: var(--hds-card); border: 1px solid var(--hds-line);">
<h2 class="text-xs font-semibold tracking-[0.25em] uppercase mb-3" style="color: var(--color-hds-naranja);">Email</h2>
<a href="mailto:contacto@hostingdelsur.net" class="text-lg font-semibold hover:underline break-all" style="color: var(--color-hds-naranja);">contacto@hostingdelsur.net</a>
</div>
<div class="rounded-2xl p-6" style="background: var(--hds-card); border: 1px solid var(--hds-line);">
<h2 class="text-xs font-semibold tracking-[0.25em] uppercase mb-3" style="color: var(--color-hds-naranja);">{lang === 'en' ? 'Location' : 'Ubicación'}</h2>
<p style="color: var(--hds-fg-soft);">Maldonado, Uruguay</p>
</div>
</aside>
<div class="lg:col-span-2">
<form
action="/api/contact.php"
method="POST"
class="rounded-2xl p-8 md:p-10 space-y-5"
style="background: var(--hds-card); border: 1px solid var(--hds-line);"
id="contact-form"
novalidate
>
<input type="hidden" name="lang" value={lang} />
<input type="hidden" name="g-recaptcha-response" id="g-recaptcha-response" />
<div class="absolute -left-[9999px]" aria-hidden="true">
<label for="website">Website</label>
<input type="text" id="website" name="website" tabindex="-1" autocomplete="off" />
</div>
<div>
<label for="name" class="block text-sm font-medium mb-1.5" style="color: var(--hds-fg);">
{lang === 'en' ? 'Name' : 'Nombre'} <span style="color: var(--color-hds-error);">*</span>
</label>
<input
type="text"
id="name"
name="name"
required
autocomplete="name"
maxlength="100"
class="w-full px-3.5 py-2.5 rounded-md outline-none transition-colors"
style="background: var(--hds-bg); color: var(--hds-fg); border: 1px solid var(--hds-line);"
/>
</div>
<div>
<label for="email" class="block text-sm font-medium mb-1.5" style="color: var(--hds-fg);">
Email <span style="color: var(--color-hds-error);">*</span>
</label>
<input
type="email"
id="email"
name="email"
required
autocomplete="email"
maxlength="200"
class="w-full px-3.5 py-2.5 rounded-md outline-none transition-colors"
style="background: var(--hds-bg); color: var(--hds-fg); border: 1px solid var(--hds-line);"
/>
</div>
<div>
<label for="message" class="block text-sm font-medium mb-1.5" style="color: var(--hds-fg);">
{lang === 'en' ? 'Message' : 'Mensaje'} <span style="color: var(--color-hds-error);">*</span>
</label>
<textarea
id="message"
name="message"
required
rows="5"
maxlength="5000"
class="w-full px-3.5 py-2.5 rounded-md outline-none transition-colors resize-y"
style="background: var(--hds-bg); color: var(--hds-fg); border: 1px solid var(--hds-line);"
></textarea>
</div>
<div class="flex flex-col sm:flex-row sm:items-center sm:justify-between gap-4 pt-2">
<p class="text-xs" style="color: var(--hds-fg-muted);">
{lang === 'en' ? 'We typically reply within 24 business hours.' : 'Respondemos típicamente dentro de las 24 hs hábiles.'}
</p>
<button type="submit" class="btn-primary text-sm">
<span id="contact-submit-label">{lang === 'en' ? 'Send message' : 'Enviar mensaje'}</span>
</button>
</div>
<div id="contact-status" role="status" aria-live="polite" class="hidden text-sm"></div>
</form>
</div>
</div>
</div>
</section>
<script src={`https://www.google.com/recaptcha/api.js?render=${reCAPTCHA_site_key}`} async defer></script>
<noscript>
<p class="text-xs mt-2" style="color: var(--color-hds-error);">JavaScript is required for the form to work.</p>
</noscript>
<script is:inline define:vars={{ siteKey: reCAPTCHA_site_key }}>
(function() {
const form = document.getElementById('contact-form');
if (!form) return;
const status = document.getElementById('contact-status');
const submit = form.querySelector('button[type="submit"]');
const label = document.getElementById('contact-submit-label');
const langInput = form.querySelector('input[name="lang"]');
const isEn = langInput && langInput.value === 'en';
const sendingLabel = isEn ? 'Sending…' : 'Enviando…';
const successMsg = isEn ? 'Message sent. We will reply soon.' : 'Mensaje enviado. Te respondemos pronto.';
const errorMsg = isEn ? 'Could not send. Please try again or contact us via WhatsApp.' : 'No se pudo enviar. Probá de nuevo o contactanos por WhatsApp.';
window.addEventListener('load', () => {
if (window.grecaptcha && window.grecaptcha.ready) {
window.grecaptcha.ready();
}
});
form.addEventListener('submit', async (e) => {
e.preventDefault();
const originalLabel = label.textContent;
label.textContent = sendingLabel;
submit.disabled = true;
status.classList.remove('hidden');
status.className = 'text-sm';
status.textContent = '';
status.style.color = 'var(--hds-fg-soft)';
try {
let token = '';
if (window.grecaptcha && window.grecaptcha.execute) {
try {
token = await Promise.race([
window.grecaptcha.execute(siteKey, { action: 'contact' }),
new Promise((_, reject) => setTimeout(() => reject(new Error('recaptcha timeout')), 5000)),
]);
} catch (e) { /* fall through without token */ }
}
document.getElementById('g-recaptcha-response').value = token || '';
const formData = new FormData(form);
const res = await fetch(form.action, {
method: 'POST',
body: formData,
headers: { 'X-Requested-With': 'fetch' },
});
const data = await res.json().catch(() => ({}));
if (res.ok && data.ok) {
status.style.color = 'var(--color-hds-exito)';
status.textContent = successMsg;
form.reset();
} else {
throw new Error(data.error || 'error');
}
} catch (err) {
status.style.color = 'var(--color-hds-error)';
status.textContent = errorMsg;
} finally {
label.textContent = originalLabel;
submit.disabled = false;
}
});
})();
</script>
</BaseLayout>
+56
View File
@@ -0,0 +1,56 @@
---
import BaseLayout from '@/layouts/BaseLayout.astro';
import { getLangFromUrl } from '@/i18n/utils';
const lang = getLangFromUrl(Astro.url);
const base = lang === 'en' ? '/en' : '';
---
<BaseLayout
title={lang === 'en' ? 'Privacy policy' : 'Política de privacidad'}
description={lang === 'en' ? 'Privacy policy of Hosting del Sur.' : 'Política de privacidad de Hosting del Sur.'}
lang={lang}
>
<article class="py-16 md:py-20 bg-hds-marfil">
<div class="max-w-3xl mx-auto px-4 sm:px-6 lg:px-8 prose prose-lg">
<h1>{lang === 'en' ? 'Privacy policy' : 'Política de privacidad'}</h1>
<p class="text-sm text-hds-humo">
{lang === 'en' ? 'Last updated' : 'Última actualización'}: 2026
</p>
<h2>{lang === 'en' ? '1. Data we collect' : '1. Datos que recopilamos'}</h2>
<p>
{lang === 'en'
? 'When you fill out the contact form, we collect: name, email and the message you send us. We use this data exclusively to respond to your inquiry.'
: 'Cuando completás el formulario de contacto, recopilamos: nombre, email y el mensaje que nos envías. Usamos estos datos exclusivamente para responder a tu consulta.'}
</p>
<h2>{lang === 'en' ? '2. How we use your data' : '2. Cómo usamos tus datos'}</h2>
<p>
{lang === 'en'
? 'We use the data you provide solely to: (a) respond to your inquiry, (b) follow up if you become a customer. We do not sell, rent or share your data with third parties.'
: 'Usamos los datos que nos proporcionás únicamente para: (a) responder a tu consulta, (b) dar seguimiento si te convertís en cliente. No vendemos, alquilamos ni compartimos tus datos con terceros.'}
</p>
<h2>{lang === 'en' ? '3. Hosting and data location' : '3. Hosting y ubicación de datos'}</h2>
<p>
{lang === 'en'
? 'Our infrastructure is in datacenters in the United States and Europe. If you require data to be hosted in a specific country, please let us know and we will work out the best option.'
: 'Nuestra infraestructura se encuentra en datacenters en Estados Unidos y Europa. Si necesitás que los datos se hospeden en un país específico, avísanos y acordamos la mejor opción.'}
</p>
<h2>{lang === 'en' ? '4. Your rights' : '4. Tus derechos'}</h2>
<p>
{lang === 'en'
? 'You can request access, rectification or deletion of your data at any time by writing to contacto@hostingdelsur.net.'
: 'Podés solicitar acceso, rectificación o eliminación de tus datos en cualquier momento escribiendo a contacto@hostingdelsur.net.'}
</p>
<h2>{lang === 'en' ? '5. Cookies' : '5. Cookies'}</h2>
<p>
{lang === 'en'
? 'This site does not use tracking cookies. We may use strictly necessary cookies for the language preference.'
: 'Este sitio no utiliza cookies de seguimiento. Podemos usar cookies estrictamente necesarias para la preferencia de idioma.'}
</p>
</div>
</article>
</BaseLayout>
+48
View File
@@ -0,0 +1,48 @@
---
import BaseLayout from '@/layouts/BaseLayout.astro';
import { getLangFromUrl } from '@/i18n/utils';
const lang = getLangFromUrl(Astro.url);
---
<BaseLayout
title={lang === 'en' ? 'Terms of service' : 'Términos del servicio'}
description={lang === 'en' ? 'Terms of service of Hosting del Sur.' : 'Términos del servicio de Hosting del Sur.'}
lang={lang}
>
<article class="py-16 md:py-20 bg-hds-marfil">
<div class="max-w-3xl mx-auto px-4 sm:px-6 lg:px-8 prose prose-lg">
<h1>{lang === 'en' ? 'Terms of service' : 'Términos del servicio'}</h1>
<p class="text-sm text-hds-humo">
{lang === 'en' ? 'Last updated' : 'Última actualización'}: 2026
</p>
<h2>{lang === 'en' ? '1. Services' : '1. Servicios'}</h2>
<p>
{lang === 'en'
? 'Hosting del Sur provides web hosting, email, web development, e-commerce, content management and IT infrastructure services under individual agreements with each client.'
: 'Hosting del Sur brinda servicios de hosting web, correo, desarrollo web, e-commerce, gestión de contenido e infraestructura IT bajo acuerdos individuales con cada cliente.'}
</p>
<h2>{lang === 'en' ? '2. Acceptable use' : '2. Uso aceptable'}</h2>
<p>
{lang === 'en'
? 'The client agrees to use the services in accordance with current legislation and the Acceptable Use Policy, refraining from activities that may damage third parties or the integrity of our infrastructure.'
: 'El cliente se compromete a utilizar los servicios de conformidad con la legislación vigente y la Política de Uso Aceptable, absteniéndose de realizar actividades que puedan dañar a terceros o la integridad de nuestra infraestructura.'}
</p>
<h2>{lang === 'en' ? '3. Liability' : '3. Responsabilidad'}</h2>
<p>
{lang === 'en'
? 'Hosting del Sur is not liable for damages caused by improper use of the services, force majeure, or third-party actions beyond our control.'
: 'Hosting del Sur no se hace responsable por daños causados por uso indebido de los servicios, fuerza mayor o acciones de terceros fuera de nuestro control.'}
</p>
<h2>{lang === 'en' ? '4. Modifications' : '4. Modificaciones'}</h2>
<p>
{lang === 'en'
? 'We reserve the right to modify these terms. Clients will be notified with reasonable advance notice.'
: 'Nos reservamos el derecho de modificar estos términos. Los clientes serán notificados con antelación razonable.'}
</p>
</div>
</article>
</BaseLayout>
+68
View File
@@ -0,0 +1,68 @@
---
import BaseLayout from '@/layouts/BaseLayout.astro';
import SectionEyebrow from '@/components/SectionEyebrow.astro';
import PricingTiers from '@/components/PricingTiers.astro';
import CtaFinal from '@/components/CtaFinal.astro';
import { PLANS, ADDITIONAL_PLANS, monthlyEquivalent } from '@/lib/pricing';
import { getLangFromUrl, useTranslations } from '@/i18n/utils';
const lang = getLangFromUrl(Astro.url);
const t = useTranslations(lang);
const whatsappUrl = 'https://wa.me/59899812487';
const base = lang === 'en' ? '/en' : '';
---
<BaseLayout
title={lang === 'en' ? 'Hosting plans' : 'Planes de hosting'}
description={lang === 'en'
? 'Hosting plans in USD, billed annually. Basic, Institutional and E-commerce tiers with optional WordPress, Advanced and Corporate plans.'
: 'Planes de hosting en USD, con cobro anual. Básico, Institucional y E-commerce, más planes opcionales WordPress, Avanzado y Corporativo.'}
lang={lang}
>
<section class="pt-20 pb-12 md:pt-28 md:pb-16" style="background: var(--hds-bg-soft);">
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
<SectionEyebrow text={lang === 'en' ? 'Hosting plans' : 'Planes de hosting'} />
<h1 class="font-display leading-tight mt-5" style="font-size: clamp(2.5rem, 6vw, 4.5rem); color: var(--hds-fg);">
Elegí el plan que se<br/>adapta a tu <span style="color: var(--color-hds-naranja); font-style: italic;">proyecto</span>.
</h1>
<p class="text-lg mt-5 max-w-2xl" style="color: var(--hds-fg-soft);">
{lang === 'en'
? 'Prices in USD, billed annually. Features may vary depending on the project and server configuration.'
: 'Precios en USD, con cobro anual. Las características pueden variar según el proyecto y la configuración del servidor.'}
</p>
</div>
</section>
<section class="py-20 md:py-24" style="background: var(--hds-bg);">
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
<PricingTiers
plans={PLANS}
whatsappUrl={whatsappUrl}
/>
<div class="mt-10 text-center text-sm space-y-1" style="color: var(--hds-fg-muted);">
<p>⚠️ {lang === 'en'
? 'Prices are in US Dollars (USD). Billed annually.'
: 'Los precios están expresados en dólares estadounidenses (USD). El cobro es anual.'}</p>
<p>{lang === 'en'
? 'Features may vary based on project and server configuration.'
: 'Las características pueden variar según el proyecto y la configuración del servidor.'}</p>
</div>
</div>
</section>
<section class="py-20" style="background: var(--hds-bg-soft);">
<div class="max-w-3xl mx-auto px-4 sm:px-6 lg:px-8 text-center">
<h2 class="font-display mb-4" style="font-size: clamp(1.75rem, 4vw, 2.5rem); color: var(--hds-fg);">
{lang === 'en' ? 'Need a different plan?' : '¿Necesitás otro plan?'}
</h2>
<p class="text-lg mb-8" style="color: var(--hds-fg-soft);">
{lang === 'en' ? 'We also have ' : 'También tenemos '}
<strong>{ADDITIONAL_PLANS.join(', ')}</strong>.
{lang === 'en' ? ' Tell us about your project and we will tailor a plan to you.' : ' Charlá con nosotros y te armamos un plan a medida.'}
</p>
<a href={whatsappUrl} target="_blank" rel="noopener noreferrer" class="btn-primary">
{lang === 'en' ? 'Chat on WhatsApp' : 'Hablar por WhatsApp'}
</a>
</div>
</section>
</BaseLayout>
+268
View File
@@ -0,0 +1,268 @@
---
import BaseLayout from '@/layouts/BaseLayout.astro';
import { getLangFromUrl, useTranslations } from '@/i18n/utils';
import MailIcon from '@/components/icons/MailIcon.astro';
import WordpressIcon from '@/components/icons/WordpressIcon.astro';
import CodeIcon from '@/components/icons/CodeIcon.astro';
import ShopIcon from '@/components/icons/ShopIcon.astro';
import TranslateIcon from '@/components/icons/TranslateIcon.astro';
import ServerIcon from '@/components/icons/ServerIcon.astro';
const lang = getLangFromUrl(Astro.url);
const t = useTranslations(lang);
const slug = Astro.params.slug;
export function getStaticPaths() {
return [
{ params: { slug: 'hosting-correo-web' } },
{ params: { slug: 'mantenimiento-wordpress' } },
{ params: { slug: 'desarrollo-webs-institucionales' } },
{ params: { slug: 'e-commerce' } },
{ params: { slug: 'gestion-contenido-traducciones' } },
{ params: { slug: 'servidores-linux-virtualizacion' } },
];
}
const services: Record<string, {
icon: any;
title_es: string;
title_en: string;
category: string;
body_es: string;
body_en: string;
features_es: string[];
features_en: string[];
}> = {
'hosting-correo-web': {
icon: MailIcon,
title_es: 'Hosting correo y web',
title_en: 'Hosting for email and web',
category: 'Hosting & Correo',
body_es: 'Alojamiento web optimizado con cPanel. Infraestructura estable y profesional para que tu sitio rinda al máximo sin complicaciones técnicas. Soporte para WordPress, PHP y MySQL.',
body_en: 'Optimized web hosting with cPanel. Stable, professional infrastructure for your site to perform at its best without technical complications. WordPress, PHP and MySQL support.',
features_es: [
'Panel cPanel intuitivo',
'PHP 7.4 a 8.3, MySQL/MariaDB',
'SSL gratis (Let\'s Encrypt)',
'Backups automáticos diarios',
'Soporte para WordPress optimizado',
'Correo electrónico corporativo',
],
features_en: [
'Intuitive cPanel',
'PHP 7.4 to 8.3, MySQL/MariaDB',
'Free SSL (Let\'s Encrypt)',
'Daily automatic backups',
'Optimized WordPress support',
'Corporate email',
],
},
'mantenimiento-wordpress': {
icon: WordpressIcon,
title_es: 'Mantenimiento WordPress',
title_en: 'WordPress maintenance',
category: 'Hosting & Correo',
body_es: 'Mantenimiento proactivo y parches de seguridad por expertos que participan en el ecosistema oficial de WordPress. Tu sitio, siempre protegido.',
body_en: 'Proactive maintenance and security patches by experts participating in the official WordPress ecosystem. Your site, always protected.',
features_es: [
'Actualizaciones de core, themes y plugins',
'Parches de seguridad críticos',
'Backups antes de cada cambio',
'Monitoreo de uptime 24/7',
'Reporte mensual de actividad',
'Restauración ante incidentes',
],
features_en: [
'Core, theme and plugin updates',
'Critical security patches',
'Backups before every change',
'24/7 uptime monitoring',
'Monthly activity report',
'Incident restoration',
],
},
'desarrollo-webs-institucionales': {
icon: CodeIcon,
title_es: 'Desarrollo webs institucionales',
title_en: 'Institutional website development',
category: 'Diseño & Contenido',
body_es: 'Diseño y desarrollo de sitios web corporativos a medida de tu negocio. Trabajamos con foco en performance, accesibilidad y SEO.',
body_en: 'Design and development of corporate websites tailored to your business. We focus on performance, accessibility and SEO.',
features_es: [
'Diseño responsive y accesible (WCAG AA)',
'Optimización SEO técnico desde el inicio',
'Performance > 90 en Lighthouse',
'CMS amigable para edición autónoma',
'Formación de uso al equipo del cliente',
'Soporte post-lanzamiento',
],
features_en: [
'Responsive, accessible design (WCAG AA)',
'Technical SEO from the start',
'Lighthouse performance > 90',
'Friendly CMS for autonomous editing',
'Training for the client team',
'Post-launch support',
],
},
'e-commerce': {
icon: ShopIcon,
title_es: 'Sitios web con e-commerce',
title_en: 'E-commerce websites',
category: 'Diseño & Contenido',
body_es: 'Tiendas online robustas con WooCommerce. Pagos seguros, gestión de inventario, envíos y todo lo necesario para vender online.',
body_en: 'Robust online stores with WooCommerce. Secure payments, inventory management, shipping and everything you need to sell online.',
features_es: [
'WooCommerce con pasarelas de pago locales',
'Gestión de stock y pedidos',
'Integración con transportistas',
'Panel de reportes de venta',
'Cupones, descuentos y envíos gratis',
'Optimización para Core Web Vitals',
],
features_en: [
'WooCommerce with local payment gateways',
'Stock and order management',
'Carrier integration',
'Sales reporting panel',
'Coupons, discounts and free shipping',
'Core Web Vitals optimization',
],
},
'gestion-contenido-traducciones': {
icon: TranslateIcon,
title_es: 'Gestión de contenido y traducciones',
title_en: 'Content management and translations',
category: 'Diseño & Contenido',
body_es: 'Servicio editorial recurrente: redacción, actualización de contenido, gestión de blog y traducción multilenguaje. Tu sitio siempre al día, sin que tengas que ocuparte.',
body_en: 'Recurring editorial service: copywriting, content updates, blog management and multilingual translation. Your site always up to date, without you having to worry.',
features_es: [
'Redacción profesional de artículos',
'Traducción es/en/pt',
'Publicación en CMS o WordPress',
'Calendario editorial mensual',
'Optimización SEO de cada pieza',
'Reporte de tráfico y engagement',
],
features_en: [
'Professional article writing',
'ES/EN/PT translation',
'CMS or WordPress publishing',
'Monthly editorial calendar',
'SEO optimization of every piece',
'Traffic and engagement report',
],
},
'servidores-linux-virtualizacion': {
icon: ServerIcon,
title_es: 'Servidores Linux y virtualización',
title_en: 'Linux servers and virtualization',
category: 'Infraestructura',
body_es: 'Diseño, instalación y administración de servidores Linux con virtualización KVM. Nubes privadas, servicios empresariales y plataformas de alta disponibilidad.',
body_en: 'Design, installation and administration of Linux servers with KVM virtualization. Private clouds, enterprise services and high-availability platforms.',
features_es: [
'Servidores dedicados o VPS con KVM',
'Nubes privadas estilo Nextcloud',
'Alta disponibilidad y balanceo',
'Monitoreo 24/7 con Prometheus/Grafana',
'Respaldos automatizados',
'Hardening y seguridad perimetral',
],
features_en: [
'Dedicated servers or VPS with KVM',
'Nextcloud-style private clouds',
'High availability and balancing',
'24/7 monitoring with Prometheus/Grafana',
'Automated backups',
'Hardening and perimeter security',
],
},
};
const service = services[slug as keyof typeof services];
if (!service) {
return Astro.redirect(lang === 'en' ? '/en/servicios/' : '/servicios/');
}
const title = lang === 'en' ? service.title_en : service.title_es;
const body = lang === 'en' ? service.body_en : service.body_es;
const features = lang === 'en' ? service.features_en : service.features_es;
const base = lang === 'en' ? '/en' : '';
const whatsappUrl = 'https://wa.me/59899812487';
---
<BaseLayout
title={title}
description={body}
lang={lang}
>
<section class="bg-hds-crema py-12 md:py-16">
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
<nav aria-label="Breadcrumb" class="text-sm text-hds-humo mb-6">
<ol class="flex flex-wrap items-center gap-2">
<li><a href={`${base}/`} class="hover:text-hds-naranja">{lang === 'en' ? 'Home' : 'Inicio'}</a></li>
<li aria-hidden="true">/</li>
<li><a href={`${base}/servicios/`} class="hover:text-hds-naranja">{lang === 'en' ? 'Services' : 'Servicios'}</a></li>
<li aria-hidden="true">/</li>
<li class="text-hds-grafito" aria-current="page">{title}</li>
</ol>
</nav>
<div class="flex items-start gap-5 mb-4">
<div class="flex-shrink-0 bg-white rounded-lg p-3 border border-hds-linea">
<service.icon class="w-10 h-10" />
</div>
<div>
<p class="text-xs font-semibold tracking-wider uppercase text-hds-naranja mb-1">
{service.category}
</p>
<h1 class="text-3xl md:text-5xl text-hds-tinta leading-tight">
{title}
</h1>
</div>
</div>
</div>
</section>
<section class="py-16 md:py-20 bg-hds-marfil">
<div class="max-w-4xl mx-auto px-4 sm:px-6 lg:px-8">
<p class="text-lg text-hds-grafito leading-relaxed mb-10">
{body}
</p>
<h2 class="text-2xl md:text-3xl text-hds-tinta mb-6">
{lang === 'en' ? 'What is included' : 'Qué incluye'}
</h2>
<ul class="space-y-3 mb-12">
{features.map((feature) => (
<li class="flex items-start gap-3">
<svg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="#EE7623" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" class="flex-shrink-0 mt-0.5" aria-hidden="true">
<polyline points="20 6 9 17 4 12"/>
</svg>
<span class="text-hds-grafito">{feature}</span>
</li>
))}
</ul>
<div class="bg-hds-crema rounded-lg p-8 border border-hds-linea">
<h3 class="text-xl text-hds-tinta mb-2">
{lang === 'en' ? 'Want to know more?' : '¿Querés saber más?'}
</h3>
<p class="text-hds-grafito mb-5">
{lang === 'en'
? 'Tell us about your project and we will reply with a tailor-made proposal.'
: 'Contanos sobre tu proyecto y te respondemos con una propuesta a medida.'}
</p>
<a
href={whatsappUrl}
target="_blank"
rel="noopener noreferrer"
class="inline-flex items-center justify-center gap-2 bg-hds-naranja hover:bg-hds-naranja-hover text-white text-sm font-semibold px-5 py-2.5 rounded-md transition-colors"
>
{lang === 'en' ? 'Chat on WhatsApp' : 'Hablar por WhatsApp'}
</a>
</div>
</div>
</section>
</BaseLayout>
+91
View File
@@ -0,0 +1,91 @@
---
import BaseLayout from '@/layouts/BaseLayout.astro';
import SectionEyebrow from '@/components/SectionEyebrow.astro';
import ServiceCard from '@/components/ServiceCard.astro';
import CtaFinal from '@/components/CtaFinal.astro';
import { getLangFromUrl, useTranslations } from '@/i18n/utils';
import MailIcon from '@/components/icons/MailIcon.astro';
import WordpressIcon from '@/components/icons/WordpressIcon.astro';
import CodeIcon from '@/components/icons/CodeIcon.astro';
import ShopIcon from '@/components/icons/ShopIcon.astro';
import TranslateIcon from '@/components/icons/TranslateIcon.astro';
import ServerIcon from '@/components/icons/ServerIcon.astro';
const lang = getLangFromUrl(Astro.url);
const t = useTranslations(lang);
const base = lang === 'en' ? '/en' : '';
const whatsappUrl = 'https://wa.me/59899812487';
const groups = [
{
title: t('services.cat.hosting'),
items: [
{ slug: 'hosting-correo-web', title: lang === 'en' ? 'Hosting for email & web' : 'Hosting correo y web', desc: lang === 'en' ? 'Optimized hosting with cPanel for WordPress, PHP and MySQL.' : 'Alojamiento optimizado con cPanel para WordPress, PHP y MySQL.', Icon: MailIcon, border: 'var(--color-hds-naranja)' },
{ slug: 'mantenimiento-wordpress', title: lang === 'en' ? 'WordPress maintenance' : 'Mantenimiento WordPress', desc: lang === 'en' ? 'Security patches and updates by official WordPress ecosystem experts.' : 'Parches de seguridad y actualizaciones por expertos del ecosistema WP.', Icon: WordpressIcon, border: 'var(--color-hds-naranja)' },
],
},
{
title: t('services.cat.design'),
items: [
{ slug: 'desarrollo-webs-institucionales', title: lang === 'en' ? 'Institutional websites' : 'Desarrollo webs institucionales', desc: lang === 'en' ? 'Corporate sites tailored to your business and identity.' : 'Sitios corporativos a medida de tu negocio e identidad.', Icon: CodeIcon, border: 'var(--color-hds-coral)' },
{ slug: 'e-commerce', title: lang === 'en' ? 'E-commerce websites' : 'Sitios web con e-commerce', desc: lang === 'en' ? 'WooCommerce stores with secure payments and inventory.' : 'Tiendas WooCommerce con pagos seguros y gestión de stock.', Icon: ShopIcon, border: 'var(--color-hds-coral)' },
{ slug: 'gestion-contenido-traducciones', title: lang === 'en' ? 'Content & translations' : 'Gestión de contenido y traducciones', desc: lang === 'en' ? 'Recurring editorial: copy, updates, blog and translations.' : 'Servicio editorial recurrente: redacción, blog, traducciones.', Icon: TranslateIcon, border: 'var(--color-hds-coral)' },
],
},
{
title: t('services.cat.infra'),
items: [
{ slug: 'servidores-linux-virtualizacion', title: lang === 'en' ? 'Linux servers & virtualization' : 'Servidores Linux y virtualización', desc: lang === 'en' ? 'Linux servers, KVM virtualization, private clouds.' : 'Servidores Linux, virtualización KVM, nubes privadas.', Icon: ServerIcon, border: 'var(--color-hds-durazno)' },
],
},
];
---
<BaseLayout
title={lang === 'en' ? 'Services' : 'Servicios'}
description={lang === 'en'
? 'Hosting, web development, e-commerce, content management and infrastructure services.'
: 'Servicios de hosting, desarrollo web, e-commerce, gestión de contenido e infraestructura.'}
lang={lang}
>
<section class="pt-20 pb-12 md:pt-28 md:pb-16" style="background: var(--hds-bg-soft);">
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
<SectionEyebrow text={lang === 'en' ? 'What we do' : 'Lo que hacemos'} />
<h1 class="font-display leading-tight mt-5" style="font-size: clamp(2.5rem, 6vw, 4.5rem); color: var(--hds-fg);">
{lang === 'en' ? 'Our' : 'Nuestros'} <span style="color: var(--color-hds-naranja); font-style: italic;">{lang === 'en' ? 'services' : 'servicios'}</span>.
</h1>
<p class="text-lg mt-5 max-w-2xl" style="color: var(--hds-fg-soft);">
{lang === 'en'
? 'A complete stack of services to support your business at every step, from basic hosting to complex infrastructure.'
: 'Un stack completo de servicios para acompañar a tu empresa en cada paso, desde el hosting básico hasta la infraestructura compleja.'}
</p>
</div>
</section>
<section class="py-20 md:py-24" style="background: var(--hds-bg);">
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 space-y-14">
{groups.map((group) => (
<div>
<div class="flex flex-wrap items-baseline gap-3 mb-6">
<h2 class="text-2xl md:text-3xl font-display" style="color: var(--hds-fg);">{group.title}</h2>
<span class="text-xs font-semibold tracking-[0.25em] uppercase" style="color: var(--color-hds-naranja);">
{group.items.length} {group.items.length === 1 ? (lang === 'en' ? 'service' : 'servicio') : (lang === 'en' ? 'services' : 'servicios')}
</span>
</div>
<div class="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-5">
{group.items.map((item) => (
<ServiceCard
href={`${base}/servicios/${item.slug}/`}
title={item.title}
description={item.desc}
Icon={item.Icon}
borderColor={item.border}
/>
))}
</div>
</div>
))}
</div>
</section>
<CtaFinal t={t} whatsappUrl={whatsappUrl} />
</BaseLayout>
+81
View File
@@ -0,0 +1,81 @@
---
import BaseLayout from '@/layouts/BaseLayout.astro';
import SectionEyebrow from '@/components/SectionEyebrow.astro';
import { getLangFromUrl, useTranslations } from '@/i18n/utils';
const lang = getLangFromUrl(Astro.url);
const t = useTranslations(lang);
const base = lang === 'en' ? '/en' : '';
const whatsappUrl = 'https://wa.me/59899812487';
const categories = [
{ key: 'correo', title: lang === 'en' ? 'Email' : 'Correo electrónico', desc: lang === 'en' ? 'Configuration in clients, IMAP/SMTP, webmail.' : 'Configuración en clientes, IMAP/SMTP, webmail.' },
{ key: 'wordpress', title: 'WordPress', desc: lang === 'en' ? 'Updates, backups, restoration, security.' : 'Actualizaciones, backups, restauración, seguridad.' },
{ key: 'dominios', title: lang === 'en' ? 'Domains & DNS' : 'Dominios y DNS', desc: lang === 'en' ? 'Point a domain, transfers, DNS records.' : 'Apuntar un dominio, transferencias, registros DNS.' },
{ key: 'cpanel', title: 'cPanel', desc: lang === 'en' ? 'Email accounts, FTP, databases, files.' : 'Cuentas de correo, FTP, bases de datos, archivos.' },
{ key: 'ssl', title: lang === 'en' ? 'SSL certificates' : 'Certificados SSL', desc: lang === 'en' ? 'Install, renewal, force HTTPS.' : 'Instalación, renovación, HTTPS forzado.' },
{ key: 'backups', title: lang === 'en' ? 'Backups' : 'Respaldos', desc: lang === 'en' ? 'JetBackup, file and email restoration.' : 'JetBackup, restauración de archivos y correos.' },
];
---
<BaseLayout
title={lang === 'en' ? 'Tutorials' : 'Instructivos'}
description={lang === 'en'
? 'Step-by-step guides to the most common questions from Hosting del Sur clients.'
: 'Guías paso a paso para las consultas más frecuentes de los clientes de Hosting del Sur.'}
lang={lang}
>
<section class="pt-20 pb-12 md:pt-28 md:pb-16" style="background: var(--hds-bg-soft);">
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
<SectionEyebrow text={lang === 'en' ? 'Knowledge base' : 'Base de conocimiento'} />
<h1 class="font-display leading-tight mt-5" style="font-size: clamp(2.5rem, 6vw, 4.5rem); color: var(--hds-fg);">
{lang === 'en' ? 'Tutorials' : 'Instructivos'}.
</h1>
<p class="text-lg mt-5 max-w-2xl" style="color: var(--hds-fg-soft);">
{lang === 'en'
? 'Step-by-step guides for the questions we receive most often. We are preparing detailed tutorials for each category.'
: 'Guías paso a paso para las preguntas que más recibimos. Estamos preparando instructivos detallados para cada categoría.'}
</p>
</div>
</section>
<section class="py-20 md:py-24" style="background: var(--hds-bg);">
<div class="max-w-5xl mx-auto px-4 sm:px-6 lg:px-8">
<div class="rounded-2xl p-6 md:p-8 mb-12 flex flex-col md:flex-row md:items-center md:justify-between gap-6" style="background: linear-gradient(135deg, rgba(238,118,35,0.08) 0%, rgba(250,159,92,0.12) 100%); border: 1px solid rgba(238,118,35,0.25);">
<div>
<h2 class="text-xl font-semibold mb-2" style="color: var(--hds-fg);">
{lang === 'en' ? 'Coming soon' : 'Próximamente'}
</h2>
<p style="color: var(--hds-fg-soft);">
{lang === 'en'
? 'We are writing detailed tutorials for each category. In the meantime, write to us on WhatsApp and we will help you right away.'
: 'Estamos escribiendo instructivos detallados para cada categoría. Mientras tanto, escribinos por WhatsApp y te ayudamos al instante.'}
</p>
</div>
<a
href={whatsappUrl}
target="_blank"
rel="noopener noreferrer"
class="btn-primary text-sm flex-shrink-0"
>
{lang === 'en' ? 'Chat on WhatsApp' : 'Hablar por WhatsApp'}
</a>
</div>
<h2 class="text-2xl mb-6 font-display" style="color: var(--hds-fg);">
{lang === 'en' ? 'Categories' : 'Categorías'}
</h2>
<div class="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-4">
{categories.map((cat) => (
<div class="service-card">
<h3 class="text-base font-semibold mb-1" style="color: var(--hds-fg);">{cat.title}</h3>
<p class="text-sm mb-3" style="color: var(--hds-fg-soft);">{cat.desc}</p>
<p class="text-xs italic" style="color: var(--hds-fg-muted);">
{lang === 'en' ? 'No tutorials yet' : 'Sin instructivos aún'}
</p>
</div>
))}
</div>
</div>
</section>
</BaseLayout>
+30
View File
@@ -0,0 +1,30 @@
---
import BaseLayout from '@/layouts/BaseLayout.astro';
import Hero from '@/components/Hero.astro';
import StatsSection from '@/components/StatsSection.astro';
import DifferenceCards from '@/components/DifferenceCards.astro';
import ServicesSection from '@/components/ServicesSection.astro';
import ProcessSteps from '@/components/ProcessSteps.astro';
import CtaFinal from '@/components/CtaFinal.astro';
import { getLangFromUrl, useTranslations } from '@/i18n/utils';
const lang = getLangFromUrl(Astro.url);
const t = useTranslations(lang);
const whatsappUrl = 'https://wa.me/59899812487';
const description = lang === 'en'
? 'Cloud hosting, websites, e-commerce and infrastructure with real human support from Maldonado, Uruguay. Hosting del Sur — technology with a human face.'
: 'Alojamiento en la nube, sitios web, e-commerce e infraestructura con soporte humano real desde Maldonado, Uruguay. Hosting del Sur — tecnología con cara de persona.';
---
<BaseLayout
title={lang === 'en' ? 'Cloud hosting with real human support' : 'Alojamiento en la nube con soporte humano real'}
description={description}
lang={lang}
>
<Hero t={t} whatsappUrl={whatsappUrl} />
<StatsSection t={t} />
<DifferenceCards t={t} />
<ServicesSection t={t} lang={lang} />
<ProcessSteps t={t} />
<CtaFinal t={t} whatsappUrl={whatsappUrl} />
</BaseLayout>
+81
View File
@@ -0,0 +1,81 @@
---
import BaseLayout from '@/layouts/BaseLayout.astro';
import SectionEyebrow from '@/components/SectionEyebrow.astro';
import { getLangFromUrl, useTranslations } from '@/i18n/utils';
const lang = getLangFromUrl(Astro.url);
const t = useTranslations(lang);
const base = lang === 'en' ? '/en' : '';
const whatsappUrl = 'https://wa.me/59899812487';
const categories = [
{ key: 'correo', title: lang === 'en' ? 'Email' : 'Correo electrónico', desc: lang === 'en' ? 'Configuration in clients, IMAP/SMTP, webmail.' : 'Configuración en clientes, IMAP/SMTP, webmail.' },
{ key: 'wordpress', title: 'WordPress', desc: lang === 'en' ? 'Updates, backups, restoration, security.' : 'Actualizaciones, backups, restauración, seguridad.' },
{ key: 'dominios', title: lang === 'en' ? 'Domains & DNS' : 'Dominios y DNS', desc: lang === 'en' ? 'Point a domain, transfers, DNS records.' : 'Apuntar un dominio, transferencias, registros DNS.' },
{ key: 'cpanel', title: 'cPanel', desc: lang === 'en' ? 'Email accounts, FTP, databases, files.' : 'Cuentas de correo, FTP, bases de datos, archivos.' },
{ key: 'ssl', title: lang === 'en' ? 'SSL certificates' : 'Certificados SSL', desc: lang === 'en' ? 'Install, renewal, force HTTPS.' : 'Instalación, renovación, HTTPS forzado.' },
{ key: 'backups', title: lang === 'en' ? 'Backups' : 'Respaldos', desc: lang === 'en' ? 'JetBackup, file and email restoration.' : 'JetBackup, restauración de archivos y correos.' },
];
---
<BaseLayout
title={lang === 'en' ? 'Tutorials' : 'Instructivos'}
description={lang === 'en'
? 'Step-by-step guides to the most common questions from Hosting del Sur clients.'
: 'Guías paso a paso para las consultas más frecuentes de los clientes de Hosting del Sur.'}
lang={lang}
>
<section class="pt-20 pb-12 md:pt-28 md:pb-16" style="background: var(--hds-bg-soft);">
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
<SectionEyebrow text={lang === 'en' ? 'Knowledge base' : 'Base de conocimiento'} />
<h1 class="font-display leading-tight mt-5" style="font-size: clamp(2.5rem, 6vw, 4.5rem); color: var(--hds-fg);">
{lang === 'en' ? 'Tutorials' : 'Instructivos'}.
</h1>
<p class="text-lg mt-5 max-w-2xl" style="color: var(--hds-fg-soft);">
{lang === 'en'
? 'Step-by-step guides for the questions we receive most often. We are preparing detailed tutorials for each category.'
: 'Guías paso a paso para las preguntas que más recibimos. Estamos preparando instructivos detallados para cada categoría.'}
</p>
</div>
</section>
<section class="py-20 md:py-24" style="background: var(--hds-bg);">
<div class="max-w-5xl mx-auto px-4 sm:px-6 lg:px-8">
<div class="rounded-2xl p-6 md:p-8 mb-12 flex flex-col md:flex-row md:items-center md:justify-between gap-6" style="background: linear-gradient(135deg, rgba(238,118,35,0.08) 0%, rgba(250,159,92,0.12) 100%); border: 1px solid rgba(238,118,35,0.25);">
<div>
<h2 class="text-xl font-semibold mb-2" style="color: var(--hds-fg);">
{lang === 'en' ? 'Coming soon' : 'Próximamente'}
</h2>
<p style="color: var(--hds-fg-soft);">
{lang === 'en'
? 'We are writing detailed tutorials for each category. In the meantime, write to us on WhatsApp and we will help you right away.'
: 'Estamos escribiendo instructivos detallados para cada categoría. Mientras tanto, escribinos por WhatsApp y te ayudamos al instante.'}
</p>
</div>
<a
href={whatsappUrl}
target="_blank"
rel="noopener noreferrer"
class="btn-primary text-sm flex-shrink-0"
>
{lang === 'en' ? 'Chat on WhatsApp' : 'Hablar por WhatsApp'}
</a>
</div>
<h2 class="text-2xl mb-6 font-display" style="color: var(--hds-fg);">
{lang === 'en' ? 'Categories' : 'Categorías'}
</h2>
<div class="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-4">
{categories.map((cat) => (
<div class="service-card">
<h3 class="text-base font-semibold mb-1" style="color: var(--hds-fg);">{cat.title}</h3>
<p class="text-sm mb-3" style="color: var(--hds-fg-soft);">{cat.desc}</p>
<p class="text-xs italic" style="color: var(--hds-fg-muted);">
{lang === 'en' ? 'No tutorials yet' : 'Sin instructivos aún'}
</p>
</div>
))}
</div>
</div>
</section>
</BaseLayout>
+56
View File
@@ -0,0 +1,56 @@
---
import BaseLayout from '@/layouts/BaseLayout.astro';
import { getLangFromUrl } from '@/i18n/utils';
const lang = getLangFromUrl(Astro.url);
const base = lang === 'en' ? '/en' : '';
---
<BaseLayout
title={lang === 'en' ? 'Privacy policy' : 'Política de privacidad'}
description={lang === 'en' ? 'Privacy policy of Hosting del Sur.' : 'Política de privacidad de Hosting del Sur.'}
lang={lang}
>
<article class="py-16 md:py-20 bg-hds-marfil">
<div class="max-w-3xl mx-auto px-4 sm:px-6 lg:px-8 prose prose-lg">
<h1>{lang === 'en' ? 'Privacy policy' : 'Política de privacidad'}</h1>
<p class="text-sm text-hds-humo">
{lang === 'en' ? 'Last updated' : 'Última actualización'}: 2026
</p>
<h2>{lang === 'en' ? '1. Data we collect' : '1. Datos que recopilamos'}</h2>
<p>
{lang === 'en'
? 'When you fill out the contact form, we collect: name, email and the message you send us. We use this data exclusively to respond to your inquiry.'
: 'Cuando completás el formulario de contacto, recopilamos: nombre, email y el mensaje que nos envías. Usamos estos datos exclusivamente para responder a tu consulta.'}
</p>
<h2>{lang === 'en' ? '2. How we use your data' : '2. Cómo usamos tus datos'}</h2>
<p>
{lang === 'en'
? 'We use the data you provide solely to: (a) respond to your inquiry, (b) follow up if you become a customer. We do not sell, rent or share your data with third parties.'
: 'Usamos los datos que nos proporcionás únicamente para: (a) responder a tu consulta, (b) dar seguimiento si te convertís en cliente. No vendemos, alquilamos ni compartimos tus datos con terceros.'}
</p>
<h2>{lang === 'en' ? '3. Hosting and data location' : '3. Hosting y ubicación de datos'}</h2>
<p>
{lang === 'en'
? 'Our infrastructure is in datacenters in the United States and Europe. If you require data to be hosted in a specific country, please let us know and we will work out the best option.'
: 'Nuestra infraestructura se encuentra en datacenters en Estados Unidos y Europa. Si necesitás que los datos se hospeden en un país específico, avísanos y acordamos la mejor opción.'}
</p>
<h2>{lang === 'en' ? '4. Your rights' : '4. Tus derechos'}</h2>
<p>
{lang === 'en'
? 'You can request access, rectification or deletion of your data at any time by writing to contacto@hostingdelsur.net.'
: 'Podés solicitar acceso, rectificación o eliminación de tus datos en cualquier momento escribiendo a contacto@hostingdelsur.net.'}
</p>
<h2>{lang === 'en' ? '5. Cookies' : '5. Cookies'}</h2>
<p>
{lang === 'en'
? 'This site does not use tracking cookies. We may use strictly necessary cookies for the language preference.'
: 'Este sitio no utiliza cookies de seguimiento. Podemos usar cookies estrictamente necesarias para la preferencia de idioma.'}
</p>
</div>
</article>
</BaseLayout>
+48
View File
@@ -0,0 +1,48 @@
---
import BaseLayout from '@/layouts/BaseLayout.astro';
import { getLangFromUrl } from '@/i18n/utils';
const lang = getLangFromUrl(Astro.url);
---
<BaseLayout
title={lang === 'en' ? 'Terms of service' : 'Términos del servicio'}
description={lang === 'en' ? 'Terms of service of Hosting del Sur.' : 'Términos del servicio de Hosting del Sur.'}
lang={lang}
>
<article class="py-16 md:py-20 bg-hds-marfil">
<div class="max-w-3xl mx-auto px-4 sm:px-6 lg:px-8 prose prose-lg">
<h1>{lang === 'en' ? 'Terms of service' : 'Términos del servicio'}</h1>
<p class="text-sm text-hds-humo">
{lang === 'en' ? 'Last updated' : 'Última actualización'}: 2026
</p>
<h2>{lang === 'en' ? '1. Services' : '1. Servicios'}</h2>
<p>
{lang === 'en'
? 'Hosting del Sur provides web hosting, email, web development, e-commerce, content management and IT infrastructure services under individual agreements with each client.'
: 'Hosting del Sur brinda servicios de hosting web, correo, desarrollo web, e-commerce, gestión de contenido e infraestructura IT bajo acuerdos individuales con cada cliente.'}
</p>
<h2>{lang === 'en' ? '2. Acceptable use' : '2. Uso aceptable'}</h2>
<p>
{lang === 'en'
? 'The client agrees to use the services in accordance with current legislation and the Acceptable Use Policy, refraining from activities that may damage third parties or the integrity of our infrastructure.'
: 'El cliente se compromete a utilizar los servicios de conformidad con la legislación vigente y la Política de Uso Aceptable, absteniéndose de realizar actividades que puedan dañar a terceros o la integridad de nuestra infraestructura.'}
</p>
<h2>{lang === 'en' ? '3. Liability' : '3. Responsabilidad'}</h2>
<p>
{lang === 'en'
? 'Hosting del Sur is not liable for damages caused by improper use of the services, force majeure, or third-party actions beyond our control.'
: 'Hosting del Sur no se hace responsable por daños causados por uso indebido de los servicios, fuerza mayor o acciones de terceros fuera de nuestro control.'}
</p>
<h2>{lang === 'en' ? '4. Modifications' : '4. Modificaciones'}</h2>
<p>
{lang === 'en'
? 'We reserve the right to modify these terms. Clients will be notified with reasonable advance notice.'
: 'Nos reservamos el derecho de modificar estos términos. Los clientes serán notificados con antelación razonable.'}
</p>
</div>
</article>
</BaseLayout>
+97
View File
@@ -0,0 +1,97 @@
---
import BaseLayout from '@/layouts/BaseLayout.astro';
import SectionEyebrow from '@/components/SectionEyebrow.astro';
import WorldMap from '@/components/icons/WorldMap.astro';
import CtaFinal from '@/components/CtaFinal.astro';
import { getLangFromUrl, useTranslations } from '@/i18n/utils';
const lang = getLangFromUrl(Astro.url);
const t = useTranslations(lang);
const whatsappUrl = 'https://wa.me/59899812487';
---
<BaseLayout
title={lang === 'en' ? 'About us' : 'Nosotros'}
description={lang === 'en'
? 'Since 2000, Hosting del Sur provides technology services with a human touch from Maldonado, Uruguay, across four countries.'
: 'Desde 2000, Hosting del Sur brinda servicios de tecnología con atención humana desde Maldonado, Uruguay, con alcance en cuatro países.'}
lang={lang}
>
<section class="pt-20 pb-12 md:pt-28 md:pb-16" style="background: var(--hds-bg-soft);">
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
<SectionEyebrow text={lang === 'en' ? 'About us' : 'Nosotros'} />
<h1 class="font-display leading-tight mt-5 max-w-4xl" style="font-size: clamp(2.5rem, 6vw, 4.5rem); color: var(--hds-fg);">
{lang === 'en'
? <>Technology with a <span style="color: var(--color-hds-naranja); font-style: italic;">human face</span> since 2000.</>
: <>Tecnología con <span style="color: var(--color-hds-naranja); font-style: italic;">cara de persona</span> desde 2000.</>}
</h1>
</div>
</section>
<section class="py-16 md:py-20" style="background: var(--hds-bg);">
<div class="max-w-4xl mx-auto px-4 sm:px-6 lg:px-8">
<div class="prose prose-lg max-w-none" style="color: var(--hds-fg-soft);">
<p class="text-lg leading-relaxed" style="color: var(--hds-fg-soft);">
{lang === 'en'
? 'We are a small team of senior SysAdmins and SREs based in Maldonado, Uruguay. We work with clients across Latin America and the world.'
: 'Somos un equipo chico de SysAdmins y SREs senior, radicados en Maldonado, Uruguay. Trabajamos con clientes de toda Latinoamérica y el mundo.'}
</p>
<h2 class="font-display mt-12 mb-4" style="color: var(--hds-fg); font-size: 2rem;">
{lang === 'en' ? 'Our story' : 'Nuestra historia'}
</h2>
<p>
{lang === 'en'
? 'Hosting del Sur was born in 2000 as a hosting services provider for Uruguayan businesses. From the beginning we were clear: we wanted to offer enterprise-level technology with the closeness of a small team. Twenty-six years later we are still the same — fewer tickets, real names, infrastructure we know by heart.'
: 'Hosting del Sur nació en el año 2000 como proveedor de servicios de hosting para empresas uruguayas. Desde el principio teníamos claro: queríamos ofrecer tecnología de nivel enterprise con la cercanía de un equipo chico. Veintiséis años después seguimos siendo lo mismo — menos tickets, nombres reales, infraestructura que conocemos de memoria.'}
</p>
<h2 class="font-display mt-12 mb-4" style="color: var(--hds-fg); font-size: 2rem;">
{lang === 'en' ? 'What we believe' : 'En qué creemos'}
</h2>
<ul class="space-y-2" style="color: var(--hds-fg-soft);">
<li><strong style="color: var(--hds-fg);">{lang === 'en' ? 'A real person answers.' : 'Una persona real te responde.'}</strong> {lang === 'en' ? 'Always.' : 'Siempre.'}</li>
<li><strong style="color: var(--hds-fg);">{lang === 'en' ? 'You own your data.' : 'Tus datos son tuyos.'}</strong> {lang === 'en' ? 'We just host it.' : 'Nosotros solo los hospedamos.'}</li>
<li><strong style="color: var(--hds-fg);">{lang === 'en' ? 'Open source first.' : 'Open source primero.'}</strong> {lang === 'en' ? 'Vendor lock-in never.' : 'Vendor lock-in nunca.'}</li>
<li><strong style="color: var(--hds-fg);">{lang === 'en' ? 'No magic, no jargon.' : 'Sin magia, sin jerga.'}</strong> {lang === 'en' ? 'We explain what we do.' : 'Explicamos lo que hacemos.'}</li>
</ul>
</div>
</div>
</section>
<section class="py-20 md:py-24" style="background: var(--hds-bg-soft);">
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
<div class="grid grid-cols-1 lg:grid-cols-2 gap-12 items-center">
<div>
<SectionEyebrow text={lang === 'en' ? 'Where we work' : 'Dónde trabajamos'} />
<h2 class="font-display leading-tight mt-5" style="font-size: clamp(2rem, 4.5vw, 3rem); color: var(--hds-fg);">
{lang === 'en'
? <>Four countries,<br/><span style="color: var(--color-hds-naranja); font-style: italic;">one team</span>.</>
: <>Cuatro países,<br/><span style="color: var(--color-hds-naranja); font-style: italic;">un equipo</span>.</>}
</h2>
<p class="text-lg mt-5" style="color: var(--hds-fg-soft);">
{lang === 'en'
? 'We operate from Maldonado, Uruguay, with infrastructure distributed across four countries: Canada, the United States, Germany and Uruguay. We combine providers in three regions with our own equipment in Uruguay to give you redundancy, low latency and data sovereignty.'
: 'Operamos desde Maldonado, Uruguay, con infraestructura distribuida en cuatro países: Canadá, Estados Unidos, Alemania y Uruguay. Combinamos proveedores en tres regiones con equipos propios en Uruguay para darte redundancia, baja latencia y soberanía de datos.'}
</p>
<ul class="mt-8 space-y-3 text-sm" style="color: var(--hds-fg-soft);">
<li class="flex items-start gap-3">
<span class="mt-1.5 w-2 h-2 rounded-full flex-shrink-0" style="background: var(--color-hds-naranja);"></span>
<span><strong style="color: var(--hds-fg);">{lang === 'en' ? 'Canada, USA, Germany:' : 'Canadá, USA, Alemania:'}</strong> {lang === 'en' ? 'provider infrastructure.' : 'infraestructura de proveedores.'}</span>
</li>
<li class="flex items-start gap-3">
<span class="mt-1.5 w-2 h-2 rounded-full flex-shrink-0" style="background: var(--color-hds-naranja);"></span>
<span><strong style="color: var(--hds-fg);">{lang === 'en' ? 'Uruguay:' : 'Uruguay:'}</strong> {lang === 'en' ? 'our own equipment and headquarters.' : 'equipos propios y sede operativa.'}</span>
</li>
</ul>
</div>
<div class="rounded-2xl p-6 lg:p-8" style="background: var(--hds-card); border: 1px solid var(--hds-line);">
<WorldMap class="w-full h-auto" />
</div>
</div>
</div>
</section>
<CtaFinal t={t} whatsappUrl={whatsappUrl} />
</BaseLayout>
+68
View File
@@ -0,0 +1,68 @@
---
import BaseLayout from '@/layouts/BaseLayout.astro';
import SectionEyebrow from '@/components/SectionEyebrow.astro';
import PricingTiers from '@/components/PricingTiers.astro';
import CtaFinal from '@/components/CtaFinal.astro';
import { PLANS, ADDITIONAL_PLANS, monthlyEquivalent } from '@/lib/pricing';
import { getLangFromUrl, useTranslations } from '@/i18n/utils';
const lang = getLangFromUrl(Astro.url);
const t = useTranslations(lang);
const whatsappUrl = 'https://wa.me/59899812487';
const base = lang === 'en' ? '/en' : '';
---
<BaseLayout
title={lang === 'en' ? 'Hosting plans' : 'Planes de hosting'}
description={lang === 'en'
? 'Hosting plans in USD, billed annually. Basic, Institutional and E-commerce tiers with optional WordPress, Advanced and Corporate plans.'
: 'Planes de hosting en USD, con cobro anual. Básico, Institucional y E-commerce, más planes opcionales WordPress, Avanzado y Corporativo.'}
lang={lang}
>
<section class="pt-20 pb-12 md:pt-28 md:pb-16" style="background: var(--hds-bg-soft);">
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
<SectionEyebrow text={lang === 'en' ? 'Hosting plans' : 'Planes de hosting'} />
<h1 class="font-display leading-tight mt-5" style="font-size: clamp(2.5rem, 6vw, 4.5rem); color: var(--hds-fg);">
Elegí el plan que se<br/>adapta a tu <span style="color: var(--color-hds-naranja); font-style: italic;">proyecto</span>.
</h1>
<p class="text-lg mt-5 max-w-2xl" style="color: var(--hds-fg-soft);">
{lang === 'en'
? 'Prices in USD, billed annually. Features may vary depending on the project and server configuration.'
: 'Precios en USD, con cobro anual. Las características pueden variar según el proyecto y la configuración del servidor.'}
</p>
</div>
</section>
<section class="py-20 md:py-24" style="background: var(--hds-bg);">
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
<PricingTiers
plans={PLANS}
whatsappUrl={whatsappUrl}
/>
<div class="mt-10 text-center text-sm space-y-1" style="color: var(--hds-fg-muted);">
<p>⚠️ {lang === 'en'
? 'Prices are in US Dollars (USD). Billed annually.'
: 'Los precios están expresados en dólares estadounidenses (USD). El cobro es anual.'}</p>
<p>{lang === 'en'
? 'Features may vary based on project and server configuration.'
: 'Las características pueden variar según el proyecto y la configuración del servidor.'}</p>
</div>
</div>
</section>
<section class="py-20" style="background: var(--hds-bg-soft);">
<div class="max-w-3xl mx-auto px-4 sm:px-6 lg:px-8 text-center">
<h2 class="font-display mb-4" style="font-size: clamp(1.75rem, 4vw, 2.5rem); color: var(--hds-fg);">
{lang === 'en' ? 'Need a different plan?' : '¿Necesitás otro plan?'}
</h2>
<p class="text-lg mb-8" style="color: var(--hds-fg-soft);">
{lang === 'en' ? 'We also have ' : 'También tenemos '}
<strong>{ADDITIONAL_PLANS.join(', ')}</strong>.
{lang === 'en' ? ' Tell us about your project and we will tailor a plan to you.' : ' Charlá con nosotros y te armamos un plan a medida.'}
</p>
<a href={whatsappUrl} target="_blank" rel="noopener noreferrer" class="btn-primary">
{lang === 'en' ? 'Chat on WhatsApp' : 'Hablar por WhatsApp'}
</a>
</div>
</section>
</BaseLayout>
+55
View File
@@ -0,0 +1,55 @@
---
import BaseLayout from '@/layouts/BaseLayout.astro';
import SectionEyebrow from '@/components/SectionEyebrow.astro';
import FAQAccordion from '@/components/FAQAccordion.astro';
import CtaFinal from '@/components/CtaFinal.astro';
import { getLangFromUrl, useTranslations } from '@/i18n/utils';
const lang = getLangFromUrl(Astro.url);
const t = useTranslations(lang);
const whatsappUrl = 'https://wa.me/59899812487';
const faqs = lang === 'en' ? [
{ q: 'What makes you different from a regular hosting provider?', a: 'A real person answers your call. We are a small team of senior SysAdmins/SREs based in Maldonado, Uruguay. No tickets, no chatbots, no offshore call centers.' },
{ q: 'Where is my data physically located?', a: 'We operate infrastructure across four countries: Canada, the United States, Germany and Uruguay. We can work with you to choose the region that best fits your compliance and latency needs.' },
{ q: 'Do you offer 24/7 support?', a: 'No. We are available during business hours (Monday to Friday, 9 to 18 UYT). Outside those hours we monitor critical alerts, but human support is provided during business hours.' },
{ q: 'Do you manage WordPress sites?', a: 'Yes. We are part of the official WordPress ecosystem. We offer hosting, maintenance, security patches, performance tuning and full development.' },
{ q: 'Can you build my company website from scratch?', a: 'Yes. We design and develop institutional sites and e-commerce stores (WooCommerce) with focus on performance, accessibility (WCAG AA) and SEO.' },
{ q: 'What if I need a plan that is not listed?', a: 'We have additional tiers (WordPress, Empresarial, Avanzado, Avanzado HD, Corporativo, Corporativo HD). Chat with us on WhatsApp and we will tailor a plan for you.' },
{ q: 'Do you provide cloud servers and virtualization?', a: 'Yes. We install and administer Linux servers, KVM virtualization, private clouds (Nextcloud-style), high availability and 24/7 monitoring with Prometheus/Grafana.' },
] : [
{ q: '¿Qué los diferencia de un proveedor de hosting tradicional?', a: 'Una persona real te atiende. Somos un equipo chico de SysAdmins/SREs senior radicados en Maldonado, Uruguay. Sin tickets, sin chatbots, sin call centers offshore.' },
{ q: '¿Dónde están físicamente mis datos?', a: 'Operamos infraestructura en cuatro países: Canadá, Estados Unidos, Alemania y Uruguay. Podemos trabajar con vos para elegir la región que mejor se ajuste a tus necesidades de compliance y latencia.' },
{ q: '¿Tienen soporte 24/7?', a: 'No. Estamos disponibles en horario comercial (lunes a viernes, 9 a 18 hs UYT). Fuera de ese horario monitoreamos alertas críticas, pero el soporte humano se brinda en horario comercial.' },
{ q: '¿Manejan sitios WordPress?', a: 'Sí. Somos parte del ecosistema oficial de WordPress. Ofrecemos hosting, mantenimiento, parches de seguridad, optimización de performance y desarrollo completo.' },
{ q: '¿Pueden armar el sitio web de mi empresa desde cero?', a: 'Sí. Diseñamos y desarrollamos sitios institucionales y e-commerce (WooCommerce) con foco en performance, accesibilidad (WCAG AA) y SEO.' },
{ q: '¿Qué pasa si necesito un plan que no está en la lista?', a: 'Tenemos tiers adicionales (WordPress, Empresarial, Avanzado, Avanzado HD, Corporativo, Corporativo HD). Charlá con nosotros por WhatsApp y te armamos un plan a medida.' },
{ q: '¿Brindan servidores cloud y virtualización?', a: 'Sí. Instalamos y administramos servidores Linux, virtualización KVM, nubes privadas (estilo Nextcloud), alta disponibilidad y monitoreo 24/7 con Prometheus/Grafana.' },
];
---
<BaseLayout
title={lang === 'en' ? 'FAQ' : 'Preguntas frecuentes'}
description={lang === 'en'
? 'Frequently asked questions about Hosting del Sur, our plans, infrastructure and support.'
: 'Preguntas frecuentes sobre Hosting del Sur, nuestros planes, infraestructura y soporte.'}
lang={lang}
>
<section class="pt-20 pb-12 md:pt-28 md:pb-16" style="background: var(--hds-bg-soft);">
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
<SectionEyebrow text={lang === 'en' ? 'FAQ' : 'Preguntas frecuentes'} />
<h1 class="font-display leading-tight mt-5" style="font-size: clamp(2.5rem, 6vw, 4.5rem); color: var(--hds-fg);">
{lang === 'en'
? <>Common <span style="color: var(--color-hds-naranja); font-style: italic;">questions</span>.</>
: <>Preguntas <span style="color: var(--color-hds-naranja); font-style: italic;">frecuentes</span>.</>}
</h1>
</div>
</section>
<section class="py-20 md:py-24" style="background: var(--hds-bg);">
<div class="max-w-3xl mx-auto px-4 sm:px-6 lg:px-8">
<FAQAccordion items={faqs} />
</div>
</section>
<CtaFinal t={t} whatsappUrl={whatsappUrl} />
</BaseLayout>
+268
View File
@@ -0,0 +1,268 @@
---
import BaseLayout from '@/layouts/BaseLayout.astro';
import { getLangFromUrl, useTranslations } from '@/i18n/utils';
import MailIcon from '@/components/icons/MailIcon.astro';
import WordpressIcon from '@/components/icons/WordpressIcon.astro';
import CodeIcon from '@/components/icons/CodeIcon.astro';
import ShopIcon from '@/components/icons/ShopIcon.astro';
import TranslateIcon from '@/components/icons/TranslateIcon.astro';
import ServerIcon from '@/components/icons/ServerIcon.astro';
const lang = getLangFromUrl(Astro.url);
const t = useTranslations(lang);
const slug = Astro.params.slug;
export function getStaticPaths() {
return [
{ params: { slug: 'hosting-correo-web' } },
{ params: { slug: 'mantenimiento-wordpress' } },
{ params: { slug: 'desarrollo-webs-institucionales' } },
{ params: { slug: 'e-commerce' } },
{ params: { slug: 'gestion-contenido-traducciones' } },
{ params: { slug: 'servidores-linux-virtualizacion' } },
];
}
const services: Record<string, {
icon: any;
title_es: string;
title_en: string;
category: string;
body_es: string;
body_en: string;
features_es: string[];
features_en: string[];
}> = {
'hosting-correo-web': {
icon: MailIcon,
title_es: 'Hosting correo y web',
title_en: 'Hosting for email and web',
category: 'Hosting & Correo',
body_es: 'Alojamiento web optimizado con cPanel. Infraestructura estable y profesional para que tu sitio rinda al máximo sin complicaciones técnicas. Soporte para WordPress, PHP y MySQL.',
body_en: 'Optimized web hosting with cPanel. Stable, professional infrastructure for your site to perform at its best without technical complications. WordPress, PHP and MySQL support.',
features_es: [
'Panel cPanel intuitivo',
'PHP 7.4 a 8.3, MySQL/MariaDB',
'SSL gratis (Let\'s Encrypt)',
'Backups automáticos diarios',
'Soporte para WordPress optimizado',
'Correo electrónico corporativo',
],
features_en: [
'Intuitive cPanel',
'PHP 7.4 to 8.3, MySQL/MariaDB',
'Free SSL (Let\'s Encrypt)',
'Daily automatic backups',
'Optimized WordPress support',
'Corporate email',
],
},
'mantenimiento-wordpress': {
icon: WordpressIcon,
title_es: 'Mantenimiento WordPress',
title_en: 'WordPress maintenance',
category: 'Hosting & Correo',
body_es: 'Mantenimiento proactivo y parches de seguridad por expertos que participan en el ecosistema oficial de WordPress. Tu sitio, siempre protegido.',
body_en: 'Proactive maintenance and security patches by experts participating in the official WordPress ecosystem. Your site, always protected.',
features_es: [
'Actualizaciones de core, themes y plugins',
'Parches de seguridad críticos',
'Backups antes de cada cambio',
'Monitoreo de uptime 24/7',
'Reporte mensual de actividad',
'Restauración ante incidentes',
],
features_en: [
'Core, theme and plugin updates',
'Critical security patches',
'Backups before every change',
'24/7 uptime monitoring',
'Monthly activity report',
'Incident restoration',
],
},
'desarrollo-webs-institucionales': {
icon: CodeIcon,
title_es: 'Desarrollo webs institucionales',
title_en: 'Institutional website development',
category: 'Diseño & Contenido',
body_es: 'Diseño y desarrollo de sitios web corporativos a medida de tu negocio. Trabajamos con foco en performance, accesibilidad y SEO.',
body_en: 'Design and development of corporate websites tailored to your business. We focus on performance, accessibility and SEO.',
features_es: [
'Diseño responsive y accesible (WCAG AA)',
'Optimización SEO técnico desde el inicio',
'Performance > 90 en Lighthouse',
'CMS amigable para edición autónoma',
'Formación de uso al equipo del cliente',
'Soporte post-lanzamiento',
],
features_en: [
'Responsive, accessible design (WCAG AA)',
'Technical SEO from the start',
'Lighthouse performance > 90',
'Friendly CMS for autonomous editing',
'Training for the client team',
'Post-launch support',
],
},
'e-commerce': {
icon: ShopIcon,
title_es: 'Sitios web con e-commerce',
title_en: 'E-commerce websites',
category: 'Diseño & Contenido',
body_es: 'Tiendas online robustas con WooCommerce. Pagos seguros, gestión de inventario, envíos y todo lo necesario para vender online.',
body_en: 'Robust online stores with WooCommerce. Secure payments, inventory management, shipping and everything you need to sell online.',
features_es: [
'WooCommerce con pasarelas de pago locales',
'Gestión de stock y pedidos',
'Integración con transportistas',
'Panel de reportes de venta',
'Cupones, descuentos y envíos gratis',
'Optimización para Core Web Vitals',
],
features_en: [
'WooCommerce with local payment gateways',
'Stock and order management',
'Carrier integration',
'Sales reporting panel',
'Coupons, discounts and free shipping',
'Core Web Vitals optimization',
],
},
'gestion-contenido-traducciones': {
icon: TranslateIcon,
title_es: 'Gestión de contenido y traducciones',
title_en: 'Content management and translations',
category: 'Diseño & Contenido',
body_es: 'Servicio editorial recurrente: redacción, actualización de contenido, gestión de blog y traducción multilenguaje. Tu sitio siempre al día, sin que tengas que ocuparte.',
body_en: 'Recurring editorial service: copywriting, content updates, blog management and multilingual translation. Your site always up to date, without you having to worry.',
features_es: [
'Redacción profesional de artículos',
'Traducción es/en/pt',
'Publicación en CMS o WordPress',
'Calendario editorial mensual',
'Optimización SEO de cada pieza',
'Reporte de tráfico y engagement',
],
features_en: [
'Professional article writing',
'ES/EN/PT translation',
'CMS or WordPress publishing',
'Monthly editorial calendar',
'SEO optimization of every piece',
'Traffic and engagement report',
],
},
'servidores-linux-virtualizacion': {
icon: ServerIcon,
title_es: 'Servidores Linux y virtualización',
title_en: 'Linux servers and virtualization',
category: 'Infraestructura',
body_es: 'Diseño, instalación y administración de servidores Linux con virtualización KVM. Nubes privadas, servicios empresariales y plataformas de alta disponibilidad.',
body_en: 'Design, installation and administration of Linux servers with KVM virtualization. Private clouds, enterprise services and high-availability platforms.',
features_es: [
'Servidores dedicados o VPS con KVM',
'Nubes privadas estilo Nextcloud',
'Alta disponibilidad y balanceo',
'Monitoreo 24/7 con Prometheus/Grafana',
'Respaldos automatizados',
'Hardening y seguridad perimetral',
],
features_en: [
'Dedicated servers or VPS with KVM',
'Nextcloud-style private clouds',
'High availability and balancing',
'24/7 monitoring with Prometheus/Grafana',
'Automated backups',
'Hardening and perimeter security',
],
},
};
const service = services[slug as keyof typeof services];
if (!service) {
return Astro.redirect(lang === 'en' ? '/en/servicios/' : '/servicios/');
}
const title = lang === 'en' ? service.title_en : service.title_es;
const body = lang === 'en' ? service.body_en : service.body_es;
const features = lang === 'en' ? service.features_en : service.features_es;
const base = lang === 'en' ? '/en' : '';
const whatsappUrl = 'https://wa.me/59899812487';
---
<BaseLayout
title={title}
description={body}
lang={lang}
>
<section class="bg-hds-crema py-12 md:py-16">
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
<nav aria-label="Breadcrumb" class="text-sm text-hds-humo mb-6">
<ol class="flex flex-wrap items-center gap-2">
<li><a href={`${base}/`} class="hover:text-hds-naranja">{lang === 'en' ? 'Home' : 'Inicio'}</a></li>
<li aria-hidden="true">/</li>
<li><a href={`${base}/servicios/`} class="hover:text-hds-naranja">{lang === 'en' ? 'Services' : 'Servicios'}</a></li>
<li aria-hidden="true">/</li>
<li class="text-hds-grafito" aria-current="page">{title}</li>
</ol>
</nav>
<div class="flex items-start gap-5 mb-4">
<div class="flex-shrink-0 bg-white rounded-lg p-3 border border-hds-linea">
<service.icon class="w-10 h-10" />
</div>
<div>
<p class="text-xs font-semibold tracking-wider uppercase text-hds-naranja mb-1">
{service.category}
</p>
<h1 class="text-3xl md:text-5xl text-hds-tinta leading-tight">
{title}
</h1>
</div>
</div>
</div>
</section>
<section class="py-16 md:py-20 bg-hds-marfil">
<div class="max-w-4xl mx-auto px-4 sm:px-6 lg:px-8">
<p class="text-lg text-hds-grafito leading-relaxed mb-10">
{body}
</p>
<h2 class="text-2xl md:text-3xl text-hds-tinta mb-6">
{lang === 'en' ? 'What is included' : 'Qué incluye'}
</h2>
<ul class="space-y-3 mb-12">
{features.map((feature) => (
<li class="flex items-start gap-3">
<svg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="#EE7623" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" class="flex-shrink-0 mt-0.5" aria-hidden="true">
<polyline points="20 6 9 17 4 12"/>
</svg>
<span class="text-hds-grafito">{feature}</span>
</li>
))}
</ul>
<div class="bg-hds-crema rounded-lg p-8 border border-hds-linea">
<h3 class="text-xl text-hds-tinta mb-2">
{lang === 'en' ? 'Want to know more?' : '¿Querés saber más?'}
</h3>
<p class="text-hds-grafito mb-5">
{lang === 'en'
? 'Tell us about your project and we will reply with a tailor-made proposal.'
: 'Contanos sobre tu proyecto y te respondemos con una propuesta a medida.'}
</p>
<a
href={whatsappUrl}
target="_blank"
rel="noopener noreferrer"
class="inline-flex items-center justify-center gap-2 bg-hds-naranja hover:bg-hds-naranja-hover text-white text-sm font-semibold px-5 py-2.5 rounded-md transition-colors"
>
{lang === 'en' ? 'Chat on WhatsApp' : 'Hablar por WhatsApp'}
</a>
</div>
</div>
</section>
</BaseLayout>
+91
View File
@@ -0,0 +1,91 @@
---
import BaseLayout from '@/layouts/BaseLayout.astro';
import SectionEyebrow from '@/components/SectionEyebrow.astro';
import ServiceCard from '@/components/ServiceCard.astro';
import CtaFinal from '@/components/CtaFinal.astro';
import { getLangFromUrl, useTranslations } from '@/i18n/utils';
import MailIcon from '@/components/icons/MailIcon.astro';
import WordpressIcon from '@/components/icons/WordpressIcon.astro';
import CodeIcon from '@/components/icons/CodeIcon.astro';
import ShopIcon from '@/components/icons/ShopIcon.astro';
import TranslateIcon from '@/components/icons/TranslateIcon.astro';
import ServerIcon from '@/components/icons/ServerIcon.astro';
const lang = getLangFromUrl(Astro.url);
const t = useTranslations(lang);
const base = lang === 'en' ? '/en' : '';
const whatsappUrl = 'https://wa.me/59899812487';
const groups = [
{
title: t('services.cat.hosting'),
items: [
{ slug: 'hosting-correo-web', title: lang === 'en' ? 'Hosting for email & web' : 'Hosting correo y web', desc: lang === 'en' ? 'Optimized hosting with cPanel for WordPress, PHP and MySQL.' : 'Alojamiento optimizado con cPanel para WordPress, PHP y MySQL.', Icon: MailIcon, border: 'var(--color-hds-naranja)' },
{ slug: 'mantenimiento-wordpress', title: lang === 'en' ? 'WordPress maintenance' : 'Mantenimiento WordPress', desc: lang === 'en' ? 'Security patches and updates by official WordPress ecosystem experts.' : 'Parches de seguridad y actualizaciones por expertos del ecosistema WP.', Icon: WordpressIcon, border: 'var(--color-hds-naranja)' },
],
},
{
title: t('services.cat.design'),
items: [
{ slug: 'desarrollo-webs-institucionales', title: lang === 'en' ? 'Institutional websites' : 'Desarrollo webs institucionales', desc: lang === 'en' ? 'Corporate sites tailored to your business and identity.' : 'Sitios corporativos a medida de tu negocio e identidad.', Icon: CodeIcon, border: 'var(--color-hds-coral)' },
{ slug: 'e-commerce', title: lang === 'en' ? 'E-commerce websites' : 'Sitios web con e-commerce', desc: lang === 'en' ? 'WooCommerce stores with secure payments and inventory.' : 'Tiendas WooCommerce con pagos seguros y gestión de stock.', Icon: ShopIcon, border: 'var(--color-hds-coral)' },
{ slug: 'gestion-contenido-traducciones', title: lang === 'en' ? 'Content & translations' : 'Gestión de contenido y traducciones', desc: lang === 'en' ? 'Recurring editorial: copy, updates, blog and translations.' : 'Servicio editorial recurrente: redacción, blog, traducciones.', Icon: TranslateIcon, border: 'var(--color-hds-coral)' },
],
},
{
title: t('services.cat.infra'),
items: [
{ slug: 'servidores-linux-virtualizacion', title: lang === 'en' ? 'Linux servers & virtualization' : 'Servidores Linux y virtualización', desc: lang === 'en' ? 'Linux servers, KVM virtualization, private clouds.' : 'Servidores Linux, virtualización KVM, nubes privadas.', Icon: ServerIcon, border: 'var(--color-hds-durazno)' },
],
},
];
---
<BaseLayout
title={lang === 'en' ? 'Services' : 'Servicios'}
description={lang === 'en'
? 'Hosting, web development, e-commerce, content management and infrastructure services.'
: 'Servicios de hosting, desarrollo web, e-commerce, gestión de contenido e infraestructura.'}
lang={lang}
>
<section class="pt-20 pb-12 md:pt-28 md:pb-16" style="background: var(--hds-bg-soft);">
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
<SectionEyebrow text={lang === 'en' ? 'What we do' : 'Lo que hacemos'} />
<h1 class="font-display leading-tight mt-5" style="font-size: clamp(2.5rem, 6vw, 4.5rem); color: var(--hds-fg);">
{lang === 'en' ? 'Our' : 'Nuestros'} <span style="color: var(--color-hds-naranja); font-style: italic;">{lang === 'en' ? 'services' : 'servicios'}</span>.
</h1>
<p class="text-lg mt-5 max-w-2xl" style="color: var(--hds-fg-soft);">
{lang === 'en'
? 'A complete stack of services to support your business at every step, from basic hosting to complex infrastructure.'
: 'Un stack completo de servicios para acompañar a tu empresa en cada paso, desde el hosting básico hasta la infraestructura compleja.'}
</p>
</div>
</section>
<section class="py-20 md:py-24" style="background: var(--hds-bg);">
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 space-y-14">
{groups.map((group) => (
<div>
<div class="flex flex-wrap items-baseline gap-3 mb-6">
<h2 class="text-2xl md:text-3xl font-display" style="color: var(--hds-fg);">{group.title}</h2>
<span class="text-xs font-semibold tracking-[0.25em] uppercase" style="color: var(--color-hds-naranja);">
{group.items.length} {group.items.length === 1 ? (lang === 'en' ? 'service' : 'servicio') : (lang === 'en' ? 'services' : 'servicios')}
</span>
</div>
<div class="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-5">
{group.items.map((item) => (
<ServiceCard
href={`${base}/servicios/${item.slug}/`}
title={item.title}
description={item.desc}
Icon={item.Icon}
borderColor={item.border}
/>
))}
</div>
</div>
))}
</div>
</section>
<CtaFinal t={t} whatsappUrl={whatsappUrl} />
</BaseLayout>
+233
View File
@@ -0,0 +1,233 @@
@import "tailwindcss";
@font-face {
font-family: 'Arista Pro Alternate';
src: url('/fonts/Arista-Pro-Alternate-Regular.woff2') format('woff2'),
url('/fonts/Arista-Pro-Alternate-Regular.woff') format('woff');
font-weight: 400;
font-style: normal;
font-display: swap;
}
@import "@fontsource/mulish/400.css";
@import "@fontsource/mulish/500.css";
@import "@fontsource/mulish/600.css";
@import "@fontsource/mulish/700.css";
@import "@fontsource/cormorant-garamond/400.css";
@import "@fontsource/cormorant-garamond/500.css";
@custom-variant dark (&:where(.dark, .dark *));
@theme {
--color-hds-naranja: #EE7623;
--color-hds-naranja-hover: #D8651A;
--color-hds-coral: #FA9F5C;
--color-hds-durazno: #FFCBA1;
--color-hds-tinta: #1A1612;
--font-display: 'Arista Pro Alternate', 'Mulish', system-ui, sans-serif;
--font-sans: 'Mulish', system-ui, -apple-system, BlinkMacSystemFont, sans-serif;
--font-editorial: 'Cormorant Garamond', Georgia, serif;
--tracking-display: -0.02em;
--tracking-eyebrow: 0.25em;
}
@layer base {
:root {
color-scheme: light;
--hds-bg: #FAF6EE;
--hds-bg-soft: #F5EFE3;
--hds-bg-section: #FFFFFF;
--hds-fg: #1A1612;
--hds-fg-soft: #4A4540;
--hds-fg-muted: #8A8580;
--hds-line: #E8E2D5;
--hds-card: #FFFFFF;
--hds-card-soft: #FFFFFF;
}
:root.dark {
color-scheme: dark;
--hds-bg: #1A1612;
--hds-bg-soft: #221E1A;
--hds-bg-section: #2A2520;
--hds-fg: #FAF6EE;
--hds-fg-soft: #C8C2B8;
--hds-fg-muted: #8A8580;
--hds-line: #3A332C;
--hds-card: #2A2520;
--hds-card-soft: #221E1A;
}
html {
scroll-behavior: smooth;
-webkit-text-size-adjust: 100%;
}
body {
font-family: var(--font-sans);
color: var(--hds-fg);
background-color: var(--hds-bg);
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
transition: background-color 0.2s ease, color 0.2s ease;
}
h1, h2, h3, h4 {
font-family: var(--font-display);
font-weight: 400;
letter-spacing: var(--tracking-display);
}
a {
color: inherit;
text-decoration: none;
}
}
@layer components {
.font-display { font-family: var(--font-display); }
.font-editorial { font-family: var(--font-editorial); }
.eyebrow {
display: inline-flex;
align-items: center;
gap: 0.75rem;
font-size: 0.7rem;
font-weight: 600;
letter-spacing: var(--tracking-eyebrow);
text-transform: uppercase;
color: var(--color-hds-naranja);
}
.eyebrow::after {
content: '';
display: inline-block;
width: 3rem;
height: 1px;
background: var(--color-hds-naranja);
}
.btn-primary {
background: var(--color-hds-naranja);
color: #FFFFFF;
padding: 0.875rem 1.5rem;
border-radius: 6px;
font-weight: 600;
display: inline-flex;
align-items: center;
gap: 0.5rem;
font-size: 0.95rem;
transition: background 0.2s ease, transform 0.2s ease;
border: 2px solid var(--color-hds-naranja);
cursor: pointer;
}
.btn-primary:hover {
background: var(--color-hds-naranja-hover);
border-color: var(--color-hds-naranja-hover);
}
.btn-secondary {
border: 2px solid var(--hds-fg);
color: var(--hds-fg);
padding: 0.78rem 1.4rem;
border-radius: 6px;
font-weight: 600;
display: inline-flex;
align-items: center;
gap: 0.5rem;
font-size: 0.95rem;
transition: all 0.2s ease;
background: transparent;
cursor: pointer;
}
.btn-secondary:hover {
background: var(--hds-fg);
color: var(--hds-bg);
}
.btn-ghost {
color: var(--color-hds-naranja);
font-weight: 600;
font-size: 0.95rem;
display: inline-flex;
align-items: center;
gap: 0.4rem;
transition: gap 0.2s ease;
background: transparent;
border: none;
cursor: pointer;
}
.btn-ghost:hover {
gap: 0.7rem;
}
.icon-circle {
width: 56px;
height: 56px;
border-radius: 50%;
border: 1.5px solid var(--color-hds-naranja);
display: flex;
align-items: center;
justify-content: center;
color: var(--color-hds-naranja);
flex-shrink: 0;
}
.service-card {
background: var(--hds-card);
border: 1px solid var(--hds-line);
border-radius: 12px;
padding: 2rem;
transition: all 0.25s ease;
}
.service-card:hover {
border-color: var(--color-hds-naranja);
transform: translateY(-2px);
box-shadow: 0 12px 32px rgba(238,118,35,0.08);
}
.particle-grid {
background-image:
linear-gradient(to right, rgba(238,118,35,0.10) 1px, transparent 1px),
linear-gradient(to bottom, rgba(238,118,35,0.10) 1px, transparent 1px);
background-size: 56px 56px;
}
:root.dark .particle-grid {
background-image:
linear-gradient(to right, rgba(238,118,35,0.18) 1px, transparent 1px),
linear-gradient(to bottom, rgba(238,118,35,0.18) 1px, transparent 1px);
}
.skip-link {
position: absolute;
top: -100px;
left: 1rem;
z-index: 9999;
padding: 0.75rem 1rem;
background: var(--color-hds-naranja);
color: white;
border-radius: 6px;
text-decoration: none;
font-weight: 600;
transition: top 0.2s ease;
}
.skip-link:focus { top: 1rem; }
}
:focus-visible {
outline: 2px solid var(--color-hds-naranja);
outline-offset: 3px;
border-radius: 2px;
}
@media (prefers-reduced-motion: reduce) {
*, *::before, *::after {
animation-duration: 0.01ms !important;
animation-iteration-count: 1 !important;
transition-duration: 0.01ms !important;
scroll-behavior: auto !important;
}
}
+11
View File
@@ -0,0 +1,11 @@
{
"extends": "astro/tsconfigs/strict",
"include": [".astro/types.d.ts", "**/*"],
"exclude": ["dist"],
"compilerOptions": {
"baseUrl": ".",
"paths": {
"@/*": ["src/*"]
}
}
}