Autosave: 20260323-113738

This commit is contained in:
Flatlogic Bot 2026-03-23 11:37:38 +00:00
parent a64664a505
commit ceaa8d10c9
9 changed files with 245 additions and 7 deletions

View File

@ -27,11 +27,46 @@ main {
}
.section {
position: relative;
isolation: isolate;
overflow: visible;
padding: 72px 0;
}
.section > .container {
padding-inline: clamp(0.75rem, 2vw, 1.25rem);
}
.section h2 {
letter-spacing: -0.02em;
}
.section .lead,
.section p {
line-height: 1.7;
}
.section > .container {
position: relative;
z-index: 2;
}
.section-muted {
background: #f1f3f6;
background: linear-gradient(180deg, rgba(241, 243, 246, 0.78), rgba(246, 247, 249, 0.56));
border-top: 1px solid rgba(255, 255, 255, 0.72);
border-bottom: 1px solid rgba(229, 231, 235, 0.55);
overflow: visible;
}
.section-muted::before {
content: '';
position: absolute;
inset: 0;
pointer-events: none;
background:
radial-gradient(circle at 12% 18%, rgba(255, 255, 255, 0.42), transparent 30%),
radial-gradient(circle at 86% 78%, rgba(37, 99, 235, 0.1), transparent 24%);
z-index: 0;
}
.eyebrow {
@ -116,6 +151,24 @@ footer a {
.hero-section {
padding-top: 40px;
}
.hero-collage {
grid-template-columns: 1fr;
}
.hero-collage-main {
min-height: 260px;
}
.hero-collage-stack {
grid-template-columns: 1fr 1fr;
}
.hero-collage-stack img {
min-height: 160px;
}
.hero-collage-strip {
grid-template-columns: 1fr;
}
.hero-strip-photo {
height: 180px;
}
}
@ -220,7 +273,14 @@ footer {
position: absolute;
inset: 0;
pointer-events: none;
background: linear-gradient(135deg, rgba(255, 255, 255, 0.18), rgba(255, 255, 255, 0));
}
.hero-section::after {
background: linear-gradient(135deg, rgba(255, 255, 255, 0.16), rgba(255, 255, 255, 0));
}
.section-muted::after {
background: linear-gradient(135deg, rgba(255, 255, 255, 0.08), rgba(255, 255, 255, 0));
}
.hero-card,
@ -246,6 +306,133 @@ footer {
box-shadow: 0 20px 60px rgba(15, 23, 42, 0.08);
}
.work-card,
.about-panel,
.contact-box,
.testimonial-card {
border-radius: 24px;
}
.hero-collage {
display: grid;
grid-template-columns: minmax(0, 1.45fr) minmax(0, 0.85fr);
gap: 14px;
}
.hero-collage-main,
.hero-collage-stack,
.hero-collage-strip {
position: relative;
overflow: hidden;
border-radius: 24px;
background: linear-gradient(135deg, rgba(37, 99, 235, 0.08), rgba(16, 185, 129, 0.08));
}
.hero-collage-main {
min-height: 320px;
}
.hero-collage-main img,
.hero-collage-stack img,
.hero-strip-photo {
width: 100%;
height: 100%;
object-fit: cover;
display: block;
}
.hero-collage-main::after,
.hero-collage-stack::after,
.hero-collage-strip::after {
content: '';
position: absolute;
inset: 0;
background: linear-gradient(180deg, rgba(15, 23, 42, 0) 35%, rgba(15, 23, 42, 0.2) 100%);
pointer-events: none;
}
.hero-collage-main img,
.hero-collage-stack img,
.hero-strip-photo {
transform: scale(1.03);
}
.hero-collage-stack {
display: grid;
gap: 14px;
}
.hero-collage-stack img {
min-height: 153px;
}
.hero-collage-badge {
position: absolute;
left: 16px;
bottom: 16px;
z-index: 1;
display: inline-flex;
align-items: center;
padding: 0.45rem 0.8rem;
border-radius: 999px;
background: rgba(255, 255, 255, 0.86);
color: #0f172a;
font-weight: 600;
font-size: 0.8rem;
box-shadow: 0 10px 24px rgba(15, 23, 42, 0.15);
}
.hero-collage-strip {
display: grid;
grid-template-columns: 96px minmax(0, 1fr);
gap: 14px;
align-items: center;
padding: 14px;
}
.hero-strip-photo {
height: 96px;
border-radius: 18px;
}
.hero-strip-copy {
min-width: 0;
}
.parallax-media {
will-change: transform;
transform-origin: center center;
transition: transform 0.16s linear;
}
.card-img-top.parallax-media,
.testi-img.parallax-media {
transform: scale(1.02);
}
.card {
overflow: hidden;
}
.work-card {
border: 1px solid rgba(229, 231, 235, 0.9);
background: rgba(255, 255, 255, 0.98);
}
.work-card .card-body,
.testimonial-card .card-body {
padding: 1.35rem;
}
.testimonial-card {
border: 1px solid rgba(229, 231, 235, 0.9);
background: rgba(255, 255, 255, 0.98);
}
.contact-box {
background: linear-gradient(180deg, rgba(255,255,255,0.98), rgba(248,250,252,0.95));
}
.btn-primary,
.btn-outline-dark {
transition: transform 0.25s ease, box-shadow 0.25s ease;
@ -284,4 +471,9 @@ footer {
.bg-cursor-glow {
display: none;
}
.parallax-media {
transition: none;
transform: none !important;
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 92 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 42 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 50 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 97 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 42 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 59 KiB

View File

@ -20,10 +20,12 @@ document.addEventListener('DOMContentLoaded', () => {
const prefersReducedMotion = window.matchMedia('(prefers-reduced-motion: reduce)').matches;
const orbs = Array.from(document.querySelectorAll('.bg-orb'));
const cursorGlow = document.querySelector('.bg-cursor-glow');
const parallaxItems = Array.from(document.querySelectorAll('[data-parallax]'));
if (!prefersReducedMotion && (orbs.length || cursorGlow)) {
if (!prefersReducedMotion && (orbs.length || cursorGlow || parallaxItems.length)) {
const pointer = { x: window.innerWidth / 2, y: window.innerHeight / 3 };
const smooth = { x: pointer.x, y: pointer.y };
let scrollY = window.scrollY;
const render = () => {
smooth.x += (pointer.x - smooth.x) * 0.08;
@ -37,6 +39,18 @@ document.addEventListener('DOMContentLoaded', () => {
orb.style.transform = `translate3d(${dx}px, ${dy}px, 0)`;
});
parallaxItems.forEach((item, index) => {
const depth = Number(item.dataset.parallax || 12);
const direction = Number(item.dataset.parallaxDirection || (index % 2 === 0 ? 1 : -1));
const rawMoveX = ((smooth.x / window.innerWidth) - 0.5) * depth * 0.7 * direction;
const rawMoveY = ((smooth.y / window.innerHeight) - 0.5) * depth * 0.45 + (scrollY * 0.004 * depth * direction);
const limitX = Math.max(8, depth * 1.6);
const limitY = Math.max(10, depth * 1.8);
const moveX = Math.max(-limitX, Math.min(limitX, rawMoveX));
const moveY = Math.max(-limitY, Math.min(limitY, rawMoveY));
item.style.transform = `translate3d(${moveX}px, ${moveY}px, 0) scale(1.02)`;
});
if (cursorGlow) {
cursorGlow.style.transform = `translate3d(${smooth.x}px, ${smooth.y}px, 0)`;
}
@ -50,6 +64,7 @@ document.addEventListener('DOMContentLoaded', () => {
}, { passive: true });
window.addEventListener('scroll', () => {
scrollY = window.scrollY;
pointer.y = window.innerHeight / 3 + (window.scrollY * 0.08);
}, { passive: true });

View File

@ -26,6 +26,7 @@ $projectImageUrl = $_SERVER['PROJECT_IMAGE_URL'] ?? '';
$now = date('Y-m-d H:i:s');
// Fetch images for sections
$heroImages = get_images('studio,workspace,creative,editorial');
$workImages = get_images('design,code,analytics');
$testimonialImages = get_images('person,professional,business');
@ -181,6 +182,36 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
</div>
<div class="col-lg-6">
<div class="hero-card p-4 p-lg-5">
<div class="hero-collage mb-4">
<?php
$heroDefaults = [
['src' => 'https://picsum.photos/seed/hero-main/900/1080', 'alt' => 'Creative desk setup with sketches and display screens'],
['src' => 'https://picsum.photos/seed/hero-side-a/720/720', 'alt' => 'Moodboard with typography and color samples'],
['src' => 'https://picsum.photos/seed/hero-side-b/720/720', 'alt' => 'Product interface on a laptop screen'],
['src' => 'https://picsum.photos/seed/hero-side-c/720/720', 'alt' => 'Team workshop notes and sticky planning cards'],
];
$heroSources = [];
for ($i = 0; $i < 4; $i++) {
$heroSources[$i] = $heroImages[$i] ?? $heroDefaults[$i];
}
?>
<div class="hero-collage-main">
<img src="<?= htmlspecialchars($heroSources[0]['src']) ?>" class="hero-photo parallax-media" data-parallax="18" alt="<?= htmlspecialchars($heroSources[0]['alt']) ?>">
<span class="hero-collage-badge">Live creative direction</span>
</div>
<div class="hero-collage-stack">
<img src="<?= htmlspecialchars($heroSources[1]['src']) ?>" class="hero-photo parallax-media" data-parallax="12" data-parallax-direction="-1" alt="<?= htmlspecialchars($heroSources[1]['alt']) ?>">
<img src="<?= htmlspecialchars($heroSources[2]['src']) ?>" class="hero-photo parallax-media" data-parallax="14" alt="<?= htmlspecialchars($heroSources[2]['alt']) ?>">
</div>
</div>
<div class="hero-collage-strip mb-4">
<img src="<?= htmlspecialchars($heroSources[3]['src']) ?>" class="hero-strip-photo parallax-media" data-parallax="9" data-parallax-direction="-1" alt="<?= htmlspecialchars($heroSources[3]['alt']) ?>">
<div class="hero-strip-copy">
<p class="text-muted small text-uppercase mb-1">Current focus</p>
<p class="fw-semibold mb-1">Visual systems, motion, and product storytelling</p>
<p class="text-muted small mb-0">Designed to keep the page lively without overpowering the content.</p>
</div>
</div>
<h2 class="h5 fw-semibold mb-3">Recent highlights</h2>
<ul class="list-unstyled mb-4">
<li class="d-flex justify-content-between border-bottom py-3">
@ -228,8 +259,8 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$img = $workImages[$i] ?? ['src' => 'https://picsum.photos/600/400'];
?>
<div class="col-md-4">
<article class="card shadow-sm h-100 border-0">
<img src="<?= htmlspecialchars($img['src']) ?>" class="card-img-top" alt="<?= htmlspecialchars($project['title']) ?>">
<article class="card work-card shadow-sm h-100 border-0">
<img src="<?= htmlspecialchars($img['src']) ?>" class="card-img-top parallax-media" data-parallax="10" data-parallax-direction="<?= $i % 2 === 0 ? 1 : -1 ?>" alt="<?= htmlspecialchars($project['title']) ?>">
<div class="card-body d-flex flex-column">
<p class="text-muted small text-uppercase mb-2"><?= htmlspecialchars($project['type']) ?></p>
<h3 class="h5 fw-semibold"><?= htmlspecialchars($project['title']) ?></h3>
@ -315,9 +346,9 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$img = $testimonialImages[$i] ?? ['src' => 'https://picsum.photos/100'];
?>
<div class="col-md-6">
<div class="card border-0 shadow-sm h-100">
<div class="card testimonial-card border-0 shadow-sm h-100">
<div class="card-body d-flex gap-3">
<img src="<?= htmlspecialchars($img['src']) ?>" class="testi-img" alt="Testimonial photo">
<img src="<?= htmlspecialchars($img['src']) ?>" class="testi-img parallax-media" data-parallax="6" data-parallax-direction="<?= $i % 2 === 0 ? 1 : -1 ?>" alt="Testimonial photo">
<div>
<p class="text-muted mb-2"><?= htmlspecialchars($item['quote']) ?></p>
<p class="fw-semibold mb-0"><?= htmlspecialchars($item['name']) ?></p>