feat(site): blocos 3D da marca, novas ofertas e hero mais abrangente
Hero e movimento - cena 3D em tempo real com os blocos da marca (kit feito no Blender, 3d/blocos.py): marca, tela, integrações e dados; segue a rolagem, tem vida em repouso, reage ao cursor e, parada no topo, passa sozinha pelos estados com legenda - três níveis de aparelho (full, lite, static); sem WebGL fica o pôster - título novo: "Sites e sistemas sob medida para o jeito que a sua empresa trabalha." - faixa de clientes com o ramo, linha do primeiro passo, hero alinhado às seções - rótulos digitados, entrada dos blocos, cortina de blocos entre páginas e capa compartilhada entre a lista de cases e o case Ofertas - atendimento no WhatsApp com IA e nota fiscal para a reforma tributária (páginas de serviço, cartões da home, formulário e aviso com data de validade) - página /ia atualizada, com fontes - peças 3D em loop nos cartões e topos de página (3d/pecas.py) Design - hover por papel (bloco nos botões, barra nos links), rótulos sem caixa alta - um destino por rótulo: "Falar sobre meu projeto" leva ao formulário, "Chamar no WhatsApp" abre o WhatsApp - logo montado em blocos, 404 redesenhado, grades sem célula vazia - ícones do PWA e manifesto novos Specs em specs/, contexto de design em DESIGN.md e PRODUCT.md.
This commit is contained in:
1 parent
4671837c44
commit
c7d09d63d4
165 files changed
+7940
-3790
No files matched your search
@@ -1,11 +1,19 @@
|
||||
import HoverPrefetchLink from "./HoverPrefetchLink";
|
||||
|
||||
export type ClientLink = { id: string; name: string };
|
||||
export type ClientLink = {
|
||||
id: string;
|
||||
name: string;
|
||||
/** Ramo do cliente ("loja virtual"), sob o nome de 640 px em diante (lib/proof.ts). */
|
||||
sector?: string;
|
||||
};
|
||||
|
||||
/**
|
||||
* Faixa "Já entregue para" do hero: só projetos de cliente (lib/proof.ts), cada um levando ao próprio case, e na
|
||||
* mesma linha os anos de experiência (calculados em app/page.tsx). Sem clientes e sem anos, nada é desenhado.
|
||||
* Os links têm 44 px de altura de toque; a rota só é pré-carregada quando a pessoa chega no link.
|
||||
* De 640 px em diante cada cliente é um par empilhado: o nome (link) sobre o ramo, em 13 px e apagado; abaixo disso,
|
||||
* só os nomes. Os links têm 44 px de altura de toque no celular e 24 px a partir de 640 px, onde o ramo divide a
|
||||
* altura do item; a rota só é pré-carregada quando a pessoa chega no link. Os pontos, o rótulo e os anos se alinham
|
||||
* pela linha dos nomes (`sm:items-start`).
|
||||
*
|
||||
* O ponto separador vem ANTES de cada item, menos do primeiro, e só aparece ENTRE itens da mesma linha. Cada item
|
||||
* (menos o primeiro) tem 16 px de margem negativa (`-ml-4`), que cobrem os 16 px de respiro (`pr-4`) do item
|
||||
@@ -30,12 +38,19 @@ export default function ClientStrip({
|
||||
...clients.map((client) => ({
|
||||
key: client.id,
|
||||
node: (
|
||||
<HoverPrefetchLink
|
||||
href={`/cases/${client.id}`}
|
||||
className="inline-flex min-h-11 items-center font-medium text-[#f4f2ed] no-underline underline-offset-4 hover:underline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-[var(--slash)]"
|
||||
>
|
||||
{client.name}
|
||||
</HoverPrefetchLink>
|
||||
<span className="flex flex-col">
|
||||
<HoverPrefetchLink
|
||||
href={`/cases/${client.id}`}
|
||||
className="inline-flex min-h-11 items-center self-start font-medium text-[#f4f2ed] no-underline underline-offset-4 hover:underline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-[var(--slash)] sm:min-h-6"
|
||||
>
|
||||
{client.name}
|
||||
</HoverPrefetchLink>
|
||||
{client.sector && (
|
||||
<span className="text-[13px] leading-[18px] max-sm:hidden">
|
||||
{client.sector}
|
||||
</span>
|
||||
)}
|
||||
</span>
|
||||
),
|
||||
})),
|
||||
...(years
|
||||
@@ -57,14 +72,16 @@ export default function ClientStrip({
|
||||
|
||||
return (
|
||||
<div
|
||||
className={`flex flex-wrap items-center gap-x-sp-3 gap-y-sp-1 font-display text-[15px] leading-6 text-[rgba(244,242,237,.64)] ${className}`.trim()}
|
||||
className={`flex flex-wrap items-center gap-x-sp-3 gap-y-sp-1 font-display text-[15px] leading-6 text-[rgba(244,242,237,.64)] sm:items-start ${className}`.trim()}
|
||||
>
|
||||
{clients.length > 0 && <p>Já entregue para:</p>}
|
||||
<ul className="-ml-1 flex flex-wrap items-center overflow-x-clip pl-1">
|
||||
{/* de 640 px em diante a lista fica ao lado do rótulo enquanto sobram 24rem, e quebra por dentro; menos que isso,
|
||||
ela desce para baixo do rótulo e usa a largura toda */}
|
||||
<ul className="-ml-1 flex flex-wrap items-center overflow-x-clip pl-1 sm:min-w-[min(24rem,100%)] sm:flex-1 sm:basis-0 sm:items-start sm:gap-y-sp-2">
|
||||
{items.map((item, index) => (
|
||||
<li
|
||||
key={item.key}
|
||||
className={`flex items-center pr-4${index > 0 ? " -ml-4" : ""}`}
|
||||
className={`flex items-center pr-4 sm:items-start${index > 0 ? " -ml-4" : ""}`}
|
||||
>
|
||||
{index > 0 && (
|
||||
<span
|
||||
|
||||
Reference in new issue
Block a user