diff --git a/web/src/components/LibraryPanel.tsx b/web/src/components/LibraryPanel.tsx index 1faa97b..c52d7de 100644 --- a/web/src/components/LibraryPanel.tsx +++ b/web/src/components/LibraryPanel.tsx @@ -63,7 +63,7 @@ function MiniWave({ songId, active }: { songId: string; active: boolean }) { height: `${h}%`, borderRadius: 1, background: active - ? `rgba(139,92,246,${0.3 + (h / 100) * 0.5})` + ? `rgba(20,184,166,${0.3 + (h / 100) * 0.5})` : "rgba(255,255,255,0.1)", transition: "background 0.15s", }} @@ -76,7 +76,7 @@ function MiniWave({ songId, active }: { songId: string; active: boolean }) { // ── Tag badge ───────────────────────────────────────────────────────────────── const TAG_COLORS: Record = { - jam: { bg: "rgba(139,92,246,0.12)", color: "#a78bfa" }, + jam: { bg: "rgba(20,184,166,0.12)", color: "#2dd4bf" }, riff: { bg: "rgba(34,211,238,0.1)", color: "#67e8f9" }, idea: { bg: "rgba(52,211,153,0.1)", color: "#6ee7b7" }, }; @@ -117,19 +117,19 @@ function TrackRow({ padding: "9px 20px", cursor: "pointer", position: "relative", - background: active ? "rgba(139,92,246,0.06)" : hovered ? "rgba(255,255,255,0.025)" : "transparent", + background: active ? "rgba(20,184,166,0.06)" : hovered ? "rgba(255,255,255,0.025)" : "transparent", transition: "background 0.12s", }} > {active && ( -
+
)} {String(index + 1).padStart(2, "0")} - + {song.title} @@ -191,7 +191,7 @@ function SessionGroup({ > {formatSessionDate(session.date)} @@ -280,7 +280,7 @@ export function LibraryPanel({ bandId, selectedSongId, onSelectSong }: LibraryPa flex: 1, display: "flex", flexDirection: "column", - background: "#10131f", + background: "#0c1612", height: "100%", overflow: "hidden", }}> @@ -292,8 +292,8 @@ export function LibraryPanel({ bandId, selectedSongId, onSelectSong }: LibraryPa {/* Search */} -
(e.currentTarget.style.borderColor = "rgba(139,92,246,0.4)")} +
(e.currentTarget.style.borderColor = "rgba(20,184,166,0.4)")} onBlurCapture={(e) => (e.currentTarget.style.borderColor = border)} > @@ -304,7 +304,7 @@ export function LibraryPanel({ bandId, selectedSongId, onSelectSong }: LibraryPa value={search} onChange={(e) => setSearch(e.target.value)} placeholder="Search recordings…" - style={{ background: "none", border: "none", outline: "none", fontFamily: "inherit", fontSize: 13, color: "#e8e9f0", flex: 1, caretColor: "#a78bfa" }} + style={{ background: "none", border: "none", outline: "none", fontFamily: "inherit", fontSize: 13, color: "#e8e9f0", flex: 1, caretColor: "#2dd4bf" }} /> {search && (
+
{getInitials(c.author_name)}
{c.author_name} - {formatTime(c.timestamp!)} + {formatTime(c.timestamp!)}
{c.body.length > 80 ? c.body.slice(0, 80) + "…" : c.body} @@ -271,7 +271,7 @@ export function PlayerPanel({ songId, bandId, onBack }: PlayerPanelProps) { // ── Render ──────────────────────────────────────────────────────────────── return ( -
+
{/* Breadcrumb / header */}
@@ -304,7 +304,7 @@ export function PlayerPanel({ songId, bandId, onBack }: PlayerPanelProps) {
{versions.map((v) => ( ))} @@ -340,7 +340,7 @@ export function PlayerPanel({ songId, bandId, onBack }: PlayerPanelProps) { {/* Time bar */}
- {formatTime(currentTime)} + {formatTime(currentTime)} {isReady && duration > 0 ? formatTime(duration / 2) : "—"} {isReady ? formatTime(duration) : "—"}
@@ -352,9 +352,9 @@ export function PlayerPanel({ songId, bandId, onBack }: PlayerPanelProps) { @@ -369,7 +369,7 @@ export function PlayerPanel({ songId, bandId, onBack }: PlayerPanelProps) {
Comments {comments && comments.length > 0 && ( - {comments.length} + {comments.length} )}
@@ -383,8 +383,8 @@ export function PlayerPanel({ songId, bandId, onBack }: PlayerPanelProps) { )}
-
- {isPlaying &&
} +
+ {isPlaying &&
} {formatTime(currentTime)}
· pins to playhead @@ -395,7 +395,7 @@ export function PlayerPanel({ songId, bandId, onBack }: PlayerPanelProps) { onFocus={() => setComposeFocused(true)} onBlur={() => { if (!commentBody.trim()) setComposeFocused(false); }} placeholder="What do you hear at this moment…" - style={{ width: "100%", background: "rgba(255,255,255,0.04)", border: composeFocused ? "1px solid rgba(139,92,246,0.35)" : `1px solid rgba(255,255,255,0.07)`, borderRadius: 7, padding: "8px 10px", color: "#e8e9f0", fontSize: 12, resize: "none", outline: "none", fontFamily: "inherit", height: composeFocused ? 68 : 42, transition: "height 0.18s, border-color 0.15s", boxSizing: "border-box" }} + style={{ width: "100%", background: "rgba(255,255,255,0.04)", border: composeFocused ? "1px solid rgba(20,184,166,0.35)" : `1px solid rgba(255,255,255,0.07)`, borderRadius: 7, padding: "8px 10px", color: "#e8e9f0", fontSize: 12, resize: "none", outline: "none", fontFamily: "inherit", height: composeFocused ? 68 : 42, transition: "height 0.18s, border-color 0.15s", boxSizing: "border-box" }} /> {composeFocused && (
@@ -410,7 +410,7 @@ export function PlayerPanel({ songId, bandId, onBack }: PlayerPanelProps) {
@@ -427,15 +427,15 @@ export function PlayerPanel({ songId, bandId, onBack }: PlayerPanelProps) { return (
+ style={{ marginBottom: 14, paddingBottom: 14, borderBottom: `1px solid rgba(255,255,255,0.04)`, borderRadius: isNearPlayhead ? 6 : undefined, background: isNearPlayhead ? "rgba(20,184,166,0.04)" : undefined, border: isNearPlayhead ? "1px solid rgba(20,184,166,0.12)" : undefined, padding: isNearPlayhead ? 8 : undefined }}>
{c.author_name} {c.timestamp != null && ( diff --git a/web/src/components/Sidebar.tsx b/web/src/components/Sidebar.tsx index 6ddff4c..821c344 100755 --- a/web/src/components/Sidebar.tsx +++ b/web/src/components/Sidebar.tsx @@ -71,7 +71,7 @@ function NavItem({ icon, label, active, onClick, disabled, badge, collapsed }: N const [hovered, setHovered] = useState(false); const fg = active - ? "#a78bfa" + ? "#2dd4bf" : disabled ? "rgba(255,255,255,0.16)" : hovered @@ -79,7 +79,7 @@ function NavItem({ icon, label, active, onClick, disabled, badge, collapsed }: N : "rgba(232,233,240,0.35)"; const bg = active - ? "rgba(139,92,246,0.12)" + ? "rgba(20,184,166,0.12)" : hovered && !disabled ? "rgba(255,255,255,0.04)" : "transparent"; @@ -115,7 +115,7 @@ function NavItem({ icon, label, active, onClick, disabled, badge, collapsed }: N
)} @@ -129,7 +129,7 @@ function NavItem({ icon, label, active, onClick, disabled, badge, collapsed }: N {!collapsed && badge != null && badge > 0 && ( {badge} @@ -168,13 +168,13 @@ export function Sidebar({ children }: { children: React.ReactNode }) { const border = "rgba(255,255,255,0.06)"; return ( -
+
{/* ── Sidebar ── */} {/* ── Main content ── */} -
+
{children} diff --git a/web/src/components/TopBandBar.tsx b/web/src/components/TopBandBar.tsx index 5660a9f..19dd60e 100644 --- a/web/src/components/TopBandBar.tsx +++ b/web/src/components/TopBandBar.tsx @@ -48,7 +48,7 @@ export function TopBandBar() { gap: 8, padding: "0 20px", borderBottom: `1px solid ${border}`, - background: "#10131f", + background: "#0c1612", zIndex: 10, }}> {/* Band switcher */} @@ -72,10 +72,10 @@ export function TopBandBar() { <>
{getInitials(activeBand.name)}
@@ -93,7 +93,7 @@ export function TopBandBar() {
{ if (band.id !== currentBandId) e.currentTarget.style.background = "rgba(255,255,255,0.04)"; }} onMouseLeave={(e) => { if (band.id !== currentBandId) e.currentTarget.style.background = "transparent"; }} > -
+
{getInitials(band.name)}
{band.name} {band.id === currentBandId && ( - + )} ))} diff --git a/web/src/index.css b/web/src/index.css index 12647e0..c351e48 100755 --- a/web/src/index.css +++ b/web/src/index.css @@ -16,11 +16,11 @@ input, textarea, button, select { /* ── Design system (dark only — no light mode in v1) ─────────────────────── */ :root { - /* v2 dark-space palette */ - --bg: #0c0e1a; - --bg-card: #10131f; - --bg-raised: #151828; - --bg-hover: #1a1e30; + /* v2 dark-teal palette */ + --bg: #080f0d; + --bg-card: #0c1612; + --bg-raised: #101c18; + --bg-hover: #142420; --bg-subtle: rgba(255,255,255,0.025); --bg-inset: rgba(255,255,255,0.04); --border: rgba(255,255,255,0.06); @@ -29,12 +29,12 @@ input, textarea, button, select { --text: #e8e9f0; --text-muted: rgba(232,233,240,0.55); --text-subtle: rgba(232,233,240,0.28); - /* Violet accent */ - --accent: #8b5cf6; - --accent-light: #a78bfa; - --accent-hover: #9f70f8; - --accent-bg: rgba(139,92,246,0.12); - --accent-border: rgba(139,92,246,0.3); + /* Teal accent */ + --accent: #14b8a6; + --accent-light: #2dd4bf; + --accent-hover: #10a89a; + --accent-bg: rgba(20,184,166,0.12); + --accent-border: rgba(20,184,166,0.3); --accent-fg: #ffffff; --teal: #34d399; --teal-bg: rgba(52,211,153,0.1); @@ -53,7 +53,7 @@ input, textarea, button, select { /* Bottom Navigation Bar */ nav[style*="position: fixed"] { display: flex; - background: #0b0b0e; + background: #060d0b; border-top: 1px solid rgba(255, 255, 255, 0.06); padding: 8px 16px; } diff --git a/web/src/pages/SettingsPage.tsx b/web/src/pages/SettingsPage.tsx index 5e2e546..561e048 100755 --- a/web/src/pages/SettingsPage.tsx +++ b/web/src/pages/SettingsPage.tsx @@ -95,8 +95,8 @@ function Input(props: React.InputHTMLAttributes) { onBlur={(e) => { setFocused(false); props.onBlur?.(e); }} style={{ width: "100%", padding: "8px 12px", - background: "#151828", - border: `1px solid ${focused ? "rgba(139,92,246,0.4)" : border}`, + background: "#101c18", + border: `1px solid ${focused ? "rgba(20,184,166,0.4)" : border}`, borderRadius: 8, color: "#e8e9f0", fontSize: 13, fontFamily: "inherit", outline: "none", boxSizing: "border-box", @@ -114,13 +114,13 @@ function SaveBtn({ pending, saved, onClick }: { pending: boolean; saved: boolean disabled={pending} style={{ padding: "8px 20px", borderRadius: 8, - background: saved ? "rgba(52,211,153,0.12)" : "linear-gradient(135deg, #7b5cf6, #06b6d4)", + background: saved ? "rgba(52,211,153,0.12)" : "linear-gradient(135deg, #0d9488, #06b6d4)", border: saved ? "1px solid rgba(52,211,153,0.3)" : "none", color: saved ? "#34d399" : "white", cursor: pending ? "default" : "pointer", fontSize: 13, fontWeight: 600, fontFamily: "inherit", transition: "all 0.2s", - boxShadow: saved ? "none" : "0 2px 12px rgba(139,92,246,0.3)", + boxShadow: saved ? "none" : "0 2px 12px rgba(20,184,166,0.3)", }} > {pending ? "Saving…" : saved ? "Saved ✓" : "Save"} @@ -211,7 +211,7 @@ function ProfileSection({ me }: { me: MemberRead }) { } finally { setUploading(false); } }} /> -
)} {inviteLink && ( -
+

Invite link (copied · valid 72h):

- {inviteLink} + {inviteLink} @@ -528,7 +528,7 @@ function MembersSection({ bandId, band, amAdmin, members, membersLoading }: { ba
{m.display_name}
{m.email}
- + {m.role} {amAdmin && m.role !== "admin" && ( @@ -545,7 +545,7 @@ function MembersSection({ bandId, band, amAdmin, members, membersLoading }: { ba {/* Role legend */}
-
Admin
+
Admin
Upload, delete, manage members and storage
@@ -627,9 +627,9 @@ function BandSection({ bandId, band }: { bandId: string; band: Band }) {
{tags.map((t) => ( - + {t} - + ))}
@@ -671,13 +671,13 @@ function NavItem({ label, active, onClick }: { label: string; active: boolean; o padding: "8px 10px", borderRadius: 8, border: "none", cursor: "pointer", fontSize: 13, fontFamily: "inherit", fontWeight: active ? 600 : 400, - background: active ? "rgba(139,92,246,0.1)" : hovered ? "rgba(255,255,255,0.04)" : "transparent", - color: active ? "#a78bfa" : hovered ? "rgba(232,233,240,0.75)" : "rgba(232,233,240,0.45)", + background: active ? "rgba(20,184,166,0.1)" : hovered ? "rgba(255,255,255,0.04)" : "transparent", + color: active ? "#2dd4bf" : hovered ? "rgba(232,233,240,0.75)" : "rgba(232,233,240,0.45)", transition: "all 0.12s", position: "relative", }} > - {active &&
} + {active &&
} {label} ); @@ -744,7 +744,7 @@ export function SettingsPage() { {section !== "profile" || searchParams.has("section") ? (
@@ -782,7 +782,7 @@ export function SettingsPage() {
{/* Left nav */} -