Commit 61919d6a by PLN (Algolia)

fix(parvagues): poster overflow, dark mode, reveal visibility

- Use inline opacity (0.15) on poster image — Tailwind opacity-20 not
  applying in production build
- Add color-scheme: dark meta tag for browser/reader mode compatibility
- Set html/body background to #0a0a0a to prevent white bleed
- Fix reveal animation: sections visible by default, animate only after
  JS hydration via .reveal-ready class on documentElement
- Bump screenshots script to domcontentloaded + 3s render wait
parent 9b00e9b9
...@@ -9,7 +9,8 @@ export default function Hero() { ...@@ -9,7 +9,8 @@ export default function Hero() {
src="/images/parvagues/lives/2024/ccc_release_party/poster.png" src="/images/parvagues/lives/2024/ccc_release_party/poster.png"
alt="" alt=""
fill fill
className="object-cover opacity-20" className="object-cover"
style={{ opacity: 0.15 }}
priority priority
/> />
{/* Heavy overlay to kill poster text bleed */} {/* Heavy overlay to kill poster text bleed */}
......
...@@ -2,7 +2,7 @@ import Head from 'next/head'; ...@@ -2,7 +2,7 @@ import Head from 'next/head';
import Link from 'next/link'; import Link from 'next/link';
import Image from 'next/image'; import Image from 'next/image';
import { Syne } from 'next/font/google'; import { Syne } from 'next/font/google';
import { useState, useEffect, useCallback } from 'react'; import { useState, useEffect } from 'react';
import { FaEnvelope, FaInstagram, FaYoutube, FaGithub } from 'react-icons/fa'; import { FaEnvelope, FaInstagram, FaYoutube, FaGithub } from 'react-icons/fa';
import { SiBluesky, SiMastodon } from 'react-icons/si'; import { SiBluesky, SiMastodon } from 'react-icons/si';
...@@ -31,8 +31,11 @@ export default function Layout({ children, title = 'ParVagues' }) { ...@@ -31,8 +31,11 @@ export default function Layout({ children, title = 'ParVagues' }) {
return () => window.removeEventListener('scroll', onScroll); return () => window.removeEventListener('scroll', onScroll);
}, []); }, []);
// Scroll-triggered reveal for sections // Scroll-triggered reveal for sections (only after JS hydration)
useEffect(() => { useEffect(() => {
// Mark wrapper so CSS knows JS is ready — sections stay visible without JS
document.documentElement.classList.add('reveal-ready');
const observer = new IntersectionObserver( const observer = new IntersectionObserver(
(entries) => { (entries) => {
entries.forEach((entry) => { entries.forEach((entry) => {
...@@ -52,6 +55,7 @@ export default function Layout({ children, title = 'ParVagues' }) { ...@@ -52,6 +55,7 @@ export default function Layout({ children, title = 'ParVagues' }) {
<Head> <Head>
<title>{title}</title> <title>{title}</title>
<meta name="viewport" content="width=device-width, initial-scale=1" /> <meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="color-scheme" content="dark" />
<meta name="description" content="ParVagues - Livecoding de musique électronique. Ondes binaires, plages sonores." /> <meta name="description" content="ParVagues - Livecoding de musique électronique. Ondes binaires, plages sonores." />
<meta property="og:title" content={title} /> <meta property="og:title" content={title} />
<meta property="og:type" content="music.musician" /> <meta property="og:type" content="music.musician" />
......
...@@ -30,9 +30,9 @@ const SECTIONS = ['tour', 'music', 'video', 'booking']; ...@@ -30,9 +30,9 @@ const SECTIONS = ['tour', 'music', 'video', 'booking'];
async function captureViewport({ name, width, height }) { async function captureViewport({ name, width, height }) {
const browser = await chromium.launch(); const browser = await chromium.launch();
const page = await browser.newPage({ viewport: { width, height } }); const page = await browser.newPage({ viewport: { width, height } });
await page.goto(BASE_URL, { waitUntil: 'load', timeout: 30000 }); await page.goto(BASE_URL, { waitUntil: 'domcontentloaded', timeout: 60000 });
// Wait for content to render // Wait for content to render + images to load
await new Promise((r) => setTimeout(r, 2000)); await new Promise((r) => setTimeout(r, 3000));
// Full-page screenshot // Full-page screenshot
await page.screenshot({ path: path.join(OUT_DIR, `${name}-full.png`), fullPage: true }); await page.screenshot({ path: path.join(OUT_DIR, `${name}-full.png`), fullPage: true });
......
...@@ -17,6 +17,12 @@ ...@@ -17,6 +17,12 @@
--text-muted: #737373; --text-muted: #737373;
} }
html, body {
background-color: #0a0a0a;
color: #e5e5e5;
color-scheme: dark;
}
html { html {
scroll-behavior: smooth; scroll-behavior: smooth;
scroll-padding-top: 4.5rem; scroll-padding-top: 4.5rem;
...@@ -62,14 +68,14 @@ html { ...@@ -62,14 +68,14 @@ html {
background-color: #0e0e0e; background-color: #0e0e0e;
} }
/* Scroll-triggered reveal */ /* Scroll-triggered reveal — only animate after JS loads */
.reveal { .reveal-ready .reveal {
opacity: 0; opacity: 0;
transform: translateY(20px); transform: translateY(20px);
transition: opacity 0.6s ease-out, transform 0.6s ease-out; transition: opacity 0.6s ease-out, transform 0.6s ease-out;
} }
.reveal.visible { .reveal-ready .reveal.visible {
opacity: 1; opacity: 1;
transform: translateY(0); transform: translateY(0);
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment