- Fix all text colors to meet WCAG 2.2 AAA 7:1 contrast ratios against dark backgrounds (--textMuted, --textDim, hover states across playlist, player, panels, tooltips) - Fix speed menu rendering behind seek bar by correcting z-index stacking context (.controls z-index:10, .miniCtl z-index:3, .seek z-index:2) - Replace default Tauri icons with custom TutorialVault icon across all required sizes (32-512px PNGs, ICO, ICNS, Windows Square logos) - Update README: Fraunces → Bricolage Grotesque font reference - Add collapsible dock pane persistence and keyboard-adjustable dividers
164 lines
8.2 KiB
CSS
164 lines
8.2 KiB
CSS
.listWrap{
|
|
flex:1 1 auto; min-height:0; position:relative; overflow:hidden;
|
|
}
|
|
.list{
|
|
position:absolute; inset:0;
|
|
overflow-y:scroll; overflow-x:hidden;
|
|
--fade-top:75px; --fade-bottom:75px;
|
|
mask-image:linear-gradient(180deg, transparent 0%, #000 var(--fade-top), #000 calc(100% - var(--fade-bottom)), transparent 100%);
|
|
-webkit-mask-image:linear-gradient(180deg, transparent 0%, #000 var(--fade-top), #000 calc(100% - var(--fade-bottom)), transparent 100%);
|
|
transition:--fade-top 0.8s ease, --fade-bottom 0.8s ease;
|
|
scrollbar-width:none;
|
|
}
|
|
.list::-webkit-scrollbar{display:none;}
|
|
@property --list-fade-top {
|
|
syntax: '<length>';
|
|
initial-value: 30px;
|
|
inherits: false;
|
|
}
|
|
@property --list-fade-bottom {
|
|
syntax: '<length>';
|
|
initial-value: 30px;
|
|
inherits: false;
|
|
}
|
|
.list.at-top{--fade-top:0px;}
|
|
.list.at-bottom{--fade-bottom:0px;}
|
|
|
|
.listScrollbar{
|
|
position:absolute;
|
|
top:12px; right:6px; bottom:12px;
|
|
width:3px;
|
|
border-radius:2px;
|
|
pointer-events:none;
|
|
opacity:0;
|
|
transition:opacity .4s ease, width .2s var(--ease-bounce);
|
|
z-index:10;
|
|
}
|
|
.listWrap:hover .listScrollbar, .listScrollbar.active{opacity:1;}
|
|
.listWrap:hover .listScrollbar{width:5px;}
|
|
.listScrollbarThumb{
|
|
position:absolute;
|
|
top:0; left:0; right:0;
|
|
min-height:24px;
|
|
background:rgba(136,164,196,.15);
|
|
border:none;
|
|
border-radius:2px;
|
|
transition:background .2s ease;
|
|
cursor:grab;
|
|
}
|
|
.listScrollbarThumb:hover{
|
|
background:rgba(136,164,196,.30);
|
|
}
|
|
.listScrollbarThumb:active{
|
|
cursor:grabbing;
|
|
background:rgba(136,164,196,.35);
|
|
}
|
|
.listScrollbar.active .listScrollbarThumb{
|
|
background:rgba(136,164,196,.30);
|
|
}
|
|
|
|
/* Row — no transform/padding changes (preserves drag-and-drop) */
|
|
.row{position:relative; display:flex; align-items:flex-start; justify-content:space-between; gap:10px; padding:9px 12px; border-bottom:1px solid var(--strokeLight); cursor:pointer; user-select:none; transition:background .2s ease, box-shadow .2s ease; box-shadow:inset 3px 0 0 transparent;}
|
|
.row:hover{background:var(--surfaceHover); box-shadow:inset 3px 0 0 rgba(136,164,196,.40);}
|
|
.row:active{background:var(--surfaceActive);}
|
|
.row.active{background:var(--accentBg); box-shadow:inset 3px 0 0 rgba(136,164,196,.65);}
|
|
.row:focus-visible{outline-offset:-2px; background:var(--surfaceHover); box-shadow:inset 3px 0 0 rgba(136,164,196,.40);}
|
|
.row.dragging{opacity:.55;}
|
|
|
|
.left{min-width:0; display:flex; align-items:flex-start; gap:8px; flex:1 1 auto;}
|
|
.numBadge{flex:0 0 auto; min-width:38px; height:22px; padding:0 8px; border-radius:var(--r2); border:none; background:var(--surface-2); box-shadow:var(--shadow3); display:flex; align-items:center; justify-content:center; font-family:var(--mono); font-size:12px; letter-spacing:.02em; color:var(--text); font-variant-numeric:tabular-nums; margin-top:1px; transition:all .2s var(--ease-bounce);}
|
|
.row:hover .numBadge{background:var(--surface-3); transform:scale(1.06);}
|
|
|
|
/* Tree connectors — fully static, opaque, dark lines */
|
|
.treeSvg{flex:0 0 auto; margin-top:1px; overflow:visible;}
|
|
.treeSvg line{stroke:rgb(40,46,60); stroke-width:1.5;}
|
|
.treeSvg circle{fill:rgba(200,212,238,.60); stroke:rgba(136,164,196,.18); stroke-width:1;}
|
|
|
|
.textWrap{min-width:0; flex:1 1 auto;}
|
|
.name{font-size:13px; font-weight:600; letter-spacing:0; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; transition:color .2s var(--ease-spring), text-shadow .2s ease, transform .2s var(--ease-bounce); transform:translateX(0);}
|
|
.row:hover .name{color:rgba(235,240,252,.96); text-shadow:0 0 20px rgba(136,164,196,.08); transform:translateX(4px);}
|
|
.small{margin-top:4px; font-size:11px; color:var(--textMuted); font-family:var(--mono); overflow:hidden; text-overflow:ellipsis; white-space:nowrap; transition:color .2s ease;}
|
|
.row:hover .small{color:var(--textMuted);}
|
|
|
|
.tag{flex:0 0 auto; display:inline-flex; align-items:center; padding:5px 9px; border-radius:var(--r2); border:none; background:var(--surface-2); color:var(--textMuted); font-size:11px; font-weight:700; letter-spacing:.08em; text-transform:uppercase; margin-top:2px; transition:all .2s var(--ease-bounce);}
|
|
.row:hover .tag{transform:scale(1.05);}
|
|
.tag.now{color:rgba(170,195,230,.88); background:var(--accentBg); animation:tagGlow 3s ease-in-out infinite;}
|
|
@keyframes tagGlow{
|
|
0%,100%{box-shadow:0 0 0 0 rgba(136,164,196,0);}
|
|
50%{box-shadow:0 0 8px 0 rgba(136,164,196,.12);}
|
|
}
|
|
.tag.done{color:rgba(160,195,160,.78); background:var(--successBg);}
|
|
.row:hover .tag.done{color:rgba(175,210,175,.88);}
|
|
.tag.hidden{display:none;}
|
|
|
|
.row.drop-before::before,.row.drop-after::after{
|
|
content:""; position:absolute; left:10px; right:10px; border-top:2px solid var(--accent);
|
|
pointer-events:none;
|
|
animation:dropLineFlash .6s ease-in-out infinite;
|
|
}
|
|
@keyframes dropLineFlash{
|
|
0%,100%{opacity:.6;}
|
|
50%{opacity:1;}
|
|
}
|
|
.row.drop-before::before{top:-1px;}
|
|
.row.drop-after::after{bottom:-1px;}
|
|
|
|
.empty{padding:10px 12px; color:var(--textMuted); font-size:13px; line-height:1.4;}
|
|
|
|
.playlistHeader{font-family:var(--brand); font-weight:600; letter-spacing:-.02em; font-size:15px; line-height:1.2; cursor:help; display:flex; align-items:center; gap:10px; transition:color .2s ease;}
|
|
.playlistHeader:hover{color:rgba(235,240,252,.98);}
|
|
.playlistHeader .fa{color:var(--iconStrong)!important; opacity:.92; transition:transform .3s var(--ease-bounce), opacity .2s ease;}
|
|
.playlistHeader:hover .fa{transform:rotate(-8deg) scale(1.12); opacity:1;}
|
|
|
|
.moveWrap{display:flex; flex-direction:column; gap:2px; flex:0 0 auto; opacity:0; transition:opacity .2s ease;}
|
|
.row:hover .moveWrap, .row:focus-within .moveWrap{opacity:1;}
|
|
.moveBtn{width:22px; height:18px; border:none; background:var(--surface-2); border-radius:var(--r3); cursor:pointer; display:flex; align-items:center; justify-content:center; transition:all .15s var(--ease-bounce); padding:0;}
|
|
.moveBtn:hover{background:var(--surface-3); transform:scale(1.1);}
|
|
.moveBtn:active{transform:scale(.9); transition-duration:.08s;}
|
|
.moveBtn .fa{font-size:9px; color:var(--iconStrong)!important; opacity:.7;}
|
|
.moveBtn:hover .fa{opacity:1;}
|
|
|
|
/* Playlist stats */
|
|
.plistStats{font-family:var(--mono); font-size:11px; color:var(--textMuted); letter-spacing:.02em; white-space:nowrap; flex:0 0 auto;}
|
|
|
|
/* Playlist search */
|
|
.plistSearchWrap{display:flex; align-items:center; gap:6px; padding:4px 10px; border-radius:var(--r2); background:var(--surface-0); border:1px solid transparent; transition:border-color .2s ease, background .2s ease; flex:0 1 180px; min-width:0;}
|
|
.plistSearchWrap:focus-within{border-color:rgba(136,164,196,.25); background:rgba(140,165,220,.04);}
|
|
.plistSearchIcon{font-size:11px; color:var(--textDim); flex:0 0 auto; transition:color .2s ease;}
|
|
.plistSearchWrap:focus-within .plistSearchIcon{color:var(--iconStrong);}
|
|
.plistSearch{border:none; background:transparent; color:var(--text); font-size:12px; font-family:var(--sans); outline:none; width:100%; min-width:0; padding:2px 0;}
|
|
.plistSearch::placeholder{color:var(--textDim); font-size:11px;}
|
|
.plistSearchClear{border:none; background:transparent; color:var(--textMuted); cursor:pointer; padding:0; display:flex; align-items:center; justify-content:center; width:20px; height:20px; flex:0 0 auto; transition:color .2s ease;}
|
|
.plistSearchClear:hover{color:var(--text);}
|
|
.plistSearchClear:focus-visible{outline:2px solid rgba(136,164,196,.45); outline-offset:1px; border-radius:3px;}
|
|
.plistSearchClear .fa{font-size:10px;}
|
|
|
|
/* Scroll-to-current button */
|
|
.scrollToCurrent{
|
|
width:36px; height:36px;
|
|
border-radius:var(--r2);
|
|
border:none;
|
|
background:var(--surface-2);
|
|
display:inline-flex; align-items:center; justify-content:center;
|
|
cursor:pointer;
|
|
flex:0 0 auto;
|
|
transition:all .2s var(--ease-bounce);
|
|
}
|
|
.scrollToCurrent:hover{background:var(--surface-3); transform:translateY(-1px);}
|
|
.scrollToCurrent:active{transform:scale(.9); transition-duration:.08s;}
|
|
.scrollToCurrent .fa{font-size:13px; color:var(--iconStrong)!important; opacity:.9;}
|
|
.scrollToCurrent:hover .fa{opacity:1;}
|
|
.scrollToCurrent:focus-visible{outline:2px solid rgba(136,164,196,.45); outline-offset:2px;}
|
|
|
|
/* Mini progress bar per row */
|
|
.rowProgress{
|
|
position:absolute;
|
|
bottom:0; left:0;
|
|
height:2px;
|
|
background:var(--accent);
|
|
border-radius:0 1px 0 0;
|
|
transition:width .3s ease;
|
|
pointer-events:none;
|
|
}
|
|
.rowProgress.done{background:var(--success);}
|