diff --git a/media_server/static/css/styles.css b/media_server/static/css/styles.css index a9c0454..86148f0 100644 --- a/media_server/static/css/styles.css +++ b/media_server/static/css/styles.css @@ -4294,21 +4294,22 @@ header .brand-sub { margin: 14px 0 36px; border-radius: 0; gap: 0; + position: relative; + overflow-x: auto; + scrollbar-width: none; } +.tab-bar::-webkit-scrollbar { display: none; } +/* Hide the legacy tab-indicator entirely — we use ::after on .tab-btn.active instead */ .tab-indicator { - background: var(--copper); - box-shadow: 0 0 12px var(--copper-glow); - height: 2px; - bottom: -1px; - border-radius: 0; + display: none !important; } .tab-btn { background: transparent; border: 0; color: var(--ink-mute); - padding: 18px 22px 16px; + padding: 18px 26px 16px; border-radius: 0; font-family: var(--sans); font-size: 13px; @@ -4316,8 +4317,11 @@ header .brand-sub { letter-spacing: 0.04em; transition: color 180ms var(--ease); position: relative; - gap: 10px; + display: inline-flex; align-items: baseline; + gap: 10px; + white-space: nowrap; + cursor: pointer; } .tab-btn:hover { color: var(--ink-soft); background: transparent; } .tab-btn.active { @@ -4330,8 +4334,35 @@ header .brand-sub { font-variation-settings: 'opsz' 60; } -.tab-btn svg { opacity: 0.7; } -.tab-btn.active svg { opacity: 1; color: var(--copper); } +/* Tab number badge (replaces the icon) */ +.tab-btn .tab-num { + font-family: var(--mono); + font-style: normal; + font-size: 10px; + color: var(--ink-faint); + letter-spacing: 0.15em; + font-weight: 400; +} +.tab-btn.active .tab-num { + color: var(--copper); +} + +/* Hide any remaining legacy SVG icons on tabs */ +.tab-btn svg { + display: none; +} + +/* Active tab underline — only under the active tab */ +.tab-btn.active::after { + content: ""; + position: absolute; + bottom: -1px; + left: 0; + right: 0; + height: 2px; + background: var(--copper); + box-shadow: 0 0 12px var(--copper-glow); +} /* ─── Update + connection banners ───────────────────────────── */ .update-banner, @@ -5156,17 +5187,102 @@ body.visualizer-active .vinyl-stage .spectrogram-canvas { } /* ═══════════════════════════════════════════════════════════════ - MINI PLAYER — console strip + MINI PLAYER — sticky console strip (3-column grid) ═══════════════════════════════════════════════════════════════ */ .mini-player { - background: linear-gradient(180deg, rgba(14, 13, 11, 0.7) 0%, rgba(14, 13, 11, 0.96) 30%); + /* Override legacy display: flex with explicit grid */ + display: grid !important; + grid-template-columns: minmax(0, 1fr) auto minmax(0, 1fr) auto; + column-gap: 24px; + row-gap: 0; + align-items: center; + background: linear-gradient(180deg, rgba(14, 13, 11, 0.72) 0%, rgba(14, 13, 11, 0.96) 30%); backdrop-filter: blur(20px) saturate(160%); -webkit-backdrop-filter: blur(20px) saturate(160%); border-top: 1px solid var(--rule-strong); box-shadow: none; - padding: 14px 32px; - gap: 28px; - position: relative; + padding: 12px 32px; + /* Anchor firmly to the bottom of the viewport */ + position: fixed !important; + bottom: 0 !important; + left: 0 !important; + right: 0 !important; + z-index: 1000; +} + +/* Top edge progress line in copper */ +.mini-player::before { + background: var(--copper) !important; + height: 2px !important; + box-shadow: 0 0 8px var(--copper-glow); +} + +/* Column 1: track info */ +.mini-player .mini-player-info { + grid-column: 1; + grid-row: 1; + min-width: 0; + overflow: hidden; + display: flex; + align-items: center; + gap: 12px; +} + +/* Column 2: transport (centered) */ +.mini-player .mini-controls { + grid-column: 2; + grid-row: 1; + justify-self: center; + display: flex; + align-items: center; + gap: 12px; + flex-shrink: 0; +} + +/* Column 3: progress (timecodes + bar) */ +.mini-player .mini-progress-container { + grid-column: 3; + grid-row: 1; + display: flex; + flex-direction: column; + gap: 4px; + justify-self: stretch; + align-items: stretch; + min-width: 180px; + max-width: 360px; + margin: 0 auto; +} +.mini-player .mini-progress-container .mini-time-display { + display: flex; + justify-content: space-between; +} + +/* Column 4: volume controls */ +.mini-player .mini-volume-container { + grid-column: 4; + grid-row: 1; + justify-self: end; + display: flex; + align-items: center; + gap: 8px; + flex-shrink: 0; +} + +@media (max-width: 880px) { + .mini-player { + grid-template-columns: minmax(0, 1fr) auto auto; + column-gap: 14px; + } + .mini-player .mini-progress-container { display: none; } + .mini-player .mini-volume-container { grid-column: 3; } +} + +@media (max-width: 540px) { + .mini-player { + grid-template-columns: minmax(0, 1fr) auto; + padding: 10px 14px; + } + .mini-player .mini-volume-container { display: none; } } .mini-player::before { @@ -6507,13 +6623,22 @@ body.visualizer-active .now-playing .spectrogram-canvas { .now-playing #track-title { font-family: var(--serif); font-weight: 400; - font-size: clamp(42px, 5.6vw, 78px); - line-height: 0.96; + font-size: clamp(34px, 4.4vw, 64px); + line-height: 0.98; letter-spacing: -0.02em; font-variation-settings: 'opsz' 144; margin-bottom: 18px; color: var(--ink); margin-top: 0; + /* Long titles get clamped to 3 lines with ellipsis */ + display: -webkit-box; + -webkit-line-clamp: 3; + line-clamp: 3; + -webkit-box-orient: vertical; + overflow: hidden; + word-break: break-word; + overflow-wrap: anywhere; + hyphens: auto; } .now-playing .track-title em { font-style: italic; @@ -6531,7 +6656,6 @@ body.visualizer-active .now-playing .spectrogram-canvas { margin-bottom: 4px; margin-top: 0; } - .now-playing .track-album, .now-playing #album { font-family: var(--sans); @@ -6543,6 +6667,14 @@ body.visualizer-active .now-playing .spectrogram-canvas { margin-top: 0; } +/* Hide byline/album rows when their content is empty so they + don't leave a stretched blank gap. JS leaves them empty when + the source provides no metadata. */ +.now-playing #artist:empty, +.now-playing #album:empty { + display: none; +} + /* ─── 2-cell metadata grid ────────────────────────────────── */ .now-playing .meta-grid { display: grid; @@ -6772,20 +6904,13 @@ body.visualizer-active .now-playing .spectrogram-canvas { width: 24px; height: 24px; } -/* VU cluster — display-only, click toggles mute */ +/* VU cluster — meter + readout + integrated volume control */ .now-playing .vu-cluster { margin-left: auto; display: flex; align-items: center; gap: 16px; - cursor: pointer; user-select: none; - transition: opacity 200ms var(--ease); -} -.now-playing .vu-cluster:hover { opacity: 0.85; } -.now-playing .vu-cluster:focus-visible { - outline: 1px solid var(--copper); - outline-offset: 4px; } .now-playing .vu-cluster.muted .vu-needle { background: linear-gradient(to top, var(--rust) 0%, var(--ink-mute) 100%); @@ -6793,6 +6918,78 @@ body.visualizer-active .now-playing .spectrogram-canvas { } .now-playing .vu-cluster.muted .vu-readout strong { color: var(--rust); } +/* Integrated volume control: tiny mute icon + slim copper slider */ +.now-playing .vu-volume { + display: flex; + align-items: center; + gap: 10px; + padding-left: 12px; + border-left: 1px solid var(--rule); + margin-left: 4px; +} +.now-playing .vu-volume .mute-btn { + background: transparent; + border: 1px solid var(--rule-strong); + color: var(--ink-soft); + width: 30px; + height: 30px; + border-radius: 50%; + padding: 0; + margin: 0; + display: inline-flex; + align-items: center; + justify-content: center; + cursor: pointer; + transition: all 180ms var(--ease); + flex-shrink: 0; +} +.now-playing .vu-volume .mute-btn:hover { + border-color: var(--copper); + color: var(--copper); + background: rgba(224, 128, 56, 0.06); +} +.now-playing .vu-volume .mute-btn svg { + width: 14px; + height: 14px; + fill: currentColor; +} +.now-playing .vu-volume #volume-slider { + -webkit-appearance: none; + appearance: none; + width: 80px; + height: 2px; + background: var(--rule-strong); + border-radius: 0; + margin: 0; + padding: 0; + cursor: pointer; + flex: none; +} +.now-playing .vu-volume #volume-slider::-webkit-slider-thumb { + -webkit-appearance: none; + appearance: none; + width: 10px; + height: 10px; + background: var(--copper); + border-radius: 50%; + box-shadow: 0 0 8px var(--copper-glow); + border: 0; + cursor: grab; +} +.now-playing .vu-volume #volume-slider::-moz-range-thumb { + width: 10px; + height: 10px; + background: var(--copper); + border-radius: 50%; + border: 0; + cursor: grab; +} +.now-playing .vu-volume #volume-slider::-moz-range-track { + height: 2px; + background: var(--rule-strong); + border-radius: 0; +} + .now-playing .vu-meter { position: relative; width: 140px; diff --git a/media_server/static/index.html b/media_server/static/index.html index ab19ae9..42953ed 100644 --- a/media_server/static/index.html +++ b/media_server/static/index.html @@ -131,27 +131,27 @@ - +
@@ -247,7 +247,7 @@ -