Update for production backup

This commit is contained in:
2026-07-15 19:11:03 -06:00
parent 42b5f533c3
commit b228607fc0
62 changed files with 5614 additions and 6290 deletions
+16 -2
View File
@@ -1,8 +1,22 @@
-FRAMER MOTION :
npm install framer-motion
-npm run dev
# React + Vite # React + Vite
This template provides a minimal setup to get React working in Vite with HMR and some ESLint rules. This template provides a minimal setup to get React working in Vite with HMR and some ESLint rules.
Currently, two official plugins are available: Currently, two official plugins are available:
- [@vitejs/plugin-react](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react/README.md) uses [Babel](https://babeljs.io/) for Fast Refresh - [@vitejs/plugin-react](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react) uses [Babel](https://babeljs.io/) (or [oxc](https://oxc.rs) when used in [rolldown-vite](https://vite.dev/guide/rolldown)) for Fast Refresh
- [@vitejs/plugin-react-swc](https://github.com/vitejs/vite-plugin-react-swc) uses [SWC](https://swc.rs/) for Fast Refresh - [@vitejs/plugin-react-swc](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react-swc) uses [SWC](https://swc.rs/) for Fast Refresh
## React Compiler
The React Compiler is not enabled on this template because of its impact on dev & build performances. To add it, see [this documentation](https://react.dev/learn/react-compiler/installation).
## Expanding the ESLint configuration
If you are developing a production application, we recommend using TypeScript with type-aware lint rules enabled. Check out the [TS template](https://github.com/vitejs/vite/tree/main/packages/create-vite/template-react-ts) for information on how to integrate TypeScript and [`typescript-eslint`](https://typescript-eslint.io) in your project.

Before

Width:  |  Height:  |  Size: 52 KiB

After

Width:  |  Height:  |  Size: 52 KiB

Before

Width:  |  Height:  |  Size: 17 KiB

After

Width:  |  Height:  |  Size: 17 KiB

Before

Width:  |  Height:  |  Size: 31 KiB

After

Width:  |  Height:  |  Size: 31 KiB

Before

Width:  |  Height:  |  Size: 8.3 KiB

After

Width:  |  Height:  |  Size: 8.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

Before

Width:  |  Height:  |  Size: 130 KiB

After

Width:  |  Height:  |  Size: 130 KiB

Before

Width:  |  Height:  |  Size: 140 KiB

After

Width:  |  Height:  |  Size: 140 KiB

Before

Width:  |  Height:  |  Size: 143 KiB

After

Width:  |  Height:  |  Size: 143 KiB

Before

Width:  |  Height:  |  Size: 155 KiB

After

Width:  |  Height:  |  Size: 155 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

+10 -19
View File
@@ -1,13 +1,18 @@
import js from '@eslint/js' import js from '@eslint/js'
import globals from 'globals' import globals from 'globals'
import react from 'eslint-plugin-react'
import reactHooks from 'eslint-plugin-react-hooks' import reactHooks from 'eslint-plugin-react-hooks'
import reactRefresh from 'eslint-plugin-react-refresh' import reactRefresh from 'eslint-plugin-react-refresh'
import { defineConfig, globalIgnores } from 'eslint/config'
export default [ export default defineConfig([
globalIgnores(['dist']),
{ {
files: ['**/*.{js,jsx}'], files: ['**/*.{js,jsx}'],
ignores: ['dist'], extends: [
js.configs.recommended,
reactHooks.configs.flat.recommended,
reactRefresh.configs.vite,
],
languageOptions: { languageOptions: {
ecmaVersion: 2020, ecmaVersion: 2020,
globals: globals.browser, globals: globals.browser,
@@ -17,22 +22,8 @@ export default [
sourceType: 'module', sourceType: 'module',
}, },
}, },
settings: { react: { version: '18.3' } },
plugins: {
react,
'react-hooks': reactHooks,
'react-refresh': reactRefresh,
},
rules: { rules: {
...js.configs.recommended.rules, 'no-unused-vars': ['error', { varsIgnorePattern: '^[A-Z_]|motion' }],
...react.configs.recommended.rules,
...react.configs['jsx-runtime'].rules,
...reactHooks.configs.recommended.rules,
'react/jsx-no-target-blank': 'off',
'react-refresh/only-export-components': [
'warn',
{ allowConstantExport: true },
],
}, },
}, },
] ])
+31 -4
View File
@@ -1,12 +1,39 @@
<!doctype html> <!doctype html>
<html lang="en"> <html lang="es">
<head> <head>
<meta charset="UTF-8" /> <meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Vite + React</title> <meta name="theme-color" content="#020617" />
<!-- SEO Básico -->
<meta name="description" content="TESS - Consultoría de Software y Servicios de TI. Creamos aplicaciones web, móviles y soluciones robustas alineadas a los objetivos de tu negocio." />
<meta name="keywords" content="desarrollo de software, consultoria ti, aplicaciones web, outsourcing, mexico, tess, tecnologia" />
<title>TESS | Consultoría en Desarrollo de Software</title>
<!-- Open Graph (Facebook, LinkedIn, WhatsApp) -->
<meta property="og:type" content="website" />
<meta property="og:title" content="TESS | Consultoría en Desarrollo de Software" />
<meta property="og:description" content="Impulsamos el crecimiento de tu empresa mediante soluciones tecnológicas a medida." />
<meta property="og:image" content="https://tesscorp.com.mx/assets/TESS.png" />
<meta property="og:url" content="https://tesscorp.com.mx/" />
<meta property="og:site_name" content="TESS Corporation" />
<!-- Twitter Card -->
<meta name="twitter:card" content="summary_large_image" />
<meta name="twitter:title" content="TESS | Consultoría de Software" />
<meta name="twitter:description" content="Soluciones tecnológicas a medida para transformar tu negocio." />
<!-- Preloads de Recursos Críticos -->
<link rel="preload" as="image" href="/assets/TESS.png" />
<link rel="icon" type="image/jpeg" href="/assets/normal-logo-tess.jpeg" />
<!-- Fuentes (Google Fonts y Material Symbols) -->
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined:wght,FILL@100..700,0..1&display=swap" rel="stylesheet" />
<link href="https://fonts.googleapis.com/css2?family=Raleway:wght@300;400;700&display=swap" rel="stylesheet">
</head> </head>
<body> <body class="bg-brand-dark text-white font-raleway antialiased">
<div id="root"></div> <div id="root"></div>
<script type="module" src="/src/main.jsx"></script> <script type="module" src="/src/main.jsx"></script>
</body> </body>
+1541 -3711
View File
File diff suppressed because it is too large Load Diff
+18 -18
View File
@@ -1,5 +1,5 @@
{ {
"name": "tess-web", "name": "mi-portafolio-tess",
"private": true, "private": true,
"version": "0.0.0", "version": "0.0.0",
"type": "module", "type": "module",
@@ -10,24 +10,24 @@
"preview": "vite preview" "preview": "vite preview"
}, },
"dependencies": { "dependencies": {
"@headlessui/react": "^2.2.0", "framer-motion": "^12.26.2",
"@heroicons/react": "^2.1.5", "react": "^19.2.0",
"react": "^18.3.1", "react-dom": "^19.2.0",
"react-dom": "^18.3.1" "react-fast-marquee": "^1.6.5"
}, },
"devDependencies": { "devDependencies": {
"@eslint/js": "^9.8.0", "@eslint/js": "^9.39.1",
"@types/react": "^18.3.3", "@tailwindcss/postcss": "^4.1.18",
"@types/react-dom": "^18.3.0", "@types/react": "^19.2.5",
"@vitejs/plugin-react": "^4.3.1", "@types/react-dom": "^19.2.3",
"autoprefixer": "^10.4.20", "@vitejs/plugin-react": "^5.1.1",
"eslint": "^9.8.0", "autoprefixer": "^10.4.23",
"eslint-plugin-react": "^7.35.0", "eslint": "^9.39.1",
"eslint-plugin-react-hooks": "^5.1.0-rc.0", "eslint-plugin-react-hooks": "^7.0.1",
"eslint-plugin-react-refresh": "^0.4.9", "eslint-plugin-react-refresh": "^0.4.24",
"globals": "^15.9.0", "globals": "^16.5.0",
"postcss": "^8.4.49", "postcss": "^8.5.6",
"tailwindcss": "^3.4.15", "tailwindcss": "^4.1.18",
"vite": "^5.4.0" "vite": "^7.2.4"
} }
} }
+1 -1
View File
@@ -1,6 +1,6 @@
export default { export default {
plugins: { plugins: {
tailwindcss: {}, '@tailwindcss/postcss': {},
autoprefixer: {}, autoprefixer: {},
}, },
} }
Binary file not shown.

Before

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

+38 -16
View File
@@ -1,22 +1,44 @@
@tailwind base; #root {
@tailwind components; max-width: 1280px;
@tailwind utilities; margin: 0 auto;
padding: 2rem;
text-align: center;
}
html {
scroll-behavior: smooth;
}
.logo {
height: 6em;
padding: 1.5em;
will-change: filter;
transition: filter 300ms;
}
.logo:hover {
filter: drop-shadow(0 0 2em #646cffaa);
}
.logo.react:hover {
filter: drop-shadow(0 0 2em #61dafbaa);
}
.custom-background { @keyframes logo-spin {
min-height: 100vh; /* Equivale a min-h-screen en Tailwind */ from {
background-size: cover; /* bg-cover */ transform: rotate(0deg);
background-position: center; /* bg-center */ }
background-image: url('../public/colage-tess.jpeg'); /* Imagen de fondo */ to {
transform: rotate(360deg);
}
}
@media (prefers-reduced-motion: no-preference) {
a:nth-of-type(2) .logo {
animation: logo-spin infinite 20s linear;
} }
}
.card {
padding: 2em;
}
.styleCard { .read-the-docs {
z-index: 10; color: #888;
background: rgba(255, 255, 255, 0.3); /* Fondo blanco con transparencia */
backdrop-filter: blur(10px); /* Efecto de desenfoque */
-webkit-backdrop-filter: blur(10px); /* Soporte para Safari */
border-radius: 2rem; /* Bordes redondeados */
border: 1px solid rgba(255, 255, 255, 0.2); /* Borde translúcido */
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.25); /* Sombra para profundidad */
} }
+31 -151
View File
@@ -1,157 +1,37 @@
import { useState } from 'react' import Navbar from "./components/Navbar";
import { Dialog, DialogPanel } from '@headlessui/react' import Hero from "./components/Hero";
import { Bars3Icon, XMarkIcon } from '@heroicons/react/24/outline' import About from "./components/About";
import './App.css' import Work from "./components/Work";
import Services from "./components/Services";
const navigation = [ import Solutions from "./components/Solutions";
{ name: 'Product', href: '1' }, import Clients from "./components/Clients";
{ name: 'Features', href: '2' }, import Contact from "./components/Contact";
{ name: 'Marketplace', href: '3' }, import Footer from "./components/Footer";
{ name: 'Company', href: '4' }, import React, { useState } from "react";
] import { AnimatePresence } from "framer-motion";
function App() { function App() {
const [isContactOpen, setIsContactOpen] = useState(false);
const toggleContact = () => setIsContactOpen(!isContactOpen);
const [mobileMenuOpen, setMobileMenuOpen] = useState(false)
return ( return (
<> <div className="min-h-screen bg-black text-white">
<div className="custom-background backdrop-blur-sm h-screen w-screen overflow-auto"> <Navbar onContactClick={toggleContact} />
<header className="absolute inset-x-0 top-0 z-50"> <AnimatePresence>
<nav aria-label="Global" className="flex items-center justify-between p-6 lg:px-8"> {isContactOpen && <Contact onClose={toggleContact} />}
<div className="flex lg:flex-1"> </AnimatePresence>
<a href="1" className="-m-1.5 p-1.5"> <main>
<span className="sr-only">Your Company</span> <Hero />
<img <About />
alt="" <Work onOpenContact={toggleContact} />
src="../public/logotess.png" <Services />
className="h-8 w-auto" <Solutions />
/> <Clients />
</a> </main>
<span className="ml-4 text-3xl leading-8 font-semibold text-blue hover:text-blue/50 transition"> {isContactOpen && <Contact onClose={toggleContact} />}
TESS <Footer />
</span>
</div> </div>
<div className="flex lg:hidden"> );
<button
type="button"
onClick={() => setMobileMenuOpen(true)}
className="-m-2.5 inline-flex items-center justify-center rounded-md p-2.5 text-gray-700"
>
<span className="sr-only">Open main menu</span>
<Bars3Icon aria-hidden="true" className="size-6" />
</button>
</div>
<div className="hidden lg:flex lg:gap-x-12">
{navigation.map((item) => (
<a key={item.name} href={item.href} className="text-sm/6 font-semibold text-gray-900">
{item.name}
</a>
))}
</div>
<div className="hidden lg:flex lg:flex-1 lg:justify-end">
<a href="#" className="text-sm/6 font-semibold text-gray-900">
Log in <span aria-hidden="true">&rarr;</span>
</a>
</div>
</nav>
<Dialog open={mobileMenuOpen} onClose={setMobileMenuOpen} className="lg:hidden">
<div className="fixed inset-0 z-50" />
<DialogPanel className="fixed inset-y-0 right-0 z-50 w-full overflow-y-auto bg-white px-6 py-6 sm:max-w-sm sm:ring-1 sm:ring-gray-900/10">
<div className="flex items-center justify-between">
<a href="2" className="-m-1.5 p-1.5">
<span className="sr-only">Your Company</span>
<img
alt=""
src="../public/logotess.png"
className="h-8 w-auto"
/>
</a>
<button
type="button"
onClick={() => setMobileMenuOpen(false)}
className="-m-2.5 rounded-md p-2.5 text-gray-700"
>
<span className="sr-only">Close menu</span>
<XMarkIcon aria-hidden="true" className="size-6" />
</button>
</div>
<div className="mt-6 flow-root">
<div className="-my-6 divide-y divide-gray-500/10">
<div className="space-y-2 py-6">
{navigation.map((item) => (
<a
key={item.name}
href={item.href}
className="-mx-3 block rounded-lg px-3 py-2 text-base/7 font-semibold text-gray-900 hover:bg-gray-50"
>
{item.name}
</a>
))}
</div>
<div className="py-6">
<a
href="3"
className="-mx-3 block rounded-lg px-3 py-2.5 text-base/7 font-semibold text-gray-900 hover:bg-gray-50"
>
Log in
</a>
</div>
</div>
</div>
</DialogPanel>
</Dialog>
</header>
<div className="relative isolate px-6 pt-14 lg:px-8">
<div
aria-hidden="true"
className="absolute inset-x-0 -top-40 -z-10 transform-gpu overflow-hidden blur-3xl sm:-top-80"
>
</div>
<div className="margin- mx-auto max-w-2xl py-32 sm:py-48 lg:py-56 z-10 bg-white/50 backdrop-blur-lg rounded-2xl border border-white/20 shadow-2xl p-6">
<div className="hidden sm:mb-8 sm:flex sm:justify-center">
<div className="relative rounded-full px-3 py-1 text-sm/6 text-gray-600 ring-1 ring-gray-900/10 hover:ring-gray-900/20">
Announcing our next round of funding.{' '}
<a href="1" className="font-semibold text-blue-600">
<span aria-hidden="true" className="absolute inset-0" />
Read more <span aria-hidden="true">&rarr;</span>
</a>
</div>
</div>
<div className="text-center">
<h1 className="text-center text-5xl font-semibold tracking-tight sm:text-7xl text-blue hover:text-blue/50 transition duration-300">
Technology Enterprise Support System
</h1>
<div>
<p className="mt-8 text-pretty text-lg font-medium text-gray-500 sm:text-xl/8 justify-center">
Potenciamos su empresa con soluciones tecnológicas a medida. Ofrecemos consultoría especializada en optimización de procesos, implementación de TI y desarrollo de software para impulsar la eficiencia y el crecimiento de su negocio.
</p>
</div>
<div className="mt-10 flex items-center justify-center gap-x-6">
<a
href="2"
className="rounded-md bg-blue px-3.5 py-2.5 text-sm font-semibold text-white shadow-sm hover:bg-blue/75 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-indigo"
>
Get started
</a>
<a href="3" className="rounded-full bg-white/5 outline px-3.5 py-2.5 text-sm font-semibold text-black shadow-sm hover:bg-white/25 transition duration-150 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-indigo">
Learn more <span aria-hidden="true"></span>
</a>
</div>
</div>
</div>
<div
aria-hidden="true"
className="absolute inset-x-0 top-[calc(100%-13rem)] -z-10 transform-gpu overflow-hidden blur-3xl sm:top-[calc(100%-30rem)]"
>
</div>
</div>
</div>
</>
)
} }
export default App export default App;
Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 521 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 48 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.6 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.8 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 31 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

After

Width:  |  Height:  |  Size: 32 KiB

+1
View File
@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="iconify iconify--logos" width="35.93" height="32" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 228"><path fill="#00D8FF" d="M210.483 73.824a171.49 171.49 0 0 0-8.24-2.597c.465-1.9.893-3.777 1.273-5.621c6.238-30.281 2.16-54.676-11.769-62.708c-13.355-7.7-35.196.329-57.254 19.526a171.23 171.23 0 0 0-6.375 5.848a155.866 155.866 0 0 0-4.241-3.917C100.759 3.829 77.587-4.822 63.673 3.233C50.33 10.957 46.379 33.89 51.995 62.588a170.974 170.974 0 0 0 1.892 8.48c-3.28.932-6.445 1.924-9.474 2.98C17.309 83.498 0 98.307 0 113.668c0 15.865 18.582 31.778 46.812 41.427a145.52 145.52 0 0 0 6.921 2.165a167.467 167.467 0 0 0-2.01 9.138c-5.354 28.2-1.173 50.591 12.134 58.266c13.744 7.926 36.812-.22 59.273-19.855a145.567 145.567 0 0 0 5.342-4.923a168.064 168.064 0 0 0 6.92 6.314c21.758 18.722 43.246 26.282 56.54 18.586c13.731-7.949 18.194-32.003 12.4-61.268a145.016 145.016 0 0 0-1.535-6.842c1.62-.48 3.21-.974 4.76-1.488c29.348-9.723 48.443-25.443 48.443-41.52c0-15.417-17.868-30.326-45.517-39.844Zm-6.365 70.984c-1.4.463-2.836.91-4.3 1.345c-3.24-10.257-7.612-21.163-12.963-32.432c5.106-11 9.31-21.767 12.459-31.957c2.619.758 5.16 1.557 7.61 2.4c23.69 8.156 38.14 20.213 38.14 29.504c0 9.896-15.606 22.743-40.946 31.14Zm-10.514 20.834c2.562 12.94 2.927 24.64 1.23 33.787c-1.524 8.219-4.59 13.698-8.382 15.893c-8.067 4.67-25.32-1.4-43.927-17.412a156.726 156.726 0 0 1-6.437-5.87c7.214-7.889 14.423-17.06 21.459-27.246c12.376-1.098 24.068-2.894 34.671-5.345a134.17 134.17 0 0 1 1.386 6.193ZM87.276 214.515c-7.882 2.783-14.16 2.863-17.955.675c-8.075-4.657-11.432-22.636-6.853-46.752a156.923 156.923 0 0 1 1.869-8.499c10.486 2.32 22.093 3.988 34.498 4.994c7.084 9.967 14.501 19.128 21.976 27.15a134.668 134.668 0 0 1-4.877 4.492c-9.933 8.682-19.886 14.842-28.658 17.94ZM50.35 144.747c-12.483-4.267-22.792-9.812-29.858-15.863c-6.35-5.437-9.555-10.836-9.555-15.216c0-9.322 13.897-21.212 37.076-29.293c2.813-.98 5.757-1.905 8.812-2.773c3.204 10.42 7.406 21.315 12.477 32.332c-5.137 11.18-9.399 22.249-12.634 32.792a134.718 134.718 0 0 1-6.318-1.979Zm12.378-84.26c-4.811-24.587-1.616-43.134 6.425-47.789c8.564-4.958 27.502 2.111 47.463 19.835a144.318 144.318 0 0 1 3.841 3.545c-7.438 7.987-14.787 17.08-21.808 26.988c-12.04 1.116-23.565 2.908-34.161 5.309a160.342 160.342 0 0 1-1.76-7.887Zm110.427 27.268a347.8 347.8 0 0 0-7.785-12.803c8.168 1.033 15.994 2.404 23.343 4.08c-2.206 7.072-4.956 14.465-8.193 22.045a381.151 381.151 0 0 0-7.365-13.322Zm-45.032-43.861c5.044 5.465 10.096 11.566 15.065 18.186a322.04 322.04 0 0 0-30.257-.006c4.974-6.559 10.069-12.652 15.192-18.18ZM82.802 87.83a323.167 323.167 0 0 0-7.227 13.238c-3.184-7.553-5.909-14.98-8.134-22.152c7.304-1.634 15.093-2.97 23.209-3.984a321.524 321.524 0 0 0-7.848 12.897Zm8.081 65.352c-8.385-.936-16.291-2.203-23.593-3.793c2.26-7.3 5.045-14.885 8.298-22.6a321.187 321.187 0 0 0 7.257 13.246c2.594 4.48 5.28 8.868 8.038 13.147Zm37.542 31.03c-5.184-5.592-10.354-11.779-15.403-18.433c4.902.192 9.899.29 14.978.29c5.218 0 10.376-.117 15.453-.343c-4.985 6.774-10.018 12.97-15.028 18.486Zm52.198-57.817c3.422 7.8 6.306 15.345 8.596 22.52c-7.422 1.694-15.436 3.058-23.88 4.071a382.417 382.417 0 0 0 7.859-13.026a347.403 347.403 0 0 0 7.425-13.565Zm-16.898 8.101a358.557 358.557 0 0 1-12.281 19.815a329.4 329.4 0 0 1-23.444.823c-7.967 0-15.716-.248-23.178-.732a310.202 310.202 0 0 1-12.513-19.846h.001a307.41 307.41 0 0 1-10.923-20.627a310.278 310.278 0 0 1 10.89-20.637l-.001.001a307.318 307.318 0 0 1 12.413-19.761c7.613-.576 15.42-.876 23.31-.876H128c7.926 0 15.743.303 23.354.883a329.357 329.357 0 0 1 12.335 19.695a358.489 358.489 0 0 1 11.036 20.54a329.472 329.472 0 0 1-11 20.722Zm22.56-122.124c8.572 4.944 11.906 24.881 6.52 51.026c-.344 1.668-.73 3.367-1.15 5.09c-10.622-2.452-22.155-4.275-34.23-5.408c-7.034-10.017-14.323-19.124-21.64-27.008a160.789 160.789 0 0 1 5.888-5.4c18.9-16.447 36.564-22.941 44.612-18.3ZM128 90.808c12.625 0 22.86 10.235 22.86 22.86s-10.235 22.86-22.86 22.86s-22.86-10.235-22.86-22.86s10.235-22.86 22.86-22.86Z"></path></svg>

Before

Width:  |  Height:  |  Size: 0 B

After

Width:  |  Height:  |  Size: 4.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 130 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 140 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 143 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 155 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

+95
View File
@@ -0,0 +1,95 @@
import React from "react";
import collageTess from "../assets/colage-tess.jpeg";
const About = () => {
return (
<section
className="py-20 md:py-24 bg-gradient-to-b from-[#003172] to-[#001430]"
id="quienes-somos"
>
<div className="max-w-7xl mx-auto px-6 lg:px-8">
{/* Encabezado */}
<div className="text-center mb-10 md:mb-12">
<h2 className="text-white font-bold text-sm tracking-[0.3em] uppercase mb-3">
SOBRE NOSOTROS
</h2>
<h3 className="text-secondaccent text-3xl sm:text-4xl md:text-5xl font-extrabold tracking-tight">
Expertos en evolución digital
</h3>
</div>
{/* Imagen + Texto */}
<div className="grid lg:grid-cols-2 gap-8 lg:gap-12 items-center mb-12 md:mb-14">
<div className="relative drop-shadow-2xl max-w-sm md:max-w-md mx-auto lg:max-w-full">
<div className="absolute -inset-3 bg-primary/20 blur-3xl rounded-full"></div>
<img
alt="Tech Consultant workspace"
className="relative rounded-3xl shadow-2xl w-full border border-white/10 object-cover"
src={collageTess}
/>
</div>
<div className="space-y-5">
<p className="text-blue-50/90 leading-relaxed text-base sm:text-lg lg:text-xl font-light">
En TESS somos una consultora de software y servicios de TI que
ayuda a las empresas a diseñar, construir y evolucionar sus
soluciones digitales.
</p>
<p className="text-blue-50/90 leading-relaxed text-base sm:text-lg lg:text-xl font-light">
Combinamos experiencia en desarrollo de software, arquitectura de
sistemas y automatización de procesos para que la tecnología sea
el motor de tu negocio.
</p>
</div>
</div>
{/* Tarjetas */}
<div className="grid md:grid-cols-2 gap-6 lg:gap-8">
{/* Misión */}
<article className="glass-card p-6 lg:p-8 rounded-3xl border border-white/10 hover:border-secondary/30 transition-colors group text-center flex flex-col items-center">
<div className="w-12 h-12 bg-secondary/10 rounded-2xl flex items-center justify-center mb-4 group-hover:scale-110 transition-transform">
<span className="material-symbols-outlined text-accent text-4xl">
target
</span>
</div>
<h4 className="text-xl lg:text-2xl font-bold mb-3 text-accent">
Nuestra Misión
</h4>
<p className="text-blue-100/70 leading-relaxed font-light text-justify text-sm lg:text-base">
Impulsamos el crecimiento de empresas mediante soluciones
tecnológicas a medida que resuelven sus desafíos reales. Nos
especializamos en desarrollo de software personalizado y servicios
de TI adaptados a cada cliente.
</p>
</article>
{/* Visión */}
<article className="glass-card p-6 lg:p-8 rounded-3xl border border-white/10 hover:border-primary/30 transition-colors group text-center flex flex-col items-center">
<div className="w-12 h-12 bg-primary/10 rounded-2xl flex items-center justify-center mb-4 group-hover:scale-110 transition-transform">
<span className="material-symbols-outlined text-accent text-4xl">
lightbulb
</span>
</div>
<h4 className="text-xl lg:text-2xl font-bold mb-3 text-accent">
Nuestra Visión
</h4>
<p className="text-blue-100/70 leading-relaxed font-light text-justify text-sm lg:text-base">
Ser reconocidos como un referente en soluciones tecnológicas
personalizadas en Latinoamérica, destacando por innovación,
calidad humana y resultados tangibles para nuestros clientes.
</p>
</article>
</div>
</div>
</section>
);
};
export default About;
+262
View File
@@ -0,0 +1,262 @@
import React, { useState } from "react";
import Marquee from "react-fast-marquee";
import { motion, AnimatePresence } from "framer-motion";
import logo1 from "../assets/cl-1.png";
import logo2 from "../assets/cl-2.png";
import logo3 from "../assets/cl-3.jpeg";
import logo5 from "../assets/cl-5.png";
const successCases = [
{
id: 1,
name: "Hazard",
logo: logo1,
challenge:
"Necesidad de gestión delegada para infraestructura TI, hosting y correos empresariales.",
solution:
"Soporte TI integral y administración completa de servidores y correos TESS.",
result:
"Operación continua sin interrupciones técnicas y comunicación empresarial estable.",
},
{
id: 2,
name: "Vital Care",
logo: logo2,
challenge:
"Requerimiento de una aplicación médica especializada y soporte técnico concurrente para equipos.",
solution:
"Desarrollo de App a la medida para doctores + Soporte TI y Hosting TESS.",
result:
"Optimización de consultas médicas y resolución inmediata de incidencias en equipos de cómputo.",
},
{
id: 3,
name: "Clínicas de la Frontera",
logo: logo3,
challenge:
"Gestión ineficiente de infraestructura tecnológica y comunicación.",
solution: "Póliza de soporte TI y migración a Hosting y Correo TESS.",
result:
"Modernización tecnológica y alta disponibilidad en todos sus canales de comunicación.",
},
{
id: 5,
name: "TRIMAPE",
logo: logo5,
challenge:
"Control descentralizado en el mantenimiento de equipos industriales.",
solution:
"Desarrollo e implementación de TESS-ERP adaptado a sus procesos industriales.",
result:
"Trazabilidad total en mantenimientos y mejora sustancial en la logística operativa.",
},
];
const Clients = () => {
const logos = [
{ name: "Hazard", src: logo1 },
{ name: "Vital Care", src: logo2 },
{ name: "Clínicas de la Frontera", src: logo3 },
{ name: "TRIMAPE", src: logo5 },
];
const [activeCase, setActiveCase] = useState(successCases[0].id);
return (
<section
className="py-20 md:py-24 bg-brand-dark bg-gradient-to-b from-[#020617] to-[#000000] overflow-hidden"
id="clientes"
>
<div className="max-w-7xl mx-auto px-6 lg:px-8 text-center mb-10 md:mb-12">
<h2
className="text-secondary tracking-tight text-white mb-3 text-3xl font-bold md:text-4xl"
id="services-subtitle"
>
Nuestros Casos de Éxito
</h2>
<p className="max-w-2xl mx-auto text-brand-light text-base md:text-lg leading-relaxed font-light text-justify md:text-center mt-4">
Empresas de distintos sectores confían en TESS para resolver sus retos
tecnológicos y acelerar su crecimiento.
</p>
</div>
{/* Carrusel usando React Fast Marquee */}
<div className="max-w-7xl mx-auto px-6 lg:px-8 mb-24 relative">
{/* Usamos gradientColors usando formato rgb para overlayar en el fondo oscuro (#020617) */}
<Marquee
gradient={true}
gradientColor={[2, 6, 23]}
gradientWidth={100}
speed={40}
pauseOnHover={true}
autoFill={true}
className="flex items-center"
>
{logos.map((client, index) => (
<div
key={index}
className="flex-none mx-14"
>
<img
src={client.src}
alt={client.name}
className="h-11 md:h-12 w-auto object-contain"
/>
</div>
))}
</Marquee>
</div>
{/* Sección Interactiva de Casos de Éxito */}
<div className="max-w-7xl mx-auto px-6 lg:px-8 relative z-10">
<div className="grid grid-cols-1 lg:grid-cols-12 gap-8 lg:gap-12">
{/* Lista de Selección */}
<div className="col-span-1 lg:col-span-4 flex flex-col gap-3">
{successCases.map((story) => (
<button
key={story.id}
onClick={() => setActiveCase(story.id)}
className={`text-left p-5 rounded-xl transition-all duration-300 border ${
activeCase === story.id
? "bg-primary/20 border-secondaccent/50 shadow-[0_0_20px_rgba(12,192,223,0.15)]"
: "bg-brand-dark border-white/10 hover:bg-white/5 hover:border-white/20"
}`}
>
<div className="flex items-center gap-4">
<div
className={`w-12 h-12 rounded-lg flex items-center justify-center p-2 bg-white ${activeCase === story.id ? "opacity-100 shadow-[0_0_10px_rgba(100,255,218,0.5)]" : "opacity-70 grayscale"}`}
>
<img
src={story.logo}
alt={story.name}
className="max-h-full max-w-full object-contain"
/>
</div>
<div>
<h4
className={`font-semibold ${activeCase === story.id ? "text-accent" : "text-brand-light"}`}
>
{story.name}
</h4>
<p className="text-sm text-brand-light/60">
Ver caso completo
</p>
</div>
</div>
</button>
))}
</div>
{/* Panel de Detalles (Contenido Cambiante) */}
<div className="col-span-1 lg:col-span-8 bg-primary/20 border border-white/10 rounded-2xl p-6 md:p-10 relative overflow-hidden flex flex-col justify-center min-h-[400px]">
{/* Background glow para el caso activo */}
<div className="absolute top-0 right-0 w-[300px] h-[300px] bg-accent/10 blur-[100px] rounded-full"></div>
<AnimatePresence mode="wait">
{successCases.map(
(story) =>
story.id === activeCase && (
<motion.div
key={story.id}
initial={{ opacity: 0, y: 15 }}
animate={{ opacity: 1, y: 0 }}
exit={{ opacity: 0, y: -15 }}
transition={{ duration: 0.4 }}
className="relative z-10 h-full flex flex-col justify-center"
>
<div className="grid grid-cols-1 md:grid-cols-2 gap-8 md:gap-12">
{/* Columna Izquierda (Reto y Solución) */}
<div className="space-y-8">
<div>
<div className="flex items-center gap-3 mb-3">
<div className="w-8 h-8 rounded-full bg-red-400/20 text-red-400 flex items-center justify-center">
<svg
className="w-4 h-4"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
>
<path
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth="2"
d="M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z"
/>
</svg>
</div>
<h4 className="text-brand-light/70 font-medium uppercase tracking-wider text-sm">
El Reto
</h4>
</div>
<p className="text-brand-light text-lg leading-relaxed">
{story.challenge}
</p>
</div>
<div>
<div className="flex items-center gap-3 mb-3">
<div className="w-8 h-8 rounded-full bg-accent/20 text-accent flex items-center justify-center">
<svg
className="w-4 h-4"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
>
<path
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth="2"
d="M13 10V3L4 14h7v7l9-11h-7z"
/>
</svg>
</div>
<h4 className="text-brand-light/70 font-medium uppercase tracking-wider text-sm">
Nuestra Solución
</h4>
</div>
<p className="text-brand-light text-lg leading-relaxed">
{story.solution}
</p>
</div>
</div>
{/* Columna Derecha (Resultado) */}
<div className="bg-gradient-to-br from-primary/60 to-brand-dark/80 border border-primary/40 rounded-xl p-6 md:p-8 flex flex-col justify-center border-t-4 border-t-secondaccent">
<div className="flex items-center gap-3 mb-4">
<div className="w-8 h-8 rounded-full bg-secondaccent/20 text-secondaccent flex items-center justify-center">
<svg
className="w-4 h-4"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
>
<path
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth="2"
d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z"
/>
</svg>
</div>
<h4 className="text-secondaccent font-semibold uppercase tracking-wider text-sm">
Impacto / Resultado
</h4>
</div>
<p className="text-white text-xl md:text-2xl font-light leading-relaxed">
"{story.result}"
</p>
</div>
</div>
</motion.div>
),
)}
</AnimatePresence>
</div>
</div>
</div>
</section>
);
};
export default Clients;
+189
View File
@@ -0,0 +1,189 @@
import { useState } from "react";
import { motion } from "framer-motion";
{
/**modal de contacto */
}
const Contact = ({ onClose }) => {
const [formData, setFormData] = useState({
nombre: "",
email: "",
mensaje: "",
});
const [isSubmitting, setIsSubmitting] = useState(false);
const [status, setStatus] = useState(""); // 'success' | 'error' | ''
const handleChange = (e) => {
setFormData({ ...formData, [e.target.name]: e.target.value });
};
const handleSubmit = async (e) => {
e.preventDefault();
setIsSubmitting(true);
setStatus("");
try {
const response = await fetch("https://api.tesscorp.com.mx/api/contact", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify(formData),
});
if (response.ok) {
setStatus("success");
setFormData({ nombre: "", email: "", mensaje: "" });
} else {
setStatus("error");
}
} catch (error) {
console.error("Error enviando el formulario:", error);
setStatus("error");
} finally {
setIsSubmitting(false);
}
};
return (
<div className="fixed inset-0 z-[100] flex items-center justify-center p-4">
<motion.div
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
exit={{ opacity: 0 }}
onClick={onClose}
className="absolute inset-0 bg-black/10 backdrop-blur-sm"
/>
{/* El Contenedor del Formulario (Modal) */}
<motion.div
initial={{ opacity: 0, scale: 0.9, y: 20 }}
animate={{ opacity: 1, scale: 1, y: 0 }}
exit={{ opacity: 0, scale: 0.9, y: 20 }}
className="relative w-full max-w-2xl bg-white/5 backdrop-blur-2xl p-8 md:p-12 rounded-[2rem] border border-white/20 shadow-2xl z-10 overflow-y-auto max-h-[90vh]"
>
{/* Botón para cerrar (X) */}
<button
onClick={onClose}
className="absolute top-6 right-6 text-white/50 hover:text-[#0cc0df] transition-colors"
>
<span className="material-symbols-outlined text-3xl">close</span>
</button>
<div className="text-center mb-10">
<h2 className="text-white text-2xl md:text-3xl font-bold mb-2">
Ponte en contacto
</h2>
<p className="text-white/80 text-sm md:text-base font-light">
¿Tienes un proyecto en mente? Hagámoslo realidad juntos.
</p>
</div>
<form onSubmit={handleSubmit} className="space-y-6">
{/* Campo Nombre */}
<div>
<label
htmlFor="nombre"
className="block text-sm font-medium text-white mb-2"
>
Nombre Completo
</label>
<input
type="text"
id="nombre"
name="nombre"
required
value={formData.nombre}
onChange={handleChange}
className="w-full bg-white/10 backdrop-blur-md border border-white/20 rounded-xl px-4 py-3 text-white placeholder-white/50 focus:outline-none focus:ring-2 focus:ring-emerald-400/50 focus:border-emerald-400 transition-all duration-300"
placeholder="Tu nombre..."
/>
</div>
{/* Campo Email */}
<div>
<label
htmlFor="email"
className="flex items-center gap-2 text-sm font-medium text-white mb-2"
>
<span className="material-symbols-outlined text-base">mail</span>
Correo Electrónico
</label>
<input
type="email"
id="email"
name="email"
required
value={formData.email}
onChange={handleChange}
className="w-full bg-white/10 backdrop-blur-md border border-white/20 rounded-xl px-4 py-3 text-white placeholder-white/50 focus:outline-none focus:ring-2 focus:ring-emerald-400/50 focus:border-emerald-400 transition-all duration-300"
placeholder="tu@email.com"
/>
</div>
{/* Campo Mensaje */}
<div>
<label
htmlFor="mensaje"
className="flex items-center gap-2 text-sm font-medium text-white mb-2"
>
<span className="material-symbols-outlined text-base">chat</span>
Mensaje
</label>
<textarea
id="mensaje"
name="mensaje"
rows="4"
required
value={formData.mensaje}
onChange={handleChange}
className="w-full bg-white/10 backdrop-blur-md border border-white/20 rounded-xl px-4 py-3 text-white placeholder-white/50 focus:outline-none focus:ring-2 focus:ring-emerald-400/50 focus:border-emerald-400 transition-all duration-300 resize-none"
placeholder="¿En qué podemos ayudarte?"
></textarea>
</div>
{/* Mensajes de estado */}
<div aria-live="polite" className="contents">
{status === "success" && (
<div className="p-4 bg-green-500/20 border border-green-500/50 rounded-xl text-green-200 text-center">
¡Mensaje enviado con éxito! Nos pondremos en contacto contigo
pronto.
</div>
)}
{status === "error" && (
<div className="p-4 bg-red-500/20 border border-red-500/50 rounded-xl text-red-200 text-center">
Hubo un error al enviar el mensaje. Por favor, inténtalo de
nuevo más tarde o contáctanos por WhatsApp.
</div>
)}
</div>
<button
type="submit"
disabled={isSubmitting}
className={`w-full text-white font-bold py-4 rounded-xl transition-all transform hover:scale-[1.01] active:scale-[0.98] shadow-lg shadow-cyan-500/25 ${
isSubmitting
? "opacity-70 cursor-not-allowed bg-gradient-to-r from-emerald-400 to-cyan-500"
: "bg-gradient-to-r from-emerald-400 to-cyan-500 hover:from-emerald-500 hover:to-cyan-600"
}`}
>
{isSubmitting ? "Enviando..." : "Enviar Mensaje"}
</button>
{/* Opción de WhatsApp */}
<div className="flex flex-col sm:flex-row items-center justify-center gap-3 pt-6 border-t border-white/10">
<span className="text-white/80 text-sm">O comunícate de forma directa vía</span>
<a
href="https://wa.me/522292565108"
target="_blank"
rel="noopener noreferrer"
className="flex items-center gap-2 text-white bg-[#25D366] hover:bg-[#1da851] px-6 py-2.5 rounded-xl transition-all transform hover:scale-105 shadow-lg shadow-[#25D366]/30 font-bold text-sm"
>
<i className="fa-brands fa-whatsapp text-xl"></i>
WhatsApp
</a>
</div>
</form>
</motion.div>
</div>
);
};
export default Contact;
+137
View File
@@ -0,0 +1,137 @@
import logoTess from "../assets/logotesspng.png";
const Footer = () => {
const currentYear = new Date().getFullYear();
return (
<footer className="bg-black border-t border-white/5 pt-16 pb-8">
<div className="max-w-7xl mx-auto px-6 lg:px-8">
<div className="grid grid-cols-1 md:grid-cols-3 gap-12 mb-16">
{/* Identidad */}
<div className="space-y-6">
<div className="flex items-center">
<div className="w-48 sm:w-56">
<img
src={logoTess}
alt="TESS Logo"
className="w-full h-auto object-contain object-left"
/>
</div>
</div>
<p className="text-white text-sm leading-relaxed max-w-xs">
Impulsando la transformación digital con soluciones tecnológicas a
medida y estrategias de alto impacto.
</p>
</div>
{/* Navegación con Iconos */}
<div className="flex flex-col gap-6">
<h3 className="text-white font-bold text-lg uppercase tracking-widest text-sm">
Navegación
</h3>
<ul className="space-y-4">
{[
{ name: "Quienes somos", href: "#quienes-somos", icon: "info" },
{
name: "Nuestro Trabajo",
href: "#nuestro-trabajo",
icon: "terminal",
},
{ name: "Servicios", href: "#servicios", icon: "settings" },
{ name: "Clientes", href: "#clientes", icon: "group" },
].map((link) => (
<li key={link.name}>
<a
href={link.href}
className="group flex items-center gap-3 text-white hover:text-accent transition-colors text-sm"
>
<span className="material-symbols-outlined text-lg group-hover:scale-110 transition-transform">
{link.icon}
</span>
{link.name}
</a>
</li>
))}
</ul>
</div>
{/* Contacto & Social */}
<div className="flex flex-col gap-6">
<h3 className="text-white font-bold text-lg uppercase tracking-widest text-sm">
Hablemos
</h3>
<div className="flex flex-col gap-4">
<a
href="mailto:contacto@tesscorp.com.mx"
className="group flex items-center gap-2 text-white hover:text-[#0cc0df] transition-colors text-sm font-medium"
>
<span className="material-symbols-outlined text-lg">mail</span>
contacto@tesscorp.com.mx
</a>
<a
href="https://wa.me/522292565108"
target="_blank"
rel="noopener noreferrer"
className="group flex items-center gap-2 text-white hover:text-[#25D366] transition-colors text-sm font-medium"
>
<i className="fa-brands fa-whatsapp text-lg"></i>
229 256 5108
</a>
<div className="group flex items-start gap-2 text-white text-sm font-medium">
<span className="material-symbols-outlined text-lg mt-0.5">location_on</span>
<p className="leading-relaxed">
Calle Leona Vicario #1640 C.p. 91897<br />
Col. Formando Hogar. Veracruz, Ver
</p>
</div>
</div>
<div className="flex gap-6 pt-2">
<a
href="#"
className="text-white/80 hover:text-white transition-all transform hover:-translate-y-1"
>
<i className="fa-brands fa-linkedin-in text-xl"></i>
</a>
<a
href="#"
className="text-white/80 hover:text-white transition-all transform hover:-translate-y-1"
>
<i className="fa-brands fa-instagram text-xl"></i>
</a>
<a
href="#"
className="text-white/80 hover:text-white transition-all transform hover:-translate-y-1"
>
<i className="fa-brands fa-x-twitter text-xl"></i>
</a>
</div>
<div className="w-full mt-4 rounded-lg overflow-hidden border border-white/10">
<iframe
title="Ubicación de TESS"
src="https://maps.google.com/maps?q=Calle%20Leona%20Vicario%201640%2C%20Formando%20Hogar%2C%2091897%20Veracruz%2C%20Ver&t=&z=15&ie=UTF8&iwloc=&output=embed"
width="100%"
height="200"
style={{ border: 0 }}
allowFullScreen=""
loading="lazy"
referrerPolicy="no-referrer-when-downgrade"
></iframe>
</div>
</div>
</div>
{/* Copyright */}
<div className="border-t border-white/5 pt-8 text-center">
<p className="text-white/70 text-xs tracking-widest uppercase">
© {currentYear} Technology Enterprise Support System. Todos los
derechos reservados.
</p>
</div>
</div>
</footer>
);
};
export default Footer;
+40
View File
@@ -0,0 +1,40 @@
import React from "react";
import logoPrincipal from "../assets/TESS.png";
const Hero = () => {
return (
<header className="relative min-h-[92vh] flex items-center justify-center overflow-hidden bg-gradient-to-b from-[#020617] to-[#003172]">
<div className="max-w-7xl mx-auto px-6 lg:px-8 text-center relative z-10 w-full pt-32 pb-16 md:pt-40 md:pb-20 lg:pt-48">
<div className="main" />
<h1 className="text-4xl sm:text-5xl md:text-6xl lg:text-7xl font-extrabold mb-5 md:mb-6 tracking-tight leading-tight drop-shadow-lg drop-shadow-cyan-500/50">
Tecnologías que impulsan
<br />
<span className="text-transparent bg-clip-text bg-[#0cc0df]">
tu Éxito.
</span>
</h1>
<div className="my-7 md:my-8 flex justify-center">
<div className="w-full max-w-[240px] sm:max-w-[280px] md:max-w-[320px]">
<img
src={logoPrincipal}
alt="TESS Logo"
className="w-full h-auto object-contain animate-fade-in drop-shadow-[0_0_10px_rgba(255,255,255,0.8)]"
/>
</div>
</div>
<p
className="max-w-3xl mx-auto text-lg sm:text-xl md:text-2xl font-normal leading-relaxed text-blue-50/90"
id="hero-text"
>
Desarrollo de software, aplicaciones web eficientes y soporte TI que
hacen crecer tu negocio con tecnología segura y escalable.
</p>
</div>
</header>
);
};
export default Hero;
+203
View File
@@ -0,0 +1,203 @@
import React, { useState, useEffect } from "react";
import { motion, AnimatePresence } from "framer-motion";
import logoTess from "../assets/logotesspng.png";
{
/** BARRA DE NAVEGACIÓN (ง •_•)ง*/
}
const Navbar = ({ onContactClick }) => {
const [isScrolled, setIsScrolled] = useState(false);
const [isMobileMenuOpen, setIsMobileMenuOpen] = useState(false);
useEffect(() => {
const handleScroll = () => {
setIsScrolled(window.scrollY > 50);
};
window.addEventListener("scroll", handleScroll);
return () => window.removeEventListener("scroll", handleScroll);
}, []);
return (
<nav
className={`fixed top-0 left-0 right-0 z-50 px-6 lg:px-8 transition-all duration-500 ${
isScrolled
? "bg-brand-dark/70 backdrop-blur-2xl border-b border-white/10 py-2"
: "bg-transparent py-6"
}`}
>
<div className="max-w-7xl mx-auto">
<div
className={`relative flex items-center justify-between transition-all duration-500`}
>
{/* Espaciador en móvil para mantener el balance visual */}
<div className="md:hidden w-10"></div>
{/* Logo */}
<div className="absolute left-1/2 -translate-x-1/2 md:static md:translate-x-0 flex items-center gap-3">
<a
href="#"
className="flex items-center gap-2 group transition-all duration-300"
onClick={(e) => {
e.preventDefault();
// Desplazamiento suave al inicio
window.scrollTo({ top: 0, behavior: "smooth" });
}}
>
{/* Contenedor de la imagen sin restricción de altura para permitir que crezca */}
<div
className={`transition-all duration-500 flex items-center justify-center ${
isScrolled
? "w-36 sm:w-44 md:w-52"
: "w-48 sm:w-60 md:w-72 lg:w-80"
}`}
>
<img
src={logoTess}
alt="Logo TESS"
className="w-full h-auto object-contain"
/>
</div>
</a>
</div>
{/* Botón Menú Móvil (Hamburguesa) */}
<div className="md:hidden flex items-center ml-auto">
<button
onClick={() => setIsMobileMenuOpen(!isMobileMenuOpen)}
className="text-white hover:text-[#0cc0df] transition-colors p-2"
aria-label={
isMobileMenuOpen
? "Cerrar menú principal"
: "Abrir menú principal"
}
aria-expanded={isMobileMenuOpen}
>
<span className="material-symbols-outlined text-3xl">
{isMobileMenuOpen ? "close" : "menu"}
</span>
</button>
</div>
{/* Menú Escritorio */}
<div className="hidden md:block">
<div className="ml-10 flex items-center space-x-8">
<a
className="text-white/80 hover:text-white px-2 py-1 text-sm font-semibold transition-colors"
href="#quienes-somos"
>
Quienes somos
</a>
<a
className="text-white/80 hover:text-white px-2 py-1 text-sm font-semibold transition-colors"
href="#nuestro-trabajo"
>
Nuestro Trabajo
</a>
<a
className="text-white/80 hover:text-white px-2 py-1 text-sm font-semibold transition-colors"
href="#servicios"
>
Servicios
</a>
<a
className="text-white/80 hover:text-white px-2 py-1 text-sm font-semibold transition-colors"
href="#clientes"
>
Clientes
</a>
<button
onClick={onContactClick}
className="px-7 py-2.5 rounded-full text-sm font-bold shadow-lg shadow-cyan-500/25 transition-transform hover:scale-105 bg-gradient-to-r from-emerald-400 to-cyan-500 hover:from-emerald-500 hover:to-cyan-600 text-white"
>
Contáctanos
</button>
</div>
</div>
</div>
</div>
{/* Menú Móvil */}
<AnimatePresence>
{isMobileMenuOpen && (
<>
{/* Overlay */}
<motion.div
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
exit={{ opacity: 0 }}
onClick={() => setIsMobileMenuOpen(false)}
className="md:hidden fixed inset-0 bg-black/40 backdrop-blur-sm z-40"
/>
{/* Sidebar */}
<motion.div
initial={{ x: "100%" }}
animate={{ x: 0 }}
exit={{ x: "100%" }}
transition={{ type: "spring", damping: 25, stiffness: 200 }}
className="md:hidden fixed top-0 right-0 h-screen w-[80vw] max-w-sm bg-brand-dark/70 backdrop-blur-3xl border-l border-white/20 shadow-[0_0_40px_rgba(0,0,0,0.5)] rounded-l-[2rem] z-50 flex flex-col"
role="dialog"
aria-modal="true"
aria-label="Menú principal móvil"
>
<div className="flex justify-end p-6">
<button
onClick={() => setIsMobileMenuOpen(false)}
className="text-white hover:text-[#0cc0df] transition-colors p-2 flex items-center justify-center rounded-xl border border-white/10 bg-white/5 hover:bg-white/10"
aria-label="Cerrar menú principal"
>
<span className="material-symbols-outlined text-2xl">
close
</span>
</button>
</div>
<div className="flex flex-col px-8 py-4 space-y-8 text-left mt-4 h-full overflow-y-auto">
<a
className="text-white/90 hover:text-white text-xl font-medium transition-colors border-b border-white/10 pb-4"
href="#quienes-somos"
onClick={() => setIsMobileMenuOpen(false)}
>
Quienes somos
</a>
<a
className="text-white/90 hover:text-white text-xl font-medium transition-colors border-b border-white/10 pb-4"
href="#nuestro-trabajo"
onClick={() => setIsMobileMenuOpen(false)}
>
Nuestro Trabajo
</a>
<a
className="text-white/90 hover:text-white text-xl font-medium transition-colors border-b border-white/10 pb-4"
href="#servicios"
onClick={() => setIsMobileMenuOpen(false)}
>
Servicios
</a>
<a
className="text-white/90 hover:text-white text-xl font-medium transition-colors border-b border-white/10 pb-4"
href="#clientes"
onClick={() => setIsMobileMenuOpen(false)}
>
Clientes
</a>
<div className="pt-4">
<button
onClick={() => {
setIsMobileMenuOpen(false);
onContactClick();
}}
className="px-7 py-3 rounded-full text-lg font-bold shadow-lg shadow-cyan-500/25 transition-transform w-full bg-gradient-to-r from-emerald-400 to-cyan-500 hover:from-emerald-500 hover:to-cyan-600 text-white"
>
Contáctanos
</button>
</div>
</div>
</motion.div>
</>
)}
</AnimatePresence>
</nav>
);
};
export default Navbar;
+94
View File
@@ -0,0 +1,94 @@
import React from "react";
const servicesData = [
{
title: "Desarrollo a Medida",
icon: "code",
description:
"Creamos aplicaciones web, móviles y soluciones back-end robustas, diseñadas específicamente para adaptarse a los procesos únicos de tu negocio.",
color: "secondary",
},
{
title: "Consultoría y Arquitectura",
icon: "web",
description:
"Definimos arquitecturas escalables y seguras, garantizando que cada línea de código contribuya a una solución mantenible a largo plazo.",
color: "primary",
},
{
title: "Integración de Sistema",
icon: "lightbulb",
description:
"Conectamos tus herramientas y plataformas mediante APIs personalizadas para unificar el flujo de información y eliminar silos de datos.",
color: "secondary",
},
{
title: "Soporte Técnico Continuo",
icon: "support_agent",
description:
"No te dejamos solo tras el lanzamiento. Ofrecemos acompañamiento técnico, evolución de producto y soporte constante para tus soluciones en producción.",
color: "primary",
},
];
const Services = () => {
return (
<section
className="py-20 md:py-24 bg-gradient-to-b from-[#020617] to-[#020617]"
id="servicios"
>
<div className="max-w-7xl mx-auto px-6 lg:px-8">
{/* Encabezado */}
<div className="text-center mb-12 md:mb-14">
<h2 className="text-white font-bold text-sm tracking-[0.3em] uppercase mb-3">
NUESTROS SERVICIOS
</h2>
<h3
className="text-3xl sm:text-4xl md:text-5xl font-extrabold text-white"
id="services-subtitle"
>
Soluciones integrales
</h3>
</div>
{/* Grid de servicios */}
<div className="grid md:grid-cols-2 gap-6 lg:gap-8">
{servicesData.map((service, index) => (
<div
key={index}
className="glass-card p-6 lg:p-8 rounded-3xl border border-white/10 flex flex-col items-center text-center gap-4 transition-all hover:bg-white/5"
>
{/* Icono */}
<div
className={`w-14 h-14 shrink-0 rounded-2xl flex items-center justify-center
${
service.color === "primary"
? "bg-accent/20 text-accent"
: "bg-brand-light/20 text-brand-light"
}`}
>
<span className="material-symbols-outlined text-3xl">
{service.icon}
</span>
</div>
{/* Texto */}
<div>
<h4 className="text-sm font-bold tracking-[0.2em] uppercase mb-2 text-accent">
{service.title}
</h4>
<p className="text-blue-100/60 leading-relaxed text-sm md:text-base">
{service.description}
</p>
</div>
</div>
))}
</div>
</div>
</section>
);
};
export default Services;
+328
View File
@@ -0,0 +1,328 @@
import React, { useState } from "react";
import { motion, AnimatePresence } from "framer-motion";
import erpImg from "../assets/erp.png";
import crmImg from "../assets/crm.png";
const Solutions = () => {
const [selectedImage, setSelectedImage] = useState(null);
const containerVariants = {
hidden: { opacity: 0 },
visible: {
opacity: 1,
transition: {
staggerChildren: 0.3,
},
},
};
const itemVariants = {
hidden: { opacity: 0, y: 30 },
visible: {
opacity: 1,
y: 0,
transition: { duration: 0.8, ease: "easeOut" },
},
};
return (
<section
className="py-24 bg-brand-dark relative overflow-hidden"
id="soluciones"
>
<div className="max-w-7xl mx-auto px-6 lg:px-8 relative z-10">
<div className="text-center max-w-3xl mx-auto mb-20">
<motion.div
initial={{ opacity: 0, scale: 0.9 }}
whileInView={{ opacity: 1, scale: 1 }}
viewport={{ once: true }}
transition={{ duration: 0.5 }}
className="inline-block mb-4 px-4 py-1.5 rounded-full border border-accent/30 bg-accent/10 text-accent text-sm font-medium tracking-wide"
>
PRODUCTOS PROPIOS
</motion.div>
<motion.h2
initial={{ opacity: 0, y: 20 }}
whileInView={{ opacity: 1, y: 0 }}
viewport={{ once: true }}
transition={{ duration: 0.5, delay: 0.1 }}
className="text-4xl md:text-5xl font-bold mb-6 text-white tracking-tight"
>
Soluciones TESS
</motion.h2>
<motion.p
initial={{ opacity: 0, y: 20 }}
whileInView={{ opacity: 1, y: 0 }}
viewport={{ once: true }}
transition={{ duration: 0.5, delay: 0.2 }}
className="text-lg text-brand-light/80 font-light leading-relaxed"
>
Desarrollamos herramientas potentes para digitalizar, centralizar y
potenciar la gestión completa de tu negocio.
</motion.p>
</div>
<motion.div
variants={containerVariants}
initial="hidden"
whileInView="visible"
viewport={{ once: true, margin: "-100px" }}
className="space-y-32"
>
{/* TESS-ERP Section */}
<motion.div
variants={itemVariants}
className="flex flex-col lg:flex-row items-center gap-12 lg:gap-20"
>
<div className="w-full lg:w-1/2 space-y-8">
<div className="flex items-center gap-4 mb-2">
<div className="w-12 h-12 rounded-xl bg-gradient-to-br from-primary to-secondaccent flex items-center justify-center shadow-lg shadow-secondaccent/30 text-white font-bold text-xl">
E
</div>
<h3 className="text-3xl md:text-4xl font-bold text-white tracking-tight">
TESS-
<span className="text-transparent bg-clip-text bg-gradient-to-r from-accent to-secondaccent">
ERP
</span>
</h3>
</div>
<p className="text-brand-light text-lg leading-relaxed font-light">
Un sistema de planificación de recursos empresariales diseñado
para conectar todas las áreas de tu organización. Controla
inventarios, finanzas, recursos humanos y operaciones
comerciales desde una única plataforma inteligente.
</p>
<ul className="space-y-4">
{[
"Control centralizado de almacenes e inventario multisucursal.",
"Automatización de facturación y contabilidad en tiempo real.",
"Módulos escalables según el crecimiento de tu empresa.",
"Reportes avanzados e inteligencia de negocios (BI).",
].map((feature, idx) => (
<li key={idx} className="flex items-start gap-3">
<svg
className="w-6 h-6 text-accent mt-0.5 flex-shrink-0"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
>
<path
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth="2"
d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z"
/>
</svg>
<span className="text-brand-light/80">{feature}</span>
</li>
))}
</ul>
<div className="pt-4">
<button
onClick={() =>
document
.getElementById("contacto")
.scrollIntoView({ behavior: "smooth" })
}
className="px-8 py-3.5 rounded-full bg-secondaccent hover:bg-secondaccent/80 text-white font-medium transition-all duration-300 shadow-[0_0_20px_rgba(12,192,223,0.3)] hover:shadow-[0_0_30px_rgba(12,192,223,0.5)] transform hover:-translate-y-1 inline-flex items-center gap-2"
>
Solicitar Demo
<svg
className="w-5 h-5"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
>
<path
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth="2"
d="M14 5l7 7m0 0l-7 7m7-7H3"
/>
</svg>
</button>
</div>
</div>
<div className="w-full lg:w-1/2 relative group perspective-1000">
<div className="absolute inset-0 bg-gradient-to-r from-secondaccent/20 to-accent/20 rounded-2xl transform rotate-3 scale-105 opacity-50 transition-transform duration-500 group-hover:rotate-6"></div>
<div className="relative rounded-2xl overflow-hidden border border-slate-700/50 bg-slate-800 shadow-2xl transition-transform duration-500 group-hover:scale-[1.02]">
{/* Mockup Window UI */}
<div className="h-8 bg-slate-900 border-b border-slate-700 flex items-center px-4 gap-2">
<div className="w-3 h-3 rounded-full bg-red-400"></div>
<div className="w-3 h-3 rounded-full bg-amber-400"></div>
<div className="w-3 h-3 rounded-full bg-green-400"></div>
</div>
{/* Imagen del ERP */}
<div
className="aspect-[4/3] relative overflow-hidden bg-slate-900 cursor-pointer group"
onClick={() => setSelectedImage(erpImg)}
>
<img src={erpImg} alt="Dashboard de TESS-ERP" className="w-full h-full object-cover object-top transition-transform duration-500 group-hover:scale-105" />
<div className="absolute inset-0 bg-black/40 opacity-0 group-hover:opacity-100 transition-opacity duration-300 flex items-center justify-center">
<span className="text-white bg-black/50 px-4 py-2 rounded-full backdrop-blur-sm flex items-center gap-2">
<svg className="w-5 h-5" fill="none" viewBox="0 0 24 24" stroke="currentColor"><path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0zM10 7v3m0 0v3m0-3h3m-3 0H7" /></svg>
Ver detalle
</span>
</div>
</div>
</div>
</div>
</motion.div>
{/* TESS-CRM Section */}
<motion.div
variants={itemVariants}
className="flex flex-col lg:flex-row-reverse items-center gap-12 lg:gap-20"
>
<div className="w-full lg:w-1/2 space-y-8">
<div className="flex items-center gap-4 mb-2">
<div className="w-12 h-12 rounded-xl bg-accent/20 flex items-center justify-center shadow-lg shadow-accent/20 text-accent font-bold text-xl border border-accent/30">
C
</div>
<h3 className="text-3xl md:text-4xl font-bold text-white tracking-tight">
TESS-
<span className="text-accent">CRM</span>
</h3>
</div>
<p className="text-slate-300 text-lg leading-relaxed font-light">
Maximiza tus conversiones y fideliza a tus clientes. Nuestro
gestor de relaciones te permite organizar embudos de ventas,
automatizar seguimientos y medir el rendimiento de tu equipo
comercial.
</p>
<ul className="space-y-4">
{[
"Gestión visual de embudos de venta (Pipelines).",
"Historial unificado de comunicaciones por cliente.",
"Seguimiento de tareas, reuniones y alertas automatizadas.",
"Integración con correo electrónico y campañas de marketing.",
].map((feature, idx) => (
<li key={idx} className="flex items-start gap-3">
<svg
className="w-6 h-6 text-secondaccent mt-0.5 flex-shrink-0"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
>
<path
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth="2"
d="M5 13l4 4L19 7"
/>
</svg>
<span className="text-brand-light/80">{feature}</span>
</li>
))}
</ul>
<div className="pt-4">
<button
onClick={() =>
document
.getElementById("contacto")
.scrollIntoView({ behavior: "smooth" })
}
className="px-8 py-3.5 rounded-full bg-accent hover:bg-accent/80 text-primary font-bold transition-all duration-300 shadow-[0_0_20px_rgba(100,255,218,0.3)] hover:shadow-[0_0_30px_rgba(100,255,218,0.5)] transform hover:-translate-y-1 inline-flex items-center gap-2"
>
Descubrir CRM
<svg
className="w-5 h-5"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
>
<path
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth="2"
d="M14 5l7 7m0 0l-7 7m7-7H3"
/>
</svg>
</button>
</div>
</div>
<div className="w-full lg:w-1/2 relative group perspective-1000">
<div className="absolute inset-0 bg-accent/10 rounded-2xl transform -rotate-3 scale-105 opacity-50 transition-transform duration-500 group-hover:-rotate-6"></div>
<div className="relative rounded-2xl overflow-hidden border border-slate-700/50 bg-slate-800 shadow-2xl transition-transform duration-500 group-hover:scale-[1.02]">
{/* Mockup Window UI */}
<div className="h-8 bg-slate-900 border-b border-slate-700 flex items-center px-4 gap-2">
<div className="w-3 h-3 rounded-full bg-red-400"></div>
<div className="w-3 h-3 rounded-full bg-amber-400"></div>
<div className="w-3 h-3 rounded-full bg-green-400"></div>
</div>
{/* Imagen del CRM */}
<div
className="aspect-[4/3] relative overflow-hidden bg-slate-900 cursor-pointer group"
onClick={() => setSelectedImage(crmImg)}
>
<img src={crmImg} alt="Pipeline de Ventas en TESS-CRM" className="w-full h-full object-cover object-top transition-transform duration-500 group-hover:scale-105" />
<div className="absolute inset-0 bg-black/40 opacity-0 group-hover:opacity-100 transition-opacity duration-300 flex items-center justify-center">
<span className="text-white bg-black/50 px-4 py-2 rounded-full backdrop-blur-sm flex items-center gap-2">
<svg className="w-5 h-5" fill="none" viewBox="0 0 24 24" stroke="currentColor"><path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0zM10 7v3m0 0v3m0-3h3m-3 0H7" /></svg>
Ver detalle
</span>
</div>
</div>
</div>
</div>
</motion.div>
</motion.div>
</div>
{/* Modal Visor de Imágenes */}
<AnimatePresence>
{selectedImage && (
<motion.div
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
exit={{ opacity: 0 }}
onClick={() => setSelectedImage(null)}
className="fixed inset-0 z-[100] flex items-center justify-center bg-black/80 backdrop-blur-sm p-4 md:p-8"
>
<motion.div
initial={{ scale: 0.95, opacity: 0 }}
animate={{ scale: 1, opacity: 1 }}
exit={{ scale: 0.95, opacity: 0 }}
onClick={(e) => e.stopPropagation()}
className="relative w-full max-w-6xl max-h-[90vh] bg-slate-900 rounded-2xl overflow-hidden shadow-2xl border border-white/10 flex flex-col"
>
<div className="flex items-center justify-between p-4 border-b border-white/10 bg-black/20">
<div className="flex items-center gap-2">
<div className="w-3 h-3 rounded-full bg-red-500"></div>
<div className="w-3 h-3 rounded-full bg-amber-500"></div>
<div className="w-3 h-3 rounded-full bg-green-500"></div>
</div>
<button
onClick={() => setSelectedImage(null)}
className="text-white/70 hover:text-white transition-colors"
aria-label="Cerrar"
>
<svg className="w-6 h-6" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M6 18L18 6M6 6l12 12" />
</svg>
</button>
</div>
<div className="flex-1 overflow-auto bg-slate-900 flex items-center justify-center p-4">
<img
src={selectedImage}
alt="Vista detallada"
className="w-full h-auto max-h-full object-contain rounded"
/>
</div>
</motion.div>
</motion.div>
)}
</AnimatePresence>
</section>
);
};
export default Solutions;
+67
View File
@@ -0,0 +1,67 @@
import React from "react";
import imagen from "../assets/tesscorpIA.png";
const Work = ({ onOpenContact }) => {
return (
<section
className="py-20 md:py-24 bg-gradient-to-b from-[#001430] to-[#020617]"
id="nuestro-trabajo"
>
<div className="max-w-7xl mx-auto px-6 lg:px-8">
{/* Título */}
<h2
className="text-2xl md:text-3xl font-bold mb-10 md:mb-12 text-center lg:text-left tracking-tight text-secondaccent"
id="work-title"
>
Nuestro Trabajo
</h2>
<div className="grid grid-cols-1 lg:grid-cols-2 gap-10 lg:gap-14 items-center">
{/* Izquierda: Texto y Botón */}
<div className="space-y-6 text-blue-100/80">
<p className="text-base sm:text-lg md:text-xl leading-relaxed text-justify font-light">
Entendemos a fondo tu negocio para alinear la tecnología con tus
objetivos. Utilizamos metodologías ágiles y ciclos de entrega
cortos para asegurar transparencia total.
</p>
<p className="text-base sm:text-lg md:text-xl leading-relaxed text-justify font-light">
Colaboramos con tu equipo para priorizar funcionalidades y validar
soluciones rápidamente. Así construimos productos que no solo
funcionan hoy, sino que escalan hacia el futuro.
</p>
{/* Botón */}
<div className="pt-2">
<button
id="work-button"
onClick={onOpenContact}
className="inline-flex items-center justify-center gap-2 px-6 py-3 sm:px-8 sm:py-4 text-white font-bold rounded-2xl transition-all transform hover:scale-105 shadow-lg shadow-cyan-500/25 bg-gradient-to-r from-emerald-400 to-cyan-500 hover:from-emerald-500 hover:to-cyan-600"
>
Envíanos un correo!
<span className="material-symbols-outlined text-[1.2em]">mail</span>
</button>
</div>
</div>
{/* Derecha: Card Visual */}
<div className="relative group">
{/* Resplandor */}
<div className="absolute -inset-1 bg-gradient-to-r from-[#f9a14d]/20 to-blue-500/20 rounded-[2rem] blur-xl opacity-40 group-hover:opacity-80 transition duration-700"></div>
<div className="relative glass-card rounded-[2rem] border border-white/10 overflow-hidden shadow-2xl">
<img
src={imagen}
alt="Proyectos TESS"
className="w-full h-full object-cover grayscale-[0.25] group-hover:grayscale-0 transition-all duration-700 scale-[1.03] group-hover:scale-100"
/>
<div className="absolute inset-0 bg-gradient-to-t from-black/60 via-transparent to-transparent"></div>
</div>
</div>
</div>
</div>
</section>
);
};
export default Work;
View File
+245 -101
View File
@@ -1,122 +1,266 @@
:root { @import "tailwindcss";
font-family: Inter, system-ui, Avenir, Helvetica, Arial, sans-serif;
line-height: 1.5;
font-weight: 400;
color-scheme: light dark; @theme {
color: rgba(255, 255, 255, 0.899); --color-primary: #031d40;
background-color: #0A2647; --color-secondary: #020617;
background-image: url('/public/colage-tess.jpeg'); --color-accent: #64ffda;
--color-secondaccent: #0cc0df;
--color-brand-dark: #020617;
--color-brand-light: #cfcfcf;
font-synthesis: none; --font-raleway: "Raleway", sans-serif;
text-rendering: optimizeLegibility;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
} }
a { @layer base {
font-weight: 500; body {
color: #646cff; @apply font-raleway antialiased text-white bg-brand-dark;
text-decoration: inherit; }
}
a:hover {
color: #535bf2;
} }
/* estrellas del background*/
body { body {
margin: 0; background-color: #000;
display: flex;
place-items: center;
min-width: 320px;
min-height: 100vh;
background-image: url('/public/colage-tess.jpeg');
} }
h1 { .main {
font-size: 3.2em; position: fixed;
line-height: 1.1; top: 50%;
} left: 50%;
height: 1px;
width: 1px;
background-color: #fff;
border-radius: 50%;
box-shadow:
-42vw -4vh 0px 0px #fff,
25vw -41vh 0px 0px #fff,
-20vw 49vh 0px 1px #fff,
5vw 40vh 1px 1px #fff,
29vw 19vh 1px 0px #fff,
-44vw -13vh 0px 0px #fff,
46vw 41vh 0px 1px #fff,
-3vw -45vh 0px 1px #fff,
47vw 35vh 1px 0px #fff,
12vw -8vh 1px 0px #fff,
-34vw 48vh 1px 1px #fff,
32vw 26vh 1px 1px #fff,
32vw -41vh 1px 1px #fff,
0vw 37vh 1px 1px #fff,
34vw -26vh 1px 0px #fff,
-14vw -49vh 1px 0px #fff,
-12vw 45vh 0px 1px #fff,
-44vw -33vh 0px 1px #fff,
-13vw 41vh 0px 0px #fff,
-36vw -11vh 0px 1px #fff,
-23vw -24vh 1px 0px #fff,
-38vw -27vh 0px 1px #fff,
16vw -19vh 0px 0px #fff,
28vw 33vh 1px 0px #fff,
-49vw -4vh 0px 0px #fff,
16vw 32vh 0px 1px #fff,
36vw -18vh 1px 0px #fff,
-25vw -30vh 1px 0px #fff,
-23vw 24vh 0px 1px #fff,
-2vw -35vh 1px 1px #fff,
-25vw 9vh 0px 0px #fff,
-15vw -34vh 0px 0px #fff,
-8vw -19vh 1px 0px #fff,
-20vw -20vh 1px 1px #fff,
42vw 50vh 0px 1px #fff,
-32vw 10vh 1px 0px #fff,
-23vw -17vh 0px 0px #fff,
44vw 15vh 1px 0px #fff,
-40vw 33vh 1px 1px #fff,
-43vw 8vh 0px 0px #fff,
-48vw -15vh 1px 1px #fff,
-24vw 17vh 0px 0px #fff,
-31vw 50vh 1px 0px #fff,
36vw -38vh 0px 1px #fff,
-7vw 48vh 0px 0px #fff,
15vw -32vh 0px 0px #fff,
29vw -41vh 0px 0px #fff,
2vw 37vh 1px 0px #fff,
7vw -40vh 1px 1px #fff,
15vw 18vh 0px 0px #fff,
25vw -13vh 1px 1px #fff,
-46vw -12vh 1px 1px #fff,
-18vw 22vh 0px 0px #fff,
23vw -9vh 1px 0px #fff,
50vw 12vh 0px 1px #fff,
45vw 2vh 0px 0px #fff,
14vw -48vh 1px 0px #fff,
23vw 43vh 0px 1px #fff,
-40vw 16vh 1px 1px #fff,
20vw -31vh 0px 1px #fff,
-17vw 44vh 1px 1px #fff,
18vw -45vh 0px 0px #fff,
33vw -6vh 0px 0px #fff,
0vw 7vh 0px 1px #fff,
-10vw -18vh 0px 1px #fff,
-19vw 5vh 1px 0px #fff,
1vw 42vh 0px 0px #fff,
22vw 48vh 0px 1px #fff,
39vw -8vh 1px 1px #fff,
-6vw -42vh 1px 0px #fff,
-47vw 34vh 0px 0px #fff,
-46vw 19vh 0px 1px #fff,
-12vw -32vh 0px 0px #fff,
-45vw -38vh 0px 1px #fff,
-28vw 18vh 1px 0px #fff,
-38vw -46vh 1px 1px #fff,
49vw -6vh 1px 1px #fff,
-28vw 18vh 1px 1px #fff,
10vw -24vh 0px 1px #fff,
-5vw -11vh 1px 1px #fff,
33vw -8vh 1px 0px #fff,
-16vw 17vh 0px 0px #fff,
18vw 27vh 0px 1px #fff,
-8vw -10vh 1px 1px #fff;
button { /* stars were too big with the layers above but left the code in case no one cares -- as in, if noone's just that one other loner who actually cares */
border-radius: 8px;
border: 1px solid transparent;
padding: 0.6em 1.2em;
font-size: 1em;
font-weight: 500;
font-family: inherit;
background-color: #1a1a1a;
cursor: pointer;
transition: border-color 0.25s;
}
button:hover { box-shadow:
border-color: #646cff; 24vw 9vh 1px 0px #fff,
12vw -24vh 0px 1px #fff,
-45vw -22vh 0px 0px #fff,
-37vw -40vh 0px 1px #fff,
29vw 19vh 0px 1px #fff,
4vw -8vh 0px 1px #fff,
-5vw 21vh 1px 1px #fff,
-27vw 26vh 1px 1px #fff,
-47vw -3vh 1px 1px #fff,
-28vw -30vh 0px 1px #fff,
-43vw -27vh 0px 1px #fff,
4vw 22vh 1px 1px #fff,
36vw 23vh 0px 0px #fff,
-21vw 24vh 1px 1px #fff,
-16vw 2vh 1px 0px #fff,
-16vw -6vh 0px 0px #fff,
5vw 26vh 0px 0px #fff,
-34vw 41vh 0px 0px #fff,
1vw 42vh 1px 1px #fff,
11vw -13vh 1px 1px #fff,
48vw -8vh 1px 0px #fff,
22vw -15vh 0px 0px #fff,
45vw 49vh 0px 0px #fff,
43vw -27vh 1px 1px #fff,
20vw -2vh 0px 0px #fff,
8vw 22vh 0px 1px #fff,
39vw 48vh 1px 1px #fff,
-21vw -11vh 0px 1px #fff,
-40vw 45vh 0px 1px #fff,
11vw -30vh 1px 0px #fff,
26vw 30vh 1px 0px #fff,
45vw -29vh 0px 1px #fff,
-2vw 18vh 0px 0px #fff,
-29vw -45vh 1px 0px #fff,
-7vw -27vh 1px 1px #fff,
42vw 24vh 0px 0px #fff,
45vw -48vh 1px 0px #fff,
-36vw -18vh 0px 0px #fff,
-44vw 13vh 0px 1px #fff,
36vw 16vh 0px 1px #fff,
40vw 24vh 0px 0px #fff,
18vw 11vh 0px 0px #fff,
-15vw -23vh 1px 0px #fff,
-24vw 48vh 0px 1px #fff,
27vw -45vh 1px 0px #fff,
-2vw -24vh 0px 1px #fff,
-15vw -28vh 0px 0px #fff,
-43vw 13vh 1px 0px #fff,
7vw 27vh 1px 0px #fff,
47vw 5vh 0px 0px #fff,
-45vw 15vh 1px 1px #fff,
-5vw -28vh 0px 1px #fff,
38vw 25vh 1px 1px #fff,
-39vw -1vh 1px 0px #fff,
5vw 0vh 1px 0px #fff,
49vw 13vh 0px 0px #fff,
48vw 10vh 0px 1px #fff,
19vw -28vh 0px 0px #fff,
4vw 7vh 0px 0px #fff,
21vw 21vh 1px 1px #fff,
-15vw -15vh 0px 1px #fff,
-6vw -42vh 1px 0px #fff,
-15vw 48vh 1px 1px #fff,
-23vw 25vh 1px 1px #fff,
-48vw 25vh 0px 1px #fff,
-31vw -19vh 0px 1px #fff,
4vw 37vh 1px 1px #fff,
-43vw 28vh 0px 0px #fff,
3vw -25vh 0px 1px #fff,
-39vw 14vh 0px 1px #fff,
-40vw 31vh 0px 1px #fff,
35vw -36vh 1px 1px #fff,
16vw 49vh 0px 0px #fff,
6vw 39vh 0px 0px #fff,
3vw -35vh 0px 1px #fff,
-44vw -2vh 1px 0px #fff,
-6vw 21vh 1px 0px #fff,
48vw 9vh 1px 1px #fff,
-43vw 30vh 1px 1px #fff,
29vw -12vh 1px 1px #fff,
-48vw 13vh 1px 0px #fff,
-42vw 32vh 1px 1px #fff,
34vw 15vh 1px 1px #fff,
29vw -37vh 1px 1px #fff,
28vw 2vh 0px 0px #fff;
animation: zoom 16s alternate infinite;
will-change: transform;
} }
/*aqui acaban las estrellas*/
button:focus, @keyframes zoom {
button:focus-visible { 0% {
outline: 4px auto -webkit-focus-ring-color; transform: scale(1) translateZ(0);
}
@media (prefers-color-scheme: light) {
:root {
color: #213547;
background-color: #ffffff;
} }
100% {
a:hover { transform: scale(1.5) translateZ(0);
color: #747bff;
}
button {
background-color: #f9f9f9;
} }
} }
.glass-card {
background: rgba(255, 255, 255, 0.03);
body { backdrop-filter: blur(12px);
margin: 0; border: 1px solid rgba(255, 255, 255, 0.1);
display: flex; }
place-items: center; .mask-gradient {
min-width: 320px; mask-image: linear-gradient(
min-height: 100vh; to right,
background-image:"/public/colage-tess.jpeg"; transparent,
black 15%,
black 85%,
transparent
);
}
html {
scroll-behavior: smooth;
}
#hero-text {
color: transparent;
background: linear-gradient(
45deg,
#9ae7ff,
#78e4ff,
#4ddbff,
#009ec5,
#0099ad
);
-webkit-background-clip: text;
background-clip: text;
text-shadow:
0 0 5px rgba(0, 117, 212, 0.7),
0 0 10px rgba(0, 84, 117, 0.5),
0 0 15px rgba(0, 59, 70, 0.3);
} }
h1 { #work-button {
font-size: 3.2em; background-color: #00bef0;
line-height: 1.1; box-shadow: #000000;
}
#work-button:hover {
background-color: #0067ac91;
} }
button { #services-subtitle {
border-radius: 8px; color: #00bef0;
border: 1px solid transparent;
padding: 0.6em 1.2em;
font-size: 1em;
font-weight: 500;
font-family: inherit;
background-color: #1a1a1a;
cursor: pointer;
transition: border-color 0.25s;
}
button:hover {
border-color: #646cff;
}
button:focus,
button:focus-visible {
outline: 4px auto -webkit-focus-ring-color;
}
@media (prefers-color-scheme: light) {
:root {
color: #213547;
background-color: #ffffff;
}
a:hover {
color: #747bff;
}
button {
background-color: #f9f9f9;
}
} }
/*GHH ( •̀ ω •́ )y*/
+3 -1
View File
@@ -1,7 +1,9 @@
import { StrictMode } from 'react' import { StrictMode } from 'react'
import { createRoot } from 'react-dom/client' import { createRoot } from 'react-dom/client'
import App from './App.jsx' import App from './App.jsx'
import './App.css' import './index.css'
import React from 'react'
createRoot(document.getElementById('root')).render( createRoot(document.getElementById('root')).render(
<StrictMode> <StrictMode>
Binary file not shown.
+13 -12
View File
@@ -1,21 +1,22 @@
/** @type {import('tailwindcss').Config} */ /** @type {import('tailwindcss').Config} */
export default { export default {
content: [ content: [
'./index.html', // Incluye tu archivo HTML principal "./index.html",
'./src/**/*.{js,jsx,ts,tsx}', // Analiza todos los archivos de tu carpeta `src` "./src/**/*.{js,ts,jsx,tsx}", // Esto le dice que busque en toda la carpeta src
], ],
theme: { theme: {
extend: { extend: {
// Aquí puedes personalizar el tema (colores, fuentes, etc.)
colors: { colors: {
primary: "#0049ab",
'blue': '#4242EE', secondary: "rgb(59, 59, 59)",
accent: "#000000",
"brand-dark": "#020617",
"black" : "#000000",
},
fontFamily: {
raleway: ["Raleway", "sans-serif"],
}, },
}, },
}, },
plugins: [], plugins: [],
}; }
+1 -4
View File
@@ -1,10 +1,7 @@
import { defineConfig } from 'vite' import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react' import react from '@vitejs/plugin-react'
// https://vitejs.dev/config/ // https://vite.dev/config/
export default defineConfig({ export default defineConfig({
plugins: [react()], plugins: [react()],
css: {
postcss: './postcss.config.js', // Asegúrate de tener un archivo PostCSS
},
}) })