feat(phase-1): Premium design system, CapitoliumPreloader, IndexSectionIndicator, Recipe Showcase Stage
- Full CSS rewrite: Warm Ivory/Gold/Steinkohle design tokens, Floema grid, easing library - AuraMarbleBackground: fixed grain texture layer - CapitoliumPreloader: fullscreen counter animation with slide-up exit - LiquidOverlayMenu: fixed hamburger → fullscreen clip-path overlay with SlideUpTextHover nav links - IndexSectionIndicator: fixed left-side section tracker with animated fill line - Recipe Showcase Stage: GSAP ScrollTrigger pinned stage (images enter from right, exit left) with parallax inner-image effect, intro title, progress dots, hint line - LenisSmoothScroll: CDN integration synced with GSAP ticker - CapitoliumRevealButton: scaleY fill reveal on hover for all CTAs - SlideUpTextHover: overlay nav links - UnderlineExpandHover: footer + overlay footer links - head.php: GSAP 3.12.5 + ScrollTrigger + Lenis 1.0.42 CDN; Playfair Display + Manrope fonts - recipe.php: updated to new design system (btn-reveal, pill--gold, Lenis init) - impressum.php / datenschutz.php: migrated to shared head.php partial
This commit is contained in:
+34
-35
@@ -1,79 +1,78 @@
|
||||
<?php
|
||||
$langCode = (isset($lang) && $lang === 'de') ? 'de' : 'en';
|
||||
$langCode = (isset($lang) && $lang === 'de') ? 'de' : 'en';
|
||||
$langSuffix = $langCode === 'de' ? '?lang=de' : '';
|
||||
$settings = function_exists('load_site_settings') ? load_site_settings() : null;
|
||||
$settings = function_exists('load_site_settings') ? load_site_settings() : null;
|
||||
$contactEmail = $settings['imprint'][$langCode]['email'] ?? 'contact@flixcooks.at';
|
||||
?>
|
||||
<footer class="site-footer">
|
||||
<footer class="site-footer" role="contentinfo">
|
||||
<div class="footer-meta">
|
||||
<p>Website designed by Felix Brockers</p>
|
||||
<a class="contact-link" href="mailto:<?php echo e($contactEmail); ?>">Contact me</a>
|
||||
<p><?php echo $langCode === 'de' ? 'Designed & entwickelt von Felix Brockers' : 'Designed & built by Felix Brockers'; ?></p>
|
||||
<a class="contact-link underline-link" href="mailto:<?php echo e($contactEmail); ?>">
|
||||
<?php echo e($contactEmail); ?>
|
||||
</a>
|
||||
<small>© <?php echo date('Y'); ?> FlixCooks</small>
|
||||
</div>
|
||||
<div class="footer-links">
|
||||
<a href="/impressum.php<?php echo $langSuffix; ?>"><?php echo $langCode === 'de' ? 'Impressum' : 'Imprint'; ?></a>
|
||||
<a href="/datenschutz.php<?php echo $langSuffix; ?>"><?php echo $langCode === 'de' ? 'Datenschutz' : 'Privacy'; ?></a>
|
||||
<a class="underline-link" href="/impressum.php<?php echo $langSuffix; ?>">
|
||||
<?php echo $langCode === 'de' ? 'Impressum' : 'Imprint'; ?>
|
||||
</a>
|
||||
<a class="underline-link" href="/datenschutz.php<?php echo $langSuffix; ?>">
|
||||
<?php echo $langCode === 'de' ? 'Datenschutz' : 'Privacy'; ?>
|
||||
</a>
|
||||
</div>
|
||||
</footer>
|
||||
|
||||
<button id="backToTop" aria-label="Back to top">↑ Back to top</button>
|
||||
<button id="backToTop" aria-label="<?php echo $langCode === 'de' ? 'Nach oben' : 'Back to top'; ?>">↑</button>
|
||||
|
||||
<!-- Fixed dark/light toggle — always visible, scrolls with page -->
|
||||
<!-- Fixed dark/light toggle -->
|
||||
<button class="theme-toggle" data-theme-toggle aria-label="Switch to dark mode">
|
||||
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79z"/></svg>
|
||||
</button>
|
||||
|
||||
<script>
|
||||
// ── Back to top ───────────────────────────────────────────────────────────────
|
||||
// ── Back to top ────────────────────────────────────────────────
|
||||
(function(){
|
||||
const btn = document.getElementById('backToTop');
|
||||
var btn = document.getElementById('backToTop');
|
||||
if (!btn) return;
|
||||
const check = () => btn.classList.toggle('show', window.scrollY > 240);
|
||||
var check = function() { btn.classList.toggle('show', window.scrollY > 280); };
|
||||
window.addEventListener('scroll', check, { passive: true });
|
||||
btn.addEventListener('click', () => window.scrollTo({ top: 0, behavior: 'smooth' }));
|
||||
btn.addEventListener('click', function() {
|
||||
if (window.lenis) {
|
||||
window.lenis.scrollTo(0, { duration: 1.4 });
|
||||
} else {
|
||||
window.scrollTo({ top: 0, behavior: 'smooth' });
|
||||
}
|
||||
});
|
||||
check();
|
||||
})();
|
||||
|
||||
// ── Dark / light mode toggle ─────────────────────────────────────────────────
|
||||
// ── Dark / light mode toggle ───────────────────────────────────
|
||||
(function(){
|
||||
const r = document.documentElement;
|
||||
let d = r.getAttribute('data-theme') || 'light';
|
||||
var r = document.documentElement;
|
||||
var d = localStorage.getItem('fc-theme') || r.getAttribute('data-theme') || 'light';
|
||||
r.setAttribute('data-theme', d);
|
||||
|
||||
const SUN = '<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="12" cy="12" r="5"/><path d="M12 1v2M12 21v2M4.22 4.22l1.42 1.42M18.36 18.36l1.42 1.42M1 12h2M21 12h2M4.22 19.78l1.42-1.42M18.36 5.64l1.42-1.42"/></svg>';
|
||||
const MOON = '<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79z"/></svg>';
|
||||
var SUN = '<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="12" cy="12" r="5"/><path d="M12 1v2M12 21v2M4.22 4.22l1.42 1.42M18.36 18.36l1.42 1.42M1 12h2M21 12h2M4.22 19.78l1.42-1.42M18.36 5.64l1.42-1.42"/></svg>';
|
||||
var MOON = '<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79z"/></svg>';
|
||||
|
||||
function setIcon() {
|
||||
const icon = d === 'dark' ? SUN : MOON;
|
||||
const label = 'Switch to ' + (d === 'dark' ? 'light' : 'dark') + ' mode';
|
||||
document.querySelectorAll('[data-theme-toggle]').forEach(t => {
|
||||
var icon = d === 'dark' ? SUN : MOON;
|
||||
var label = 'Switch to ' + (d === 'dark' ? 'light' : 'dark') + ' mode';
|
||||
document.querySelectorAll('[data-theme-toggle]').forEach(function(t) {
|
||||
t.innerHTML = icon;
|
||||
t.setAttribute('aria-label', label);
|
||||
});
|
||||
}
|
||||
|
||||
// Use event delegation so it works regardless of DOM order
|
||||
document.addEventListener('click', function(e) {
|
||||
if (e.target.closest('[data-theme-toggle]')) {
|
||||
d = d === 'dark' ? 'light' : 'dark';
|
||||
r.setAttribute('data-theme', d);
|
||||
localStorage.setItem('fc-theme', d);
|
||||
setIcon();
|
||||
}
|
||||
});
|
||||
|
||||
// Toggle adapts visually when scrolled off landing section
|
||||
(function(){
|
||||
const landing = document.getElementById('landing');
|
||||
const toggle = document.querySelector('.theme-toggle');
|
||||
if (!toggle) return;
|
||||
function check() {
|
||||
const past = !landing || window.scrollY > (landing.offsetHeight - 80);
|
||||
toggle.classList.toggle('on-site', past);
|
||||
}
|
||||
window.addEventListener('scroll', check, { passive: true });
|
||||
check();
|
||||
})();
|
||||
|
||||
setIcon();
|
||||
})();
|
||||
</script>
|
||||
|
||||
Reference in New Issue
Block a user