fix(ui): close gaps with Studio Reference mockup

Side-by-side comparison surfaced several layout regressions vs. the
mockup. This commit lands all of them at once.

Header
- Restore centered "Media Server / Studio Reference Edition" wordmark
  in italic Fraunces
- Move folio marks to fixed page corners (visible on every tab):
  TL = green pulse + "Connected · Local 8765"
  TR = "Vol. I — Studio Reference · v0.x.x"
- Replace boxed version-label badge with copper mono inline in folio.tr
- Reduce header-to-content gap (container padding-top 28→56 with the
  folio now anchored above)

Player view
- Spectrum bars: smaller height (32px), centered with max-width so
  they don't span the whole right column
- Spectrogram canvas: hidden by default (opacity 0); reveals only when
  visualizer toggle is active. No more leaking into bottom-left.
- VU cluster volume controls: strip legacy box (background, padding,
  border-radius); compact stacked layout with thin slider, small mute
  button, mono "VOL · XX%" readout
- Disable legacy applyVinylMode() — the .vinyl class added a SECOND
  rotation animation on top of the structural .vinyl-stage spin,
  causing visible compounding. Vinyl is now purely structural.

Toggles
- Remove vinyl mode toggle button (vinyl is always on)
- Keep audio visualizer (spectrum vis) toggle — still shown by JS
  when supported

Mini player
- Force always-visible on non-player tabs regardless of scroll, by
  short-circuiting setMiniPlayerVisible when activeTab !== 'player'

i18n
- New keys: header.connected, header.volume, header.edition,
  header.edition_sub
- Removed unused: player.folio_left, player.folio_right
- en.json + ru.json updated
This commit is contained in:
2026-04-25 01:32:34 +03:00
parent 14e9f2294e
commit 265b001b99
6 changed files with 202 additions and 57 deletions
+182 -41
View File
@@ -4112,52 +4112,121 @@ body.mini-player-visible footer {
/* ─── Container & header ────────────────────────────────────── */
.container {
max-width: 1280px;
padding: 28px 48px 140px;
padding: 56px 48px 140px;
}
@media (max-width: 720px) {
.container { padding: 18px 18px 140px; }
.container { padding: 48px 18px 140px; }
}
header {
padding: 0 0 22px 0;
border-bottom: 1px solid var(--rule-strong);
margin-bottom: 18px;
position: relative;
}
/* Folio mark on left side of header */
header > div:first-child {
/* ─── Folio marks (page corners, all tabs) ────────────────── */
body > .folio {
position: fixed;
top: 16px;
z-index: 50;
font-family: var(--mono);
font-size: 11px;
letter-spacing: 0.14em;
font-size: 10px;
letter-spacing: 0.2em;
text-transform: uppercase;
color: var(--ink-mute);
color: var(--ink-faint);
display: inline-flex;
align-items: center;
gap: 8px;
pointer-events: none;
}
body > .folio.tl { left: 24px; }
body > .folio.tr { right: 24px; }
@media (max-width: 720px) {
body > .folio { font-size: 9px; letter-spacing: 0.16em; }
body > .folio.tl { left: 14px; }
body > .folio.tr { right: 14px; }
}
.status-dot {
width: 8px;
height: 8px;
/* The status-dot now lives inside the folio */
body > .folio .status-dot {
width: 7px;
height: 7px;
background: var(--jade);
border-radius: 50%;
box-shadow: 0 0 0 0 rgba(122, 178, 148, 0.55);
animation: sr-pulse 2.4s ease-in-out infinite;
}
@keyframes sr-pulse {
0%, 100% { box-shadow: 0 0 0 0 rgba(122, 178, 148, 0.55); }
50% { box-shadow: 0 0 0 8px rgba(122, 178, 148, 0); }
50% { box-shadow: 0 0 0 6px rgba(122, 178, 148, 0); }
}
.version-label {
font-family: var(--mono);
/* Hide the old in-header status-dot if any rendering remnants exist */
header .status-dot { display: none; }
/* The version-label now lives inside the folio.tr — remove the old badge styling */
.version-label,
body > .folio #version-label {
background: transparent;
color: var(--ink-mute);
border: 1px solid var(--rule-strong);
border-radius: 0;
padding: 2px 10px;
border: 0;
padding: 0;
color: var(--copper);
font-family: var(--mono);
font-size: 10px;
letter-spacing: 0.16em;
text-transform: uppercase;
border-radius: 0;
}
/* ─── Header (3-column: brand center, toolbar right) ─────── */
header {
padding: 0 0 22px 0;
border-bottom: 1px solid var(--rule-strong);
margin-bottom: 28px;
position: relative;
display: grid;
grid-template-columns: 1fr auto 1fr;
align-items: center;
gap: 20px;
}
/* Brand wordmark (centered) */
header .brand {
text-align: center;
grid-column: 2;
line-height: 1;
}
header .brand-name {
font-family: var(--serif);
font-style: italic;
font-weight: 400;
font-size: 30px;
letter-spacing: -0.015em;
color: var(--ink);
font-variation-settings: 'opsz' 144;
display: block;
}
header .brand-sub {
display: block;
font-family: var(--mono);
font-size: 9px;
letter-spacing: 0.32em;
text-transform: uppercase;
color: var(--ink-mute);
margin-top: 6px;
}
@media (max-width: 720px) {
header { grid-template-columns: 1fr; gap: 14px; }
header .brand { grid-column: 1; }
header .brand-name { font-size: 24px; }
header .header-toolbar { justify-self: center; }
}
.header-toolbar {
grid-column: 3;
justify-self: end;
}
@media (max-width: 720px) {
.header-toolbar { grid-column: 1; }
}
.header-toolbar {
@@ -4478,15 +4547,22 @@ header > div:first-child {
@keyframes sr-vinyl-spin { to { transform: rotate(360deg); } }
/* Spectrogram canvas hidden by default — visualizer toggle reveals it */
.vinyl-stage .spectrogram-canvas {
position: absolute;
bottom: -52px;
left: 0;
right: 0;
width: 100%;
height: 44px;
bottom: -56px;
left: 7%;
right: 7%;
width: 86%;
height: 38px;
border-radius: 0;
opacity: 0.7;
opacity: 0;
transition: opacity 240ms var(--ease);
pointer-events: none;
}
.vinyl-stage.visualizer-active .spectrogram-canvas,
body.visualizer-active .vinyl-stage .spectrogram-canvas {
opacity: 0.6;
}
/* ─── Player details (right column / masthead) ──────────────── */
@@ -4616,17 +4692,20 @@ header > div:first-child {
/* Hide the legacy .playback-state container (its data is now in meta-grid) */
.track-info > .playback-state { display: none; }
/* Spectrum decorative bars */
/* Spectrum decorative bars (centered, compact) */
.spectrum {
display: flex;
align-items: flex-end;
justify-content: center;
gap: 3px;
height: 38px;
margin-top: 28px;
margin-bottom: 8px;
height: 32px;
margin: 28px auto 8px;
max-width: 360px;
}
.spectrum span {
flex: 1;
display: block;
width: 3px;
flex: 0 0 3px;
background: linear-gradient(to top, var(--copper-lo), var(--copper-hi));
opacity: 0.85;
border-radius: 99px 99px 0 0;
@@ -4747,32 +4826,94 @@ header > div:first-child {
box-shadow: 0 0 8px var(--copper-glow);
}
/* Volume container nested inside vu-cluster — compact stacked controls */
/* Volume container nested inside vu-cluster — strip legacy box & make compact */
.vu-cluster .volume-container {
margin-top: 0;
padding-top: 0;
background: transparent;
border: 0;
border-top: 0;
border-radius: 0;
padding: 0;
margin: 0;
display: flex;
flex-direction: column;
gap: 8px;
gap: 6px;
align-items: stretch;
min-width: 140px;
min-width: 0;
width: 110px;
box-shadow: none;
}
.vu-cluster .volume-container > .mute-btn {
align-self: flex-start;
align-self: flex-end;
width: 28px;
height: 28px;
border-radius: 50%;
background: transparent;
border: 1px solid var(--rule-strong);
color: var(--ink-soft);
padding: 0;
margin: 0;
}
.vu-cluster .volume-container > .mute-btn:hover {
border-color: var(--copper);
color: var(--copper);
}
.vu-cluster .volume-container > .mute-btn svg {
width: 12px;
height: 12px;
fill: currentColor;
}
.vu-cluster .volume-container > #volume-slider {
width: 100%;
height: 2px;
flex: none;
background: var(--rule-strong);
border-radius: 0;
margin: 0;
padding: 0;
-webkit-appearance: none;
appearance: none;
}
.vu-cluster .volume-container > #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;
}
.vu-cluster .volume-container > .volume-display {
text-align: right;
font-family: var(--mono);
font-size: 10px;
letter-spacing: 0.16em;
text-transform: uppercase;
color: var(--ink-mute);
background: transparent;
border: 0;
padding: 0;
margin: 0;
font-variant-numeric: tabular-nums;
width: auto;
min-width: 0;
font-weight: 500;
}
.vu-cluster .volume-container > .volume-display::before {
content: "VOL · ";
color: var(--ink-faint);
font-weight: 400;
}
/* Make the player view source-info row tighter (visualizer toggle row) */
.player-details > .source-info {
margin-top: 18px;
padding-top: 14px;
border-top: 1px solid var(--rule);
display: flex;
align-items: center;
justify-content: space-between;
gap: 14px;
}
/* ─── Progress (hairline editorial) ─────────────────────────── */