diff --git a/app/components/Contact.tsx b/app/components/Contact.tsx index c0d27e8..2f2983c 100644 --- a/app/components/Contact.tsx +++ b/app/components/Contact.tsx @@ -39,8 +39,7 @@ export default function Contact() {

Retorno inicial em até 24h

Ideal para discovery técnico, revisão de arquitetura, rescue de - projeto, otimização de performance ou construção de produto do - zero. + projeto, otimização de performance ou construção de produto do zero.

WhatsApp: +55 47 99274-2365
@@ -63,7 +62,10 @@ export default function Contact() { setFormData({ ...formData, name: e.target.value }) } className="mt-sp-2 w-full border border-[rgba(255,255,255,.12)] bg-[rgba(255,255,255,.06)] px-sp-4 py-[14px] text-[12px] outline-none transition-colors focus:border-slash" - style={{ color: "#fff", backgroundColor: "rgba(255,255,255,0.06)" }} + style={{ + color: "#fff", + backgroundColor: "rgba(255,255,255,0.06)", + }} />
@@ -79,7 +81,10 @@ export default function Contact() { setFormData({ ...formData, email: e.target.value }) } className="mt-sp-2 w-full border border-[rgba(255,255,255,.12)] bg-[rgba(255,255,255,.06)] px-sp-4 py-[14px] text-[12px] outline-none transition-colors focus:border-slash" - style={{ color: "#fff", backgroundColor: "rgba(255,255,255,0.06)" }} + style={{ + color: "#fff", + backgroundColor: "rgba(255,255,255,0.06)", + }} />
@@ -114,7 +119,10 @@ export default function Contact() { setFormData({ ...formData, message: e.target.value }) } className="mt-sp-2 w-full resize-none border border-[rgba(255,255,255,.12)] bg-[rgba(255,255,255,.06)] px-sp-4 py-[14px] text-[12px] outline-none transition-colors focus:border-slash" - style={{ color: "#fff", backgroundColor: "rgba(255,255,255,0.06)" }} + style={{ + color: "#fff", + backgroundColor: "rgba(255,255,255,0.06)", + }} />
diff --git a/app/components/Hero.tsx b/app/components/Hero.tsx index 158d11a..e9af4ee 100644 --- a/app/components/Hero.tsx +++ b/app/components/Hero.tsx @@ -1,5 +1,7 @@ "use client"; +import { useState, useEffect } from "react"; +import { motion, AnimatePresence } from "framer-motion"; import { Logo } from "./Logo"; const SOCIAL_LINKS = [ @@ -30,13 +32,103 @@ const SOCIAL_LINKS = [ }, ]; -const STATS = [ - { value: "4", accent: "px", label: "Base unit" }, - { value: "9", accent: "x", label: "Type scale" }, - { value: "4", accent: "+", label: "Core tokens" }, -]; +const textToType = "evandro.dev.br"; export default function Hero() { + const [phase, setPhase] = useState<"typing" | "idle" | "glitch" | "logo">( + "typing", + ); + const [typedCount, setTypedCount] = useState(0); + + useEffect(() => { + let timeout: NodeJS.Timeout; + + if (phase === "typing") { + if (typedCount < textToType.length) { + timeout = setTimeout(() => { + setTypedCount((c) => c + 1); + }, 120); // typing speed + } else { + timeout = setTimeout(() => { + setPhase("idle"); + }, 1200); // Wait after typing finishes + } + } else if (phase === "idle") { + timeout = setTimeout(() => { + setPhase("glitch"); + }, 100); // trigger glitch + } else if (phase === "glitch") { + timeout = setTimeout(() => { + setPhase("logo"); + }, 600); // Glitch out duration + } else if (phase === "logo") { + timeout = setTimeout(() => { + setTypedCount(0); + setPhase("typing"); + }, 3500); // Logo display and blink duration + } + + return () => clearTimeout(timeout); + }, [phase, typedCount]); + + const renderTypedText = () => { + const chars = []; + for (let i = 0; i < typedCount; i++) { + const char = textToType[i]; + if (i < 7) { + chars.push( + + {char} + , + ); + } else if (i === 7) { + chars.push(
); + chars.push( + + {char} + , + ); + } else if (i < 11) { + chars.push( + + {char} + , + ); + } else if (i === 11) { + chars.push(
); + chars.push( + + {char} + , + ); + } else { + chars.push( + + {char} + , + ); + } + } + // blinking cursor + if (phase === "typing" || phase === "idle") { + chars.push( + + _ + , + ); + } + return chars; + }; + const hour = new Date().getHours(); const greeting = hour >= 8 && hour < 12 @@ -53,8 +145,13 @@ export default function Hero() {
-
-
+
+
-

- evandro -
- .dev -
- .br -

+
+ + {(phase === "typing" || phase === "idle") && ( + + {renderTypedText()} + + )} + + {phase === "logo" && ( + + + + )} + +

-

+ ); diff --git a/app/components/WorkModalities.tsx b/app/components/WorkModalities.tsx index 5d0926e..d058ce9 100644 --- a/app/components/WorkModalities.tsx +++ b/app/components/WorkModalities.tsx @@ -92,7 +92,9 @@ function TierCard({ tier }: { tier: Tier }) { onBlur={() => setHovered(false)} tabIndex={0} style={{ - border: tier.featured ? "2px solid #0A0A0A" : "1px solid rgba(10,10,10,0.1)", + border: tier.featured + ? "2px solid #0A0A0A" + : "1px solid rgba(10,10,10,0.1)", background: tier.featured ? "#0A0A0A" : "#fff", padding: "var(--sp-6)", display: "flex", @@ -108,7 +110,13 @@ function TierCard({ tier }: { tier: Tier }) { }} > {/* Top row */} -
+
@@ -159,7 +171,15 @@ function TierCard({ tier }: { tier: Tier }) {
{/* Description */} -

+

{tier.description}

@@ -183,7 +203,9 @@ function TierCard({ tier }: { tier: Tier }) { {/* Pricing */}
@@ -198,7 +220,16 @@ function TierCard({ tier }: { tier: Tier }) { > {tier.pricing}
-
+
{tier.pricingNote}
diff --git a/app/components/ui/NumberIcons.tsx b/app/components/ui/NumberIcons.tsx index 5715d84..c08ed65 100644 --- a/app/components/ui/NumberIcons.tsx +++ b/app/components/ui/NumberIcons.tsx @@ -1,5 +1,5 @@ // src/components/ui/NumberIcons.tsx -import React from 'react'; +import React from "react"; interface NumberIconProps extends React.SVGProps { /** Tamanho em pixels. Escala mantendo o viewBox 80x80 */ @@ -9,9 +9,9 @@ interface NumberIconProps extends React.SVGProps { } const baseProps = { - fill: 'none', - xmlns: 'http://www.w3.org/2000/svg', - viewBox: '0 0 80 80', + fill: "none", + xmlns: "http://www.w3.org/2000/svg", + viewBox: "0 0 80 80", }; /** @@ -22,44 +22,53 @@ const GraphicShell = () => ( <> {/* Base Background */} - + {/* Borda reativa ao hover */} - - + {/* Grid de background sutil (Cyberpunk/Tech feel) */} {/* Brand Slash (Acento) com Motion */} - ); -export const NumberOne = ({ size = 80, className = '', ...props }: NumberIconProps) => ( - ( + - 1 @@ -67,23 +76,28 @@ export const NumberOne = ({ size = 80, className = '', ...props }: NumberIconPro ); -export const NumberTwo = ({ size = 80, className = '', ...props }: NumberIconProps) => ( - ( + - 2 @@ -91,23 +105,28 @@ export const NumberTwo = ({ size = 80, className = '', ...props }: NumberIconPro ); -export const NumberThree = ({ size = 80, className = '', ...props }: NumberIconProps) => ( - ( + - 3 @@ -115,23 +134,28 @@ export const NumberThree = ({ size = 80, className = '', ...props }: NumberIconP ); -export const NumberFour = ({ size = 80, className = '', ...props }: NumberIconProps) => ( - ( + - 4 diff --git a/app/globals.css b/app/globals.css index bbf74fd..e934e92 100644 --- a/app/globals.css +++ b/app/globals.css @@ -1,16 +1,16 @@ @import url("https://fonts.googleapis.com/css2?family=Syne:wght@400;500;600;700;800&family=Geist+Mono:wght@300;400;500;600&display=swap"); @font-face { - font-family: 'Monument Extended'; - src: url('/fonts/MonumentExtended-Regular.otf') format('opentype'); + font-family: "Monument Extended"; + src: url("/fonts/MonumentExtended-Regular.otf") format("opentype"); font-weight: 400; font-style: normal; font-display: swap; } @font-face { - font-family: 'Monument Extended'; - src: url('/fonts/MonumentExtended-Ultrabold.otf') format('opentype'); + font-family: "Monument Extended"; + src: url("/fonts/MonumentExtended-Ultrabold.otf") format("opentype"); font-weight: 800; font-style: normal; font-display: swap; @@ -66,7 +66,7 @@ --r-lg: 16px; --r-full: 999px; --font-display: "Syne", sans-serif; - --font-hero: 'Monument Extended', sans-serif; + --font-hero: "Monument Extended", sans-serif; --font-mono: "Geist Mono", monospace; --ease-out: cubic-bezier(0.16, 1, 0.3, 1); --ease-in: cubic-bezier(0.4, 0, 1, 1); @@ -124,7 +124,7 @@ textarea { } .ds-main { - padding-top: 52px; + /* padding-top: 52px; removed since there is no header now */ } .ds-section { diff --git a/app/page.tsx b/app/page.tsx index 16416a7..dad2d05 100644 --- a/app/page.tsx +++ b/app/page.tsx @@ -1,7 +1,6 @@ import About from "./components/About"; import Contact from "./components/Contact"; import Experience from "./components/Experience"; -import { Header } from "./components/Header"; import Hero from "./components/Hero"; import Projects from "./components/Projects"; import Skills from "./components/Skills"; @@ -10,7 +9,6 @@ import { WorkModalities } from "./components/WorkModalities"; export default function Home() { return (
-