diff --git a/src/assets/styles/player.css b/src/assets/styles/player.css index 83a2bee..72ae265 100644 --- a/src/assets/styles/player.css +++ b/src/assets/styles/player.css @@ -1,6 +1,36 @@ -/* player.css moved to /public/styles/player.css — kept empty here to avoid - accidental inclusion by the build tool during development. */ +/* Universal box-sizing for consistency */ +*, +*::before, +*::after { + box-sizing: border-box; +} +:root { + --lrc-text-color: #333; /* darker text */ + --lrc-bg-color: rgba(0, 0, 0, 0.05); + --lrc-active-color: #000; /* bold black for active */ + --lrc-active-shadow: none; /* no glow in light mode */ + --lrc-hover-color: #005fcc; /* darker blue hover */ +} + +[data-theme="dark"] { + --lrc-text-color: #ccc; /* original gray */ + --lrc-bg-color: rgba(255, 255, 255, 0.02); + --lrc-active-color: #fff; /* bright white for active */ + --lrc-active-shadow: 0 0 4px rgba(212, 175, 55, 0.6); /* gold glow */ + --lrc-hover-color: #4fa2ff; /* original blue hover */ +} + +body { + font-family: sans-serif; + width: 100%; + height: 100%; + margin: 0; + padding: 0; + min-width: 100vw; + min-height: 100vh; + /* background: linear-gradient(-45deg, #FFCDD2 50%, #B2EBF2 50%); */ +} /* Container for the player and album cover */ .music-container { diff --git a/src/components/AppLayout.jsx b/src/components/AppLayout.jsx index 0e73510..8ae881b 100644 --- a/src/components/AppLayout.jsx +++ b/src/components/AppLayout.jsx @@ -30,11 +30,10 @@ export default function Root({ child, user = undefined, ...props }) { // runtime flag `window.__IS_SUBSITE` from the server layout so pages // don't need to pass guards. const isSubsite = typeof document !== 'undefined' && document.documentElement.getAttribute('data-subsite') === 'true'; - // Helpful runtime debugging: only log when child changes so we don't spam - // the console on every render. Use an effect so output is stable. + // Log when the active child changes (DEV only) useEffect(() => { try { - if (typeof console !== 'undefined' && typeof document !== 'undefined') { + if (typeof console !== 'undefined' && typeof document !== 'undefined' && import.meta.env.DEV) { console.debug(`[AppLayout] child=${String(child)}, data-subsite=${document.documentElement.getAttribute('data-subsite')}`); } } catch (e) { @@ -58,13 +57,13 @@ export default function Root({ child, user = undefined, ...props }) { useEffect(() => { let mounted = true; if (wantPlayer) { - try { console.debug('[AppLayout] dynamic-import: requesting AudioPlayer'); } catch (e) { } + if (import.meta.env.DEV) { try { console.debug('[AppLayout] dynamic-import: requesting AudioPlayer'); } catch (e) { } } import('./AudioPlayer.jsx') .then((mod) => { if (!mounted) return; // set the component factory setPlayerComp(() => mod.default ?? null); - try { console.debug('[AppLayout] AudioPlayer import succeeded'); } catch (e) { } + if (import.meta.env.DEV) { try { console.debug('[AppLayout] AudioPlayer import succeeded'); } catch (e) { } } }) .catch((err) => { console.error('[AppLayout] AudioPlayer import failed', err); @@ -94,7 +93,7 @@ export default function Root({ child, user = undefined, ...props }) { {child == "LoginPage" && ()} {child == "LyricSearch" && ()} {child == "Player" && !isSubsite && PlayerComp && ( - Loading player...}> + )} diff --git a/src/components/AudioPlayer.jsx b/src/components/AudioPlayer.jsx index 32da0be..328368f 100644 --- a/src/components/AudioPlayer.jsx +++ b/src/components/AudioPlayer.jsx @@ -1,11 +1,9 @@ import React, { useState, useEffect, useRef, Suspense, lazy, useMemo, useCallback } from "react"; +import "@styles/player.css"; import { metaData } from "../config"; import Play from "@mui/icons-material/PlayArrow"; import Pause from "@mui/icons-material/Pause"; -// Load AudioPlayer CSS at runtime only when the player mounts on the client. -// This avoids including the stylesheet in pages where the AudioPlayer never -// gets loaded (subsidiary/whitelabel sites). We dynamically import the -// stylesheet inside a client-only effect below. +import "@styles/player.css"; import { Dialog } from "primereact/dialog"; import { AutoComplete } from "primereact/autocomplete"; import { DataTable } from "primereact/datatable"; @@ -51,31 +49,6 @@ const STATIONS = { export default function Player({ user }) { - // Log lifecycle so we can confirm the player mounted in the browser - useEffect(() => { - // Load the player stylesheet from /public/styles/player.css so it will be - // requested at runtime only when the AudioPlayer mounts. This prevents the - // CSS from being included as a route asset for subsites. - try { - if (typeof window !== 'undefined') { - if (!document.getElementById('audio-player-css')) { - const link = document.createElement('link'); - link.id = 'audio-player-css'; - link.rel = 'stylesheet'; - link.href = '/styles/player.css'; - link.onload = () => { try { console.debug('[AudioPlayer] CSS loaded (link)'); } catch (e) { } }; - link.onerror = (err) => { console.warn('[AudioPlayer] CSS link failed', err); }; - document.head.appendChild(link); - } - } - } catch (e) { - // ignore - } - try { console.debug('[AudioPlayer] mounted'); } catch (e) { } - return () => { - try { console.debug('[AudioPlayer] unmounted'); } catch (e) { } - }; - }, []); // Inject custom paginator styles useEffect(() => { const styleId = 'queue-paginator-styles'; diff --git a/src/components/BaseHead.astro b/src/components/BaseHead.astro index 022b496..1a7153c 100644 --- a/src/components/BaseHead.astro +++ b/src/components/BaseHead.astro @@ -20,7 +20,7 @@ const trimmedTitle = title?.trim(); const seoTitle = trimmedTitle || metaData.title; const shareTitle = isWhitelabel ? (trimmedTitle || (metaData.shareTitle ?? metaData.title)) : (trimmedTitle ? `${trimmedTitle} | ${metaData.title}` : (metaData.shareTitle ?? metaData.title)); const seoTitleTemplate = isWhitelabel ? "%s" : (trimmedTitle ? `%s | ${metaData.title}` : "%s"); -const shareDescription = description ?? metaData.shareDescription ?? metaData.description; +const shareDescription = isWhitelabel ? "%s" : (description ?? metaData.shareDescription ?? metaData.description); const canonicalUrl = url?.href ?? metaData.baseUrl; const shareImage = new URL(image ?? metaData.ogImage, metaData.baseUrl).toString(); const shareImageAlt = metaData.shareImageAlt ?? metaData.shareTitle ?? metaData.title; diff --git a/src/components/Lighting.jsx b/src/components/Lighting.jsx index de63a8c..1cd86c7 100644 --- a/src/components/Lighting.jsx +++ b/src/components/Lighting.jsx @@ -27,7 +27,7 @@ export default function Lighting() { }, []); const handleColorChange = (color) => { - console.log('Handle color change:', color); + if (import.meta.env.DEV) console.debug('Handle color change:', color); const { r, g, b } = color.rgb; updateLighting({ ...state, @@ -128,7 +128,7 @@ export default function Lighting() { s / 100, // saturation: 0-100 -> 0-1 (v ?? 100) / 100 // value: 0-100 -> 0-1, default to 1 if undefined ); - console.log('Converting color:', color.hsva, 'to RGB:', rgb); + if (import.meta.env.DEV) console.debug('Converting color:', color.hsva, 'to RGB:', rgb); updateLighting({ ...state, red: rgb.red, diff --git a/src/components/req/ReqForm.jsx b/src/components/req/ReqForm.jsx index 64c785a..b67ae54 100644 --- a/src/components/req/ReqForm.jsx +++ b/src/components/req/ReqForm.jsx @@ -1,7 +1,7 @@ import React, { useState, useEffect } from "react"; import { toast } from "react-toastify"; import { Button } from "@mui/joy"; -import { Dropdown } from "primereact/dropdown/dropdown.esm.js"; +// Dropdown not used in this form; removed to avoid unused-import warnings import { AutoComplete } from "primereact/autocomplete/autocomplete.esm.js"; import { InputText } from "primereact/inputtext/inputtext.esm.js"; @@ -133,7 +133,8 @@ export default function ReqForm() { if (e.value.year) setYear(e.value.year); setSelectedOverview(e.value.overview || ""); }} - placeholder="Enter movie or TV show title" + placeholder="Enter movie or TV title" + title="Enter movie or TV show title" className="w-full" inputClassName="w-full border-2 border-gray-200 dark:border-gray-600 rounded-xl px-4 py-3 focus:border-[#12f8f4] transition-colors" panelClassName="border-2 border-gray-200 dark:border-gray-600 rounded-xl" diff --git a/src/config.js b/src/config.js index 4e487cc..92e1d7f 100644 --- a/src/config.js +++ b/src/config.js @@ -32,8 +32,6 @@ export const WHITELABELS = { }; // Subsite mapping: host -> site path -// Keep this in sync with your page layout (e.g. src/pages/subsites/req/ -> /subsites/req) export const SUBSITES = { 'req.boatson.boats': '/subsites/req', - 'subsite2.codey.lol': '/subsite2', }; \ No newline at end of file diff --git a/src/layouts/Base.astro b/src/layouts/Base.astro index 5c1e8bd..32aecbd 100644 --- a/src/layouts/Base.astro +++ b/src/layouts/Base.astro @@ -56,7 +56,9 @@ if (!whitelabel) { const isSubsite = (Astro.request as any)?.locals?.isSubsite ?? Boolean(whitelabel || detectedSubsite); // Debug logging -console.log(`[Base.astro] host: ${host}, forcedParam: ${forcedParam}, isReq: ${isReq}, whitelabel: ${JSON.stringify(whitelabel)}`); +if (import.meta.env.DEV) { + console.log(`[Base.astro] host: ${host}, forcedParam: ${forcedParam}, isReq: ${isReq}, whitelabel: ${JSON.stringify(whitelabel)}`); +} --- @@ -68,7 +70,6 @@ console.log(`[Base.astro] host: ${host}, forcedParam: ${forcedParam}, isReq: ${i /> - +