diff --git a/landing/app/globals.css b/landing/app/globals.css index 6525dd9..8c2c043 100644 --- a/landing/app/globals.css +++ b/landing/app/globals.css @@ -4,22 +4,79 @@ --font-sans: "Geist", "Geist Fallback", system-ui, sans-serif; --font-mono: "Geist Mono", "Geist Mono Fallback", monospace; - --color-background: #ffffff; - --color-foreground: #0f0f0f; - --color-muted: #f5f5f5; - --color-muted-foreground: #737373; - --color-primary: #7c3aed; - --color-primary-foreground: #ffffff; - --color-secondary: #f3f4f6; - --color-secondary-foreground: #1f2937; - --color-accent: #8b5cf6; - --color-border: #e5e5e5; - --color-card: #ffffff; - --color-card-foreground: #0f0f0f; + --color-background: var(--theme-background); + --color-foreground: var(--theme-foreground); + --color-muted: var(--theme-muted); + --color-muted-foreground: var(--theme-muted-foreground); + --color-primary: var(--theme-primary); + --color-primary-foreground: var(--theme-primary-foreground); + --color-secondary: var(--theme-secondary); + --color-secondary-foreground: var(--theme-secondary-foreground); + --color-accent: var(--theme-accent); + --color-border: var(--theme-border); + --color-card: var(--theme-card); + --color-card-foreground: var(--theme-card-foreground); --radius: 0.75rem; } +:root, +:root[data-theme="latte"] { + --theme-background: #eff1f5; + --theme-foreground: #4c4f69; + --theme-muted: #e6e9ef; + --theme-muted-foreground: #6c6f85; + --theme-primary: #8839ef; + --theme-primary-foreground: #eff1f5; + --theme-secondary: #dce0e8; + --theme-secondary-foreground: #4c4f69; + --theme-accent: #8839ef; + --theme-border: #ccd0da; + --theme-card: #eff1f5; + --theme-card-foreground: #4c4f69; + --theme-shadow: 76, 79, 105; + --theme-primary-rgb: 136, 57, 239; + color-scheme: light; +} + +@media (prefers-color-scheme: dark) { + :root:not([data-theme]) { + --theme-background: #1e1e2e; + --theme-foreground: #cdd6f4; + --theme-muted: #313244; + --theme-muted-foreground: #a6adc8; + --theme-primary: #cba6f7; + --theme-primary-foreground: #1e1e2e; + --theme-secondary: #45475a; + --theme-secondary-foreground: #cdd6f4; + --theme-accent: #cba6f7; + --theme-border: #45475a; + --theme-card: #181825; + --theme-card-foreground: #cdd6f4; + --theme-shadow: 17, 17, 27; + --theme-primary-rgb: 203, 166, 247; + color-scheme: dark; + } +} + +:root[data-theme="mocha"] { + --theme-background: #1e1e2e; + --theme-foreground: #cdd6f4; + --theme-muted: #313244; + --theme-muted-foreground: #a6adc8; + --theme-primary: #cba6f7; + --theme-primary-foreground: #1e1e2e; + --theme-secondary: #45475a; + --theme-secondary-foreground: #cdd6f4; + --theme-accent: #cba6f7; + --theme-border: #45475a; + --theme-card: #181825; + --theme-card-foreground: #cdd6f4; + --theme-shadow: 17, 17, 27; + --theme-primary-rgb: 203, 166, 247; + color-scheme: dark; +} + * { border-color: var(--color-border); } @@ -27,12 +84,33 @@ html { scroll-behavior: smooth; scroll-padding-top: 5rem; + transition: + background-color 240ms ease, + color 240ms ease; } body { background: var(--color-background); color: var(--color-foreground); font-family: var(--font-sans); + transition: + background-color 240ms ease, + color 240ms ease; +} + +a, +button, +section, +header, +footer, +.feature-card, +.faq-item, +.faq-toggle { + transition: + background-color 240ms ease, + border-color 240ms ease, + color 240ms ease, + box-shadow 240ms ease; } @keyframes heroIn { @@ -71,40 +149,36 @@ body { transform-style: preserve-3d; transition: transform 120ms ease, - background-color 140ms ease, - border-color 140ms ease, - color 140ms ease, - box-shadow 140ms ease; + background-color 240ms ease, + border-color 240ms ease, + color 240ms ease, + box-shadow 240ms ease; will-change: transform; } .tilt-link:hover { - box-shadow: 0 6px 14px rgba(15, 15, 15, 0.1); + box-shadow: 0 6px 14px rgba(var(--theme-shadow), 0.12); } .feature-card { color: inherit; - transition: - background-color 160ms ease, - border-color 160ms ease, - box-shadow 160ms ease; } .feature-card:hover { - background: rgba(124, 58, 237, 0.04); - border-color: rgba(124, 58, 237, 0.32); - box-shadow: 0 6px 14px rgba(15, 15, 15, 0.08); + background: rgba(var(--theme-primary-rgb), 0.06); + border-color: rgba(var(--theme-primary-rgb), 0.32); + box-shadow: 0 6px 14px rgba(var(--theme-shadow), 0.1); } .feature-card:hover .feature-icon { - background: rgba(124, 58, 237, 0.14); + background: rgba(var(--theme-primary-rgb), 0.14); } .feature-card-reveal { opacity: 0; transform: translateY(16px); transition-property: opacity, transform, background-color, border-color, box-shadow; - transition-duration: 520ms, 520ms, 160ms, 160ms, 160ms; + transition-duration: 520ms, 520ms, 240ms, 240ms, 240ms; transition-timing-function: ease, ease, ease, ease, ease; transition-delay: var(--feature-delay, 0ms), var(--feature-delay, 0ms), 0ms, 0ms, 0ms; } @@ -114,16 +188,8 @@ body { transform: translateY(0); } -.faq-item { - transition: background-color 180ms ease; -} - .faq-item:hover { - background: rgba(124, 58, 237, 0.025); -} - -.faq-trigger { - transition: color 180ms ease; + background: rgba(var(--theme-primary-rgb), 0.04); } .faq-trigger:hover { @@ -140,12 +206,12 @@ body { border-radius: 9999px; background: var(--color-muted); transition: - background-color 180ms ease, + background-color 240ms ease, transform 180ms ease; } .faq-trigger:hover .faq-toggle { - background: rgba(124, 58, 237, 0.1); + background: rgba(var(--theme-primary-rgb), 0.1); } .faq-toggle span { @@ -155,7 +221,7 @@ body { border-radius: 9999px; background: var(--color-muted-foreground); transition: - background-color 180ms ease, + background-color 240ms ease, transform 220ms ease; } @@ -168,7 +234,7 @@ body { } .faq-trigger[aria-expanded="true"] .faq-toggle { - background: rgba(124, 58, 237, 0.12); + background: rgba(var(--theme-primary-rgb), 0.12); transform: rotate(180deg); } @@ -203,29 +269,19 @@ body { scroll-behavior: auto; } + *, + *::before, + *::after { + transition: none !important; + } + .tilt-link, .tilt-link:hover { transform: none; - transition: - background-color 140ms ease, - border-color 140ms ease, - color 140ms ease; } .feature-card-reveal { opacity: 1; transform: none; - transition: - background-color 160ms ease, - border-color 160ms ease, - box-shadow 160ms ease; - } - - .faq-answer, - .faq-item, - .faq-trigger, - .faq-toggle, - .faq-toggle span { - transition: none; } } diff --git a/landing/app/page.tsx b/landing/app/page.tsx index ba0ba07..c4c6177 100644 --- a/landing/app/page.tsx +++ b/landing/app/page.tsx @@ -1,5 +1,6 @@ import { Header } from "@/components/header"; import { Hero } from "@/components/hero"; +import { TrustSignals } from "@/components/trust-signals"; import { Features } from "@/components/features"; import { Screenshots } from "@/components/screenshots"; import { FAQ } from "@/components/faq"; @@ -12,6 +13,7 @@ export default function Home() {
+ diff --git a/landing/components/download-cta.tsx b/landing/components/download-cta.tsx index ffe1555..2473a34 100644 --- a/landing/components/download-cta.tsx +++ b/landing/components/download-cta.tsx @@ -26,7 +26,7 @@ const developerSteps = [ export function DownloadCTA() { return ( -
+

@@ -63,13 +63,13 @@ export function DownloadCTA() { - Descargar para Windows + Descargar última versión para Windows

diff --git a/landing/components/faq.tsx b/landing/components/faq.tsx index a029483..be6df14 100644 --- a/landing/components/faq.tsx +++ b/landing/components/faq.tsx @@ -6,14 +6,19 @@ import { useState } from "react"; const faqs: { question: string; answer: ReactNode }[] = [ { question: "¿FreeTPV es gratis?", - answer: <>Sí. FreeTPV es gratuito y de código abierto bajo licencia MIT., + answer: ( + <> + Sí. No hay planes de pago, cuotas mensuales ni funciones bloqueadas. El código se + publica bajo licencia MIT para que puedas revisarlo o adaptarlo. + + ), }, { question: "¿Para qué negocios está pensado?", answer: ( <> - Está pensado para bares, restaurantes, cafeterías y pequeños negocios de hostelería - que necesitan un TPV sencillo y sin cuotas. + Para bares, cafeterías, restaurantes pequeños y negocios de hostelería que necesitan + vender rápido, gestionar productos y sacar tickets sin depender de un sistema complejo. ), }, @@ -21,21 +26,44 @@ const faqs: { question: string; answer: ReactNode }[] = [ question: "¿Funciona sin conexión a internet?", answer: ( <> - Sí. FreeTPV es una aplicación de escritorio y guarda los datos localmente en el equipo - donde se instala. + Sí. FreeTPV es una aplicación de escritorio: los productos, usuarios y ajustes se guardan + en una base de datos local en el equipo donde se instala. ), }, { question: "¿Qué sistema operativo soporta?", - answer: <>La versión principal está pensada para Windows 10 y Windows 11., + answer: ( + <> + La versión principal está pensada para Windows 10 y Windows 11. El instalador incluye + Java, así que no necesitas instalarlo aparte para usar la aplicación. + + ), + }, + { + question: "¿Necesito configurar algo para imprimir tickets?", + answer: ( + <> + Normalmente sí. Debes tener instalada la impresora térmica en Windows y seleccionarla en + los ajustes de FreeTPV. La impresión está pensada para tickets ESC/POS. + + ), + }, + { + question: "¿Puedo tener varios usuarios?", + answer: ( + <> + Sí. Puedes crear usuarios para el equipo y separar el acceso por roles, por ejemplo + administrador y camarero. + + ), }, { - question: "¿Permite gestionar productos, usuarios y ventas?", + question: "¿Permite gestionar productos, ventas y copias de seguridad?", answer: ( <> - Sí. Incluye gestión de productos, categorías, usuarios, permisos, ventas, cobros y - copias de seguridad. + Sí. Incluye productos y categorías, pantalla de ventas, cobro en efectivo o tarjeta, + ajustes del negocio y copias de seguridad de los datos. ), }, @@ -43,17 +71,16 @@ const faqs: { question: string; answer: ReactNode }[] = [ question: "¿Tiene virus?", answer: ( <> - No. FreeTPV es código abierto, por lo que cualquiera puede revisar el código. Las - descargas oficiales se publican desde{" "} + No. Las descargas oficiales se publican desde{" "} GitHub Releases - . + , y el código es público para que cualquiera pueda revisarlo. ), }, @@ -77,14 +104,14 @@ export function FAQ() { } return ( -
+

Preguntas frecuentes

- Respuestas rápidas sobre el funcionamiento, la licencia y la instalación de FreeTPV. + Respuestas prácticas sobre instalación, impresión, usuarios y funcionamiento local.

diff --git a/landing/components/features.tsx b/landing/components/features.tsx index 36b0f3a..c3c8981 100644 --- a/landing/components/features.tsx +++ b/landing/components/features.tsx @@ -94,29 +94,29 @@ export function Features() { }, []); return ( -
-
-
-

+
+
+
+

Todo lo que necesitas para tu negocio

-

+

FreeTPV incluye las herramientas esenciales para gestionar tu bar, restaurante o cafetería de forma profesional.

-
+
{features.map((feature, index) => (
-
- +
+
-

{feature.title}

+

{feature.title}

{feature.description}

))} diff --git a/landing/components/footer.tsx b/landing/components/footer.tsx index e3de2ac..815b3f0 100644 --- a/landing/components/footer.tsx +++ b/landing/components/footer.tsx @@ -9,9 +9,9 @@ function GithubIcon({ className }: { className?: string }) { export function Footer() { return ( diff --git a/landing/components/header.tsx b/landing/components/header.tsx index d7e7802..22e3fdb 100644 --- a/landing/components/header.tsx +++ b/landing/components/header.tsx @@ -1,96 +1,111 @@ "use client"; -import Link from "next/link"; import { Menu, X } from "lucide-react"; import { useState } from "react"; +import { ThemeToggle } from "@/components/theme-toggle"; + function GithubIcon({ className }: { className?: string }) { return ( ); } +const navItems = [ + { href: "#caracteristicas", label: "Características" }, + { href: "#capturas", label: "Capturas" }, + { href: "#faq", label: "FAQ" }, + { href: "#descargar", label: "Descargar" }, +]; + export function Header() { const [mobileMenuOpen, setMobileMenuOpen] = useState(false); + function scrollToTop() { + setMobileMenuOpen(false); + window.scrollTo({ top: 0, behavior: "smooth" }); + + if (window.location.hash) { + window.history.replaceState(null, "", window.location.pathname); + } + } + return ( -
-
-
- +
+
+
+ -
{mobileMenuOpen && ( -