feat: control room hero, SEO/AEO optimization and design system fixes

Hero: replace particle field with cobe globe (Capricorn view, multi-axis drag, reduced-motion safe), telemetry HUD with pointer parallax, particle text build effect, Space Grotesk display font. SEO: short titles with template, PT-BR accents, twitter cards on dynamic cases, escaped JSON-LD via lib/jsonld.ts, CSP report-only, 25 service FAQs answer-first. Design: fix TW4 layered reset killing spacing utilities, literal @theme tokens, mobile hero overflow, header overlap, empty case cards. Remove framer-motion (unified on motion/react), header version badge, phone number from hero CTA. Production build verified (24 static pages).
This commit is contained in:
Evandro Fonseca Junior committed 2026-08-27 10:55:21 -03:00
1 parent 0920370f30
commit b791b7de9e
94 files changed
+2621 -2889

No files matched your search

+2 -2
View File
@@ -1,6 +1,6 @@
"use client";
import { useInView } from "framer-motion";
import { useInView } from "motion/react";
import { useEffect, useRef, useState } from "react";
import { useReducedMotion } from "@/app/hooks/useReducedMotion";
@@ -42,7 +42,7 @@ export function CounterValue({
const frame = (now: number) => {
const elapsed = now - start;
const progress = Math.min(elapsed / duration, 1);
const eased = 1 - Math.pow(1 - progress, 3);
const eased = 1 - (1 - progress) ** 3;
setDisplayValue(Math.round(value * eased));
if (progress < 1) {
+1 -1
View File
@@ -1,6 +1,6 @@
"use client";
import { motion } from "framer-motion";
import { motion } from "motion/react";
import { useState } from "react";
import { useReducedMotion } from "@/app/hooks/useReducedMotion";
@@ -1,6 +1,6 @@
"use client";
import { motion } from "framer-motion";
import { motion } from "motion/react";
import Image, { type StaticImageData } from "next/image";
import { useState } from "react";
import { useReducedMotion } from "@/app/hooks/useReducedMotion";
@@ -27,9 +27,7 @@ export function LazyRevealImage({
<motion.div
className={`relative ${className}`.trim()}
initial={
shouldReduceMotion
? { opacity: 0 }
: { opacity: 0, y: 20, scale: 1.02 }
shouldReduceMotion ? { opacity: 0 } : { opacity: 0, y: 20, scale: 1.02 }
}
animate={
loaded
@@ -6,7 +6,7 @@ import { TextDiffuseReveal } from "./TextDiffuseReveal";
let mockReducedMotion = false;
let mockInView = true;
let mockAnimations: Array<{ animate?: Record<string, unknown> }> = [];
jest.mock("framer-motion", () => {
jest.mock("motion/react", () => {
const React = require("react");
return {
@@ -1,6 +1,6 @@
"use client";
import { motion, useInView } from "framer-motion";
import { motion, useInView } from "motion/react";
import { useEffect, useMemo, useRef, useState } from "react";
import { useReducedMotion } from "@/app/hooks/useReducedMotion";
+1 -1
View File
@@ -1,6 +1,6 @@
"use client";
import { motion } from "framer-motion";
import { motion } from "motion/react";
import { useReducedMotion } from "@/app/hooks/useReducedMotion";
interface TopProgressBarProps {
@@ -1,4 +1,4 @@
import React from 'react';
import React from "react";
export default function PointCloudScene() {
return <div data-testid="point-cloud-mock"></div>;
}