feat: visual redesign — gradient mesh, per-pillar accents, manifest slogans
- Gradient palette: coral/amber (warm) ↔ indigo/violet/teal (cool) - Hero: radial blob mesh bg, geometric SVG line-art, gradient on 'AI' in H1, gradient primary CTA, per-pillar accent top borders, dot-grid accent - Manifest strip 'AI dla ludzi, przez ludzi' between hero and problem - HowWeWork: per-card accents, icon bg pills, human-tagline note - Offers: gradient top bar per pillar, accent icon containers, abstract SVGs - Process: gradient numbered circles (warm→cool progression) - Contact: 'zawsze rozmawiasz z człowiekiem' guarantee badge, gradient email - Layout: grad-main/grad-cta CSS vars, gradient section hairlines, gradient btn-primary/btn-outline, .grad-text utility
This commit is contained in:
parent
3f5dd536d1
commit
b7b133647c
|
|
@ -15,7 +15,20 @@ const contactId = locale === 'en' ? 'contact' : 'kontakt';
|
|||
{locale === 'en' ? 'Contact' : 'Kontakt'}
|
||||
</span>
|
||||
<h2 id="contact-heading">{tr.contact.h2}</h2>
|
||||
<p>{tr.contact.subtitle}</p>
|
||||
<p class="contact-subtitle">{tr.contact.subtitle}</p>
|
||||
|
||||
<!-- "Zawsze rozmawiasz z człowiekiem" guarantee -->
|
||||
<div class="human-note" role="note">
|
||||
<span class="human-note-icon" aria-hidden="true">
|
||||
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor"
|
||||
stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round">
|
||||
<circle cx="12" cy="8" r="4"/>
|
||||
<path d="M4 20a8 8 0 0 1 16 0"/>
|
||||
</svg>
|
||||
</span>
|
||||
<span>{tr.contact.human_note}</span>
|
||||
</div>
|
||||
|
||||
<a href={`mailto:${tr.contact.email}`} class="contact-email">
|
||||
{tr.contact.email}
|
||||
</a>
|
||||
|
|
@ -30,35 +43,15 @@ const contactId = locale === 'en' ? 'contact' : 'kontakt';
|
|||
>
|
||||
<div class="field">
|
||||
<label for="name">{tr.contact.field_name}</label>
|
||||
<input
|
||||
type="text"
|
||||
id="name"
|
||||
name="name"
|
||||
autocomplete="name"
|
||||
required
|
||||
aria-required="true"
|
||||
/>
|
||||
<input type="text" id="name" name="name" autocomplete="name" required aria-required="true" />
|
||||
</div>
|
||||
<div class="field">
|
||||
<label for="email">{tr.contact.field_email}</label>
|
||||
<input
|
||||
type="email"
|
||||
id="email"
|
||||
name="email"
|
||||
autocomplete="email"
|
||||
required
|
||||
aria-required="true"
|
||||
/>
|
||||
<input type="email" id="email" name="email" autocomplete="email" required aria-required="true" />
|
||||
</div>
|
||||
<div class="field">
|
||||
<label for="message">{tr.contact.field_message}</label>
|
||||
<textarea
|
||||
id="message"
|
||||
name="message"
|
||||
rows="5"
|
||||
required
|
||||
aria-required="true"
|
||||
></textarea>
|
||||
<textarea id="message" name="message" rows="5" required aria-required="true"></textarea>
|
||||
</div>
|
||||
<button type="submit" class="btn-primary submit-btn">
|
||||
{tr.contact.button}
|
||||
|
|
@ -74,9 +67,9 @@ const contactId = locale === 'en' ? 'contact' : 'kontakt';
|
|||
form?.addEventListener('submit', (e) => {
|
||||
e.preventDefault();
|
||||
const fd = new FormData(form);
|
||||
const name = fd.get('name') || '';
|
||||
const emailVal = fd.get('email') || '';
|
||||
const message = fd.get('message') || '';
|
||||
const name = fd.get('name') || '';
|
||||
const emailVal = fd.get('email') || '';
|
||||
const message = fd.get('message') || '';
|
||||
const subject = locale === 'en'
|
||||
? `Message from ${name} — humanAI`
|
||||
: `Wiadomość od ${name} — humanAI`;
|
||||
|
|
@ -88,10 +81,7 @@ const contactId = locale === 'en' ? 'contact' : 'kontakt';
|
|||
</script>
|
||||
|
||||
<style>
|
||||
.contact-section {
|
||||
background: var(--color-surface);
|
||||
border-top: 1px solid var(--color-border);
|
||||
}
|
||||
.contact-section { background: var(--color-surface); }
|
||||
|
||||
.contact-inner {
|
||||
display: grid;
|
||||
|
|
@ -99,52 +89,51 @@ const contactId = locale === 'en' ? 'contact' : 'kontakt';
|
|||
gap: 3rem;
|
||||
align-items: start;
|
||||
}
|
||||
|
||||
@media (min-width: 768px) {
|
||||
.contact-inner {
|
||||
grid-template-columns: 1fr 1.2fr;
|
||||
gap: 5rem;
|
||||
}
|
||||
.contact-inner { grid-template-columns: 1fr 1.2fr; gap: 5rem; }
|
||||
}
|
||||
|
||||
.contact-intro h2 {
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
.contact-intro p {
|
||||
.contact-subtitle {
|
||||
max-width: 38ch;
|
||||
margin-bottom: 1.5rem;
|
||||
}
|
||||
|
||||
/* Human guarantee badge */
|
||||
.human-note {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 0.6rem;
|
||||
padding: 0.6rem 1rem;
|
||||
background: linear-gradient(135deg, rgba(123,57,235,.07), rgba(11,150,136,.06));
|
||||
border: 1px solid rgba(123,57,235,.18);
|
||||
border-radius: 999px;
|
||||
margin-bottom: 1.5rem;
|
||||
font-size: 0.85rem;
|
||||
font-weight: 500;
|
||||
color: var(--c-violet);
|
||||
max-width: none;
|
||||
}
|
||||
.human-note-icon { color: var(--c-violet); line-height: 0; flex-shrink: 0; }
|
||||
|
||||
.contact-email {
|
||||
display: inline-block;
|
||||
font-size: 0.9rem;
|
||||
font-weight: 500;
|
||||
color: var(--color-accent);
|
||||
background: var(--grad-cta);
|
||||
-webkit-background-clip: text;
|
||||
-webkit-text-fill-color: transparent;
|
||||
background-clip: text;
|
||||
color: transparent;
|
||||
text-decoration: none;
|
||||
}
|
||||
.contact-email:hover { text-decoration: underline; text-decoration-color: var(--c-coral); }
|
||||
|
||||
.contact-email:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
/* Form */
|
||||
.contact-form { display: flex; flex-direction: column; gap: 1.25rem; }
|
||||
|
||||
.contact-form {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 1.25rem;
|
||||
}
|
||||
.field { display: flex; flex-direction: column; gap: 0.4rem; }
|
||||
|
||||
.field {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 0.4rem;
|
||||
}
|
||||
|
||||
label {
|
||||
font-size: 0.88rem;
|
||||
font-weight: 500;
|
||||
color: var(--color-text);
|
||||
}
|
||||
label { font-size: 0.88rem; font-weight: 500; color: var(--color-text); }
|
||||
|
||||
input, textarea {
|
||||
font-family: var(--font-sans);
|
||||
|
|
@ -155,22 +144,16 @@ const contactId = locale === 'en' ? 'contact' : 'kontakt';
|
|||
background: var(--color-bg);
|
||||
color: var(--color-text);
|
||||
width: 100%;
|
||||
transition: border-color 0.18s;
|
||||
transition: border-color 0.18s, box-shadow 0.18s;
|
||||
-webkit-appearance: none;
|
||||
appearance: none;
|
||||
}
|
||||
|
||||
input:focus, textarea:focus {
|
||||
outline: none;
|
||||
border-color: var(--color-accent);
|
||||
border-color: var(--c-violet);
|
||||
box-shadow: 0 0 0 3px rgba(123,57,235,.1);
|
||||
}
|
||||
textarea { resize: vertical; min-height: 120px; }
|
||||
|
||||
textarea {
|
||||
resize: vertical;
|
||||
min-height: 120px;
|
||||
}
|
||||
|
||||
.submit-btn {
|
||||
align-self: flex-start;
|
||||
}
|
||||
.submit-btn { align-self: flex-start; }
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -6,47 +6,117 @@ interface Props { locale: Locale }
|
|||
const { locale } = Astro.props;
|
||||
const tr = t(locale);
|
||||
const contactAnchor = locale === 'en' ? '#contact' : '#kontakt';
|
||||
const offersAnchor = locale === 'en' ? '#offers' : '#oferty';
|
||||
|
||||
const pillarAccents: Record<string, string> = {
|
||||
home: '#e05c40',
|
||||
business: '#3d35c0',
|
||||
industry: '#0b9688',
|
||||
med: '#7b39eb',
|
||||
};
|
||||
---
|
||||
|
||||
<section class="hero" id="home" aria-labelledby="hero-heading">
|
||||
|
||||
<!-- Gradient mesh blobs -->
|
||||
<div class="hero-mesh" aria-hidden="true">
|
||||
<div class="blob b1"></div>
|
||||
<div class="blob b2"></div>
|
||||
<div class="blob b3"></div>
|
||||
<div class="blob b4"></div>
|
||||
</div>
|
||||
|
||||
<!-- Dot grid accent -->
|
||||
<div class="hero-dots" aria-hidden="true"></div>
|
||||
|
||||
<!-- Geometric SVG line-art -->
|
||||
<svg class="hero-geo" aria-hidden="true" viewBox="0 0 480 380" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<defs>
|
||||
<linearGradient id="geo-g" x1="0%" y1="0%" x2="100%" y2="100%">
|
||||
<stop offset="0%" stop-color="#e05c40" stop-opacity="0.55"/>
|
||||
<stop offset="50%" stop-color="#7b39eb" stop-opacity="0.45"/>
|
||||
<stop offset="100%" stop-color="#0b9688" stop-opacity="0.35"/>
|
||||
</linearGradient>
|
||||
</defs>
|
||||
<!-- Concentric rings -->
|
||||
<circle cx="390" cy="90" r="200" stroke="url(#geo-g)" stroke-width="0.7" />
|
||||
<circle cx="390" cy="90" r="135" stroke="url(#geo-g)" stroke-width="0.55"/>
|
||||
<circle cx="390" cy="90" r="68" stroke="url(#geo-g)" stroke-width="0.45"/>
|
||||
<!-- Hub node -->
|
||||
<circle cx="390" cy="90" r="4.5" fill="url(#geo-g)"/>
|
||||
<!-- Satellite nodes -->
|
||||
<circle cx="220" cy="200" r="3.5" fill="url(#geo-g)" opacity="0.65"/>
|
||||
<circle cx="430" cy="270" r="2.5" fill="url(#geo-g)" opacity="0.55"/>
|
||||
<circle cx="150" cy="68" r="2" fill="url(#geo-g)" opacity="0.45"/>
|
||||
<circle cx="460" cy="155" r="2" fill="url(#geo-g)" opacity="0.45"/>
|
||||
<!-- Connecting spokes -->
|
||||
<line x1="390" y1="90" x2="220" y2="200" stroke="url(#geo-g)" stroke-width="0.55" opacity="0.5"/>
|
||||
<line x1="390" y1="90" x2="430" y2="270" stroke="url(#geo-g)" stroke-width="0.5" opacity="0.45"/>
|
||||
<line x1="390" y1="90" x2="150" y2="68" stroke="url(#geo-g)" stroke-width="0.45" opacity="0.4"/>
|
||||
<line x1="390" y1="90" x2="460" y2="155" stroke="url(#geo-g)" stroke-width="0.45" opacity="0.4"/>
|
||||
<line x1="220" y1="200" x2="430" y2="270" stroke="url(#geo-g)" stroke-width="0.4" opacity="0.3"/>
|
||||
</svg>
|
||||
|
||||
<div class="container hero-inner">
|
||||
<div class="hero-content">
|
||||
<span class="hero-badge" role="text">{tr.hero.badge}</span>
|
||||
<h1 id="hero-heading">{tr.hero.h1}</h1>
|
||||
|
||||
<h1 id="hero-heading">
|
||||
{tr.hero.h1_base}<span class="grad-text">{tr.hero.h1_highlight}</span>
|
||||
</h1>
|
||||
|
||||
<p class="hero-sub">{tr.hero.subtitle}</p>
|
||||
|
||||
<div class="hero-actions">
|
||||
<a href={contactAnchor} class="btn-primary">{tr.hero.cta_primary}</a>
|
||||
<a href={locale === 'en' ? '#offers' : '#oferty'} class="btn-outline">{tr.hero.cta_secondary}</a>
|
||||
<a href={offersAnchor} class="btn-outline">{tr.hero.cta_secondary}</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="pillars-row" role="list" aria-label={locale === 'en' ? 'Our four focus areas' : 'Cztery obszary zastosowań'}>
|
||||
<!-- Pillar tiles -->
|
||||
<div class="pillars-row" role="list"
|
||||
aria-label={locale === 'en' ? 'Our four focus areas' : 'Cztery obszary zastosowań'}>
|
||||
{(['home','business','industry','med'] as const).map((key) => (
|
||||
<a
|
||||
href={locale === 'en' ? `#${key}` : `#${key}`}
|
||||
href={`#${key}`}
|
||||
class={`pillar pillar-${key}`}
|
||||
role="listitem"
|
||||
style={`--pa: ${pillarAccents[key]}`}
|
||||
aria-label={`${tr.pillars[key].title} — ${tr.pillars[key].tagline}`}
|
||||
>
|
||||
<span class="pillar-icon" aria-hidden="true">
|
||||
{key === 'home' && (
|
||||
<svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round">
|
||||
<path d="M3 9l9-7 9 7v11a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z"/><polyline points="9 22 9 12 15 12 15 22"/>
|
||||
<svg width="24" height="24" viewBox="0 0 48 48" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round">
|
||||
<path d="M6 20L24 6l18 14v22H6V20Z"/>
|
||||
<circle cx="24" cy="28" r="3" fill="currentColor" opacity="0.35"/>
|
||||
<circle cx="16" cy="36" r="2" fill="currentColor" opacity="0.25"/>
|
||||
<circle cx="32" cy="36" r="2" fill="currentColor" opacity="0.25"/>
|
||||
<line x1="24" y1="28" x2="16" y2="36" stroke-width="1.1" opacity="0.5"/>
|
||||
<line x1="24" y1="28" x2="32" y2="36" stroke-width="1.1" opacity="0.5"/>
|
||||
</svg>
|
||||
)}
|
||||
{key === 'business' && (
|
||||
<svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round">
|
||||
<rect x="2" y="7" width="20" height="14" rx="2"/><path d="M16 7V5a2 2 0 0 0-2-2h-4a2 2 0 0 0-2 2v2"/>
|
||||
<svg width="24" height="24" viewBox="0 0 48 48" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round">
|
||||
<circle cx="24" cy="12" r="5"/>
|
||||
<circle cx="10" cy="36" r="5"/>
|
||||
<circle cx="38" cy="36" r="5"/>
|
||||
<line x1="24" y1="17" x2="10" y2="31"/>
|
||||
<line x1="24" y1="17" x2="38" y2="31"/>
|
||||
<line x1="15" y1="36" x2="33" y2="36"/>
|
||||
</svg>
|
||||
)}
|
||||
{key === 'industry' && (
|
||||
<svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round">
|
||||
<path d="M2 20h20M4 20V10l5-5 5 5V20M14 20V14h6v6"/><line x1="9" y1="20" x2="9" y2="14"/><line x1="12" y1="20" x2="12" y2="14"/>
|
||||
<svg width="24" height="24" viewBox="0 0 48 48" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round">
|
||||
<polyline points="4,30 10,30 15,20 20,38 26,8 31,30 36,24 42,30"/>
|
||||
<line x1="4" y1="38" x2="44" y2="38" stroke-width="1"/>
|
||||
</svg>
|
||||
)}
|
||||
{key === 'med' && (
|
||||
<svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round">
|
||||
<path d="M22 12h-4l-3 9L9 3l-3 9H2"/>
|
||||
<svg width="24" height="24" viewBox="0 0 48 48" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round">
|
||||
<rect x="8" y="10" width="22" height="30" rx="3"/>
|
||||
<line x1="14" y1="22" x2="24" y2="22"/>
|
||||
<line x1="14" y1="28" x2="20" y2="28"/>
|
||||
<polyline points="28,28 33,18 38,34 42,28"/>
|
||||
</svg>
|
||||
)}
|
||||
</span>
|
||||
|
|
@ -56,23 +126,94 @@ const contactAnchor = locale === 'en' ? '#contact' : '#kontakt';
|
|||
))}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Manifest strip -->
|
||||
<div class="manifest-strip" role="note" aria-label={tr.manifest.slogan}>
|
||||
<div class="container manifest-inner">
|
||||
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor"
|
||||
stroke-width="1.5" aria-hidden="true" class="manifest-icon">
|
||||
<path d="M5 12h14M12 5l7 7-7 7"/>
|
||||
</svg>
|
||||
<p class="manifest-text">{tr.manifest.slogan}</p>
|
||||
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor"
|
||||
stroke-width="1.5" aria-hidden="true" class="manifest-icon">
|
||||
<path d="M5 12h14M12 5l7 7-7 7"/>
|
||||
</svg>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</section>
|
||||
|
||||
<style>
|
||||
/* ── Container ─────────────────────────────────────────────────────── */
|
||||
.hero {
|
||||
padding-block: clamp(4rem, 10vw, 8rem) clamp(2rem, 5vw, 4rem);
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
background: var(--color-surface);
|
||||
padding-block: clamp(4rem, 10vw, 8rem) 0;
|
||||
}
|
||||
|
||||
.hero-inner {
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 3.5rem;
|
||||
padding-bottom: clamp(2.5rem, 5vw, 4rem);
|
||||
}
|
||||
|
||||
.hero-content {
|
||||
max-width: 680px;
|
||||
/* ── Gradient mesh ──────────────────────────────────────────────────── */
|
||||
.hero-mesh { position: absolute; inset: 0; pointer-events: none; }
|
||||
|
||||
.blob {
|
||||
position: absolute;
|
||||
border-radius: 50%;
|
||||
filter: blur(72px);
|
||||
}
|
||||
.b1 {
|
||||
width: 580px; height: 440px;
|
||||
background: radial-gradient(ellipse, rgba(224,92,64,.22) 0%, transparent 70%);
|
||||
top: -160px; left: -200px;
|
||||
}
|
||||
.b2 {
|
||||
width: 500px; height: 400px;
|
||||
background: radial-gradient(ellipse, rgba(123,57,235,.18) 0%, transparent 70%);
|
||||
top: -120px; right: -140px;
|
||||
}
|
||||
.b3 {
|
||||
width: 440px; height: 380px;
|
||||
background: radial-gradient(ellipse, rgba(11,150,136,.14) 0%, transparent 70%);
|
||||
bottom: 60px; right: 10%;
|
||||
}
|
||||
.b4 {
|
||||
width: 340px; height: 300px;
|
||||
background: radial-gradient(ellipse, rgba(240,146,74,.12) 0%, transparent 70%);
|
||||
bottom: 0; left: 25%;
|
||||
}
|
||||
|
||||
/* ── Dot pattern ────────────────────────────────────────────────────── */
|
||||
.hero-dots {
|
||||
position: absolute;
|
||||
bottom: 100px; left: 0;
|
||||
width: 240px; height: 200px;
|
||||
background-image:
|
||||
radial-gradient(circle, rgba(61,53,192,.10) 1.5px, transparent 1.5px);
|
||||
background-size: 22px 22px;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
/* ── Geometric line-art SVG ─────────────────────────────────────────── */
|
||||
.hero-geo {
|
||||
position: absolute;
|
||||
top: -30px; right: -60px;
|
||||
width: clamp(260px, 42vw, 480px);
|
||||
height: auto;
|
||||
pointer-events: none;
|
||||
opacity: 0.6;
|
||||
}
|
||||
|
||||
/* ── Content ────────────────────────────────────────────────────────── */
|
||||
.hero-content { max-width: 680px; position: relative; z-index: 1; }
|
||||
|
||||
.hero-badge {
|
||||
display: inline-block;
|
||||
|
|
@ -82,20 +223,28 @@ const contactAnchor = locale === 'en' ? '#contact' : '#kontakt';
|
|||
background: var(--color-surface-alt);
|
||||
border: 1px solid var(--color-border);
|
||||
color: var(--color-text-muted);
|
||||
padding: 0.3rem 0.8rem;
|
||||
padding: 0.3rem 0.85rem;
|
||||
border-radius: 999px;
|
||||
margin-bottom: 1.25rem;
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-size: clamp(2.25rem, 7vw, 4rem);
|
||||
font-size: clamp(2.4rem, 7.5vw, 4.2rem);
|
||||
font-weight: 500;
|
||||
line-height: 1.1;
|
||||
letter-spacing: -0.025em;
|
||||
letter-spacing: -0.03em;
|
||||
margin-bottom: 1.25rem;
|
||||
color: var(--color-text);
|
||||
}
|
||||
|
||||
/* gradient on the "AI" highlight word */
|
||||
h1 .grad-text {
|
||||
font-size: inherit;
|
||||
font-weight: inherit;
|
||||
letter-spacing: inherit;
|
||||
line-height: inherit;
|
||||
}
|
||||
|
||||
.hero-sub {
|
||||
font-size: clamp(1rem, 2.5vw, 1.2rem);
|
||||
color: var(--color-text-muted);
|
||||
|
|
@ -104,16 +253,15 @@ const contactAnchor = locale === 'en' ? '#contact' : '#kontakt';
|
|||
line-height: 1.6;
|
||||
}
|
||||
|
||||
.hero-actions {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 0.75rem;
|
||||
}
|
||||
.hero-actions { display: flex; flex-wrap: wrap; gap: 0.75rem; }
|
||||
|
||||
/* ── Pillar tiles ───────────────────────────────────────────────────── */
|
||||
.pillars-row {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
|
||||
grid-template-columns: repeat(auto-fit, minmax(175px, 1fr));
|
||||
gap: 1rem;
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.pillar {
|
||||
|
|
@ -121,32 +269,60 @@ const contactAnchor = locale === 'en' ? '#contact' : '#kontakt';
|
|||
flex-direction: column;
|
||||
gap: 0.5rem;
|
||||
padding: 1.25rem;
|
||||
background: var(--color-bg);
|
||||
background: rgba(255,255,255,0.7);
|
||||
backdrop-filter: blur(6px);
|
||||
border: 1px solid var(--color-border);
|
||||
border-top: 2.5px solid var(--pa);
|
||||
border-radius: var(--radius-lg);
|
||||
text-decoration: none;
|
||||
color: var(--color-text);
|
||||
transition: border-color 0.18s, box-shadow 0.18s;
|
||||
transition: box-shadow 0.2s, transform 0.18s;
|
||||
}
|
||||
|
||||
.pillar:hover {
|
||||
border-color: var(--color-accent);
|
||||
box-shadow: 0 2px 12px rgba(26, 61, 46, 0.07);
|
||||
box-shadow: 0 4px 20px rgba(0,0,0,0.07);
|
||||
transform: translateY(-2px);
|
||||
}
|
||||
|
||||
.pillar-icon {
|
||||
color: var(--color-accent);
|
||||
line-height: 0;
|
||||
.pillar-icon { color: var(--pa); line-height: 0; }
|
||||
.pillar-title { font-weight: 500; font-size: 0.95rem; }
|
||||
.pillar-tagline { font-size: 0.82rem; color: var(--color-text-muted); line-height: 1.4; }
|
||||
|
||||
/* ── Manifest strip ─────────────────────────────────────────────────── */
|
||||
.manifest-strip {
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
padding: 1.4rem 0;
|
||||
background: linear-gradient(135deg,
|
||||
rgba(224,92,64,.06) 0%,
|
||||
rgba(123,57,235,.07) 50%,
|
||||
rgba(11,150,136,.05) 100%
|
||||
);
|
||||
border-top: 1px solid rgba(123,57,235,.15);
|
||||
}
|
||||
|
||||
.pillar-title {
|
||||
.manifest-inner {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 1.25rem;
|
||||
}
|
||||
|
||||
.manifest-text {
|
||||
font-size: clamp(0.95rem, 2.2vw, 1.15rem);
|
||||
font-weight: 500;
|
||||
font-size: 0.95rem;
|
||||
background: var(--grad-main);
|
||||
-webkit-background-clip: text;
|
||||
-webkit-text-fill-color: transparent;
|
||||
background-clip: text;
|
||||
color: transparent;
|
||||
max-width: none;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.pillar-tagline {
|
||||
font-size: 0.82rem;
|
||||
color: var(--color-text-muted);
|
||||
line-height: 1.4;
|
||||
.manifest-icon {
|
||||
color: var(--c-violet);
|
||||
opacity: 0.5;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -10,26 +10,38 @@ const features = [
|
|||
{
|
||||
key: 'local',
|
||||
data: tr.how.local,
|
||||
icon: `<svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round">
|
||||
<rect x="2" y="2" width="20" height="8" rx="2"/><rect x="2" y="14" width="20" height="8" rx="2"/>
|
||||
<line x1="6" y1="6" x2="6.01" y2="6"/><line x1="6" y1="18" x2="6.01" y2="18"/>
|
||||
accent: '#0b9688',
|
||||
icon: `<svg width="24" height="24" viewBox="0 0 48 48" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round">
|
||||
<rect x="4" y="6" width="40" height="16" rx="3"/>
|
||||
<rect x="4" y="26" width="40" height="16" rx="3"/>
|
||||
<circle cx="12" cy="14" r="2.5" fill="currentColor" opacity="0.5"/>
|
||||
<circle cx="12" cy="34" r="2.5" fill="currentColor" opacity="0.5"/>
|
||||
<line x1="20" y1="14" x2="36" y2="14" stroke-width="1.2" opacity="0.4"/>
|
||||
<line x1="20" y1="34" x2="30" y2="34" stroke-width="1.2" opacity="0.4"/>
|
||||
</svg>`,
|
||||
},
|
||||
{
|
||||
key: 'integrations',
|
||||
data: tr.how.integrations,
|
||||
icon: `<svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round">
|
||||
<circle cx="18" cy="5" r="3"/><circle cx="6" cy="12" r="3"/><circle cx="18" cy="19" r="3"/>
|
||||
<line x1="8.59" y1="13.51" x2="15.42" y2="17.49"/><line x1="15.41" y1="6.51" x2="8.59" y2="10.49"/>
|
||||
accent: '#3d35c0',
|
||||
icon: `<svg width="24" height="24" viewBox="0 0 48 48" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round">
|
||||
<circle cx="24" cy="10" r="5"/>
|
||||
<circle cx="8" cy="38" r="5"/>
|
||||
<circle cx="40" cy="38" r="5"/>
|
||||
<line x1="24" y1="15" x2="8" y2="33"/>
|
||||
<line x1="24" y1="15" x2="40" y2="33"/>
|
||||
<line x1="13" y1="38" x2="35" y2="38"/>
|
||||
</svg>`,
|
||||
},
|
||||
{
|
||||
key: 'human',
|
||||
data: tr.how.human,
|
||||
icon: `<svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round">
|
||||
<path d="M17 21v-2a4 4 0 0 0-4-4H5a4 4 0 0 0-4 4v2"/>
|
||||
<circle cx="9" cy="7" r="4"/>
|
||||
<path d="M23 21v-2a4 4 0 0 0-3-3.87"/><path d="M16 3.13a4 4 0 0 1 0 7.75"/>
|
||||
accent: '#7b39eb',
|
||||
icon: `<svg width="24" height="24" viewBox="0 0 48 48" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round">
|
||||
<circle cx="18" cy="14" r="7"/>
|
||||
<path d="M4 42v-3a10 10 0 0 1 10-10h8a10 10 0 0 1 10 10v3"/>
|
||||
<path d="M32 8a7 7 0 0 1 0 12"/>
|
||||
<path d="M44 42v-2a10 10 0 0 0-6-9.1"/>
|
||||
</svg>`,
|
||||
},
|
||||
] as const;
|
||||
|
|
@ -43,11 +55,23 @@ const features = [
|
|||
<h2 id="how-heading">{tr.how.h2}</h2>
|
||||
|
||||
<div class="features-grid" role="list">
|
||||
{features.map(({ data, icon }) => (
|
||||
<article class="feature-card" role="listitem">
|
||||
<div class="feature-icon" aria-hidden="true" set:html={icon} />
|
||||
{features.map(({ key, data, accent, icon }) => (
|
||||
<article
|
||||
class={`feature-card ${key === 'human' ? 'feature-human' : ''}`}
|
||||
role="listitem"
|
||||
style={`--fa: ${accent}`}
|
||||
>
|
||||
<div class="feature-icon-wrap">
|
||||
<div class="feature-icon" aria-hidden="true" set:html={icon} />
|
||||
</div>
|
||||
<h3>{data.title}</h3>
|
||||
<p>{data.body}</p>
|
||||
{key === 'human' && (
|
||||
<p class="human-tagline" role="note">
|
||||
<span class="tagline-dash" aria-hidden="true">—</span>
|
||||
{tr.how.human.tagline}
|
||||
</p>
|
||||
)}
|
||||
</article>
|
||||
))}
|
||||
</div>
|
||||
|
|
@ -55,48 +79,62 @@ const features = [
|
|||
</section>
|
||||
|
||||
<style>
|
||||
.how-section {
|
||||
background: var(--color-surface);
|
||||
}
|
||||
.how-section { background: var(--color-surface); }
|
||||
|
||||
.how-section h2 {
|
||||
max-width: 40ch;
|
||||
margin-bottom: 3rem;
|
||||
}
|
||||
.how-section h2 { max-width: 40ch; margin-bottom: 3rem; }
|
||||
|
||||
.features-grid {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr;
|
||||
gap: 1.5rem;
|
||||
}
|
||||
|
||||
@media (min-width: 640px) {
|
||||
.features-grid {
|
||||
grid-template-columns: repeat(3, 1fr);
|
||||
}
|
||||
.features-grid { grid-template-columns: repeat(3, 1fr); }
|
||||
}
|
||||
|
||||
.feature-card {
|
||||
padding: 1.75rem;
|
||||
background: var(--color-bg);
|
||||
border: 1px solid var(--color-border);
|
||||
border-top: 2.5px solid var(--fa);
|
||||
border-radius: var(--radius-lg);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 0;
|
||||
}
|
||||
|
||||
.feature-icon {
|
||||
color: var(--color-accent);
|
||||
margin-bottom: 1rem;
|
||||
line-height: 0;
|
||||
.feature-human {
|
||||
background: linear-gradient(
|
||||
160deg,
|
||||
rgba(123,57,235,.04) 0%,
|
||||
rgba(255,255,255,0) 60%
|
||||
);
|
||||
}
|
||||
|
||||
.feature-card h3 {
|
||||
margin-bottom: 0.6rem;
|
||||
font-size: 1rem;
|
||||
.feature-icon-wrap {
|
||||
width: 48px; height: 48px;
|
||||
border-radius: var(--radius);
|
||||
background: color-mix(in srgb, var(--fa) 10%, transparent);
|
||||
display: flex; align-items: center; justify-content: center;
|
||||
margin-bottom: 1.1rem;
|
||||
}
|
||||
|
||||
.feature-card p {
|
||||
font-size: 0.9rem;
|
||||
line-height: 1.6;
|
||||
max-width: 32ch;
|
||||
.feature-icon { color: var(--fa); line-height: 0; }
|
||||
|
||||
.feature-card h3 { margin-bottom: 0.55rem; font-size: 1rem; }
|
||||
.feature-card > p { font-size: 0.9rem; line-height: 1.6; max-width: 32ch; }
|
||||
|
||||
.human-tagline {
|
||||
margin-top: 1rem;
|
||||
padding-top: 1rem;
|
||||
border-top: 1px solid var(--color-border);
|
||||
font-size: 0.82rem;
|
||||
font-weight: 500;
|
||||
color: var(--c-violet) !important;
|
||||
max-width: none;
|
||||
display: flex;
|
||||
gap: 0.4rem;
|
||||
align-items: baseline;
|
||||
}
|
||||
.tagline-dash { opacity: 0.5; }
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -8,24 +8,53 @@ const tr = t(locale);
|
|||
|
||||
const offerKeys = ['home', 'business', 'industry', 'med'] as const;
|
||||
|
||||
const icons: Record<typeof offerKeys[number], string> = {
|
||||
home: `<svg width="28" height="28" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round">
|
||||
<path d="M3 9l9-7 9 7v11a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z"/><polyline points="9 22 9 12 15 12 15 22"/>
|
||||
</svg>`,
|
||||
business: `<svg width="28" height="28" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round">
|
||||
<rect x="2" y="7" width="20" height="14" rx="2"/><path d="M16 7V5a2 2 0 0 0-2-2h-4a2 2 0 0 0-2 2v2"/>
|
||||
<line x1="12" y1="12" x2="12" y2="17"/><line x1="9.5" y1="14.5" x2="14.5" y2="14.5"/>
|
||||
</svg>`,
|
||||
industry: `<svg width="28" height="28" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round">
|
||||
<polyline points="22 12 18 12 15 21 9 3 6 12 2 12"/>
|
||||
</svg>`,
|
||||
med: `<svg width="28" height="28" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round">
|
||||
<path d="M22 12h-4l-3 9L9 3l-3 9H2"/>
|
||||
</svg>`,
|
||||
const meta: Record<typeof offerKeys[number], { accent: string; icon: string }> = {
|
||||
home: {
|
||||
accent: '#e05c40',
|
||||
icon: `<svg width="32" height="32" viewBox="0 0 48 48" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round">
|
||||
<path d="M6 20L24 6l18 14v22H6V20Z"/>
|
||||
<circle cx="24" cy="29" r="3.5" fill="currentColor" opacity="0.3"/>
|
||||
<circle cx="15" cy="37" r="2.5" fill="currentColor" opacity="0.2"/>
|
||||
<circle cx="33" cy="37" r="2.5" fill="currentColor" opacity="0.2"/>
|
||||
<line x1="24" y1="29" x2="15" y2="37" stroke-width="1.1" opacity="0.45"/>
|
||||
<line x1="24" y1="29" x2="33" y2="37" stroke-width="1.1" opacity="0.45"/>
|
||||
</svg>`,
|
||||
},
|
||||
business: {
|
||||
accent: '#3d35c0',
|
||||
icon: `<svg width="32" height="32" viewBox="0 0 48 48" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round">
|
||||
<circle cx="24" cy="10" r="5.5"/>
|
||||
<circle cx="8" cy="38" r="5.5"/>
|
||||
<circle cx="40" cy="38" r="5.5"/>
|
||||
<line x1="24" y1="15.5" x2="8" y2="32.5"/>
|
||||
<line x1="24" y1="15.5" x2="40" y2="32.5"/>
|
||||
<line x1="13.5" y1="38" x2="34.5" y2="38"/>
|
||||
</svg>`,
|
||||
},
|
||||
industry: {
|
||||
accent: '#0b9688',
|
||||
icon: `<svg width="32" height="32" viewBox="0 0 48 48" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round">
|
||||
<polyline points="4,32 9,32 14,20 20,40 27,6 33,32 38,25 44,32"/>
|
||||
<line x1="4" y1="40" x2="44" y2="40" stroke-width="0.9" opacity="0.5"/>
|
||||
<circle cx="27" cy="6" r="2.5" fill="currentColor" opacity="0.4"/>
|
||||
</svg>`,
|
||||
},
|
||||
med: {
|
||||
accent: '#7b39eb',
|
||||
icon: `<svg width="32" height="32" viewBox="0 0 48 48" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round">
|
||||
<rect x="6" y="8" width="26" height="32" rx="3"/>
|
||||
<line x1="13" y1="20" x2="25" y2="20"/>
|
||||
<line x1="13" y1="27" x2="21" y2="27"/>
|
||||
<polyline points="29,29 34,17 39,35 43,29"/>
|
||||
</svg>`,
|
||||
},
|
||||
};
|
||||
---
|
||||
|
||||
<section class="offers-section" id="oferty" aria-labelledby="offers-heading">
|
||||
<!-- subtle dot decoration -->
|
||||
<div class="offers-dots" aria-hidden="true"></div>
|
||||
|
||||
<div class="container">
|
||||
<span class="section-label" aria-hidden="true">
|
||||
{locale === 'en' ? 'Solutions' : 'Oferta'}
|
||||
|
|
@ -35,21 +64,30 @@ const icons: Record<typeof offerKeys[number], string> = {
|
|||
<div class="offers-grid">
|
||||
{offerKeys.map((key) => {
|
||||
const offer = tr.offers[key];
|
||||
const { accent, icon } = meta[key];
|
||||
const isConservative = 'conservative' in offer && offer.conservative;
|
||||
return (
|
||||
<article
|
||||
class={`offer-card offer-${key}`}
|
||||
id={key}
|
||||
aria-labelledby={`offer-${key}-title`}
|
||||
style={`--oa: ${accent}`}
|
||||
>
|
||||
<!-- Gradient top bar -->
|
||||
<div class="offer-topbar" aria-hidden="true"></div>
|
||||
|
||||
<div class="offer-header">
|
||||
<div class="offer-icon" aria-hidden="true" set:html={icons[key]} />
|
||||
<div class="offer-icon-wrap" aria-hidden="true">
|
||||
<div class="offer-icon" set:html={icon} />
|
||||
</div>
|
||||
<div>
|
||||
<h3 id={`offer-${key}-title`}>{offer.title}</h3>
|
||||
<p class="offer-who">{offer.who}</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<p class="offer-desc">{offer.desc}</p>
|
||||
|
||||
{isConservative && (
|
||||
<p class="conservative-note" role="note">
|
||||
{locale === 'en'
|
||||
|
|
@ -57,6 +95,7 @@ const icons: Record<typeof offerKeys[number], string> = {
|
|||
: 'Rola wyłącznie doradcza — każdy wynik wymaga weryfikacji przez człowieka przed podjęciem działania.'}
|
||||
</p>
|
||||
)}
|
||||
|
||||
<blockquote class="offer-example">
|
||||
<p>{offer.example}</p>
|
||||
</blockquote>
|
||||
|
|
@ -70,23 +109,30 @@ const icons: Record<typeof offerKeys[number], string> = {
|
|||
<style>
|
||||
.offers-section {
|
||||
background: var(--color-bg);
|
||||
border-top: 1px solid var(--color-border);
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
}
|
||||
.offers-section h2 { margin-bottom: 3rem; }
|
||||
|
||||
.offers-section h2 {
|
||||
margin-bottom: 3rem;
|
||||
.offers-dots {
|
||||
position: absolute;
|
||||
top: 40px; right: 0;
|
||||
width: 200px; height: 260px;
|
||||
background-image:
|
||||
radial-gradient(circle, rgba(11,150,136,.09) 1.5px, transparent 1.5px);
|
||||
background-size: 20px 20px;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.offers-grid {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr;
|
||||
gap: 1.5rem;
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
@media (min-width: 640px) {
|
||||
.offers-grid {
|
||||
grid-template-columns: repeat(2, 1fr);
|
||||
}
|
||||
.offers-grid { grid-template-columns: repeat(2, 1fr); }
|
||||
}
|
||||
|
||||
.offer-card {
|
||||
|
|
@ -94,14 +140,22 @@ const icons: Record<typeof offerKeys[number], string> = {
|
|||
border: 1px solid var(--color-border);
|
||||
border-radius: var(--radius-lg);
|
||||
padding: 2rem;
|
||||
padding-top: 1.6rem;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 1rem;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
transition: box-shadow 0.2s;
|
||||
}
|
||||
.offer-card:hover { box-shadow: 0 4px 24px rgba(0,0,0,0.06); }
|
||||
|
||||
.offer-card.offer-industry,
|
||||
.offer-card.offer-med {
|
||||
border-top: 3px solid var(--color-industry);
|
||||
/* Gradient top bar */
|
||||
.offer-topbar {
|
||||
position: absolute;
|
||||
top: 0; left: 0; right: 0;
|
||||
height: 3px;
|
||||
background: linear-gradient(to right, var(--oa), color-mix(in srgb, var(--oa) 60%, #7b39eb));
|
||||
}
|
||||
|
||||
.offer-header {
|
||||
|
|
@ -110,40 +164,25 @@ const icons: Record<typeof offerKeys[number], string> = {
|
|||
gap: 1rem;
|
||||
}
|
||||
|
||||
.offer-icon {
|
||||
color: var(--color-accent);
|
||||
.offer-icon-wrap {
|
||||
width: 52px; height: 52px;
|
||||
border-radius: var(--radius);
|
||||
background: color-mix(in srgb, var(--oa) 10%, transparent);
|
||||
display: flex; align-items: center; justify-content: center;
|
||||
flex-shrink: 0;
|
||||
line-height: 0;
|
||||
margin-top: 2px;
|
||||
}
|
||||
|
||||
.offer-industry .offer-icon,
|
||||
.offer-med .offer-icon {
|
||||
color: var(--color-industry);
|
||||
}
|
||||
.offer-icon { color: var(--oa); line-height: 0; }
|
||||
|
||||
.offer-card h3 {
|
||||
font-size: 1.05rem;
|
||||
margin-bottom: 0.2rem;
|
||||
}
|
||||
|
||||
.offer-who {
|
||||
font-size: 0.82rem;
|
||||
color: var(--color-text-muted);
|
||||
max-width: none;
|
||||
}
|
||||
|
||||
.offer-desc {
|
||||
font-size: 0.9rem;
|
||||
line-height: 1.65;
|
||||
max-width: none;
|
||||
}
|
||||
.offer-card h3 { font-size: 1.05rem; margin-bottom: 0.2rem; }
|
||||
.offer-who { font-size: 0.82rem; color: var(--color-text-muted); max-width: none; }
|
||||
.offer-desc { font-size: 0.9rem; line-height: 1.65; max-width: none; }
|
||||
|
||||
.conservative-note {
|
||||
font-size: 0.8rem;
|
||||
color: var(--color-industry);
|
||||
background: rgba(44, 62, 80, 0.05);
|
||||
border-left: 3px solid var(--color-industry);
|
||||
color: var(--oa);
|
||||
background: color-mix(in srgb, var(--oa) 8%, transparent);
|
||||
border-left: 3px solid var(--oa);
|
||||
padding: 0.6rem 0.85rem;
|
||||
border-radius: 0 var(--radius) var(--radius) 0;
|
||||
max-width: none;
|
||||
|
|
@ -152,12 +191,10 @@ const icons: Record<typeof offerKeys[number], string> = {
|
|||
|
||||
.offer-example {
|
||||
background: var(--color-surface-alt);
|
||||
border-left: none;
|
||||
border-radius: var(--radius);
|
||||
padding: 0.9rem 1rem;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.offer-example p {
|
||||
font-size: 0.88rem;
|
||||
font-style: italic;
|
||||
|
|
|
|||
|
|
@ -5,6 +5,13 @@ import { t } from '../i18n/index.ts';
|
|||
interface Props { locale: Locale }
|
||||
const { locale } = Astro.props;
|
||||
const tr = t(locale);
|
||||
|
||||
const stepGrads = [
|
||||
'linear-gradient(135deg, #e05c40, #f0924a)',
|
||||
'linear-gradient(135deg, #7b39eb, #3d35c0)',
|
||||
'linear-gradient(135deg, #0b9688, #3d35c0)',
|
||||
];
|
||||
const connectorGrad = 'linear-gradient(to bottom, #e05c40, #7b39eb, #0b9688)';
|
||||
---
|
||||
|
||||
<section class="process-section" aria-labelledby="process-heading">
|
||||
|
|
@ -17,7 +24,12 @@ const tr = t(locale);
|
|||
<ol class="steps" aria-label={locale === 'en' ? 'How we start — 3 steps' : 'Jak zaczynamy — 3 kroki'}>
|
||||
{tr.process.steps.map((step, i) => (
|
||||
<li class="step">
|
||||
<div class="step-number" aria-hidden="true">{i + 1}</div>
|
||||
<div class="step-track" aria-hidden="true">
|
||||
<div class="step-number" style={`background: ${stepGrads[i]}`}>{i + 1}</div>
|
||||
{i < 2 && (
|
||||
<div class="step-connector" style={`background: ${connectorGrad}`}></div>
|
||||
)}
|
||||
</div>
|
||||
<div class="step-content">
|
||||
<h3>{step.title}</h3>
|
||||
<p>{step.body}</p>
|
||||
|
|
@ -29,74 +41,60 @@ const tr = t(locale);
|
|||
</section>
|
||||
|
||||
<style>
|
||||
.process-section {
|
||||
background: var(--color-surface);
|
||||
border-top: 1px solid var(--color-border);
|
||||
border-bottom: 1px solid var(--color-border);
|
||||
}
|
||||
|
||||
.process-section h2 {
|
||||
margin-bottom: 3rem;
|
||||
}
|
||||
.process-section { background: var(--color-surface); }
|
||||
.process-section h2 { margin-bottom: 3rem; }
|
||||
|
||||
.steps {
|
||||
list-style: none;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 0;
|
||||
max-width: 600px;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.step {
|
||||
display: flex;
|
||||
gap: 1.5rem;
|
||||
align-items: flex-start;
|
||||
position: relative;
|
||||
padding-bottom: 2.5rem;
|
||||
}
|
||||
|
||||
.step:last-child {
|
||||
padding-bottom: 0;
|
||||
}
|
||||
|
||||
.step::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
left: 1.1rem;
|
||||
top: 2.5rem;
|
||||
bottom: 0;
|
||||
width: 1px;
|
||||
background: var(--color-border);
|
||||
}
|
||||
|
||||
.step:last-child::after {
|
||||
display: none;
|
||||
.step-track {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.step-number {
|
||||
width: 2.25rem;
|
||||
height: 2.25rem;
|
||||
width: 2.35rem; height: 2.35rem;
|
||||
border-radius: 50%;
|
||||
background: var(--color-accent);
|
||||
color: #fff;
|
||||
font-size: 0.88rem;
|
||||
font-size: 0.9rem;
|
||||
font-weight: 500;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
flex-shrink: 0;
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
flex-shrink: 0;
|
||||
box-shadow: 0 2px 10px rgba(0,0,0,0.12);
|
||||
}
|
||||
|
||||
.step-content h3 {
|
||||
margin-top: 0.35rem;
|
||||
margin-bottom: 0.4rem;
|
||||
.step-connector {
|
||||
width: 2px;
|
||||
flex: 1;
|
||||
min-height: 2.5rem;
|
||||
border-radius: 1px;
|
||||
opacity: 0.3;
|
||||
margin-block: 4px;
|
||||
}
|
||||
|
||||
.step-content p {
|
||||
font-size: 0.92rem;
|
||||
max-width: 44ch;
|
||||
.step-content {
|
||||
padding-bottom: 2.5rem;
|
||||
padding-top: 0.3rem;
|
||||
}
|
||||
|
||||
.step:last-child .step-content { padding-bottom: 0; }
|
||||
|
||||
.step-content h3 { margin-bottom: 0.4rem; }
|
||||
.step-content p { font-size: 0.92rem; max-width: 44ch; }
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -17,11 +17,15 @@
|
|||
},
|
||||
"hero": {
|
||||
"badge": "Private, local AI systems",
|
||||
"h1": "The human side of AI",
|
||||
"h1_base": "The human side of ",
|
||||
"h1_highlight": "AI",
|
||||
"subtitle": "We build AI systems deeply integrated with your environment, always with a human in the decision loop. Not another chatbot.",
|
||||
"cta_primary": "Let's talk",
|
||||
"cta_secondary": "See what we do"
|
||||
},
|
||||
"manifest": {
|
||||
"slogan": "AI for people, by people"
|
||||
},
|
||||
"pillars": {
|
||||
"home": {
|
||||
"title": "Home",
|
||||
|
|
@ -56,7 +60,8 @@
|
|||
},
|
||||
"human": {
|
||||
"title": "Human in the loop",
|
||||
"body": "AI advises and prepares; people decide. Especially where the stakes are high."
|
||||
"body": "AI advises and prepares; people decide. Especially where the stakes are high.",
|
||||
"tagline": "You always talk to a real person"
|
||||
}
|
||||
},
|
||||
"offers": {
|
||||
|
|
@ -112,6 +117,7 @@
|
|||
"contact": {
|
||||
"h2": "Let's talk about your case",
|
||||
"subtitle": "Tell us what you need — we'll come back with a concrete proposal.",
|
||||
"human_note": "You always talk to a real person",
|
||||
"field_name": "Name",
|
||||
"field_email": "Email",
|
||||
"field_message": "Message",
|
||||
|
|
|
|||
|
|
@ -17,11 +17,15 @@
|
|||
},
|
||||
"hero": {
|
||||
"badge": "Prywatne, lokalne systemy AI",
|
||||
"h1": "Ludzka strona AI",
|
||||
"h1_base": "Ludzka strona ",
|
||||
"h1_highlight": "AI",
|
||||
"subtitle": "Budujemy systemy AI głęboko zintegrowane z Twoim otoczeniem i zawsze z człowiekiem w pętli decyzji. Nie kolejny chatbot.",
|
||||
"cta_primary": "Porozmawiajmy",
|
||||
"cta_secondary": "Zobacz, co robimy"
|
||||
},
|
||||
"manifest": {
|
||||
"slogan": "AI dla ludzi, przez ludzi"
|
||||
},
|
||||
"pillars": {
|
||||
"home": {
|
||||
"title": "Home",
|
||||
|
|
@ -56,7 +60,8 @@
|
|||
},
|
||||
"human": {
|
||||
"title": "Człowiek w pętli",
|
||||
"body": "AI doradza i przygotowuje, decyzję podejmuje człowiek. Szczególnie tam, gdzie stawka jest wysoka."
|
||||
"body": "AI doradza i przygotowuje, decyzję podejmuje człowiek. Szczególnie tam, gdzie stawka jest wysoka.",
|
||||
"tagline": "U nas zawsze rozmawiasz z człowiekiem"
|
||||
}
|
||||
},
|
||||
"offers": {
|
||||
|
|
@ -112,6 +117,7 @@
|
|||
"contact": {
|
||||
"h2": "Porozmawiajmy o Twoim przypadku",
|
||||
"subtitle": "Opowiedz, czego potrzebujesz — odezwiemy się z konkretną propozycją.",
|
||||
"human_note": "U nas zawsze rozmawiasz z człowiekiem",
|
||||
"field_name": "Imię",
|
||||
"field_email": "E-mail",
|
||||
"field_message": "Wiadomość",
|
||||
|
|
|
|||
|
|
@ -27,14 +27,12 @@ const enUrl = locale === 'en' ? url.pathname : getAlternateUrl(url, 'en');
|
|||
<link rel="alternate" hreflang="pl" href={`https://gethumanai.com${plUrl}`} />
|
||||
<link rel="alternate" hreflang="en" href={`https://gethumanai.com${enUrl}`} />
|
||||
<link rel="alternate" hreflang="x-default" href="https://gethumanai.com/" />
|
||||
<!-- Open Graph -->
|
||||
<meta property="og:type" content="website" />
|
||||
<meta property="og:url" content={canonicalUrl} />
|
||||
<meta property="og:title" content={tr.meta.og_title} />
|
||||
<meta property="og:description" content={tr.meta.og_description} />
|
||||
<meta property="og:locale" content={locale === 'pl' ? 'pl_PL' : 'en_US'} />
|
||||
<meta property="og:site_name" content="humanAI" />
|
||||
<!-- Fonts -->
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com" />
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
|
||||
<link
|
||||
|
|
@ -56,16 +54,35 @@ const enUrl = locale === 'en' ? url.pathname : getAlternateUrl(url, 'en');
|
|||
}
|
||||
|
||||
:root {
|
||||
/* Neutral surface */
|
||||
--color-bg: #fafaf8;
|
||||
--color-surface: #ffffff;
|
||||
--color-surface-alt: #f4f4f0;
|
||||
--color-text: #1a1a18;
|
||||
--color-text-muted: #6b6b65;
|
||||
--color-accent: #1a3d2e;
|
||||
--color-accent-hover: #122d21;
|
||||
--color-border: #e4e4de;
|
||||
--color-industry: #2c3e50;
|
||||
--color-med: #2c3e50;
|
||||
|
||||
/* Gradient palette — warm ↔ cool */
|
||||
--c-coral: #e05c40;
|
||||
--c-amber: #f0924a;
|
||||
--c-indigo: #3d35c0;
|
||||
--c-violet: #7b39eb;
|
||||
--c-teal: #0b9688;
|
||||
|
||||
/* Per-pillar accents */
|
||||
--c-home: var(--c-coral);
|
||||
--c-business: var(--c-indigo);
|
||||
--c-industry: var(--c-teal);
|
||||
--c-med: var(--c-violet);
|
||||
|
||||
/* Named gradients */
|
||||
--grad-main: linear-gradient(135deg, #e05c40 0%, #7b39eb 55%, #0b9688 100%);
|
||||
--grad-cta: linear-gradient(135deg, #e05c40, #7b39eb);
|
||||
--grad-sep: linear-gradient(to right, transparent, rgba(224,92,64,.18) 30%, rgba(123,57,235,.18) 70%, transparent);
|
||||
|
||||
/* Keep legacy accent for nav / focus rings */
|
||||
--color-accent: #3d35c0;
|
||||
|
||||
--font-sans: 'Inter', system-ui, -apple-system, sans-serif;
|
||||
--radius: 6px;
|
||||
--radius-lg: 12px;
|
||||
|
|
@ -73,10 +90,7 @@ const enUrl = locale === 'en' ? url.pathname : getAlternateUrl(url, 'en');
|
|||
--section-py: clamp(4rem, 8vw, 7rem);
|
||||
}
|
||||
|
||||
html {
|
||||
scroll-behavior: smooth;
|
||||
-webkit-text-size-adjust: 100%;
|
||||
}
|
||||
html { scroll-behavior: smooth; -webkit-text-size-adjust: 100%; }
|
||||
|
||||
body {
|
||||
font-family: var(--font-sans);
|
||||
|
|
@ -86,17 +100,11 @@ const enUrl = locale === 'en' ? url.pathname : getAlternateUrl(url, 'en');
|
|||
font-size: 1rem;
|
||||
}
|
||||
|
||||
img {
|
||||
max-width: 100%;
|
||||
height: auto;
|
||||
}
|
||||
|
||||
a {
|
||||
color: inherit;
|
||||
}
|
||||
img { max-width: 100%; height: auto; }
|
||||
a { color: inherit; }
|
||||
|
||||
:focus-visible {
|
||||
outline: 2px solid var(--color-accent);
|
||||
outline: 2px solid var(--c-indigo);
|
||||
outline-offset: 3px;
|
||||
border-radius: 2px;
|
||||
}
|
||||
|
|
@ -108,49 +116,63 @@ const enUrl = locale === 'en' ? url.pathname : getAlternateUrl(url, 'en');
|
|||
padding-inline: clamp(1.25rem, 5vw, 2.5rem);
|
||||
}
|
||||
|
||||
/* ── Buttons ─────────────────────────────────────────────────────────── */
|
||||
.btn-primary {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
padding: 0.75rem 1.75rem;
|
||||
background: var(--color-accent);
|
||||
background: var(--grad-cta);
|
||||
color: #fff;
|
||||
text-decoration: none;
|
||||
border-radius: var(--radius);
|
||||
font-weight: 500;
|
||||
font-size: 0.95rem;
|
||||
transition: background 0.18s;
|
||||
border: none;
|
||||
cursor: pointer;
|
||||
transition: opacity 0.18s, transform 0.15s;
|
||||
}
|
||||
.btn-primary:hover { opacity: 0.88; transform: translateY(-1px); }
|
||||
|
||||
.btn-primary:hover {
|
||||
background: var(--color-accent-hover);
|
||||
}
|
||||
|
||||
/* Gradient-border outline button via padding-box / border-box trick */
|
||||
.btn-outline {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
padding: 0.75rem 1.75rem;
|
||||
background: transparent;
|
||||
color: var(--color-accent);
|
||||
background:
|
||||
linear-gradient(#fff, #fff) padding-box,
|
||||
var(--grad-cta) border-box;
|
||||
border: 1.5px solid transparent;
|
||||
color: var(--c-violet);
|
||||
text-decoration: none;
|
||||
border-radius: var(--radius);
|
||||
font-weight: 500;
|
||||
font-size: 0.95rem;
|
||||
border: 1.5px solid var(--color-accent);
|
||||
transition: background 0.18s, color 0.18s;
|
||||
cursor: pointer;
|
||||
transition: background 0.18s, color 0.18s, transform 0.15s;
|
||||
}
|
||||
|
||||
.btn-outline:hover {
|
||||
background: var(--color-accent);
|
||||
background: var(--grad-cta) padding-box, var(--grad-cta) border-box;
|
||||
color: #fff;
|
||||
transform: translateY(-1px);
|
||||
}
|
||||
|
||||
section {
|
||||
padding-block: var(--section-py);
|
||||
/* ── Section layout ──────────────────────────────────────────────────── */
|
||||
section { padding-block: var(--section-py); }
|
||||
|
||||
/* Gradient hairline between sections */
|
||||
section + section {
|
||||
position: relative;
|
||||
}
|
||||
section + section::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 0; left: 0; right: 0;
|
||||
height: 1px;
|
||||
background: var(--grad-sep);
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
/* ── Typography utilities ────────────────────────────────────────────── */
|
||||
.section-label {
|
||||
display: inline-block;
|
||||
font-size: 0.78rem;
|
||||
|
|
@ -174,18 +196,22 @@ const enUrl = locale === 'en' ? url.pathname : getAlternateUrl(url, 'en');
|
|||
margin-bottom: 0.5rem;
|
||||
}
|
||||
|
||||
p {
|
||||
color: var(--color-text-muted);
|
||||
max-width: 60ch;
|
||||
p { color: var(--color-text-muted); max-width: 60ch; }
|
||||
|
||||
/* Gradient text utility */
|
||||
.grad-text {
|
||||
background: var(--grad-main);
|
||||
-webkit-background-clip: text;
|
||||
-webkit-text-fill-color: transparent;
|
||||
background-clip: text;
|
||||
}
|
||||
|
||||
/* Utility */
|
||||
.text-center { text-align: center; }
|
||||
.text-center p { margin-inline: auto; }
|
||||
|
||||
.sr-only {
|
||||
position: absolute;
|
||||
width: 1px;
|
||||
height: 1px;
|
||||
width: 1px; height: 1px;
|
||||
overflow: hidden;
|
||||
clip: rect(0 0 0 0);
|
||||
white-space: nowrap;
|
||||
|
|
|
|||
Loading…
Reference in a new issue