diff --git a/public/logo.png b/public/logo.png index cda5d710..85055a6a 100644 Binary files a/public/logo.png and b/public/logo.png differ diff --git a/src/assets/logo.png b/src/assets/logo.png index cda5d710..85055a6a 100644 Binary files a/src/assets/logo.png and b/src/assets/logo.png differ diff --git a/src/components/Countdown.module.scss b/src/components/Countdown.module.scss index b61baf5c..4b74177a 100644 --- a/src/components/Countdown.module.scss +++ b/src/components/Countdown.module.scss @@ -56,6 +56,49 @@ line-height: 1; } +// Compact — one line, unit letters as a suffix on the digits instead of a +// caption underneath: `069d 22h 43m 21s`. Used where the clock sits under a +// poster-scale statement and four captioned stubs would out-weigh it. +.countdownCompact { + gap: 0.55rem; + + // Sized to sit beside the footing strip's DATE/PLACE values, not tower + // over them — the full four-stub clock is display-scale on its own line; + // this one shares a row with the rest of the meta. + .value { + font-size: clamp(1.3rem, 1.75vw, 1.7rem); + } +} + +// Reserves the days digit's own width at its longest (three figures, the +// stretch above 99 days) so the 100 → 99 rollover doesn't nudge the suffix +// and everything after it — a printed leading zero would do the same job +// but read as part of the count. +.valueDays { + min-width: 3ch; + text-align: right; +} + +.unitCompact { + flex-direction: row; + align-items: baseline; + gap: 0.06em; + + .label { + font-family: var(--font-bebas-neue), sans-serif; + font-size: clamp(1rem, 1.4vw, 1.3rem); + letter-spacing: 0.02em; + text-transform: lowercase; + color: rgba(240, 237, 230, 0.5); + } +} + +@media (max-width: 600px) { + .countdownCompact .value { + font-size: 1.3rem; + } +} + @media (max-width: 600px) { .countdown { gap: 0.35rem; diff --git a/src/components/Countdown.tsx b/src/components/Countdown.tsx index 13c72c03..e230e935 100644 --- a/src/components/Countdown.tsx +++ b/src/components/Countdown.tsx @@ -14,34 +14,53 @@ function calcTimeLeft(): TimeLeft { const diff = TARGET - Date.now(); if (diff <= 0) { - return { days: '000', hours: '00', minutes: '00', seconds: '00' }; + return { days: '0', hours: '00', minutes: '00', seconds: '00' }; } return { - days: String(Math.floor(diff / (1000 * 60 * 60 * 24))).padStart(3, '0'), + days: String(Math.floor(diff / (1000 * 60 * 60 * 24))), hours: String(Math.floor((diff % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60))).padStart(2, '0'), minutes: String(Math.floor((diff % (1000 * 60 * 60)) / (1000 * 60))).padStart(2, '0'), seconds: String(Math.floor((diff % (1000 * 60)) / 1000)).padStart(2, '0'), }; } -const UNITS: { key: keyof TimeLeft; label: string }[] = [ - { key: 'days', label: 'Days' }, - { key: 'hours', label: 'Hrs' }, - { key: 'minutes', label: 'Min' }, - { key: 'seconds', label: 'Sec' }, +const UNITS: { key: keyof TimeLeft; label: string; suffix: string }[] = [ + { key: 'days', label: 'Days', suffix: 'd' }, + { key: 'hours', label: 'Hrs', suffix: 'h' }, + { key: 'minutes', label: 'Min', suffix: 'm' }, + { key: 'seconds', label: 'Sec', suffix: 's' }, ]; -const INITIAL_TIME: TimeLeft = { days: '000', hours: '00', minutes: '00', seconds: '00' }; +const INITIAL_TIME: TimeLeft = { days: '0', hours: '00', minutes: '00', seconds: '00' }; -export default function Countdown() { +interface Props { + /** + * `069d 22h 43m 21s` on one line instead of four labelled stubs separated + * by colons. The suffix is real rendered text on the unit, not a stylesheet + * `::after` — a generated-content suffix reads fine visually but is + * invisible to anything that inspects the DOM text. + */ + compact?: boolean; + /** + * Drop the seconds unit — `54D 10H 34M`, one rhythm. Seconds ticking next + * to the hero's own rotating topic is a second, unrelated clock in the + * same shot. Without seconds the display only needs to update once a + * minute; the 15s interval is just slack so a stale minute never survives + * more than that long, not a tick visitors are meant to notice. + */ + showSeconds?: boolean; +} + +export default function Countdown({ compact = false, showSeconds = true }: Props) { const [time, setTime] = useState(INITIAL_TIME); + const units = showSeconds ? UNITS : UNITS.filter((u) => u.key !== 'seconds'); useEffect(() => { setTime(calcTimeLeft()); - const id = setInterval(() => setTime(calcTimeLeft()), 1000); + const id = setInterval(() => setTime(calcTimeLeft()), showSeconds ? 1000 : 15000); return () => clearInterval(id); - }, []); + }, [showSeconds]); // The clock is decorative — screen readers get the static "doors open" // sentence instead. A per-second aria-label would spam AT without adding @@ -54,13 +73,13 @@ export default function Countdown() { return ( <> Doors open on 30 October 2026 at 9:00 AM Central European Time. -