diff --git a/media_server/static/css/styles.css b/media_server/static/css/styles.css index 62186ed..968f872 100644 --- a/media_server/static/css/styles.css +++ b/media_server/static/css/styles.css @@ -1,41 +1,194 @@ +/* ============================================================ + STUDIO REFERENCE — local fonts (Fraunces · Geist · Geist Mono) + Subsets: Latin, Latin-ext, Cyrillic. WOFF2 variable, OFL. + ============================================================ */ + +@font-face { + font-family: 'Fraunces'; + font-style: italic; + font-weight: 300 900; + font-display: swap; + src: url('/static/fonts/Fraunces-italic-latin-ext.woff2') format('woff2'); + unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF; +} +@font-face { + font-family: 'Fraunces'; + font-style: italic; + font-weight: 300 900; + font-display: swap; + src: url('/static/fonts/Fraunces-italic-latin.woff2') format('woff2'); + unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; +} +@font-face { + font-family: 'Fraunces'; + font-style: normal; + font-weight: 300 900; + font-display: swap; + src: url('/static/fonts/Fraunces-latin-ext.woff2') format('woff2'); + unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF; +} +@font-face { + font-family: 'Fraunces'; + font-style: normal; + font-weight: 300 900; + font-display: swap; + src: url('/static/fonts/Fraunces-latin.woff2') format('woff2'); + unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; +} + +@font-face { + font-family: 'Geist'; + font-style: normal; + font-weight: 300 700; + font-display: swap; + src: url('/static/fonts/Geist-cyrillic.woff2') format('woff2'); + unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; +} +@font-face { + font-family: 'Geist'; + font-style: normal; + font-weight: 300 700; + font-display: swap; + src: url('/static/fonts/Geist-latin-ext.woff2') format('woff2'); + unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF; +} +@font-face { + font-family: 'Geist'; + font-style: normal; + font-weight: 300 700; + font-display: swap; + src: url('/static/fonts/Geist-latin.woff2') format('woff2'); + unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; +} + +@font-face { + font-family: 'Geist Mono'; + font-style: normal; + font-weight: 300 600; + font-display: swap; + src: url('/static/fonts/GeistMono-cyrillic.woff2') format('woff2'); + unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; +} +@font-face { + font-family: 'Geist Mono'; + font-style: normal; + font-weight: 300 600; + font-display: swap; + src: url('/static/fonts/GeistMono-latin-ext.woff2') format('woff2'); + unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF; +} +@font-face { + font-family: 'Geist Mono'; + font-style: normal; + font-weight: 300 600; + font-display: swap; + src: url('/static/fonts/GeistMono-latin.woff2') format('woff2'); + unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; +} + +/* ============================================================ + Studio Reference — design tokens (default = warm dark) + Light theme = Paper Edition (cream + emerald) + Old token names preserved as aliases for unmigrated components. + ============================================================ */ + :root { - --bg-primary: #121212; - --bg-secondary: #1e1e1e; - --bg-tertiary: #282828; - --text-primary: #ffffff; - --text-secondary: #b3b3b3; - --text-muted: #8a8a8a; - --accent: #1db954; - --accent-hover: #1ed760; - --border: #404040; - --error: #e74c3c; - --vinyl-ring: #1a1a1a; - --vinyl-groove: #2a2a2a; + /* Studio Reference (warm dark) */ + --bg-deep: #0E0D0B; + --bg-paper: #18150F; + --bg-card: #211E18; + --bg-card-2: #26211A; + --bg-rule: #2E2820; + + --ink: #F2EBDC; + --ink-soft: #D6CDB9; + --ink-mute: #9C937F; + --ink-faint: #5C5447; + --ink-ghost: #3A3528; + + --copper: #E08038; + --copper-hi: #F4A064; + --copper-lo: #B0561F; + --copper-glow: rgba(224, 128, 56, 0.35); + + --amber: #F5C26B; + --jade: #7AB294; + --rust: #C2553F; + + --rule: rgba(242, 235, 220, 0.08); + --rule-strong: rgba(242, 235, 220, 0.18); + + --serif: 'Fraunces', 'Iowan Old Style', Georgia, 'Times New Roman', serif; + --sans: 'Geist', 'Inter', 'Segoe UI', -apple-system, BlinkMacSystemFont, 'Helvetica Neue', sans-serif; + --mono: 'Geist Mono', 'JetBrains Mono', 'Cascadia Code', ui-monospace, monospace; + + --ease: cubic-bezier(.2, .7, .2, 1); + --ease-out: cubic-bezier(.16, 1, .3, 1); + + /* Backwards-compatible aliases — components not yet migrated */ + --bg-primary: var(--bg-deep); + --bg-secondary: var(--bg-paper); + --bg-tertiary: var(--bg-card); + --text-primary: var(--ink); + --text-secondary: var(--ink-soft); + --text-muted: var(--ink-mute); + --accent: var(--copper); + --accent-hover: var(--copper-hi); + --border: var(--bg-rule); + --error: var(--rust); + --vinyl-ring: #1a1611; + --vinyl-groove: #2a241c; --vinyl-highlight: rgba(255,255,255,0.05); --vinyl-highlight-dim: rgba(255,255,255,0.03); - --vinyl-edge: #111; - --vinyl-spindle: #0a0a0a; + --vinyl-edge: #0a0907; + --vinyl-spindle: #050402; --shadow-elevation: rgba(0, 0, 0, 0.5); } :root[data-theme="light"] { - --bg-primary: #ffffff; - --bg-secondary: #f5f5f5; - --bg-tertiary: #e8e8e8; - --text-primary: #1a1a1a; - --text-secondary: #4a4a4a; - --text-muted: #888888; - --accent: #1db954; - --accent-hover: #1ed760; - --border: #d0d0d0; - --error: #e74c3c; - --vinyl-ring: #c0c0c0; - --vinyl-groove: #b0b0b0; + /* Paper Edition (warm cream) */ + --bg-deep: #F5F1EA; + --bg-paper: #EDE7DC; + --bg-card: #FFFFFF; + --bg-card-2: #FAF6EE; + --bg-rule: #D4CCB9; + + --ink: #1A1715; + --ink-soft: #4A4540; + --ink-mute: #8A8278; + --ink-faint: #B0A89A; + --ink-ghost: #C8C0B3; + + --copper: #1F4E3D; /* hunter emerald in light mode */ + --copper-hi: #2D6A53; + --copper-lo: #143E2F; + --copper-glow: rgba(31, 78, 61, 0.18); + + --amber: #C29D31; + --jade: #4D8C6F; + --rust: #B82F1A; + + --rule: rgba(26, 23, 21, 0.08); + --rule-strong: rgba(26, 23, 21, 0.18); + + /* Aliases */ + --bg-primary: var(--bg-deep); + --bg-secondary: var(--bg-paper); + --bg-tertiary: var(--bg-card); + --text-primary: var(--ink); + --text-secondary: var(--ink-soft); + --text-muted: var(--ink-mute); + --accent: var(--copper); + --accent-hover: var(--copper-hi); + --border: var(--bg-rule); + --error: var(--rust); + --vinyl-ring: #C8BFA8; + --vinyl-groove: #B0A892; --vinyl-highlight: rgba(255,255,255,0.3); --vinyl-highlight-dim: rgba(255,255,255,0.15); - --vinyl-edge: #999; - --vinyl-spindle: #888; - --shadow-elevation: rgba(0, 0, 0, 0.15); + --vinyl-edge: #968D78; + --vinyl-spindle: #8A8278; + --shadow-elevation: rgba(26, 23, 21, 0.15); } :root[data-theme="light"] .player-container, @@ -97,10 +250,50 @@ html { } body { - font-family: 'Segoe UI', -apple-system, BlinkMacSystemFont, 'Roboto', 'Helvetica Neue', 'Arial', sans-serif; + font-family: var(--sans); + font-feature-settings: 'ss01', 'cv11'; background: var(--bg-primary); color: var(--text-primary); line-height: 1.6; + -webkit-font-smoothing: antialiased; + text-rendering: optimizeLegibility; +} + +/* Film-grain overlay — adds analog warmth to the dark theme. + Disabled in light theme where it muddies cream paper. */ +body::before { + content: ""; + position: fixed; + inset: 0; + pointer-events: none; + z-index: 9999; + opacity: 0.05; + mix-blend-mode: overlay; + background-image: url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='200' height='200'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='2' stitchTiles='stitch'/%3E%3CfeColorMatrix values='0 0 0 0 0.95 0 0 0 0 0.92 0 0 0 0 0.86 0 0 0 0.7 0'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E"); +} + +:root[data-theme="light"] body::before { + opacity: 0.04; + mix-blend-mode: multiply; + background-image: url("data:image/svg+xml;utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='240' height='240'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='2' stitchTiles='stitch'/%3E%3CfeColorMatrix values='0 0 0 0 0.45 0 0 0 0 0.40 0 0 0 0 0.32 0 0 0 0.5 0'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E"); +} + +/* Reduced-motion fallback: drop the grain entirely. */ +@media (prefers-reduced-motion: reduce) { + body::before { display: none; } +} + +/* Heading defaults — components may override per-element. */ +h1, h2, h3, .editorial-heading { + font-family: var(--serif); + font-weight: 400; + letter-spacing: -0.015em; +} + +/* Mono utility — for technical readouts (timecodes, bitrates, etc.) */ +.mono, .timecode, .meta-mono { + font-family: var(--mono); + font-feature-settings: 'tnum', 'cv01'; } /* Prevent flash of untranslated content */ @@ -3909,3 +4102,1664 @@ body.mini-player-visible footer { transition-duration: 0.01ms !important; } } + +/* ════════════════════════════════════════════════════════════════ + STUDIO REFERENCE — editorial overrides + Applied on top of the legacy stylesheet. Mapped to existing + selectors so no JS / DOM changes are required. + ════════════════════════════════════════════════════════════════ */ + +/* ─── Container & header ────────────────────────────────────── */ +.container { + max-width: 1280px; + padding: 28px 48px 140px; +} + +@media (max-width: 720px) { + .container { padding: 18px 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 { + font-family: var(--mono); + font-size: 11px; + letter-spacing: 0.14em; + text-transform: uppercase; + color: var(--ink-mute); +} + +.status-dot { + width: 8px; + height: 8px; + background: var(--jade); + 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); } +} + +.version-label { + font-family: var(--mono); + background: transparent; + color: var(--ink-mute); + border: 1px solid var(--rule-strong); + border-radius: 0; + padding: 2px 10px; + font-size: 10px; + letter-spacing: 0.16em; + text-transform: uppercase; +} + +.header-toolbar { + gap: 4px; +} + +.header-btn, +.header-btn-logout, +.header-link { + background: transparent; + border: 1px solid transparent; + color: var(--ink-soft); + border-radius: 0; + width: 36px; + height: 36px; + transition: all 200ms var(--ease); +} +.header-btn:hover, +.header-btn-logout:hover, +.header-link:hover { + color: var(--copper); + border-color: var(--rule-strong); + background: transparent; +} + +.header-locale { + background: transparent; + border: 1px solid transparent; + color: var(--ink-soft); + border-radius: 0; + font-family: var(--mono); + font-size: 11px; + letter-spacing: 0.12em; + text-transform: uppercase; + height: 36px; + padding: 0 10px 0 12px; +} +.header-locale:hover { + color: var(--copper); + border-color: var(--rule-strong); +} + +.header-toolbar-sep { + background: var(--rule-strong); + height: 20px; + margin: 0 6px; +} + +.accent-dot { + box-shadow: 0 0 0 1px var(--rule-strong), 0 0 12px var(--copper-glow); +} + +.accent-picker-dropdown { + background: var(--bg-card); + border: 1px solid var(--rule-strong); + border-radius: 0; + box-shadow: 0 14px 40px rgba(0,0,0,0.5); +} + +/* ─── Tab bar (numbered editorial) ──────────────────────────── */ +.tab-bar { + background: transparent; + border-bottom: 1px solid var(--rule); + padding: 0; + margin: 14px 0 36px; + border-radius: 0; + gap: 0; +} + +.tab-indicator { + background: var(--copper); + box-shadow: 0 0 12px var(--copper-glow); + height: 2px; + bottom: -1px; + border-radius: 0; +} + +.tab-btn { + background: transparent; + border: 0; + color: var(--ink-mute); + padding: 18px 22px 16px; + border-radius: 0; + font-family: var(--sans); + font-size: 13px; + font-weight: 400; + letter-spacing: 0.04em; + transition: color 180ms var(--ease); + position: relative; + gap: 10px; + align-items: baseline; +} +.tab-btn:hover { color: var(--ink-soft); background: transparent; } +.tab-btn.active { + color: var(--ink); + background: transparent; + font-family: var(--serif); + font-style: italic; + font-size: 17px; + font-weight: 400; + font-variation-settings: 'opsz' 60; +} + +.tab-btn svg { opacity: 0.7; } +.tab-btn.active svg { opacity: 1; color: var(--copper); } + +/* ─── Update + connection banners ───────────────────────────── */ +.update-banner, +.connection-banner { + background: var(--bg-card); + border: 1px solid var(--copper); + border-radius: 0; + color: var(--ink-soft); + box-shadow: 0 0 24px var(--copper-glow); + font-family: var(--sans); + font-size: 13px; +} +.update-banner a, +.connection-banner-btn { + color: var(--copper); + font-family: var(--mono); + font-size: 11px; + letter-spacing: 0.12em; + text-transform: uppercase; + border-color: var(--copper); + border-radius: 0; + background: transparent; +} +.connection-banner-btn:hover { + background: var(--copper); + color: var(--bg-deep); +} + +/* ═══════════════════════════════════════════════════════════════ + PLAYER VIEW — magazine spread + ═══════════════════════════════════════════════════════════════ */ +.player-container { + background: transparent; + border: 0; + padding: 0; + box-shadow: none; + margin-top: 12px; +} + +.player-layout { + display: grid; + grid-template-columns: minmax(280px, 480px) 1fr; + gap: 64px; + align-items: start; +} + +@media (max-width: 980px) { + .player-layout { + grid-template-columns: 1fr; + gap: 36px; + } +} + +.album-art-container { + position: relative; + aspect-ratio: 1; + width: 100%; + max-width: none; + padding: 14px; + background: var(--bg-card); + border: 1px solid var(--rule-strong); + box-shadow: + 0 1px 0 var(--bg-paper), + 0 28px 60px -20px rgba(0, 0, 0, 0.5), + 0 8px 20px -8px rgba(0, 0, 0, 0.35); + transition: transform 400ms var(--ease); +} + +.album-art-container:hover { transform: translateY(-2px); } + +#album-art-glow { + border-radius: 0; + filter: blur(40px) saturate(1.4); + opacity: 0.5; + inset: 14px; + width: auto; + height: auto; +} + +#album-art { + border-radius: 0; + width: 100%; + height: 100%; + object-fit: cover; + display: block; +} + +.spectrogram-canvas { + bottom: 14px; + left: 14px; + right: 14px; + width: auto; + border-radius: 0; + height: 56px; +} + +/* ─── Player details (right column / masthead) ──────────────── */ +.player-details { + gap: 0; + padding-top: 12px; +} + +.track-info { + margin-bottom: 0; + position: relative; +} + +#track-title { + font-family: var(--serif); + font-weight: 400; + font-size: clamp(38px, 5vw, 68px); + line-height: 0.96; + letter-spacing: -0.02em; + color: var(--ink); + font-variation-settings: 'opsz' 144; + margin-bottom: 16px; +} + +#artist { + font-family: var(--serif); + font-style: italic; + font-weight: 300; + font-size: 22px; + color: var(--copper-hi); + font-variation-settings: 'opsz' 60; + margin-bottom: 4px; +} + +#album { + font-family: var(--sans); + font-size: 13px; + color: var(--ink-mute); + letter-spacing: 0.04em; + margin-bottom: 0; +} + +.playback-state { + margin-top: 22px; + padding: 12px 0; + border-top: 1px solid var(--rule); + border-bottom: 1px solid var(--rule); + font-family: var(--mono); + font-size: 11px; + letter-spacing: 0.16em; + text-transform: uppercase; + color: var(--ink-mute); + gap: 10px; +} + +.state-icon { + width: 14px; + height: 14px; + color: var(--copper); +} + +#playback-state { + color: var(--ink-soft); +} + +/* ─── Progress (hairline editorial) ─────────────────────────── */ +.progress-container { + margin-top: 28px; +} + +.time-display { + font-family: var(--mono); + font-size: 11px; + color: var(--ink-mute); + letter-spacing: 0.04em; + font-variant-numeric: tabular-nums; + margin-bottom: 10px; +} + +#current-time { color: var(--copper); font-weight: 500; } + +.progress-bar { + height: 2px; + background: var(--rule-strong); + border-radius: 0; + cursor: pointer; + overflow: visible; +} + +.progress-fill { + background: var(--copper); + box-shadow: 0 0 12px var(--copper-glow); + border-radius: 0; + height: 100%; + position: relative; +} + +.progress-fill::after { + content: ""; + position: absolute; + right: -5px; + top: -4px; + width: 10px; + height: 10px; + background: var(--copper); + border-radius: 50%; + box-shadow: 0 0 14px var(--copper-glow), 0 0 0 4px rgba(224, 128, 56, 0.12); +} + +/* ─── Controls (circular transport) ─────────────────────────── */ +.controls { + margin-top: 28px; + gap: 16px; + justify-content: flex-start; +} + +.controls button { + background: transparent; + border: 1px solid var(--rule-strong); + color: var(--ink-soft); + width: 48px; + height: 48px; + border-radius: 50%; + transition: all 220ms var(--ease); +} +.controls button:hover { + background: rgba(224, 128, 56, 0.06); + border-color: var(--copper); + color: var(--copper); +} +.controls button.primary { + width: 64px; + height: 64px; + background: var(--ink); + color: var(--bg-deep); + border-color: var(--ink); + box-shadow: 0 8px 28px rgba(0, 0, 0, 0.45); +} +.controls button.primary:hover { + background: var(--copper); + border-color: var(--copper); + color: var(--bg-deep); + transform: scale(1.04); + box-shadow: 0 8px 28px var(--copper-glow); +} + +.controls button svg { width: 20px; height: 20px; } +.controls button.primary svg { width: 24px; height: 24px; } + +/* ─── Volume container (VU-meter aesthetic) ─────────────────── */ +.volume-container { + margin-top: 28px; + padding-top: 22px; + border-top: 1px solid var(--rule); + gap: 14px; + display: flex; + align-items: center; +} + +.mute-btn { + background: transparent; + border: 1px solid var(--rule-strong); + color: var(--ink-soft); + border-radius: 50%; + width: 38px; + height: 38px; +} +.mute-btn:hover { + border-color: var(--copper); + color: var(--copper); + background: rgba(224, 128, 56, 0.06); +} + +#volume-slider { + height: 2px; + background: var(--rule-strong); + border-radius: 0; + flex: 1; + -webkit-appearance: none; + appearance: none; + cursor: pointer; +} +#volume-slider::-webkit-slider-thumb { + -webkit-appearance: none; + appearance: none; + width: 14px; + height: 14px; + background: var(--copper); + border-radius: 50%; + box-shadow: 0 0 12px var(--copper-glow), 0 0 0 4px rgba(224, 128, 56, 0.12); + border: 0; + cursor: grab; +} +#volume-slider::-moz-range-thumb { + width: 14px; + height: 14px; + background: var(--copper); + border-radius: 50%; + box-shadow: 0 0 12px var(--copper-glow); + border: 0; +} +#volume-slider::-moz-range-track { + height: 2px; + background: var(--rule-strong); +} + +.volume-display { + font-family: var(--mono); + font-size: 11px; + color: var(--copper); + letter-spacing: 0.06em; + font-variant-numeric: tabular-nums; + min-width: 44px; + text-align: right; + font-weight: 500; +} + +/* ─── Source info ───────────────────────────────────────────── */ +.source-info { + margin-top: 24px; + padding-top: 22px; + border-top: 1px solid var(--rule); +} + +.source-label { + font-family: var(--mono); + font-size: 10px; + letter-spacing: 0.22em; + text-transform: uppercase; + color: var(--ink-mute); + gap: 10px; +} + +.source-icon { + width: 14px; + height: 14px; + color: var(--copper); +} + +.player-toggles { gap: 8px; } + +.vinyl-toggle-btn { + background: transparent; + border: 1px solid var(--rule-strong); + color: var(--ink-mute); + border-radius: 0; + width: 30px; + height: 30px; + transition: all 180ms var(--ease); +} +.vinyl-toggle-btn:hover, +.vinyl-toggle-btn.active { + border-color: var(--copper); + color: var(--copper); + background: rgba(224, 128, 56, 0.06); +} + +/* ═══════════════════════════════════════════════════════════════ + MINI PLAYER — console strip + ═══════════════════════════════════════════════════════════════ */ +.mini-player { + background: linear-gradient(180deg, rgba(14, 13, 11, 0.7) 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; +} + +.mini-player::before { + content: ""; + position: absolute; + top: -1px; left: 32px; right: 32px; + height: 2px; + background: linear-gradient(90deg, transparent, var(--copper), transparent); + opacity: 0.55; +} + +.mini-album-art { + border-radius: 0; + box-shadow: 0 4px 14px rgba(0, 0, 0, 0.4); + width: 48px; + height: 48px; +} + +.mini-track-title { + font-family: var(--serif); + font-style: italic; + font-size: 15px; + color: var(--ink); + font-variation-settings: 'opsz' 60; + letter-spacing: 0; +} + +.mini-artist { + font-family: var(--mono); + font-size: 10px; + color: var(--ink-mute); + letter-spacing: 0.1em; + text-transform: uppercase; + margin-top: 4px; +} + +.mini-control-btn { + background: transparent; + border: 0; + color: var(--ink-soft); + border-radius: 50%; + width: 32px; + height: 32px; + transition: color 180ms var(--ease); +} +.mini-control-btn:hover { color: var(--copper); background: transparent; } +.mini-control-btn.primary, +#mini-btn-play-pause { + background: var(--ink); + color: var(--bg-deep); + width: 38px; + height: 38px; + box-shadow: 0 4px 14px rgba(0, 0, 0, 0.4); +} +#mini-btn-play-pause:hover { + background: var(--copper); + color: var(--bg-deep); +} + +.mini-time-display { + font-family: var(--mono); + font-size: 10px; + color: var(--ink-mute); + letter-spacing: 0.06em; + font-variant-numeric: tabular-nums; +} +#mini-current-time { color: var(--copper); font-weight: 500; } + +.mini-progress-bar { + height: 2px; + background: var(--rule-strong); + border-radius: 0; +} +.mini-progress-fill { + background: var(--copper); + box-shadow: 0 0 8px var(--copper-glow); + border-radius: 0; +} + +.mini-volume-slider { + -webkit-appearance: none; + appearance: none; + height: 2px; + background: var(--rule-strong); +} +.mini-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; +} +.mini-volume-slider::-moz-range-thumb { + width: 10px; height: 10px; + background: var(--copper); + border-radius: 50%; + border: 0; +} +.mini-volume-display { + font-family: var(--mono); + font-size: 10px; + color: var(--copper); + letter-spacing: 0.06em; + font-variant-numeric: tabular-nums; + font-weight: 500; +} + +/* ═══════════════════════════════════════════════════════════════ + BROWSER — editorial gallery + ═══════════════════════════════════════════════════════════════ */ +.browser-container { + background: transparent; + border: 0; + padding: 0; + box-shadow: none; + margin-top: 12px; +} + +.breadcrumb { + font-family: var(--serif); + font-style: italic; + font-size: 17px; + color: var(--ink-soft); + font-variation-settings: 'opsz' 60; + background: transparent; + border-bottom: 1px solid var(--rule); + padding: 14px 0; + margin-bottom: 22px; + border-radius: 0; +} +.breadcrumb-item, .breadcrumb-home { + color: var(--ink-soft); + font-style: italic; +} +.breadcrumb-item:hover, .breadcrumb-home:hover { color: var(--copper); } +.breadcrumb-item:last-child { + color: var(--ink); + font-weight: 400; +} +.breadcrumb-separator { + color: var(--ink-faint); + font-style: normal; + margin: 0 8px; + opacity: 1; +} + +.browser-toolbar { + background: transparent; + border: 0; + border-bottom: 1px solid var(--rule); + border-radius: 0; + padding: 0 0 14px 0; + margin-bottom: 28px; + gap: 12px; +} + +.view-toggle { + background: transparent; + border: 1px solid var(--rule-strong); + border-radius: 0; + padding: 0; + gap: 0; +} +.view-toggle-btn { + background: transparent; + border: 0; + border-right: 1px solid var(--rule-strong); + color: var(--ink-mute); + border-radius: 0; + width: 36px; + height: 36px; + transition: all 180ms var(--ease); +} +.view-toggle-btn:last-child { border-right: 0; } +.view-toggle-btn:hover { + color: var(--copper); + background: rgba(224, 128, 56, 0.04); +} +.view-toggle-btn.active { + background: var(--ink); + color: var(--bg-deep); +} + +.browser-refresh-btn, +.browser-play-all-btn { + background: transparent; + border: 1px solid var(--rule-strong); + color: var(--ink-soft); + border-radius: 0; + width: 36px; + height: 36px; + transition: all 180ms var(--ease); +} +.browser-refresh-btn:hover, +.browser-play-all-btn:hover { + color: var(--copper); + border-color: var(--copper); + background: transparent; +} +.browser-play-all-btn { + color: var(--copper); + border-color: var(--copper); +} + +.browser-search-wrapper { + background: transparent; + border: 0; + border-bottom: 1px solid var(--rule-strong); + border-radius: 0; + padding: 0 0 4px 0; + gap: 8px; + transition: border-color 180ms var(--ease); +} +.browser-search-wrapper:focus-within { + border-bottom-color: var(--copper); +} +.browser-search-input { + background: transparent; + border: 0; + color: var(--ink); + font-family: var(--sans); + font-size: 13px; + padding: 4px 0; +} +.browser-search-input::placeholder { color: var(--ink-mute); } +.browser-search-icon { color: var(--ink-mute); } +.browser-search-clear { color: var(--ink-mute); background: transparent; border: 0; } +.browser-search-clear:hover { color: var(--copper); } + +.items-per-page-label { + font-family: var(--mono); + font-size: 10px; + letter-spacing: 0.16em; + text-transform: uppercase; + color: var(--ink-mute); + gap: 8px; +} +.items-per-page-label select { + background: transparent; + border: 1px solid var(--rule-strong); + color: var(--ink); + border-radius: 0; + font-family: var(--mono); + font-size: 11px; + padding: 4px 8px; +} + +/* Browser grid items */ +.browser-grid { + gap: 28px 22px; +} + +.browser-item { + background: transparent; + border: 0; + border-radius: 0; + padding: 0; + transition: transform 280ms var(--ease); +} +.browser-item:hover { + transform: translateY(-3px); + background: transparent; + box-shadow: none; +} + +.browser-thumb-wrapper, +.browser-thumbnail { + border-radius: 0; + background: var(--bg-card); + box-shadow: 0 14px 30px -10px rgba(0,0,0,0.5); + transition: box-shadow 280ms var(--ease); +} +.browser-item:hover .browser-thumb-wrapper, +.browser-item:hover .browser-thumbnail { + box-shadow: 0 22px 50px -10px rgba(0,0,0,0.65), 0 0 0 1px var(--copper); +} + +.browser-icon { + color: var(--ink-mute); +} + +.browser-item-name { + font-family: var(--serif); + font-size: 16px; + color: var(--ink); + font-variation-settings: 'opsz' 18; + letter-spacing: 0; + margin-top: 12px; +} +.browser-item-meta, +.browser-item-type { + font-family: var(--mono); + font-size: 10px; + letter-spacing: 0.1em; + text-transform: uppercase; + color: var(--ink-mute); + margin-top: 4px; +} + +.browser-play-overlay, +.browser-list-play-overlay { + background: rgba(14, 13, 11, 0.5); +} +.browser-play-overlay svg, +.browser-list-play-overlay svg { + fill: var(--ink); + filter: drop-shadow(0 4px 12px rgba(0,0,0,0.6)); +} + +.browser-empty { + color: var(--ink-mute); + font-family: var(--serif); + font-style: italic; + font-size: 16px; + font-variation-settings: 'opsz' 30; +} + +/* List view */ +.browser-list { + background: transparent; + border: 1px solid var(--rule); + border-radius: 0; +} +.browser-list-header { + background: var(--bg-paper); + border-bottom: 1px solid var(--rule-strong); + color: var(--ink-mute); + font-family: var(--mono); + font-size: 10px; + letter-spacing: 0.18em; + text-transform: uppercase; +} +.browser-list-item { + border-bottom: 1px solid var(--rule); + transition: background 180ms var(--ease); +} +.browser-list-item:hover { background: var(--bg-paper); } +.browser-list-name { + font-family: var(--serif); + font-size: 15px; + color: var(--ink); + font-variation-settings: 'opsz' 18; +} +.browser-list-bitrate, +.browser-list-duration, +.browser-list-size { + font-family: var(--mono); + font-size: 11px; + color: var(--ink-mute); + font-variant-numeric: tabular-nums; +} + +/* Pagination */ +.pagination { + border-top: 1px solid var(--rule); + margin-top: 32px; + padding-top: 22px; + background: transparent; +} +.pagination button { + background: transparent; + border: 1px solid var(--rule-strong); + color: var(--ink-soft); + border-radius: 0; + font-family: var(--mono); + font-size: 11px; + letter-spacing: 0.12em; + text-transform: uppercase; + padding: 8px 16px; + transition: all 180ms var(--ease); +} +.pagination button:hover:not(:disabled) { + color: var(--copper); + border-color: var(--copper); +} +.pagination button:disabled { opacity: 0.4; } +.page-input { + background: transparent; + border: 1px solid var(--rule-strong); + color: var(--ink); + border-radius: 0; + font-family: var(--mono); +} +.pagination-center, +.pagination-showing { + font-family: var(--mono); + font-size: 11px; + color: var(--ink-mute); + letter-spacing: 0.04em; +} + +/* ═══════════════════════════════════════════════════════════════ + QUICK ACCESS — console rail + ═══════════════════════════════════════════════════════════════ */ +.scripts-container { + background: transparent; + border: 0; + padding: 0; + box-shadow: none; +} +.scripts-grid { + display: grid; + grid-template-columns: repeat(auto-fill, minmax(160px, 1fr)); + gap: 1px; + background: var(--rule-strong); + border: 1px solid var(--rule-strong); + padding: 0; +} +.scripts-empty { + background: var(--bg-card); + padding: 60px 24px; + color: var(--ink-mute); +} + +.script-btn, +.link-card { + background: var(--bg-card); + border: 0; + border-radius: 0; + padding: 24px 18px; + color: var(--ink); + transition: all 200ms var(--ease); + text-align: center; +} +.script-btn:hover, +.link-card:hover { + background: var(--bg-card-2); + color: var(--copper); + transform: none; +} +.script-btn .browser-icon, +.link-card .browser-icon { + color: var(--ink-soft); + margin-bottom: 12px; + transition: color 200ms var(--ease); +} +.script-btn:hover .browser-icon, +.link-card:hover .browser-icon { color: var(--copper); transform: translateY(-2px); } + +.script-btn .browser-item-name, +.link-card .browser-item-name { + font-family: var(--serif); + font-style: italic; + font-size: 14px; + color: inherit; + font-variation-settings: 'opsz' 18; +} + +/* ═══════════════════════════════════════════════════════════════ + SETTINGS — numbered editorial sections + ═══════════════════════════════════════════════════════════════ */ +.settings-container, +.script-management { + background: transparent; + border: 0; + padding: 0; + box-shadow: none; +} + +.settings-section { + background: var(--bg-card); + border: 1px solid var(--rule); + border-radius: 0; + padding: 28px 32px; + margin-bottom: 16px; + box-shadow: none; + transition: border-color 200ms var(--ease); + position: relative; + counter-increment: sr-section; +} +.settings-section:hover { border-color: var(--rule-strong); } +.settings-container { counter-reset: sr-section; } + +.settings-section summary { + font-family: var(--serif); + font-weight: 400; + font-size: 26px; + letter-spacing: -0.015em; + color: var(--ink); + font-variation-settings: 'opsz' 60; + padding: 0 0 16px 0; + border: 0; + background: transparent; + cursor: pointer; + list-style: none; + position: relative; +} +.settings-section summary::-webkit-details-marker { display: none; } +.settings-section summary::before { + content: "5." counter(sr-section, decimal-leading-zero); + font-family: var(--mono); + font-style: normal; + font-size: 10px; + letter-spacing: 0.22em; + color: var(--copper); + margin-right: 14px; + vertical-align: middle; +} +.settings-section summary::after { + content: "↓"; + position: absolute; + right: 0; + top: 0; + font-family: var(--sans); + font-size: 16px; + color: var(--ink-mute); + transition: transform 240ms var(--ease); +} +.settings-section[open] summary::after { transform: rotate(180deg); } + +.settings-section-content { + padding-top: 18px; + border-top: 1px solid var(--rule); +} + +.settings-section-description { + font-family: var(--serif); + font-style: italic; + font-size: 14px; + color: var(--ink-soft); + line-height: 1.5; + font-variation-settings: 'opsz' 18; + margin-bottom: 18px; +} + +.scripts-table { + border: 1px solid var(--rule); + border-collapse: collapse; + width: 100%; + background: transparent; +} +.scripts-table thead { + background: var(--bg-paper); +} +.scripts-table th { + font-family: var(--mono); + font-size: 10px; + letter-spacing: 0.18em; + text-transform: uppercase; + color: var(--ink-mute); + padding: 12px 14px; + text-align: left; + border-bottom: 1px solid var(--rule-strong); + font-weight: 400; +} +.scripts-table td { + padding: 12px 14px; + border-bottom: 1px solid var(--rule); + color: var(--ink-soft); + font-family: var(--sans); + font-size: 13px; + vertical-align: middle; +} +.scripts-table tr:last-child td { border-bottom: 0; } +.scripts-table .name-with-icon { + color: var(--ink); + font-family: var(--serif); + font-style: italic; + font-size: 15px; + font-variation-settings: 'opsz' 18; +} +.scripts-table .path-cell, +.scripts-table .mono { + font-family: var(--mono); + font-size: 11px; + color: var(--ink-mute); +} + +.add-card { + background: transparent; + border: 1px dashed var(--rule-strong); + border-radius: 0; + padding: 16px; + margin-top: 16px; + transition: all 200ms var(--ease); + color: var(--ink-mute); + cursor: pointer; +} +.add-card:hover { + border-color: var(--copper); + border-style: solid; + color: var(--copper); + background: rgba(224, 128, 56, 0.04); +} +.add-card-icon { + font-family: var(--serif); + font-weight: 300; + font-size: 24px; + color: inherit; +} +.add-card-grid { + grid-template-columns: repeat(auto-fill, minmax(160px, 1fr)); +} + +.audio-device-selector { + display: flex; + flex-direction: column; + gap: 12px; +} +.audio-device-selector label { + display: flex; + flex-direction: column; + gap: 8px; + font-family: var(--mono); + font-size: 10px; + letter-spacing: 0.18em; + text-transform: uppercase; + color: var(--ink-mute); +} +.audio-device-selector select { + background: transparent; + border: 1px solid var(--rule-strong); + color: var(--ink); + border-radius: 0; + font-family: var(--sans); + font-size: 13px; + padding: 10px 12px; +} +.audio-device-status { + font-family: var(--mono); + font-size: 11px; + color: var(--jade); + letter-spacing: 0.1em; + text-transform: uppercase; +} + +.folder-disabled-badge, +.folder-unavailable-badge { + background: transparent; + border: 1px solid currentColor; + border-radius: 0; + font-family: var(--mono); + font-size: 9px; + letter-spacing: 0.18em; + text-transform: uppercase; + padding: 3px 8px; + color: var(--amber); +} +.folder-unavailable-badge { color: var(--rust); } + +.empty-state-illustration { + color: var(--ink-faint); +} +.empty-state { + color: var(--ink-mute); + font-family: var(--serif); + font-style: italic; + font-size: 14px; + font-variation-settings: 'opsz' 18; + padding: 40px 20px; + text-align: center; +} + +/* ═══════════════════════════════════════════════════════════════ + DIALOGS — paper card + ═══════════════════════════════════════════════════════════════ */ +dialog { + background: var(--bg-card); + border: 1px solid var(--rule-strong); + border-radius: 0; + color: var(--ink); + box-shadow: 0 24px 60px rgba(0, 0, 0, 0.6); + padding: 0; + max-width: 560px; + width: 90%; +} +dialog::backdrop { + background: rgba(14, 13, 11, 0.7); + backdrop-filter: blur(4px); + -webkit-backdrop-filter: blur(4px); +} + +.dialog-header { + padding: 24px 28px 18px; + border-bottom: 1px solid var(--rule); + background: transparent; +} +.dialog-header h3 { + font-family: var(--serif); + font-weight: 400; + font-style: italic; + font-size: 24px; + color: var(--ink); + font-variation-settings: 'opsz' 60; + letter-spacing: -0.01em; +} + +.dialog-body { + padding: 22px 28px; +} +.dialog-body label { + display: flex; + flex-direction: column; + gap: 8px; + margin-bottom: 16px; +} +.dialog-body label > span { + font-family: var(--mono); + font-size: 10px; + letter-spacing: 0.16em; + text-transform: uppercase; + color: var(--ink-mute); +} +.dialog-body input, +.dialog-body textarea, +.dialog-body select { + background: transparent; + border: 0; + border-bottom: 1px solid var(--rule-strong); + border-radius: 0; + color: var(--ink); + font-family: var(--sans); + font-size: 14px; + padding: 8px 0; + transition: border-color 180ms var(--ease); +} +.dialog-body input:focus, +.dialog-body textarea:focus, +.dialog-body select:focus { + outline: 0; + border-bottom-color: var(--copper); +} +.dialog-body textarea { + border: 1px solid var(--rule-strong); + padding: 10px 12px; + resize: vertical; + min-height: 60px; + font-family: var(--mono); + font-size: 12px; +} + +.dialog-footer { + padding: 16px 28px 22px; + border-top: 1px solid var(--rule); + background: transparent; + gap: 10px; +} + +.btn-primary { + background: var(--ink); + color: var(--bg-deep); + border: 1px solid var(--ink); + border-radius: 0; + font-family: var(--mono); + font-size: 11px; + letter-spacing: 0.18em; + text-transform: uppercase; + padding: 10px 18px; + transition: all 200ms var(--ease); +} +.btn-primary:hover { + background: var(--copper); + border-color: var(--copper); + color: var(--bg-deep); +} +.btn-secondary, .btn-cancel { + background: transparent; + color: var(--ink-soft); + border: 1px solid var(--rule-strong); + border-radius: 0; + font-family: var(--mono); + font-size: 11px; + letter-spacing: 0.18em; + text-transform: uppercase; + padding: 10px 18px; + transition: all 200ms var(--ease); +} +.btn-secondary:hover, .btn-cancel:hover { + color: var(--copper); + border-color: var(--copper); +} +.btn-danger { + background: var(--rust); + color: var(--bg-deep); + border: 1px solid var(--rust); + border-radius: 0; + font-family: var(--mono); + font-size: 11px; + letter-spacing: 0.18em; + text-transform: uppercase; + padding: 10px 18px; +} +.btn-danger:hover { background: transparent; color: var(--rust); } +.btn-small { + background: transparent; + border: 1px solid var(--rule-strong); + color: var(--ink-soft); + border-radius: 0; + font-family: var(--mono); + font-size: 10px; + letter-spacing: 0.16em; + text-transform: uppercase; + padding: 6px 12px; +} +.btn-small:hover { border-color: var(--copper); color: var(--copper); } + +.confirm-dialog { + padding: 28px; + max-width: 460px; +} +.confirm-dialog p { + font-family: var(--serif); + font-style: italic; + font-size: 17px; + color: var(--ink-soft); + line-height: 1.5; + margin-bottom: 22px; + font-variation-settings: 'opsz' 30; +} +.confirm-dialog-actions { + display: flex; + justify-content: flex-end; + gap: 10px; +} + +.execution-status { + font-family: var(--mono); + font-size: 12px; + letter-spacing: 0.1em; + text-transform: uppercase; + color: var(--copper); + padding: 10px 14px; + border: 1px solid var(--rule-strong); + background: var(--bg-paper); + margin-bottom: 14px; +} +.execution-result { + background: var(--bg-paper); + border: 1px solid var(--rule); + border-radius: 0; +} +.execution-result pre { + font-family: var(--mono); + font-size: 11px; + color: var(--ink-soft); + padding: 14px; +} +.result-section h4 { + font-family: var(--mono); + font-size: 10px; + letter-spacing: 0.18em; + text-transform: uppercase; + color: var(--ink-mute); + margin-bottom: 8px; + font-weight: 400; +} + +.icon-input-wrapper { + display: flex; + align-items: center; + gap: 10px; +} +.icon-preview { + background: var(--bg-paper); + border: 1px solid var(--rule-strong); + border-radius: 0; + width: 36px; + height: 36px; + color: var(--copper); +} + +.params-section { + margin-top: 18px; + padding-top: 14px; + border-top: 1px solid var(--rule); +} +.params-header { + font-family: var(--mono); + font-size: 10px; + letter-spacing: 0.18em; + text-transform: uppercase; + color: var(--ink-mute); +} +.param-row { + background: var(--bg-paper); + border: 1px solid var(--rule); + border-radius: 0; + padding: 12px; + margin-top: 10px; +} +.param-row-header { + font-family: var(--mono); + font-size: 11px; + color: var(--copper); + letter-spacing: 0.08em; +} +.param-required-label { + color: var(--rust); + font-family: var(--mono); + font-size: 9px; + letter-spacing: 0.18em; + text-transform: uppercase; +} +.param-hint { + font-family: var(--serif); + font-style: italic; + font-size: 12px; + color: var(--ink-mute); + font-variation-settings: 'opsz' 18; +} +.param-remove-btn { + color: var(--rust); + background: transparent; + border: 1px solid var(--rule-strong); + border-radius: 0; +} +.param-remove-btn:hover { border-color: var(--rust); } + +/* Icon select popup */ +.icon-select-popup { + background: var(--bg-card); + border: 1px solid var(--rule-strong); + border-radius: 0; + box-shadow: 0 14px 40px rgba(0,0,0,0.5); +} +.icon-select-trigger { + background: transparent; + border: 1px solid var(--rule-strong); + border-radius: 0; + color: var(--ink); + font-family: var(--mono); + font-size: 12px; + padding: 8px 12px; +} +.icon-select-trigger:hover { border-color: var(--copper); color: var(--copper); } +.icon-select-cell { + border-radius: 0; + color: var(--ink-soft); + font-family: var(--mono); + font-size: 10px; +} +.icon-select-cell:hover { + background: rgba(224, 128, 56, 0.06); + color: var(--copper); +} + +/* ═══════════════════════════════════════════════════════════════ + AUTH MODAL — paper card + ═══════════════════════════════════════════════════════════════ */ +#auth-overlay { + background: rgba(14, 13, 11, 0.85); + backdrop-filter: blur(8px); + -webkit-backdrop-filter: blur(8px); +} +.auth-modal { + background: var(--bg-card); + border: 1px solid var(--rule-strong); + border-radius: 0; + padding: 40px 36px; + max-width: 440px; + box-shadow: 0 30px 80px rgba(0, 0, 0, 0.6); + position: relative; +} +.auth-modal h2 { + font-family: var(--serif); + font-weight: 400; + font-style: italic; + font-size: 36px; + line-height: 1; + margin-bottom: 12px; + font-variation-settings: 'opsz' 144; + letter-spacing: -0.02em; + color: var(--ink); +} +.auth-modal p { + font-family: var(--serif); + font-style: italic; + font-size: 15px; + color: var(--ink-soft); + line-height: 1.5; + margin-bottom: 18px; + font-variation-settings: 'opsz' 18; +} +.auth-modal input { + background: transparent; + border: 0; + border-bottom: 1px solid var(--rule-strong); + border-radius: 0; + color: var(--ink); + font-family: var(--mono); + font-size: 14px; + padding: 10px 0; + width: 100%; + margin-bottom: 18px; +} +.auth-modal input:focus { + outline: 0; + border-bottom-color: var(--copper); +} +.btn-connect { + background: var(--ink); + color: var(--bg-deep); + border: 1px solid var(--ink); + border-radius: 0; + width: 100%; + padding: 14px; + font-family: var(--mono); + font-size: 11px; + letter-spacing: 0.22em; + text-transform: uppercase; + transition: all 200ms var(--ease); + cursor: pointer; +} +.btn-connect:hover { + background: var(--copper); + border-color: var(--copper); +} +.help-text { + margin-top: 22px; + padding-top: 18px; + border-top: 1px solid var(--rule); + font-family: var(--mono); + font-size: 11px; + color: var(--ink-mute); + letter-spacing: 0.04em; +} +.help-text code { + background: var(--bg-paper); + color: var(--copper); + border: 1px solid var(--rule); + padding: 2px 6px; + font-family: var(--mono); + font-size: 11px; +} +.error-message { + color: var(--rust); + font-family: var(--mono); + font-size: 11px; + letter-spacing: 0.1em; + text-transform: uppercase; + margin-top: 14px; +} + +/* ═══════════════════════════════════════════════════════════════ + TOAST NOTIFICATIONS + ═══════════════════════════════════════════════════════════════ */ +.toast { + background: var(--bg-card); + border: 1px solid var(--copper); + border-radius: 0; + color: var(--ink); + font-family: var(--sans); + font-size: 13px; + padding: 14px 18px; + box-shadow: 0 14px 40px rgba(0,0,0,0.5), 0 0 24px var(--copper-glow); +} +.toast.success { border-color: var(--jade); box-shadow: 0 14px 40px rgba(0,0,0,0.5); } +.toast.error { border-color: var(--rust); box-shadow: 0 14px 40px rgba(0,0,0,0.5); } +.toast.info { border-color: var(--rule-strong); box-shadow: 0 14px 40px rgba(0,0,0,0.5); } + +/* ═══════════════════════════════════════════════════════════════ + FOOTER (colophon) + ═══════════════════════════════════════════════════════════════ */ +footer { + margin-top: 80px; + padding: 28px 0 0; + border-top: 1px solid var(--rule-strong); + background: transparent; + font-family: var(--mono); + font-size: 10px; + letter-spacing: 0.16em; + text-transform: uppercase; + color: var(--ink-faint); + text-align: center; +} +footer a { + color: var(--copper); + text-decoration: none; + border-bottom: 1px solid transparent; + transition: border-color 200ms var(--ease); +} +footer a:hover { border-bottom-color: var(--copper); } +footer strong { + font-family: var(--serif); + font-style: italic; + font-weight: 400; + font-size: 14px; + color: var(--ink-soft); + letter-spacing: 0.01em; + text-transform: none; + font-variation-settings: 'opsz' 30; +} +footer .separator { color: var(--ink-ghost); margin: 0 8px; } + +/* ═══════════════════════════════════════════════════════════════ + DISPLAY container (monitors tab) + ═══════════════════════════════════════════════════════════════ */ +.display-container { + background: transparent; + border: 0; + padding: 0; + box-shadow: none; +} + +/* ─── Light theme overrides for SR overrides ──────────────── */ +:root[data-theme="light"] .album-art-container { + box-shadow: + 0 1px 0 var(--bg-paper), + 0 28px 60px -20px rgba(26, 23, 21, 0.18), + 0 8px 20px -8px rgba(26, 23, 21, 0.12); +} +:root[data-theme="light"] .mini-player { + background: linear-gradient(180deg, rgba(245, 241, 234, 0.7) 0%, rgba(245, 241, 234, 0.96) 30%); +} +:root[data-theme="light"] dialog::backdrop { + background: rgba(26, 23, 21, 0.5); +} +:root[data-theme="light"] #auth-overlay { + background: rgba(245, 241, 234, 0.85); +} +:root[data-theme="light"] .toast { + box-shadow: 0 14px 40px rgba(26,23,21,0.18), 0 0 24px var(--copper-glow); +} + +/* ─── Mobile breakpoint refinements ──────────────────────── */ +@media (max-width: 720px) { + #track-title { font-size: 36px; } + .player-layout { gap: 24px; } + .album-art-container { padding: 10px; } + .album-art-container::before { font-size: 8px; bottom: -18px; } + .controls { gap: 12px; } + .controls button { width: 42px; height: 42px; } + .controls button.primary { width: 56px; height: 56px; } + .mini-player { padding: 12px 16px; gap: 16px; } + .tab-btn { padding: 14px 12px 12px; font-size: 12px; } + .tab-btn.active { font-size: 15px; } + .breadcrumb { font-size: 14px; } + .browser-toolbar { flex-wrap: wrap; } + .auth-modal { padding: 28px 22px; } + .auth-modal h2 { font-size: 28px; } + .settings-section { padding: 20px; } + .settings-section summary { font-size: 22px; } + footer { font-size: 9px; } +} diff --git a/media_server/static/fonts/Fraunces-italic-latin-ext.woff2 b/media_server/static/fonts/Fraunces-italic-latin-ext.woff2 new file mode 100644 index 0000000..2e65049 Binary files /dev/null and b/media_server/static/fonts/Fraunces-italic-latin-ext.woff2 differ diff --git a/media_server/static/fonts/Fraunces-italic-latin.woff2 b/media_server/static/fonts/Fraunces-italic-latin.woff2 new file mode 100644 index 0000000..b2cf648 Binary files /dev/null and b/media_server/static/fonts/Fraunces-italic-latin.woff2 differ diff --git a/media_server/static/fonts/Fraunces-latin-ext.woff2 b/media_server/static/fonts/Fraunces-latin-ext.woff2 new file mode 100644 index 0000000..b6e3e3a Binary files /dev/null and b/media_server/static/fonts/Fraunces-latin-ext.woff2 differ diff --git a/media_server/static/fonts/Fraunces-latin.woff2 b/media_server/static/fonts/Fraunces-latin.woff2 new file mode 100644 index 0000000..cb295bf Binary files /dev/null and b/media_server/static/fonts/Fraunces-latin.woff2 differ diff --git a/media_server/static/fonts/Geist-cyrillic.woff2 b/media_server/static/fonts/Geist-cyrillic.woff2 new file mode 100644 index 0000000..2000e32 Binary files /dev/null and b/media_server/static/fonts/Geist-cyrillic.woff2 differ diff --git a/media_server/static/fonts/Geist-latin-ext.woff2 b/media_server/static/fonts/Geist-latin-ext.woff2 new file mode 100644 index 0000000..9608c47 Binary files /dev/null and b/media_server/static/fonts/Geist-latin-ext.woff2 differ diff --git a/media_server/static/fonts/Geist-latin.woff2 b/media_server/static/fonts/Geist-latin.woff2 new file mode 100644 index 0000000..93552f5 Binary files /dev/null and b/media_server/static/fonts/Geist-latin.woff2 differ diff --git a/media_server/static/fonts/GeistMono-cyrillic.woff2 b/media_server/static/fonts/GeistMono-cyrillic.woff2 new file mode 100644 index 0000000..dbd7964 Binary files /dev/null and b/media_server/static/fonts/GeistMono-cyrillic.woff2 differ diff --git a/media_server/static/fonts/GeistMono-latin-ext.woff2 b/media_server/static/fonts/GeistMono-latin-ext.woff2 new file mode 100644 index 0000000..f638b47 Binary files /dev/null and b/media_server/static/fonts/GeistMono-latin-ext.woff2 differ diff --git a/media_server/static/fonts/GeistMono-latin.woff2 b/media_server/static/fonts/GeistMono-latin.woff2 new file mode 100644 index 0000000..504be86 Binary files /dev/null and b/media_server/static/fonts/GeistMono-latin.woff2 differ diff --git a/media_server/static/locales/en.json b/media_server/static/locales/en.json index 64bc2a0..50c326a 100644 --- a/media_server/static/locales/en.json +++ b/media_server/static/locales/en.json @@ -126,8 +126,8 @@ "callbacks.msg.list_failed": "Failed to load callbacks", "callbacks.confirm.delete": "Are you sure you want to delete the callback \"{name}\"?", "callbacks.confirm.unsaved": "You have unsaved changes. Are you sure you want to discard them?", - "tab.player": "Player", - "tab.browser": "Browser", + "tab.player": "Now Spinning", + "tab.browser": "Library", "tab.quick_access": "Quick Access", "tab.settings": "Settings", "tab.display": "Display", diff --git a/media_server/static/locales/ru.json b/media_server/static/locales/ru.json index 30d5a25..91ead82 100644 --- a/media_server/static/locales/ru.json +++ b/media_server/static/locales/ru.json @@ -126,8 +126,8 @@ "callbacks.msg.list_failed": "Не удалось загрузить обратные вызовы", "callbacks.confirm.delete": "Вы уверены, что хотите удалить обратный вызов \"{name}\"?", "callbacks.confirm.unsaved": "У вас есть несохраненные изменения. Вы уверены, что хотите отменить их?", - "tab.player": "Плеер", - "tab.browser": "Браузер", + "tab.player": "Сейчас играет", + "tab.browser": "Библиотека", "tab.quick_access": "Быстрый Доступ", "tab.settings": "Настройки", "tab.display": "Дисплей",