/* ─── Psysonic App Shell ─── */ .app-shell { position: relative; display: grid; grid-template-columns: var(--sidebar-width) 1fr var(--queue-width); grid-template-rows: 1fr var(--player-height); grid-template-areas: "sidebar main queue" "player player player"; height: 100vh; overflow: hidden; background: var(--bg-app); } /* ─── Resizer Handles ─── */ .resizer { position: absolute; top: 0; bottom: var(--player-height); width: 6px; cursor: col-resize; z-index: 50; background: transparent; transition: background var(--transition-fast); } .resizer:hover, .resizer:active { background: var(--accent); } .resizer-sidebar { left: calc(var(--sidebar-width) - 3px); } .resizer-queue { right: calc(var(--queue-width) - 3px); } /* ─── Sidebar ─── */ .sidebar { grid-area: sidebar; display: flex; flex-direction: column; background: var(--bg-sidebar); border-right: 1px solid var(--border-subtle); overflow: hidden; } .sidebar-brand { display: flex; align-items: center; gap: var(--space-3); padding: 0 var(--space-5); height: 64px; box-sizing: border-box; border-bottom: 1px solid var(--border-subtle); } .sidebar-brand .logo-icon { width: 32px; height: 32px; flex-shrink: 0; } .sidebar-brand .brand-name { font-family: var(--font-display); font-size: 20px; font-weight: 700; letter-spacing: -0.02em; background: linear-gradient(135deg, var(--ctp-mauve), var(--ctp-blue)); -webkit-background-clip: text; -webkit-text-fill-color: transparent; background-clip: text; } .sidebar-nav { flex: 1; padding: var(--space-4) var(--space-3); display: flex; flex-direction: column; gap: var(--space-1); overflow-y: auto; } .nav-section-label { font-size: 10px; font-weight: 600; letter-spacing: 0.1em; text-transform: uppercase; color: var(--text-muted); padding: var(--space-4) var(--space-3) var(--space-2); } .nav-link { display: flex; align-items: center; gap: var(--space-3); padding: var(--space-3) var(--space-3); border-radius: var(--radius-md); color: var(--text-secondary); font-size: 14px; font-weight: 500; transition: all var(--transition-fast); cursor: pointer; text-decoration: none; position: relative; } .nav-link:hover { background: var(--bg-hover); color: var(--text-primary); } .nav-link.active { background: var(--accent-dim); color: var(--accent); } .nav-link.active::before { content: ''; position: absolute; left: 0; top: 50%; transform: translateY(-50%); width: 3px; height: 60%; background: var(--accent); border-radius: 0 var(--radius-full) var(--radius-full) 0; } .nav-link svg { flex-shrink: 0; opacity: 0.7; transition: opacity var(--transition-fast); } .nav-link.active svg, .nav-link:hover svg { opacity: 1; } /* Collapsed Sidebar Styles */ .sidebar.collapsed .sidebar-brand { justify-content: center; padding: 0; } .sidebar.collapsed .nav-link { justify-content: center; padding: var(--space-3) 0; } .collapse-btn { background: transparent; border: none; color: var(--text-muted); cursor: pointer; padding: var(--space-2); border-radius: var(--radius-md); display: flex; align-items: center; justify-content: center; transition: all var(--transition-fast); } .collapse-btn:hover { background: var(--bg-hover); color: var(--text-primary); } /* ─── Main Content ─── */ .main-content { grid-area: main; display: flex; flex-direction: column; overflow: hidden; min-width: 0; background: var(--bg-app); } .content-header { display: flex; align-items: center; gap: var(--space-4); padding: 0 var(--space-6); height: 64px; box-sizing: border-box; border-bottom: 1px solid var(--border-subtle); background: var(--bg-app); position: relative; z-index: 10; } .content-header h1 { font-family: var(--font-display); font-size: 18px; font-weight: 600; color: var(--text-primary); } .content-header .spacer { flex: 1; } .content-body { flex: 1; overflow-y: auto; overflow-x: hidden; padding: var(--space-6); } /* ─── Player Bar ─── */ .player-bar { grid-area: player; display: grid; grid-template-columns: 280px 1fr 280px; align-items: center; gap: var(--space-4); padding: 0 var(--space-6); background: var(--bg-player); border-top: 1px solid var(--border-subtle); height: var(--player-height); position: relative; z-index: 100; } .player-track-info { display: flex; align-items: center; gap: var(--space-3); min-width: 0; } .player-album-art { width: 52px; height: 52px; border-radius: var(--radius-md); object-fit: cover; background: var(--bg-card); flex-shrink: 0; box-shadow: var(--shadow-md); } .player-album-art-placeholder { width: 52px; height: 52px; border-radius: var(--radius-md); background: var(--bg-card); flex-shrink: 0; display: flex; align-items: center; justify-content: center; color: var(--text-muted); } .player-album-art-wrap { position: relative; flex-shrink: 0; border-radius: var(--radius-sm); overflow: hidden; } .player-album-art-wrap::after { content: ''; position: absolute; inset: 0; background: rgba(0, 0, 0, 0.3); opacity: 0; transition: opacity var(--transition-fast); pointer-events: none; } .player-album-art-wrap.clickable { cursor: pointer; } .player-album-art-wrap:hover::after { opacity: 1; } /* Expand icon hint that appears on cover hover */ .player-art-expand-hint { position: absolute; inset: 0; display: flex; align-items: center; justify-content: center; color: white; opacity: 0; transition: opacity var(--transition-fast); pointer-events: none; z-index: 1; } .player-album-art-wrap.clickable:hover .player-art-expand-hint { opacity: 1; } .player-track-meta { min-width: 0; } .player-track-name { font-size: 14px; font-weight: 600; color: var(--text-primary); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; } .player-track-artist { font-size: 12px; color: var(--text-secondary); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; margin-top: 2px; } .player-controls { display: flex; flex-direction: column; align-items: center; gap: var(--space-2); } .player-buttons { display: flex; align-items: center; gap: var(--space-3); } .player-btn { display: flex; align-items: center; justify-content: center; width: 36px; height: 36px; border-radius: 50%; color: var(--text-muted); transition: all var(--transition-fast); } .player-btn:hover { background: var(--bg-hover); color: var(--text-primary); transform: scale(1.12); } .player-btn-primary { width: 48px; height: 48px; background: linear-gradient(135deg, var(--ctp-mauve), var(--ctp-lavender)); color: var(--ctp-crust); border-radius: 50%; box-shadow: 0 4px 18px rgba(0, 0, 0, 0.4); flex-shrink: 0; } .player-btn-primary:hover { background: linear-gradient(135deg, var(--ctp-lavender), var(--ctp-mauve)); color: var(--ctp-crust); transform: scale(1.07); box-shadow: 0 6px 24px rgba(0, 0, 0, 0.4), var(--shadow-glow); } .player-progress { display: flex; align-items: center; gap: var(--space-3); width: 100%; max-width: 480px; } .player-time { font-size: 11px; color: var(--text-muted); font-variant-numeric: tabular-nums; white-space: nowrap; } .player-progress-bar { flex: 1; position: relative; } .player-progress-bar input[type="range"] { width: 100%; } .player-right { display: flex; align-items: center; justify-content: flex-end; gap: var(--space-3); } .volume-control { display: flex; align-items: center; gap: var(--space-2); min-width: 120px; } .volume-control svg { flex-shrink: 0; color: var(--text-muted); } .volume-control input[type="range"] { flex: 1; } /* Connection Toggle */ .conn-toggle { display: flex; align-items: center; background: var(--bg-card); border: 1px solid var(--border); border-radius: var(--radius-full); padding: 2px; font-size: 11px; font-weight: 600; overflow: hidden; user-select: none; } .conn-toggle-btn { padding: 4px 10px; border-radius: var(--radius-full); transition: all var(--transition-fast); color: var(--text-muted); cursor: pointer; letter-spacing: 0.03em; } .conn-toggle-btn.active { background: var(--accent); color: var(--ctp-crust); } /* ─── Queue Panel ─── */ .queue-panel { grid-area: queue; background: var(--bg-sidebar); border-left: 1px solid var(--border-subtle); display: flex; flex-direction: column; overflow: hidden; min-width: 0; } .queue-header { height: 64px; box-sizing: border-box; padding: 0 var(--space-4); background: var(--bg-app); border-bottom: 1px solid var(--bg-surface); display: flex; justify-content: space-between; align-items: center; flex-shrink: 0; } .queue-current-track { padding: var(--space-4); display: flex; flex-direction: column; gap: var(--space-3); flex-shrink: 0; } .queue-current-cover { width: 100%; aspect-ratio: 1 / 1; border-radius: var(--radius-md); overflow: hidden; background: var(--bg-surface); display: flex; align-items: center; justify-content: center; box-shadow: 0 4px 12px rgba(0,0,0,0.15); } .queue-current-cover img { width: 100%; height: 100%; object-fit: cover; } .queue-current-cover .fallback { color: var(--text-muted); } .queue-current-info { display: flex; flex-direction: column; gap: 2px; } .queue-current-info h3 { font-size: 16px; font-weight: 700; margin: 0; color: var(--text-primary); } .queue-current-sub { font-size: 12px; color: var(--text-secondary); } .queue-current-tech { font-size: 10px; font-family: monospace; letter-spacing: 0.05em; background: var(--bg-surface); color: var(--text-muted); padding: 2px 6px; border-radius: 4px; border: 1px solid var(--border-subtle); display: inline-block; } .queue-divider { padding: var(--space-4) var(--space-5) 0; flex-shrink: 0; } .queue-list { flex: 1; overflow-y: auto; padding: var(--space-2); } .queue-empty { padding: var(--space-4); color: var(--text-muted); text-align: center; font-size: 14px; } .queue-item { display: flex; align-items: center; justify-content: space-between; padding: var(--space-2) var(--space-3); border-radius: var(--radius-sm); cursor: pointer; transition: background var(--transition-fast); color: var(--text-secondary); } /* Prevent child elements from stealing dragenter/dragleave events */ .queue-item > * { pointer-events: none; } .queue-item:hover { background: var(--bg-hover); color: var(--text-primary); } .queue-item.active { background: var(--accent-dim); color: var(--accent); } .queue-item-info { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 2px; } .queue-item-title { font-size: 12px; font-weight: 500; color: inherit; } .queue-item-artist { font-size: 11px; color: var(--text-muted); } .queue-item-duration { font-size: 11px; color: var(--text-muted); flex-shrink: 0; margin-left: var(--space-3); } .queue-item.active .queue-item-artist, .queue-item.active .queue-item-duration { color: inherit; opacity: 0.8; }