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
/>
-
+