.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: ''; initial-value: 30px; inherits: false; } @property --list-fade-bottom { syntax: ''; 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);}