Files
tutorialvault/src/styles/playlist.css
Your Name 4e21662e5f fix: WCAG AAA contrast compliance, speed menu z-index, custom app icon
- 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
2026-02-19 18:23:38 +02:00

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);}