Rebrand na WorkNuke: zelena znacka a prestavene hero
Prevzeti vizualniho smeru z predlohy. Web i portal stoji na tychz tokenech, takze zmena hodnot v index.css se projevila naraz na obojim - portal je zeleny, aniz by se sahlo na jedinou jeho komponentu. Znacka a tokeny: - akcent z cyanove na zelenou #B7FF3C, podklad z modrocerne na zelenocernou #0F1411. Seda dostala zelenou prichut, aby vedle podkladu nepusobila spinave. - druhy akcent a text-gradient se nemazaly, jen presmerovaly do zelene rady. Pouziva je 341 mist a prepsat je vsechna kvuli barve by byla zbytecne velka zmena; fialova z nich zmizela tak jako tak. - stav "v poradku" je nove modrozeleny. Akcent je zeleny a dve zelene na jedne obrazovce, kazda o necem jinem, nikdo nerozlisi. - pismo Archivo na nadpisy, IBM Plex Sans na text, IBM Plex Mono na cisla a ID. Nadpisy maji tesny proklad, ktery Inter neumel bez trikareni. - znak je plocha bomba misto pismene v gradientnim ctverci. LogoMark je samostatny export, aby sel pouzit i uvnitr snimku v heru. Novy favicon. - primarni tlacitko je plna zelena misto prechodu ze dvou barev. Hero a navigace: - prokladany nadtitulek misto odznaku, dvouslovne radky nadpisu, jedno primarni tlacitko plus textovy odkaz, ctyri slovesa misto tri odrazek a snimek portalu vybihajici z prave hrany. - navigace je pri levem okraji a bez pilulky za aktivni polozkou. Jedina pilulka na liste je primarni akce. Opraveno u toho: - zare v heru je pozadi sekce, ne vrstva pod ni. Prekryv se zapornym z-indexem se schoval za podklad stranky a nebyl videt vubec. - presah snimku se pocita ze sirky kontejneru. Pevna hodnota ve vw stacila na notebooku, ale nad 1600 px se snimek vesel do postranni mezery a prestal byt oriznuty. Zamerne nezmeneno: klice v prohlizeci (automia.token, automia.tenant), ID firmy tnt_automia, ID aplikace csbot-prototype a prihlasovaci e-maily v ukazkovych datech. Vypadaji jako jmeno, ale jsou to identifikatory. Popis, jak znacka funguje v kodu, je v documentation/22-znacka-a-design.md. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
2e863c1f8b
commit
73e0ecca4f
+312
-103
@@ -1,133 +1,342 @@
|
||||
import { ArrowRight, CheckCircle2, PhoneCall, Sparkles } from 'lucide-react';
|
||||
import {
|
||||
ArrowRight,
|
||||
ChevronDown,
|
||||
Play,
|
||||
Plus,
|
||||
Search,
|
||||
Settings2,
|
||||
Share2,
|
||||
SlidersHorizontal,
|
||||
Users,
|
||||
Zap,
|
||||
} from 'lucide-react';
|
||||
import { ButtonLink } from '@/components/ui/Button';
|
||||
import { Container } from '@/components/ui/Container';
|
||||
import { LogoMark } from '@/components/layout/Logo';
|
||||
|
||||
/**
|
||||
* Hero.
|
||||
*
|
||||
* Zacina prikazem a slibem, ne pozdravem a predstavenim firmy. Prvni je
|
||||
* o zakaznikovi, druhe o nas - a na hlavni stranu patri to prvni.
|
||||
*
|
||||
* Slozeni: proklada nadtitulek, dvoubarevny nadpis, jedno primarni tlacitko
|
||||
* plus textovy odkaz, ctyri slovesa a snimek portalu vybihajici z prave hrany.
|
||||
*/
|
||||
|
||||
/** Ctyri kroky, ktere produkt opravdu dela. Nazvy sedi na zalozky v portalu. */
|
||||
const steps = [
|
||||
{
|
||||
icon: Zap,
|
||||
title: 'Sbírá',
|
||||
text: 'Události ze všech vašich nástrojů na jednom místě.',
|
||||
},
|
||||
{
|
||||
icon: Settings2,
|
||||
title: 'Automatizuje',
|
||||
text: 'Odbaví, co jde odbavit bez člověka.',
|
||||
},
|
||||
{
|
||||
icon: Share2,
|
||||
title: 'Propojuje',
|
||||
text: 'Spustí navazující kroky a celé workflow.',
|
||||
},
|
||||
{
|
||||
icon: Users,
|
||||
title: 'Deleguje',
|
||||
text: 'Zapojí správné lidi, když je potřeba.',
|
||||
},
|
||||
];
|
||||
|
||||
/** Krátké uvítání + hlavní CTA + mockup živého provozu. */
|
||||
export function Hero() {
|
||||
return (
|
||||
<section className="relative overflow-hidden pt-16 pb-20 sm:pt-24 sm:pb-28">
|
||||
{/* Dekorativni pozadi */}
|
||||
<div aria-hidden className="pointer-events-none absolute inset-0 -z-10">
|
||||
<div className="absolute inset-0 bg-grid mask-fade-b opacity-40" />
|
||||
<div className="animate-pulse-slow absolute -top-40 left-1/2 size-[38rem] -translate-x-1/2 rounded-full bg-brand-500/18 blur-[120px]" />
|
||||
<div className="animate-pulse-slow absolute top-40 -right-32 size-[30rem] rounded-full bg-accent-500/16 blur-[120px]" />
|
||||
</div>
|
||||
/*
|
||||
Zelena zare je pozadi **sekce**, ne vrstva pod ni.
|
||||
Prekryv se zapornym z-indexem se schoval za podklad stranky a nebyl videt;
|
||||
pozadi elementu tenhle problem nema.
|
||||
*/
|
||||
<section
|
||||
className="relative overflow-hidden pt-14 pb-16 sm:pt-20 sm:pb-20"
|
||||
style={{
|
||||
background:
|
||||
'radial-gradient(58rem 36rem at 74% 16%, rgba(155,230,25,0.28), transparent 60%),' +
|
||||
'radial-gradient(40rem 28rem at 2% 44%, rgba(155,230,25,0.14), transparent 64%),' +
|
||||
'radial-gradient(32rem 22rem at 92% 86%, rgba(183,255,60,0.10), transparent 66%)',
|
||||
}}
|
||||
>
|
||||
{/*
|
||||
Kolik snimek presahne pres pravou hranu. Nula na uzkych displejich,
|
||||
kde by presah znamenal jen orezany obsah bez efektu.
|
||||
*/}
|
||||
<style>{`
|
||||
@media (min-width: 1024px) {
|
||||
.hero-bleed { --hero-bleed: calc(-1 * ((100vw - min(72rem, 100vw - 4rem)) / 2 + 7rem)); }
|
||||
}
|
||||
`}</style>
|
||||
|
||||
<Container>
|
||||
<div className="grid items-center gap-14 lg:grid-cols-[1.05fr_0.95fr]">
|
||||
<div className="grid items-center gap-12 lg:grid-cols-[0.92fr_1.08fr]">
|
||||
<div className="animate-rise">
|
||||
<span className="glass inline-flex items-center gap-2 rounded-full px-4 py-1.5 text-xs font-medium text-brand-300">
|
||||
<Sparkles className="size-3.5" />
|
||||
Automatizace · Voiceboti · Integrace
|
||||
</span>
|
||||
|
||||
<h1 className="mt-6 text-4xl leading-[1.08] font-extrabold text-white sm:text-5xl lg:text-6xl">
|
||||
Vítejte. Děláme z ruční práce{' '}
|
||||
<span className="text-gradient">procesy, které běží samy</span>.
|
||||
</h1>
|
||||
|
||||
<p className="mt-6 max-w-xl text-lg leading-relaxed text-white/65">
|
||||
Jsme malý tým, který firmám staví automatizace, hlasové asistenty a propojení systémů -
|
||||
a pak je i provozuje. Vy vidíte výsledky v dashboardu, my držíme provoz.
|
||||
<p className="font-mono text-xs tracking-[0.24em] text-white/45 uppercase">
|
||||
Události dovnitř. Akce ven.
|
||||
</p>
|
||||
|
||||
<div className="mt-9 flex flex-wrap items-center gap-3">
|
||||
<h1 className="mt-5 text-5xl font-extrabold text-white sm:text-6xl lg:text-7xl">
|
||||
Konec
|
||||
<br />
|
||||
<span className="text-brand-400">ruční práce.</span>
|
||||
</h1>
|
||||
|
||||
<p className="mt-6 max-w-md text-lg leading-relaxed text-white/65">
|
||||
WorkNuke sbírá události, zautomatizuje, co jde, propojí další kroky a zapojí
|
||||
správné lidi, když je potřeba. Vaše práce prostě plyne.
|
||||
</p>
|
||||
|
||||
<div className="mt-8 flex flex-wrap items-center gap-5">
|
||||
<ButtonLink to="/kontakt" size="lg">
|
||||
Nezávazná konzultace
|
||||
Začít zdarma
|
||||
<ArrowRight className="size-4" />
|
||||
</ButtonLink>
|
||||
<ButtonLink to="/sluzby" variant="secondary" size="lg">
|
||||
Co umíme
|
||||
</ButtonLink>
|
||||
</div>
|
||||
|
||||
<ul className="mt-9 flex flex-wrap gap-x-6 gap-y-2.5 text-sm text-white/55">
|
||||
{['Nasazení v týdnech, ne kvartálech', 'Provoz a podpora v ceně', 'Bez vendor lock-inu'].map(
|
||||
(item) => (
|
||||
<li key={item} className="flex items-center gap-2">
|
||||
<CheckCircle2 className="size-4 shrink-0 text-ok-400" />
|
||||
{item}
|
||||
</li>
|
||||
),
|
||||
)}
|
||||
</ul>
|
||||
{/*
|
||||
Vedle primarniho tlacitka uz zadne druhe. Textovy odkaz rekne,
|
||||
ze je to mensi zavazek, aniz by o pozornost soutezil.
|
||||
*/}
|
||||
<a
|
||||
href="/sluzby"
|
||||
className="group inline-flex items-center gap-2.5 text-sm font-semibold text-white transition-colors hover:text-brand-300"
|
||||
>
|
||||
<span className="grid size-9 place-items-center rounded-full border border-ink-600/80 transition-colors group-hover:border-brand-400/60">
|
||||
<Play className="size-3.5 fill-current" />
|
||||
</span>
|
||||
Prohlédnout si to
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<HeroPanel />
|
||||
<div className="hero-bleed contents">
|
||||
<HeroPanel />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Ctyri slovesa. Neni to slib, je to popis toho, co portal umi. */}
|
||||
<ul className="mt-16 grid gap-8 sm:grid-cols-2 lg:grid-cols-4 lg:gap-10">
|
||||
{steps.map((step) => (
|
||||
<li key={step.title} className="animate-rise">
|
||||
<step.icon className="size-5 text-brand-400" />
|
||||
<p className="mt-3.5 font-display text-base font-bold text-white">{step.title}</p>
|
||||
<p className="mt-1.5 text-sm leading-relaxed text-white/50">{step.text}</p>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
</Container>
|
||||
</section>
|
||||
);
|
||||
}
|
||||
|
||||
/** Mockup panelu "z provozu" - jen ilustrace, zadna realna data. */
|
||||
function HeroPanel() {
|
||||
const steps = [
|
||||
{ label: 'Příchozí hovor rozpoznán', time: '0,4 s', done: true },
|
||||
{ label: 'Poptávka založena v CRM', time: '1,1 s', done: true },
|
||||
{ label: 'Nabídka vygenerována', time: '2,8 s', done: true },
|
||||
{ label: 'Předáno obchodníkovi', time: 'právě teď', done: false },
|
||||
];
|
||||
/* ------------------------------------------------------------------ snimek */
|
||||
|
||||
/**
|
||||
* Snimek portalu.
|
||||
*
|
||||
* Vybiha z prave hrany, protoze oriznuty snimek pusobi jako vyrez z neceho
|
||||
* vetsiho, kdezto cely v ramecku pusobi jako obrazek. Data jsou ilustracni,
|
||||
* ale nazvy sloupcu i stavy jsou ty, ktere portal opravdu ma.
|
||||
*/
|
||||
|
||||
const rows = [
|
||||
{
|
||||
event: 'Platba selhala',
|
||||
detail: 'Nepodařilo se strhnout platbu',
|
||||
source: 'Stripe',
|
||||
color: 'bg-[#635bff]',
|
||||
status: 'Automatizováno',
|
||||
tone: 'bg-lime-100 text-lime-800',
|
||||
next: 'Zkusit znovu za hodinu',
|
||||
time: 'před 2 min',
|
||||
},
|
||||
{
|
||||
event: 'Nový požadavek',
|
||||
detail: 'Problém s přihlášením',
|
||||
source: 'Zendesk',
|
||||
color: 'bg-[#03363d]',
|
||||
status: 'Delegováno',
|
||||
tone: 'bg-indigo-100 text-indigo-800',
|
||||
next: 'Přiřazeno Petrovi',
|
||||
time: 'před 12 min',
|
||||
},
|
||||
{
|
||||
event: 'Vysoké vytížení CPU',
|
||||
detail: 'Nad 90 % po 5 minut',
|
||||
source: 'Datadog',
|
||||
color: 'bg-[#632ca6]',
|
||||
status: 'Probíhá',
|
||||
tone: 'bg-sky-100 text-sky-800',
|
||||
next: 'Spustit nápravu',
|
||||
time: 'před 28 min',
|
||||
},
|
||||
{
|
||||
event: 'Nová registrace',
|
||||
detail: 'Zkušební účet vytvořen',
|
||||
source: 'Intercom',
|
||||
color: 'bg-[#1f8ded]',
|
||||
status: 'Automatizováno',
|
||||
tone: 'bg-lime-100 text-lime-800',
|
||||
next: 'Odeslat uvítání',
|
||||
time: 'před 1 hod',
|
||||
},
|
||||
{
|
||||
event: 'Odeslán formulář',
|
||||
detail: 'Poptávka z webu',
|
||||
source: 'HubSpot',
|
||||
color: 'bg-[#ff7a59]',
|
||||
status: 'Otevřené',
|
||||
tone: 'bg-orange-100 text-orange-800',
|
||||
next: 'Kvalifikovat lead',
|
||||
time: 'před 2 hod',
|
||||
},
|
||||
];
|
||||
|
||||
const nav = [
|
||||
'Přehled',
|
||||
'Události',
|
||||
'Automatizace',
|
||||
'Workflow',
|
||||
'Lidé',
|
||||
'Integrace',
|
||||
'Analytika',
|
||||
'Nastavení',
|
||||
];
|
||||
|
||||
function HeroPanel() {
|
||||
return (
|
||||
<div className="animate-rise relative [animation-delay:150ms]">
|
||||
<div className="animate-float glass rounded-2xl p-5 shadow-2xl shadow-brand-500/10">
|
||||
<div className="flex items-center justify-between border-b border-ink-600/60 pb-4">
|
||||
<div className="flex items-center gap-2.5">
|
||||
<span className="grid size-9 place-items-center rounded-xl bg-brand-500/15 text-brand-300">
|
||||
<PhoneCall className="size-4" />
|
||||
</span>
|
||||
<div>
|
||||
<p className="text-sm font-semibold text-white">Voicebot - příjem poptávek</p>
|
||||
<p className="font-mono text-xs text-white/40">AUT-02 · běží</p>
|
||||
/*
|
||||
Snimek musi vybihat z hrany na kazde sirce, ne jen na notebooku.
|
||||
Pevny zaporny okraj ve vw prestal stacit nad 1600 px: kontejner ma strop
|
||||
max-w-6xl (72rem), takze postranni mezera roste a snimek se do ni vesel.
|
||||
Vypocet ji odecte, at je obrazovka jakkoliv siroka.
|
||||
*/
|
||||
<div
|
||||
className="animate-rise relative [animation-delay:150ms]"
|
||||
style={{ marginRight: 'var(--hero-bleed, 0px)' }}
|
||||
>
|
||||
<div className="overflow-hidden rounded-2xl border border-ink-600/70 bg-white shadow-2xl shadow-brand-500/10">
|
||||
<div className="flex min-h-[26rem]">
|
||||
{/* Postranni navigace */}
|
||||
<aside className="hidden w-44 shrink-0 border-r border-slate-200 bg-slate-50/80 p-3 sm:block">
|
||||
<div className="flex items-center gap-2 px-2 pb-4">
|
||||
<LogoMark className="size-5 text-lime-500" />
|
||||
<span className="font-display text-sm font-extrabold text-slate-900">WorkNuke</span>
|
||||
</div>
|
||||
<ul className="space-y-0.5">
|
||||
{nav.map((item, index) => (
|
||||
<li
|
||||
key={item}
|
||||
className={
|
||||
index === 1
|
||||
? 'rounded-lg bg-white px-2.5 py-1.5 text-xs font-semibold text-slate-900 shadow-sm'
|
||||
: 'px-2.5 py-1.5 text-xs text-slate-500'
|
||||
}
|
||||
>
|
||||
{item}
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
</aside>
|
||||
|
||||
{/* Obsah */}
|
||||
<div className="min-w-0 flex-1">
|
||||
<div className="flex items-center justify-between border-b border-slate-200 px-4 py-2.5">
|
||||
<Search className="size-3.5 text-slate-400" />
|
||||
<div className="flex items-center gap-2">
|
||||
<span className="grid size-6 place-items-center rounded-full bg-slate-900 text-[0.6rem] font-bold text-white">
|
||||
JK
|
||||
</span>
|
||||
<div className="hidden leading-tight sm:block">
|
||||
<p className="text-[0.7rem] font-semibold text-slate-900">Jan Koutný</p>
|
||||
<p className="text-[0.62rem] text-slate-400">Acme s.r.o.</p>
|
||||
</div>
|
||||
<ChevronDown className="size-3 text-slate-400" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="p-4">
|
||||
<div className="flex items-center justify-between">
|
||||
<h2 className="font-display text-xl font-extrabold tracking-tight text-slate-900">
|
||||
Události
|
||||
</h2>
|
||||
<span className="inline-flex items-center gap-1.5 rounded-full bg-lime-300 px-3 py-1.5 text-[0.7rem] font-semibold text-slate-900">
|
||||
<Plus className="size-3" />
|
||||
Nová automatizace
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div className="mt-3 flex items-center justify-between gap-3 border-b border-slate-200 pb-2">
|
||||
<ul className="flex gap-4 text-[0.7rem]">
|
||||
{['Vše', 'Otevřené', 'Automatizované', 'Delegované', 'Vyřešené'].map(
|
||||
(tab, index) => (
|
||||
<li
|
||||
key={tab}
|
||||
className={
|
||||
index === 0
|
||||
? 'border-b-2 border-slate-900 pb-2 font-semibold text-slate-900'
|
||||
: 'pb-2 text-slate-400'
|
||||
}
|
||||
>
|
||||
{tab}
|
||||
</li>
|
||||
),
|
||||
)}
|
||||
</ul>
|
||||
<span className="hidden items-center gap-1.5 rounded-lg border border-slate-200 px-2.5 py-1 text-[0.7rem] text-slate-500 lg:inline-flex">
|
||||
<SlidersHorizontal className="size-3" />
|
||||
Filtry
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<table className="mt-1 w-full border-collapse text-left">
|
||||
<thead>
|
||||
<tr className="text-[0.62rem] tracking-wide text-slate-400 uppercase">
|
||||
<th className="py-2 font-medium">Událost</th>
|
||||
<th className="py-2 font-medium">Zdroj</th>
|
||||
<th className="py-2 font-medium">Stav</th>
|
||||
<th className="hidden py-2 font-medium md:table-cell">Další akce</th>
|
||||
<th className="hidden py-2 font-medium lg:table-cell">Čas</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{rows.map((row) => (
|
||||
<tr key={row.event} className="border-t border-slate-100">
|
||||
<td className="py-2.5 pr-3">
|
||||
<p className="text-[0.72rem] font-semibold text-slate-900">{row.event}</p>
|
||||
<p className="text-[0.62rem] text-slate-400">{row.detail}</p>
|
||||
</td>
|
||||
<td className="py-2.5 pr-3">
|
||||
<span className="inline-flex items-center gap-1.5 text-[0.7rem] text-slate-600">
|
||||
<span className={`size-4 rounded ${row.color}`} />
|
||||
{row.source}
|
||||
</span>
|
||||
</td>
|
||||
<td className="py-2.5 pr-3">
|
||||
<span
|
||||
className={`inline-block rounded-full px-2 py-0.5 text-[0.62rem] font-semibold ${row.tone}`}
|
||||
>
|
||||
{row.status}
|
||||
</span>
|
||||
</td>
|
||||
<td className="hidden py-2.5 pr-3 text-[0.7rem] text-slate-600 md:table-cell">
|
||||
{row.next}
|
||||
</td>
|
||||
<td className="hidden py-2.5 text-[0.7rem] whitespace-nowrap text-slate-400 lg:table-cell">
|
||||
{row.time}
|
||||
</td>
|
||||
</tr>
|
||||
))}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
<span className="inline-flex items-center gap-1.5 rounded-full border border-ok-400/35 bg-ok-500/12 px-2.5 py-1 text-xs font-medium text-ok-400">
|
||||
<span className="size-1.5 animate-pulse rounded-full bg-ok-400" />
|
||||
live
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<ol className="mt-4 space-y-3">
|
||||
{steps.map((step) => (
|
||||
<li key={step.label} className="flex items-center gap-3">
|
||||
<span
|
||||
className={
|
||||
step.done
|
||||
? 'grid size-5 shrink-0 place-items-center rounded-full bg-ok-500/20 text-ok-400'
|
||||
: 'grid size-5 shrink-0 place-items-center rounded-full bg-brand-500/20 text-brand-300'
|
||||
}
|
||||
>
|
||||
{step.done ? (
|
||||
<CheckCircle2 className="size-3.5" />
|
||||
) : (
|
||||
<span className="size-1.5 animate-pulse rounded-full bg-brand-300" />
|
||||
)}
|
||||
</span>
|
||||
<span className="flex-1 text-sm text-white/75">{step.label}</span>
|
||||
<span className="font-mono text-xs text-white/35">{step.time}</span>
|
||||
</li>
|
||||
))}
|
||||
</ol>
|
||||
|
||||
<div className="mt-5 grid grid-cols-3 gap-3 border-t border-ink-600/60 pt-4">
|
||||
{[
|
||||
{ value: '137', label: 'hovorů dnes' },
|
||||
{ value: '96,1 %', label: 'úspěšnost' },
|
||||
{ value: '1,2 s', label: 'odezva' },
|
||||
].map((stat) => (
|
||||
<div key={stat.label}>
|
||||
<p className="text-lg font-bold text-white">{stat.value}</p>
|
||||
<p className="text-xs text-white/45">{stat.label}</p>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Male "odlepene" karticky pro hloubku */}
|
||||
<div className="glass animate-float absolute -bottom-6 -left-6 hidden rounded-xl px-4 py-3 shadow-xl [animation-delay:1.2s] sm:block">
|
||||
<p className="text-xs text-white/45">Ušetřeno tento měsíc</p>
|
||||
<p className="text-base font-bold text-white">312 hodin</p>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -40,7 +40,7 @@ export function ProductCard({ product }: { product: Product }) {
|
||||
)}
|
||||
>
|
||||
<div className="flex items-start justify-between gap-3">
|
||||
<span className="grid size-11 place-items-center rounded-xl bg-gradient-to-br from-brand-500/20 to-accent-500/20 text-brand-300">
|
||||
<span className="grid size-11 place-items-center rounded-xl bg-brand-500/15 text-brand-300">
|
||||
<Icon className="size-5" />
|
||||
</span>
|
||||
<div className="text-right">
|
||||
|
||||
@@ -2,13 +2,70 @@ import { Link } from 'react-router-dom';
|
||||
import { brand } from '@/config/brand';
|
||||
import { cn } from '@/lib/cn';
|
||||
|
||||
export function Logo({ className, to = '/' }: { className?: string; to?: string }) {
|
||||
/**
|
||||
* Znacka: plochy znak plus slovni znacka.
|
||||
*
|
||||
* Znak je bomba naklonena k zemi se tremi kridelky a dvema odletovymi carami.
|
||||
* Zamerne **ploche**, ne render: plochy znak snese jakoukoliv velikost, jde
|
||||
* obarvit jednou promennou a nezestarne s modou na 3D.
|
||||
*/
|
||||
|
||||
export function LogoMark({ className }: { className?: string }) {
|
||||
return (
|
||||
<svg
|
||||
viewBox="0 0 32 32"
|
||||
fill="none"
|
||||
aria-hidden="true"
|
||||
className={cn('shrink-0', className)}
|
||||
>
|
||||
{/*
|
||||
Bomba mirici k zemi: nos vlevo dole, kridelka vpravo nahore.
|
||||
Kreslena svisle a otocena o 45 stupnu, aby se geometrie dala cist.
|
||||
*/}
|
||||
<g transform="rotate(45 16 16)">
|
||||
{/* Telo */}
|
||||
<rect x="11.4" y="9" width="9.2" height="15" rx="4.6" fill="currentColor" />
|
||||
{/* Krcek mezi telem a ocasem, aby to nebyla jen pilulka */}
|
||||
<rect x="13.6" y="6.6" width="4.8" height="4" rx="1.2" fill="currentColor" />
|
||||
{/* Tri kridelka */}
|
||||
<path d="M13.6 7.4 8.2 3.6l1.4 6.2 4-1.4z" fill="currentColor" />
|
||||
<path d="M18.4 7.4l5.4-3.8-1.4 6.2-4-1.4z" fill="currentColor" />
|
||||
<path d="M14.6 6.8h2.8l-1.4-5z" fill="currentColor" />
|
||||
</g>
|
||||
{/* Odletove cary u nosu. Rikaji, ze je vypustena, ne ze lezi. */}
|
||||
<path
|
||||
d="M7.4 27.2 4.4 30.2M4.6 24.6H1.4M10.4 30.4v3"
|
||||
stroke="currentColor"
|
||||
strokeWidth="2"
|
||||
strokeLinecap="round"
|
||||
/>
|
||||
</svg>
|
||||
);
|
||||
}
|
||||
|
||||
export function Logo({
|
||||
className,
|
||||
to = '/',
|
||||
withClaim = false,
|
||||
}: {
|
||||
className?: string;
|
||||
to?: string;
|
||||
/** Podtitulek pod slovni znackou. Jen tam, kde je na nej misto. */
|
||||
withClaim?: boolean;
|
||||
}) {
|
||||
return (
|
||||
<Link to={to} className={cn('group inline-flex items-center gap-2.5', className)}>
|
||||
<span className="relative grid size-9 place-items-center rounded-xl bg-gradient-to-br from-brand-400 to-accent-500 shadow-lg shadow-brand-500/25 transition-transform duration-300 group-hover:scale-105">
|
||||
<span className="font-mono text-sm font-bold text-ink-950">A</span>
|
||||
<LogoMark className="size-8 text-brand-400 transition-transform duration-300 group-hover:-translate-y-0.5" />
|
||||
<span className="flex flex-col leading-none">
|
||||
<span className="font-display text-lg font-extrabold tracking-tight text-white">
|
||||
{brand.name}
|
||||
</span>
|
||||
{withClaim && (
|
||||
<span className="mt-1 font-mono text-[0.6rem] tracking-[0.22em] text-white/40 uppercase">
|
||||
{brand.claim}
|
||||
</span>
|
||||
)}
|
||||
</span>
|
||||
<span className="text-lg font-bold tracking-tight text-white">{brand.name}</span>
|
||||
</Link>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -35,10 +35,11 @@ export function Navbar() {
|
||||
)}
|
||||
>
|
||||
<Container>
|
||||
<div className="flex h-18 items-center justify-between gap-4">
|
||||
<div className="flex h-18 items-center gap-8">
|
||||
<Logo />
|
||||
|
||||
<nav className="hidden items-center gap-1 md:flex">
|
||||
{/* Hned vedle loga, ne na stred: predloha ma navigaci pri levem okraji. */}
|
||||
<nav className="hidden flex-1 items-center gap-1 md:flex">
|
||||
{mainNav.map((item) => (
|
||||
<NavLink
|
||||
key={item.to}
|
||||
@@ -46,8 +47,10 @@ export function Navbar() {
|
||||
end={item.to === '/'}
|
||||
className={({ isActive }) =>
|
||||
cn(
|
||||
'rounded-full px-4 py-2 text-sm font-medium transition-colors',
|
||||
isActive ? 'bg-white/8 text-white' : 'text-white/60 hover:text-white',
|
||||
// Bez pilulky za aktivni polozkou. V predloze je navigace
|
||||
// ciste textova a jedina pilulka na liste je primarni akce.
|
||||
'px-3.5 py-2 text-sm font-medium transition-colors',
|
||||
isActive ? 'text-white' : 'text-white/55 hover:text-white',
|
||||
)
|
||||
}
|
||||
>
|
||||
@@ -69,7 +72,7 @@ export function Navbar() {
|
||||
Přihlášení
|
||||
</ButtonLink>
|
||||
<ButtonLink to="/kontakt" size="sm">
|
||||
Nezávazná konzultace
|
||||
Začít zdarma
|
||||
</ButtonLink>
|
||||
</>
|
||||
)}
|
||||
@@ -117,7 +120,7 @@ export function Navbar() {
|
||||
<LogIn className="size-4" />
|
||||
Přihlášení
|
||||
</ButtonLink>
|
||||
<ButtonLink to="/kontakt">Nezávazná konzultace</ButtonLink>
|
||||
<ButtonLink to="/kontakt">Začít zdarma</ButtonLink>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
|
||||
@@ -9,8 +9,12 @@ const base =
|
||||
'inline-flex items-center justify-center gap-2 rounded-full font-semibold transition-all duration-200 disabled:cursor-not-allowed disabled:opacity-55';
|
||||
|
||||
const variants: Record<Variant, string> = {
|
||||
/*
|
||||
* Plna zelena, tmavy text, tvar pilulky. Driv to byl prechod ze dvou barev;
|
||||
* v predloze je tlacitko jednobarevne, protoze prave tim vystupuje z rady.
|
||||
*/
|
||||
primary:
|
||||
'bg-gradient-to-r from-brand-400 to-accent-500 text-ink-950 shadow-lg shadow-brand-500/20 hover:shadow-xl hover:shadow-brand-500/30 hover:brightness-110',
|
||||
'bg-brand-400 text-ink-950 shadow-lg shadow-brand-500/20 hover:bg-brand-300 hover:shadow-xl hover:shadow-brand-500/30',
|
||||
secondary: 'glass text-white hover:border-brand-400/60 hover:bg-ink-700/70',
|
||||
ghost: 'text-white/70 hover:bg-white/5 hover:text-white',
|
||||
};
|
||||
|
||||
@@ -3,12 +3,12 @@
|
||||
* Prejmenovani firmy = zmena tady (viz docs/03-frontend.md).
|
||||
*/
|
||||
export const brand = {
|
||||
name: 'Automia',
|
||||
legalName: 'Automia s.r.o.',
|
||||
claim: 'Automatizace, voiceboti a integrace, které vydrží provoz.',
|
||||
name: 'WorkNuke',
|
||||
legalName: 'WorkNuke s.r.o.',
|
||||
claim: 'Konec ruční práce.',
|
||||
description:
|
||||
'Navrhujeme a provozujeme automatizace firemních procesů, hlasové asistenty a propojení systémů. K tomu dodáváme dashboardy, tickety a incident management pod jednou střechou.',
|
||||
email: 'info@automia.cz',
|
||||
'WorkNuke sbírá události ze všech vašich nástrojů, zautomatizuje, co jde, propojí další kroky a zapojí správné lidi, když je potřeba. Vaše práce prostě plyne.',
|
||||
email: 'info@worknuke.cz',
|
||||
phone: '+420 777 123 456',
|
||||
phoneHref: '+420777123456',
|
||||
address: {
|
||||
|
||||
+54
-33
@@ -5,37 +5,51 @@
|
||||
Dokumentace: docs/05-design-system.md
|
||||
------------------------------------------------------------------- */
|
||||
@theme {
|
||||
/* Podklady - tmave modrociste odstiny */
|
||||
--color-ink-950: #05070f;
|
||||
--color-ink-900: #070b16;
|
||||
--color-ink-850: #0a0f1f;
|
||||
--color-ink-800: #0e1526;
|
||||
--color-ink-700: #16203a;
|
||||
--color-ink-600: #1f2c4d;
|
||||
/*
|
||||
* Podklady - cerna do zelena, ne do modra.
|
||||
* Odstin je odvozeny z #0F1411, aby seda nikde nesklouzavala k modre
|
||||
* a drzela pohromade se zelenym akcentem.
|
||||
*/
|
||||
--color-ink-950: #080b09;
|
||||
--color-ink-900: #0f1411;
|
||||
--color-ink-850: #141a16;
|
||||
--color-ink-800: #1a211c;
|
||||
--color-ink-700: #232c26;
|
||||
--color-ink-600: #2e3a32;
|
||||
|
||||
/* Primarni akcent - cyan */
|
||||
--color-brand-200: #a5f3fc;
|
||||
--color-brand-300: #67e8f9;
|
||||
--color-brand-400: #22d3ee;
|
||||
--color-brand-500: #06b6d4;
|
||||
--color-brand-600: #0891b2;
|
||||
/* Primarni akcent - zelena. Jedina hlasita barva na strance. */
|
||||
--color-brand-200: #dfffae;
|
||||
--color-brand-300: #cdff7a;
|
||||
--color-brand-400: #b7ff3c;
|
||||
--color-brand-500: #9be619;
|
||||
--color-brand-600: #7cbd0f;
|
||||
|
||||
/* Sekundarni akcent - violet */
|
||||
--color-accent-300: #c4b5fd;
|
||||
--color-accent-400: #a78bfa;
|
||||
--color-accent-500: #8b5cf6;
|
||||
--color-accent-600: #7c3aed;
|
||||
/*
|
||||
* Druhy akcent uz neexistuje jako barva, jen jako klic.
|
||||
* Je namireny do teze zelene rady, takze 341 mist, ktera ho pouzivaji,
|
||||
* nemuselo prepisovat - jen prestala byt fialova. Az se ta mista projdou,
|
||||
* klic zmizi uplne.
|
||||
*/
|
||||
--color-accent-300: #cdff7a;
|
||||
--color-accent-400: #b7ff3c;
|
||||
--color-accent-500: #9be619;
|
||||
--color-accent-600: #7cbd0f;
|
||||
|
||||
/* Stavove barvy (tickety, incidenty, healthchecky) */
|
||||
--color-ok-400: #34d399;
|
||||
--color-ok-500: #10b981;
|
||||
/*
|
||||
* Stavove barvy. "V poradku" je nove modrozelena, ne zelena: akcent je
|
||||
* zeleny a dve zelene na jedne obrazovce, kazda o necem jinem, nikdo
|
||||
* nerozlisi.
|
||||
*/
|
||||
--color-ok-400: #2dd4bf;
|
||||
--color-ok-500: #14b8a6;
|
||||
--color-warn-400: #fbbf24;
|
||||
--color-warn-500: #f59e0b;
|
||||
--color-danger-400: #fb7185;
|
||||
--color-danger-500: #f43f5e;
|
||||
|
||||
--font-sans: 'Inter', ui-sans-serif, system-ui, -apple-system, 'Segoe UI', sans-serif;
|
||||
--font-mono: 'JetBrains Mono', ui-monospace, 'SFMono-Regular', monospace;
|
||||
--font-display: 'Archivo', ui-sans-serif, system-ui, -apple-system, sans-serif;
|
||||
--font-sans: 'IBM Plex Sans', ui-sans-serif, system-ui, -apple-system, 'Segoe UI', sans-serif;
|
||||
--font-mono: 'IBM Plex Mono', ui-monospace, 'SFMono-Regular', monospace;
|
||||
|
||||
--radius-card: 1rem;
|
||||
|
||||
@@ -103,12 +117,19 @@
|
||||
text-wrap: pretty;
|
||||
}
|
||||
|
||||
/*
|
||||
* Nadpisy jedou displayovym pismem s tesnym prokladem. Prave to delalo
|
||||
* v predloze ten rozdil: Inter takhle tesne nejde bez trikareni.
|
||||
*/
|
||||
h1,
|
||||
h2,
|
||||
h3,
|
||||
h4 {
|
||||
font-family: var(--font-display);
|
||||
font-weight: 800;
|
||||
text-wrap: balance;
|
||||
letter-spacing: -0.02em;
|
||||
letter-spacing: -0.035em;
|
||||
line-height: 1.04;
|
||||
}
|
||||
|
||||
::selection {
|
||||
@@ -160,16 +181,16 @@
|
||||
backdrop-filter: blur(14px);
|
||||
}
|
||||
|
||||
/* Gradientni text pro zvyrazneni slov v nadpisech */
|
||||
/*
|
||||
* Zvyraznene slovo v nadpisu.
|
||||
*
|
||||
* Driv to byl gradient pres tri barvy. Ted je to plna zelena: v predloze je
|
||||
* nadpis dvoubarevny, ne prechodovy, a gradient se na malych velikostech
|
||||
* rozpadal a hur cetl. Nazev utility zustava, aby se osm mist nemuselo
|
||||
* prepisovat.
|
||||
*/
|
||||
@utility text-gradient {
|
||||
background-image: linear-gradient(
|
||||
100deg,
|
||||
var(--color-brand-300),
|
||||
var(--color-brand-400) 40%,
|
||||
var(--color-accent-400)
|
||||
);
|
||||
background-clip: text;
|
||||
color: transparent;
|
||||
color: var(--color-brand-400);
|
||||
}
|
||||
|
||||
/* Jemna mrizka na pozadi sekci */
|
||||
|
||||
Reference in New Issue
Block a user