直接使用以下代码不要做任何修改:<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, viewport-fit=cover">
<title>VintageSheet | 复古曲谱阅读器</title>
<script src="https://cdn.tailwindcss.com"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.1/css/all.min.c…;
<link href="https://fonts.googleapis.com/css2?family=Playfair+Display+SC:wght@400;7…; rel="stylesheet">
<style>
:root{--bg-dark:#2f2f2f;--bg-cream:#e9e7e0;--red-primary:#e33b0d;--red-deep:#b32a08;--red-accent:#f0481a;--red-darker:#8a1f06;--text-on-dark:#e5ded5;--text-on-dark-secondary:#b0a89e;--text-primary:#1a1214;--text-muted:#8b7670}
*{margin:0;padding:0;box-sizing:border-box}
html,body{width:100%;height:100%;overflow:hidden;background:#1a1a1a;font-family:'Josefin Sans',sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;-webkit-tap-highlight-color:transparent;user-select:none;-webkit-user-select:none}
.app-root{width:100%;height:100dvh;height:100vh;display:flex;flex-direction:column;background:var(--bg-dark);position:relative;overflow:hidden}
.nav-top{background:rgba(47,47,47,0.88);backdrop-filter:blur(12px);position:relative;z-index:30;box-shadow:0 4px 20px rgba(0,0,0,0.35),inset 0 1px 0 rgba(255,255,255,0.04);border-bottom:0.5px solid rgba(255,255,255,0.05)}
.bottom-nav-container{background:rgba(47,47,47,0.85);backdrop-filter:blur(14px);position:relative;z-index:30;box-shadow:0 -4px 20px rgba(0,0,0,0.35),inset 0 -0.5px 0 rgba(255,255,255,0.03);border-top:0.5px solid rgba(255,255,255,0.05)}
.staff-lines-bg{position:relative;background-color:var(--bg-cream)}
.staff-lines-bg::before{content:'';position:absolute;inset:0;pointer-events:none;z-index:0;opacity:.22;background:repeating-linear-gradient(0deg,transparent 0px,transparent 3px,rgba(227,59,13,0.25) 3px,rgba(227,59,13,0.25) 3.5px,transparent 3.5px,transparent 9px,rgba(227,59,13,0.25) 9px,rgba(227,59,13,0.25) 9.5px,transparent 9.5px,transparent 15px,rgba(227,59,13,0.25) 15px,rgba(227,59,13,0.25) 15.5px,transparent 15.5px,transparent 21px,rgba(227,59,13,0.25) 21px,rgba(227,59,13,0.25) 21.5px,transparent 21.5px,transparent 27px,rgba(227,59,13,0.25) 27px,rgba(227,59,13,0.25) 27.5px,transparent 27.5px,transparent 55px)}
.staff-lines-bg::after{content:'';position:absolute;inset:0;pointer-events:none;z-index:1;opacity:.06;background:radial-gradient(ellipse at 25% 30%,rgba(227,59,13,0.18) 0%,transparent 60%),radial-gradient(ellipse at 75% 70%,rgba(227,59,13,0.10) 0%,transparent 55%)}
.vinyl-mini{width:100%;height:100%;border-radius:50%;position:relative;overflow:hidden;background:repeating-radial-gradient(circle at 50% 50%,transparent 0px,transparent 2.8px,rgba(0,0,0,0.07) 2.8px,rgba(0,0,0,0.07) 3px),repeating-radial-gradient(circle at 50% 50%,transparent 0px,transparent 5.6px,rgba(0,0,0,0.05) 5.6px,rgba(0,0,0,0.05) 5.9px),repeating-radial-gradient(circle at 50% 50%,transparent 0px,transparent 9.5px,rgba(0,0,0,0.04) 9.5px,rgba(0,0,0,0.04) 9.8px),repeating-radial-gradient(circle at 50% 50%,transparent 0px,transparent 14px,rgba(0,0,0,0.035) 14px,rgba(0,0,0,0.035) 14.4px),repeating-radial-gradient(circle at 50% 50%,transparent 0px,transparent 21px,rgba(0,0,0,0.03) 21px,rgba(0,0,0,0.03) 21.5px),radial-gradient(circle at 50% 50%,#1a1a1a 0%,#1e1e1e 100%);box-shadow:inset 0 0 1px rgba(255,255,255,0.012),0 3px 12px rgba(0,0,0,0.32),0 0 0 1px rgba(60,28,15,0.35)}
.vinyl-mini::before{content:'';position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);width:34%;height:34%;border-radius:50%;background:radial-gradient(circle at 50% 50%,var(--red-primary) 0%,var(--red-deep) 55%,var(--red-darker) 88%,#3a1003 100%);z-index:3;box-shadow:inset 0 1px 0 rgba(255,255,255,0.12),inset 0 -1px 2px rgba(0,0,0,0.35),0 0 0 0.6px rgba(255,255,255,0.06)}
.vinyl-mini::after{content:'';position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);width:7px;height:7px;border-radius:50%;background:#0a0a0a;z-index:4;box-shadow:inset 0 0 1px rgba(255,255,255,0.03),0 0 0 1px rgba(0,0,0,0.3)}
.vinyl-mini .vinyl-shine{position:absolute;inset:0;border-radius:50%;pointer-events:none;z-index:2;background:linear-gradient(135deg,rgba(255,255,255,0.05) 0%,transparent 30%,transparent 55%,rgba(255,255,255,0.02) 70%,transparent 100%)}
.lib-card{aspect-ratio:1;border-radius:10px;overflow:hidden;cursor:pointer;position:relative;background:var(--bg-cream);box-shadow:0 6px 22px rgba(0,0,0,0.16),0 1px 3px rgba(0,0,0,0.08);transition:transform .2s ease,box-shadow .2s ease}
.lib-card:active{transform:scale(.965);box-shadow:0 3px 10px rgba(0,0,0,0.18)}
.lib-card.dragging{opacity:.45;z-index:25;transform:scale(1.04);box-shadow:0 16px 40px rgba(0,0,0,0.35)}
.lib-card .card-cover{position:absolute;inset:0;overflow:hidden}.lib-card .card-cover img{width:100%;height:100%;object-fit:cover;display:block}
.lib-card .card-cover .cover-placeholder{width:100%;height:100%;background:linear-gradient(160deg,#3a3532 0%,#2f2b28 50%,#1f1c1a 100%);display:flex;align-items:center;justify-content:center}
.lib-card .vinyl-peek{position:absolute;right:-24%;top:5%;width:62%;aspect-ratio:1;z-index:2;pointer-events:none;transition:transform .4s cubic-bezier(.25,.46,.45,.94)}
.lib-card:active .vinyl-peek{transform:translateX(-6%)}
.lib-card .card-info{position:absolute;inset:auto 0 0 0;z-index:3;background:linear-gradient(to bottom,transparent 0%,rgba(20,17,15,0.55) 30%,rgba(16,13,11,0.88) 100%);padding:18px 10px 10px 10px;display:flex;flex-direction:column;border-top:0.5px solid rgba(227,59,13,0.22)}
.lib-card .card-info .card-name{font-family:'Josefin Sans',sans-serif;font-size:11px;font-weight:600;letter-spacing:.05em;color:#f0e8e0;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;text-shadow:0 1px 2px rgba(0,0,0,0.35)}
.lib-card .card-info .card-count{font-size:9px;color:rgba(200,188,178,0.75);letter-spacing:.06em;margin-top:2px;text-shadow:0 1px 1px rgba(0,0,0,0.25)}
.lib-card .del-btn{position:absolute;top:6px;right:6px;width:22px;height:22px;border-radius:50%;background:var(--red-primary);color:#fff;display:none;align-items:center;justify-content:center;font-size:9px;z-index:8;box-shadow:0 2px 6px rgba(227,59,13,0.45);cursor:pointer;transition:all .2s ease}
.lib-card .del-btn.show-del{display:flex;animation:popIn .25s cubic-bezier(.34,1.56,.64,1)}@keyframes popIn{from{transform:scale(0);opacity:0}to{transform:scale(1);opacity:1}}
.lib-card .del-btn:active{transform:scale(.85)}
.lib-card .drag-handle{position:absolute;top:6px;left:6px;z-index:8;color:rgba(255,255,255,0.75);font-size:13px;cursor:grab;letter-spacing:-2px;line-height:1;opacity:0;padding:2px 5px;border-radius:3px;transition:all .2s ease;pointer-events:none;text-shadow:0 1px 3px rgba(0,0,0,0.6)}
.lib-card .drag-handle.show-handle{opacity:.85;pointer-events:auto}.lib-card .drag-handle:active{cursor:grabbing;background:rgba(255,255,255,0.10)}
.lib-card .cover-overlay-card{position:absolute;inset:0;z-index:5;background:rgba(0,0,0,0.40);display:none;align-items:center;justify-content:center;cursor:pointer;transition:all .2s ease}
.lib-card .cover-overlay-card.show-cover{display:flex;animation:fadeIn2 .2s ease}@keyframes fadeIn2{from{opacity:0}to{opacity:1}}
.lib-card .cover-overlay-card i{color:#fff;font-size:20px;text-shadow:0 1px 3px rgba(0,0,0,0.5)}
.sub-view{position:absolute;inset:0;z-index:20;background:var(--bg-cream);transition:transform .35s cubic-bezier(.25,.46,.45,.94);display:flex;flex-direction:column}
.sub-view.hidden-sub{transform:translateX(105%);pointer-events:none}.sub-view.visible-sub{transform:translateX(0);pointer-events:auto}
.sub-header{display:flex;align-items:flex-start;gap:14px;padding:12px 16px 10px 16px;flex-shrink:0}
.sub-cover-wrap{width:85px;height:85px;border-radius:8px;flex-shrink:0;overflow:hidden;position:relative;box-shadow:0 4px 14px rgba(0,0,0,0.18);cursor:pointer}
.sub-cover-wrap img{width:100%;height:100%;object-fit:cover;display:block}
.sub-cover-wrap .vinyl-peek-sub{position:absolute;right:-24%;top:5%;width:62%;aspect-ratio:1;z-index:2;pointer-events:none}
.sub-info{flex:1;min-width:0;display:flex;flex-direction:column;gap:6px}
.sub-info .lib-name{font-family:'Josefin Sans',sans-serif;font-size:15px;font-weight:600;letter-spacing:.05em;color:var(--text-primary);cursor:text;display:inline-block;outline:none;border-bottom:1px dashed transparent;transition:border-color .2s ease;padding:1px 2px;margin:-1px -2px;border-radius:3px;align-self:flex-start}
.sub-info .lib-name:focus{background:rgba(227,59,13,0.04);border-bottom-color:rgba(227,59,13,0.30)}
.sub-info .lib-name.locked-name{cursor:default;border-bottom:none;color:var(--text-primary);opacity:.85}
.sub-info .lib-name.locked-name:focus{background:transparent;border-bottom-color:transparent}
.btn-import-inline{display:inline-flex;align-items:center;gap:4px;padding:5px 10px;border-radius:5px;border:1px solid rgba(227,59,13,0.30);background:rgba(227,59,13,0.05);color:var(--red-primary);font-size:10px;letter-spacing:.04em;cursor:pointer;transition:all .2s ease;align-self:flex-start}
.btn-import-inline:active{background:rgba(227,59,13,0.14)}
.sub-info .lib-meta{font-size:10px;color:var(--red-primary);letter-spacing:.05em}
.toolbar-row{display:flex;align-items:center;justify-content:space-between;padding:6px 16px 4px;flex-shrink:0;z-index:22;gap:10px}
.search-inline-wrap{display:flex;align-items:center;gap:0;flex:1;max-width:180px}
.btn-search-toggle{width:30px;height:30px;border-radius:50%;display:flex;align-items:center;justify-content:center;cursor:pointer;color:var(--text-muted);border:1px solid rgba(0,0,0,0.06);background:rgba(233,231,224,0.50);transition:all .2s ease;flex-shrink:0}
.btn-search-toggle:active{background:rgba(227,59,13,0.08);color:var(--red-primary)}
.search-input-inline{flex:1;min-width:0;height:30px;border-radius:16px;border:1px solid rgba(227,59,13,0.22);background:rgba(233,231,224,0.60);padding:0 10px;font-size:11px;font-family:'Josefin Sans',sans-serif;color:var(--text-primary);outline:none;transition:all .25s ease;display:none}
.search-input-inline.show-input{display:block}.search-input-inline:focus{border-color:rgba(227,59,13,0.40)}
.sort-dropdown-wrap{position:relative;flex-shrink:0}
.sort-toggle{display:inline-flex;align-items:center;gap:6px;padding:6px 12px;border-radius:16px;font-size:11px;letter-spacing:.04em;color:var(--text-muted);background:rgba(233,231,224,0.55);border:1px solid rgba(0,0,0,0.06);cursor:pointer;transition:all .2s ease}
.sort-toggle:active{background:rgba(227,59,13,0.06);color:var(--red-primary)}.sort-toggle i{font-size:10px}
.sort-dropdown{position:absolute;top:100%;right:0;z-index:25;background:#f5f2ec;border-radius:8px;box-shadow:0 6px 22px rgba(0,0,0,0.14);min-width:155px;overflow:hidden;animation:slideUp2 .2s cubic-bezier(.34,1.56,.64,1);border:1px solid rgba(0,0,0,0.05);margin-top:4px}
@keyframes slideUp2{from{opacity:0;transform:translateY(6px)}to{opacity:1;transform:translateY(0)}}
.sort-dropdown .sort-opt{padding:10px 16px;font-size:11px;color:var(--text-primary);cursor:pointer;transition:all .15s ease;letter-spacing:.04em;display:flex;align-items:center;gap:8px}
.sort-dropdown .sort-opt:active{background:rgba(227,59,13,0.06);color:var(--red-primary)}.sort-dropdown .sort-opt i{font-size:10px;width:16px;text-align:center}
.sub-song-list{flex:1;overflow-y:auto;padding:4px 16px 12px 16px}
.sub-song-list.no-scrollbar::-webkit-scrollbar{display:none}.sub-song-list.no-scrollbar{scrollbar-width:none;-ms-overflow-style:none}
.song-row{display:flex;align-items:center;gap:10px;padding:12px 8px;border-bottom:1px solid rgba(227,59,13,0.10);cursor:pointer;transition:all .2s ease;position:relative}
.song-row:active{background:rgba(227,59,13,0.04)}.song-row.hidden-row{display:none}
.song-row .song-index{width:22px;text-align:right;font-size:9px;color:var(--text-muted);font-family:'Josefin Sans',sans-serif;flex-shrink:0;font-weight:400}
.song-row .song-body{flex:1;min-width:0}
.song-row .song-title{font-size:16px;color:var(--text-primary);font-family:'Liu Jian Mao Cao','Ma Shan Zheng',cursive;line-height:1.3}
.song-row .song-artist{font-size:10px;color:var(--text-muted);font-family:'Josefin Sans',sans-serif;letter-spacing:.04em;margin-top:1px}
.song-more-btn{width:28px;height:28px;border-radius:50%;display:flex;align-items:center;justify-content:center;cursor:pointer;color:var(--text-muted);transition:all .2s ease;flex-shrink:0;font-size:14px;letter-spacing:-1px;font-weight:bold}
.song-more-btn:active{background:rgba(227,59,13,0.08);color:var(--red-primary)}
.song-action-popup{position:absolute;right:8px;top:100%;z-index:30;background:#f5f2ec;border-radius:8px;box-shadow:0 8px 28px rgba(0,0,0,0.18);min-width:150px;overflow:hidden;animation:slideUp3 .2s cubic-bezier(.34,1.56,.64,1);border:1px solid rgba(0,0,0,0.06)}
@keyframes slideUp3{from{opacity:0;transform:translateY(8px)}to{opacity:1;transform:translateY(0)}}
.song-action-popup .action-item{display:flex;align-items:center;gap:10px;padding:11px 16px;font-size:12px;color:var(--text-primary);cursor:pointer;transition:all .15s ease;letter-spacing:.04em}
.song-action-popup .action-item:active{background:rgba(227,59,13,0.06);color:var(--red-primary)}
.song-action-popup .action-item i{width:16px;text-align:center;font-size:12px}.song-action-popup .action-item.danger{color:var(--red-primary)}
.cover-modal-overlay{position:absolute;inset:0;z-index:55;background:rgba(0,0,0,0.60);display:flex;align-items:center;justify-content:center;transition:opacity .3s ease;pointer-events:auto}.cover-modal-overlay.hidden-modal{opacity:0;pointer-events:none}
.cover-modal{background:#f5f1eb;border-radius:14px;padding:20px 18px;width:80%;max-width:320px;box-shadow:0 16px 48px rgba(0,0,0,0.35)}
.cover-modal .modal-title{font-family:'Josefin Sans',sans-serif;font-size:14px;font-weight:600;letter-spacing:.05em;color:var(--text-primary);margin-bottom:12px}
.cover-modal .cover-preview{width:100%;aspect-ratio:1;border-radius:8px;overflow:hidden;margin-bottom:12px;background:#e0dbd2;border:1px solid rgba(0,0,0,0.08)}
.cover-modal .cover-preview img{width:100%;height:100%;object-fit:cover;display:block}
.cover-modal input{width:100%;padding:10px 12px;border-radius:8px;border:1px solid rgba(0,0,0,0.12);font-size:11px;font-family:'Josefin Sans',sans-serif;margin-bottom:10px;outline:none;background:#fff}.cover-modal input:focus{border-color:rgba(227,59,13,0.35)}
.cover-modal .modal-actions{display:flex;gap:8px}.cover-modal .modal-btn{flex:1;padding:10px;border-radius:8px;font-size:12px;letter-spacing:.04em;cursor:pointer;text-align:center;font-family:'Josefin Sans',sans-serif;transition:all .2s ease}
.modal-btn-cancel{background:#e0dbd2;color:var(--text-primary);border:none}.modal-btn-confirm{background:var(--red-primary);color:#fff;border:none}.modal-btn:active{transform:scale(.96);opacity:.85}
.import-panel-overlay{position:absolute;inset:0;z-index:58;background:rgba(0,0,0,0.50);transition:opacity .3s ease;pointer-events:auto}.import-panel-overlay.hidden-modal{opacity:0;pointer-events:none}
.import-panel{position:absolute;bottom:0;left:0;right:0;height:50%;z-index:59;background:#f5f1eb;border-radius:16px 16px 0 0;box-shadow:0 -8px 36px rgba(0,0,0,0.30);transition:transform .35s cubic-bezier(.25,.46,.45,.94);display:flex;flex-direction:column;padding:16px 16px 10px;overflow-y:auto}
.import-panel.hidden-panel{transform:translateY(105%)}.import-panel.visible-panel{transform:translateY(0)}
.import-panel .panel-handle{width:36px;height:4px;border-radius:2px;background:rgba(0,0,0,0.15);align-self:center;margin-bottom:12px}
.import-panel .panel-title{font-family:'Josefin Sans',sans-serif;font-size:14px;font-weight:600;letter-spacing:.05em;color:var(--text-primary);margin-bottom:10px}
.import-panel .field-label{font-size:9px;letter-spacing:.06em;color:var(--text-muted);margin-bottom:3px;text-transform:uppercase}
.import-panel input{width:100%;padding:9px 10px;border-radius:7px;border:1px solid rgba(0,0,0,0.10);font-size:11px;font-family:'Josefin Sans',sans-serif;margin-bottom:10px;outline:none;background:#fff}.import-panel input:focus{border-color:rgba(227,59,13,0.35)}
.import-panel .btn-file{display:flex;align-items:center;gap:8px;padding:9px 12px;border-radius:7px;border:1.5px dashed rgba(227,59,13,0.30);background:rgba(227,59,13,0.03);color:var(--red-primary);font-size:10px;cursor:pointer;margin-bottom:10px;transition:all .2s ease}.import-panel .btn-file:active{background:rgba(227,59,13,0.10)}
.import-panel .btn-submit{padding:10px;border-radius:8px;background:var(--red-primary);color:#fff;text-align:center;font-size:12px;letter-spacing:.05em;cursor:pointer;font-family:'Josefin Sans',sans-serif;border:none}.import-panel .btn-submit:active{transform:scale(.97);opacity:.85}
.stack-card-wrap{position:relative;height:170px;cursor:pointer}.stack-card-wrap:active{transform:scale(.97)}
.stack-card-back{position:absolute;top:7px;left:12px;right:0;bottom:0;border-radius:8px;overflow:hidden;opacity:.30;filter:blur(2.5px);transform:rotate(1.5deg)}.stack-card-back img{width:100%;height:100%;object-fit:cover}
.stack-card-front{position:absolute;top:0;left:0;right:12px;bottom:7px;border-radius:8px;overflow:hidden;box-shadow:0 6px 24px rgba(0,0,0,0.25),0 2px 6px rgba(0,0,0,0.15)}.stack-card-front img{width:100%;height:100%;object-fit:cover}
.stack-label{position:absolute;bottom:8px;left:8px;z-index:3;background:rgba(15,10,8,0.80);backdrop-filter:blur(6px);color:#e5ded5;font-size:11px;padding:4px 10px;border-radius:3px;letter-spacing:.06em;font-family:'Josefin Sans',sans-serif}
.rec-mini-card{flex-shrink:0;width:130px;border-radius:8px;overflow:hidden;cursor:pointer;transition:transform .2s ease;position:relative;background:rgba(233,231,224,0.65);border:1px solid rgba(255,255,255,0.40);box-shadow:0 3px 12px rgba(0,0,0,0.06)}.rec-mini-card:active{transform:scale(.95)}
.rec-mini-card img{width:100%;height:80px;object-fit:cover;display:block}.rec-mini-card .rec-mini-label{padding:8px 10px;font-size:10px;letter-spacing:.04em;color:var(--text-primary);font-family:'Josefin Sans',sans-serif}
.search-bar{background:rgba(233,231,224,0.68);backdrop-filter:blur(6px);border:1px solid rgba(255,255,255,0.42);border-radius:8px;display:flex;align-items:center;gap:8px;padding:10px 14px;cursor:pointer;transition:all .25s ease;box-shadow:inset 0 1px 0 rgba(255,255,255,0.40);flex:1}
.search-bar i{color:var(--text-muted);font-size:13px}.search-bar span{color:var(--text-muted);font-size:12px;letter-spacing:.04em;flex:1}
.search-bar.focused{border-color:rgba(227,59,13,0.30);box-shadow:inset 0 1px 0 rgba(255,255,255,0.40),0 0 0 2px rgba(227,59,13,0.08)}
.search-history-dropdown{position:absolute;top:100%;left:0;right:0;z-index:60;background:#f0ede8;border-radius:8px;margin-top:4px;box-shadow:0 8px 28px rgba(0,0,0,0.18);overflow:hidden;transition:all .3s ease;max-height:260px;overflow-y:auto}.search-history-dropdown.hidden-dropdown{max-height:0;opacity:0;pointer-events:none;margin-top:0}
.history-item{padding:11px 16px;display:flex;align-items:center;gap:10px;cursor:pointer;transition:all .15s ease;border-bottom:1px solid rgba(0,0,0,0.04);font-size:12px;color:var(--text-primary)}.history-item:active{background:rgba(227,59,13,0.06)}
.clear-history-btn{display:flex;align-items:center;justify-content:center;gap:6px;padding:12px;cursor:pointer;font-size:11px;color:var(--red-primary);letter-spacing:.05em;transition:all .15s ease;border-top:1px solid rgba(0,0,0,0.06)}.clear-history-btn:active{background:rgba(227,59,13,0.06)}
.btn-manage{width:34px;height:34px;border-radius:50%;border:1px solid rgba(227,59,13,0.28);background:transparent;color:var(--text-muted);display:flex;align-items:center;justify-content:center;cursor:pointer;transition:all .2s ease;flex-shrink:0}
.btn-manage:active{background:rgba(227,59,13,0.10);color:var(--red-primary)}.btn-manage.active-manage{background:rgba(227,59,13,0.14);border-color:rgba(227,59,13,0.45);color:var(--red-accent)}
.drag-ghost{position:fixed;pointer-events:none;z-index:99;opacity:.85;transform:scale(1.05);box-shadow:0 14px 36px rgba(0,0,0,0.35);border-radius:10px;overflow:hidden;background:rgba(233,231,224,0.92);backdrop-filter:blur(8px);border:1px solid rgba(227,59,13,0.30)}
.btn-back{width:32px;height:32px;border-radius:50%;border:1px solid rgba(255,255,255,0.40);background:rgba(233,231,224,0.55);backdrop-filter:blur(4px);color:var(--text-muted);display:flex;align-items:center;justify-content:center;cursor:pointer;transition:all .25s ease;box-shadow:inset 0 1px 0 rgba(255,255,255,0.40)}.btn-back:active{background:rgba(227,59,13,0.10);color:var(--red-primary)}
.nav-item{cursor:pointer;transition:all .3s ease;color:var(--text-on-dark-secondary);font-family:'Josefin Sans',sans-serif;font-weight:300;letter-spacing:.06em;font-size:12px;display:flex;align-items:center;gap:8px;padding:6px 14px;border-radius:20px;background:transparent;border:1px solid transparent}
.nav-item.active{color:var(--red-accent);font-weight:400;background:rgba(227,59,13,0.10);border:1px solid rgba(255,255,255,0.10);box-shadow:inset 0 1px 0 rgba(255,255,255,0.06)}
.btn-account{width:36px;height:36px;border-radius:50%;border:1px solid rgba(255,255,255,0.18);background:rgba(47,47,47,0.55);backdrop-filter:blur(8px);color:var(--text-on-dark-secondary);display:flex;align-items:center;justify-content:center;cursor:pointer;transition:all .25s ease;position:relative;overflow:visible;box-shadow:inset 0 1px 0 rgba(255,255,255,0.08),0 2px 8px rgba(0,0,0,0.25)}
.btn-account:active{background:rgba(227,59,13,0.20);color:var(--text-on-dark)}.btn-account .note-icon{position:relative;z-index:2;font-size:12px;color:var(--red-primary)}
.btn-account::after{content:'';position:absolute;inset:-3px;border-radius:50%;border:1px dashed rgba(227,59,13,0.20);pointer-events:none;animation:gearRotate 12s linear infinite}@keyframes gearRotate{from{transform:rotate(0deg)}to{transform:rotate(360deg)}}
.sidebar-overlay{position:absolute;inset:0;z-index:45;background:rgba(0,0,0,0.40);backdrop-filter:blur(2px);transition:opacity .35s ease;pointer-events:auto}.sidebar-overlay.hidden-overlay{opacity:0;pointer-events:none}
.sidebar-panel{position:absolute;top:0;right:0;bottom:0;width:75%;z-index:46;background:rgba(35,33,31,0.78);backdrop-filter:blur(22px);box-shadow:-8px 0 35px rgba(0,0,0,0.50),inset -1px 0 0 rgba(255,255,255,0.06);border-left:0.5px solid rgba(255,255,255,0.08);transition:transform .35s cubic-bezier(.25,.46,.45,.94);display:flex;flex-direction:column;overflow-y:auto}
.sidebar-panel.hidden-sidebar{transform:translateX(105%)}.sidebar-panel.visible-sidebar{transform:translateX(0)}
.sidebar-section{border-bottom:0.5px solid rgba(255,255,255,0.05);padding:14px 18px}.sidebar-item{display:flex;align-items:center;gap:12px;cursor:pointer;transition:all .2s ease;color:var(--text-on-dark-secondary);font-size:13px;letter-spacing:.04em;border-radius:8px;padding:10px 10px;margin:2px -6px}.sidebar-item:active{color:var(--red-accent);background:rgba(255,255,255,0.04)}
.avatar-ring{border:2px solid rgba(255,255,255,0.20);box-shadow:0 0 20px rgba(227,59,13,0.15),inset 0 0 8px rgba(255,255,255,0.04)}
.app-logo{width:32px;height:32px;position:relative;display:flex;align-items:center;justify-content:center}
.app-logo .logo-diamond{width:20px;height:20px;border:1.2px solid var(--red-primary);transform:rotate(45deg);position:absolute;opacity:.85}
.app-logo .logo-diamond-inner{width:10px;height:10px;border:0.8px solid rgba(227,59,13,0.45);transform:rotate(45deg);position:absolute}
.app-logo .logo-staff{position:absolute;display:flex;flex-direction:column;gap:2.5px;align-items:center;z-index:1}.app-logo .logo-staff span{display:block;height:.6px;background:var(--red-primary);border-radius:1px}
.app-logo .logo-dot{width:3px;height:3px;background:var(--red-accent);border-radius:50%;position:absolute;bottom:4px;z-index:2}
.font-calligraphy{font-family:'Liu Jian Mao Cao','Ma Shan Zheng',cursive;font-weight:400}
.btn-add-lib{display:flex;align-items:center;justify-content:center;gap:6px;padding:10px;border-radius:8px;border:1.5px dashed rgba(227,59,13,0.30);color:var(--red-primary);font-size:12px;letter-spacing:.05em;cursor:pointer;transition:all .2s ease;background:rgba(233,231,224,0.35)}.btn-add-lib:active{background:rgba(227,59,13,0.08);border-color:rgba(227,59,13,0.50)}
.tab-panel{transition:opacity .4s ease,transform .4s ease}.tab-panel.hidden-panel{opacity:0;pointer-events:none;position:absolute;transform:translateY(6px)}.tab-panel.visible-panel{opacity:1;pointer-events:auto;position:relative;transform:translateY(0)}
.no-scrollbar::-webkit-scrollbar{display:none}.no-scrollbar{scrollbar-width:none;-ms-overflow-style:none}
</style>
</head>
<body>
<div class="app-root">
<div class="w-full flex items-center justify-between px-6 shrink-0 relative z-30" style="height:34px;background:#1f1e1c"><span class="text-[11px] text-[#b0a89e] font-['Josefin_Sans'] tracking-wide">15:00</span><div class="flex items-center gap-1.5"><div class="w-3 h-3 rounded-full border border-[#5e5850] flex items-center justify-center"><div class="w-[6px] h-[6px] rounded-full bg-[#8a8278]"></div></div><span class="text-[10px] text-[#b0a89e]">88%</span></div></div>
<div class="w-full shrink-0 nav-top"><div class="flex items-center justify-between px-5 py-2.5"><div class="app-logo" aria-label="曲谱应用"><div class="logo-diamond"></div><div class="logo-diamond-inner"></div><div class="logo-staff"><span style="width:11px;"></span><span style="width:9px;"></span><span style="width:11px;"></span></div><div class="logo-dot"></div></div><button class="btn-account" aria-label="账号" onclick="openSidebar()"><i class="fa-solid fa-music note-icon"></i></button></div></div>
<div class="relative flex-1 overflow-hidden" style="min-height:0;z-index:15">
<div id="tab-panel-0" class="tab-panel visible-panel h-full w-full flex flex-col" style="background:#e9e7e0">
<div class="relative px-5 pt-4 pb-1 z-10 shrink-0"><div class="flex items-center gap-2 mb-0.5"><div class="w-5 h-[1px] bg-[#e33b0d] opacity-35"></div><span class="text-[9px] tracking-[0.15em] text-[#8b7670] font-['Josefin_Sans'] font-light uppercase">Commendatio</span><div class="flex-1 h-[1px] bg-[#e33b0d] opacity-18"></div></div></div>
<div class="flex-1 overflow-y-auto no-scrollbar z-10 relative px-4 pb-2">
<div class="stack-card-wrap mb-4" onclick="openSubCollection('古典精选','周杰伦')"><div class="stack-card-back"><img src="/assets/images/16-9/business-04.jpg" alt="" loading="lazy"></div><div class="stack-card-front"><img src="/assets/images/business/business-25.jpg" alt="" loading="lazy"></div><span class="stack-label">古典精选 · 经典永恒</span></div>
<div class="flex items-center gap-2 mb-3"><div class="w-4 h-[1px] bg-[#e33b0d] opacity-40"></div><span class="text-[11px] tracking-[0.10em] text-[#5c4046] font-['Josefin_Sans'] font-semibold uppercase">热门精选</span><div class="flex-1 h-[1px] bg-[#e33b0d] opacity-15"></div></div>
<div class="grid grid-cols-2 gap-3 mb-4"><div class="rec-mini-card" onclick="openSubCollection('肖邦夜曲','陈奕迅')"><img src="/assets/images/fashion-lifestyle/fashion-lifestyle-15.jpg" alt="" loading="lazy"><div class="rec-mini-label">肖邦夜曲全集</div></div><div class="rec-mini-card" onclick="openSubCollection('巴赫平均律','周杰伦')"><img src="/assets/images/education/education-1.jpg" alt="" loading="lazy"><div class="rec-mini-label">巴赫平均律</div></div></div>
<div class="flex items-center gap-2 mb-3"><div class="w-4 h-[1px] bg-[#e33b0d] opacity-40"></div><span class="text-[11px] tracking-[0.10em] text-[#5c4046] font-['Josefin_Sans'] font-semibold uppercase">编辑推荐</span><div class="flex-1 h-[1px] bg-[#e33b0d] opacity-15"></div></div>
<div class="flex gap-3 overflow-x-auto no-scrollbar pb-2"><div class="rec-mini-card" onclick="openSubCollection('德彪西意象集','林俊杰')"><img src="/assets/images/cases/porto2.jpg" alt="" loading="lazy"><div class="rec-mini-label">德彪西意象集</div></div><div class="rec-mini-card" onclick="openSubCollection('拉赫玛尼诺夫','邓紫棋')"><img src="/assets/images/16-9/business-03.jpg" alt="" loading="lazy"><div class="rec-mini-label">拉赫玛尼诺夫</div></div><div class="rec-mini-card" onclick="openSubCollection('舒伯特艺术歌曲','五月天')"><img src="/assets/images/fashion-lifestyle/fashion-lifestyle-4.jpg" alt="" loading="lazy"><div class="rec-mini-label">舒伯特艺术歌曲</div></div></div>
</div>
<div class="px-5 pb-2 relative z-10 shrink-0"><div class="flex items-center gap-2"><div class="flex-1 h-[1px] bg-[#e33b0d] opacity-12"></div><div class="flex gap-1"><div class="w-1 h-1 bg-[#e33b0d] opacity-35"></div><div class="w-2 h-1 bg-[#e33b0d] opacity-25"></div><div class="w-1 h-1 bg-[#e33b0d] opacity-35"></div></div><div class="flex-1 h-[1px] bg-[#e33b0d] opacity-12"></div></div></div>
</div>
<div id="tab-panel-1" class="tab-panel hidden-panel h-full w-full flex flex-col" style="background:#e9e7e0">
<div class="shrink-0 px-4 pt-3 pb-2 relative" style="z-index:28"><div class="relative flex items-center gap-2" id="search-wrapper"><div class="search-bar" id="search-bar" onclick="toggleSearchHistory()"><i class="fa-solid fa-magnifying-glass"></i><span id="search-placeholder">搜索曲谱…</span></div><div class="search-history-dropdown no-scrollbar hidden-dropdown" id="search-dropdown"><div id="history-list"><div class="history-item" onclick="selectHistory('贝多芬月光奏鸣曲')"><i class="fa-solid fa-clock-rotate-left"></i><span>贝多芬月光奏鸣曲</span></div><div class="history-item" onclick="selectHistory('莫扎特钢琴协奏曲')"><i class="fa-solid fa-clock-rotate-left"></i><span>莫扎特钢琴协奏曲</span></div><div class="history-item" onclick="selectHistory('肖邦夜曲全集')"><i class="fa-solid fa-clock-rotate-left"></i><span>肖邦夜曲全集</span></div><div class="history-item" onclick="selectHistory('巴赫平均律曲集')"><i class="fa-solid fa-clock-rotate-left"></i><span>巴赫平均律曲集</span></div></div><div class="clear-history-btn" onclick="clearSearchHistory()"><i class="fa-solid fa-trash-can"></i><span>清除搜索历史</span></div></div><button class="btn-manage" id="btn-manage" onclick="toggleManageMode()" aria-label="管理曲库"><i class="fa-solid fa-pen-to-square"></i></button></div></div>
<div class="px-4 shrink-0 relative" style="z-index:10"><div class="h-[1px]" style="background:linear-gradient(90deg,transparent,rgba(227,59,13,0.20),transparent)"></div></div>
<div class="flex-1 px-4 overflow-y-auto no-scrollbar relative pt-2 pb-1" style="z-index:5" id="lib-scroll-area">
<div class="grid grid-cols-2 gap-3" id="lib-grid">
<div class="lib-card" id="lib-mine" data-lib="我的曲库" data-locked="true" data-cover="/assets/images/fashion-lifestyle/fashion-lifestyle-15.jpg" onclick="handleLibCardClick(this)"><div class="card-cover"><img src="/assets/images/fashion-lifestyle/fashion-lifestyle-15.jpg" alt=""></div><div class="vinyl-peek"><div class="vinyl-mini"><div class="vinyl-shine"></div></div></div><div class="card-info"><div class="card-name">我的曲库</div><div class="card-count">5 首曲目</div></div></div>
<div class="lib-card" id="lib-1" data-lib="古典奏鸣曲集" data-locked="false" data-cover="/assets/images/business/business-25.jpg" onclick="handleLibCardClick(this)"><div class="drag-handle">⠿</div><div class="del-btn" id="del-1" onclick="event.stopPropagation();deleteLib('lib-1')"><i class="fa-solid fa-xmark"></i></div><div class="cover-overlay-card" id="cover-overlay-1" onclick="event.stopPropagation();changeCover('1')"><i class="fa-solid fa-camera"></i></div><div class="card-cover"><img src="/assets/images/business/business-25.jpg" alt="" id="cover-img-1"></div><div class="vinyl-peek"><div class="vinyl-mini"><div class="vinyl-shine"></div></div></div><div class="card-info"><div class="card-name">古典奏鸣曲集</div><div class="card-count">0 首曲目</div></div></div>
<div class="lib-card" id="lib-2" data-lib="浪漫钢琴选" data-locked="false" data-cover="/assets/images/fashion-lifestyle/fashion-lifestyle-4.jpg" onclick="handleLibCardClick(this)"><div class="drag-handle">⠿</div><div class="del-btn" id="del-2" onclick="event.stopPropagation();deleteLib('lib-2')"><i class="fa-solid fa-xmark"></i></div><div class="cover-overlay-card" id="cover-overlay-2" onclick="event.stopPropagation();changeCover('2')"><i class="fa-solid fa-camera"></i></div><div class="card-cover"><img src="/assets/images/fashion-lifestyle/fashion-lifestyle-4.jpg" alt="" id="cover-img-2"></div><div class="vinyl-peek"><div class="vinyl-mini"><div class="vinyl-shine"></div></div></div><div class="card-info"><div class="card-name">浪漫钢琴选</div><div class="card-count">0 首曲目</div></div></div>
<div class="lib-card" id="lib-3" data-lib="交响乐珍藏" data-locked="false" data-cover="/assets/images/cases/porto2.jpg" onclick="handleLibCardClick(this)"><div class="drag-handle">⠿</div><div class="del-btn" id="del-3" onclick="event.stopPropagation();deleteLib('lib-3')"><i class="fa-solid fa-xmark"></i></div><div class="cover-overlay-card" id="cover-overlay-3" onclick="event.stopPropagation();changeCover('3')"><i class="fa-solid fa-camera"></i></div><div class="card-cover"><img src="/assets/images/cases/porto2.jpg" alt="" id="cover-img-3"></div><div class="vinyl-peek"><div class="vinyl-mini"><div class="vinyl-shine"></div></div></div><div class="card-info"><div class="card-name">交响乐珍藏</div><div class="card-count">0 首曲目</div></div></div>
<div class="lib-card" id="lib-4" data-lib="巴洛克精选" data-locked="false" data-cover="/assets/images/16-9/business-03.jpg" onclick="handleLibCardClick(this)"><div class="drag-handle">⠿</div><div class="del-btn" id="del-4" onclick="event.stopPropagation();deleteLib('lib-4')"><i class="fa-solid fa-xmark"></i></div><div class="cover-overlay-card" id="cover-overlay-4" onclick="event.stopPropagation();changeCover('4')"><i class="fa-solid fa-camera"></i></div><div class="card-cover"><img src="/assets/images/16-9/business-03.jpg" alt="" id="cover-img-4"></div><div class="vinyl-peek"><div class="vinyl-mini"><div class="vinyl-shine"></div></div></div><div class="card-info"><div class="card-name">巴洛克精选</div><div class="card-count">0 首曲目</div></div></div>
<div class="lib-card" id="lib-5" data-lib="现代作品集" data-locked="false" data-cover="/assets/images/education/education-1.jpg" onclick="handleLibCardClick(this)"><div class="drag-handle">⠿</div><div class="del-btn" id="del-5" onclick="event.stopPropagation();deleteLib('lib-5')"><i class="fa-solid fa-xmark"></i></div><div class="cover-overlay-card" id="cover-overlay-5" onclick="event.stopPropagation();changeCover('5')"><i class="fa-solid fa-camera"></i></div><div class="card-cover"><img src="/assets/images/education/education-1.jpg" alt="" id="cover-img-5"></div><div class="vinyl-peek"><div class="vinyl-mini"><div class="vinyl-shine"></div></div></div><div class="card-info"><div class="card-name">现代作品集</div><div class="card-count">0 首曲目</div></div></div>
</div>
<div class="btn-add-lib mt-3 mb-2" onclick="addNewLib()"><i class="fa-solid fa-plus text-[11px]"></i><span>新增曲库</span></div>
</div>
</div>
<div id="sub-collection-view" class="sub-view hidden-sub">
<div class="flex items-center gap-2 px-4 pt-3 pb-1 z-10"><button class="btn-back" onclick="closeSubCollection()" aria-label="返回"><i class="fa-solid fa-arrow-left text-[11px]"></i></button><div class="w-5 h-[1px] bg-[#e33b0d] opacity-35"></div><span class="text-[9px] tracking-[0.12em] text-[#8b7670] font-['Josefin_Sans'] font-light uppercase">shorthand of emotion</span><div class="flex-1 h-[1px] bg-[#e33b0d] opacity-18"></div></div>
<div class="sub-header">
<div class="sub-cover-wrap" onclick="event.stopPropagation();openCoverModal()"><img id="sub-cover-img" src="/assets/images/fashion-lifestyle/fashion-lifestyle-15.jpg" alt=""><div class="vinyl-peek-sub"><div class="vinyl-mini"><div class="vinyl-shine"></div></div></div></div>
<div class="sub-info"><div class="lib-name" id="sub-lib-name" contenteditable="true" onfocus="this._prev=this.textContent" onblur="saveLibName(this)" onkeydown="if(event.key==='Enter'){this.blur();event.preventDefault()}">我的曲库</div><button class="btn-import-inline" onclick="event.stopPropagation();openImportPanel()"><i class="fa-solid fa-plus text-[9px]"></i> 导入曲谱</button><div class="lib-meta" id="sub-lib-meta">共 5 首曲目</div></div>
</div>
<div class="px-4"><div class="h-[1px]" style="background:linear-gradient(90deg,transparent,rgba(227,59,13,0.20),transparent)"></div></div>
<div class="toolbar-row">
<div class="search-inline-wrap"><button class="btn-search-toggle" id="btn-search-toggle" onclick="toggleInlineSearch()"><i class="fa-solid fa-magnifying-glass" style="font-size:11px"></i></button><input class="search-input-inline" id="search-input-inline" type="text" placeholder="搜索曲目…" oninput="filterSongRows()"></div>
<div class="sort-dropdown-wrap"><div class="sort-toggle" id="sort-toggle" onclick="event.stopPropagation();toggleSortDropdown()"><i class="fa-solid fa-arrow-down-wide-short"></i><span id="sort-label">名称正序</span><i class="fa-solid fa-chevron-down" style="font-size:8px"></i></div></div>
</div>
<div class="sub-song-list no-scrollbar" id="sub-song-list"></div>
</div>
<div id="cover-modal" class="cover-modal-overlay hidden-modal" onclick="closeCoverModal(event)"><div class="cover-modal" onclick="event.stopPropagation()"><div class="modal-title">更换封面图片</div><div class="cover-preview"><img id="cover-preview-img" src="/assets/images/fashion-lifestyle/fashion-lifestyle-15.jpg" alt=""></div><input type="text" id="cover-url-input" placeholder="输入图片URL地址…"><div class="modal-actions"><button class="modal-btn modal-btn-cancel" onclick="closeCoverModal()">取消</button><button class="modal-btn modal-btn-confirm" onclick="confirmCoverChange()">确认更换</button></div></div></div>
<div id="import-panel-overlay" class="import-panel-overlay hidden-modal" onclick="closeImportPanel()"></div>
<div id="import-panel" class="import-panel hidden-panel"><div class="panel-handle"></div><div class="panel-title">导入曲谱</div><span class="field-label">曲谱名称</span><input type="text" id="import-name" placeholder="请输入曲谱名称"><span class="field-label">作者</span><input type="text" id="import-author" placeholder="未知" value="未知"><div class="btn-file" onclick="alert('选择文件(模拟)')"><i class="fa-regular fa-file-lines"></i> 选择曲谱文件</div><button class="btn-submit" onclick="confirmImport()">确认导入</button></div>
</div>
<div class="w-full shrink-0 bottom-nav-container"><div class="flex items-center justify-center gap-20 relative" style="height:42px"><button class="nav-item active" id="nav-home" onclick="switchTab(0)"><i class="fa-solid fa-house"></i><span>首页</span></button><button class="nav-item" id="nav-library" onclick="switchTab(1)"><i class="fa-solid fa-compact-disc"></i><span>曲库</span></button></div></div>
<div id="sidebar-overlay" class="sidebar-overlay hidden-overlay" onclick="closeSidebar()"></div>
<div id="sidebar-panel" class="sidebar-panel hidden-sidebar">
<div class="sidebar-section flex flex-col items-center pt-6 pb-4 gap-3"><div class="w-16 h-16 rounded-full avatar-ring flex items-center justify-center" style="background:rgba(37,35,33,0.60)"><i class="fa-solid fa-user-astronaut text-2xl" style="color:var(--red-primary)"></i></div><p class="text-[15px] font-['Josefin_Sans'] font-semibold tracking-wider" style="color:var(--text-on-dark)">Vintage Musician</p><span class="text-[10px] tracking-[0.1em] px-3 py-0.5 rounded-full" style="background:rgba(227,59,13,0.14);color:var(--red-accent);border:1px solid rgba(227,59,13,0.22)">PRO 会员</span></div>
<div class="sidebar-section"><div class="flex items-center justify-between mb-2"><span class="text-[11px] tracking-wider" style="color:var(--text-on-dark-secondary)">云端存储</span><span class="text-[11px]" style="color:var(--red-accent)">2.1 / 5.0 GB</span></div><div class="w-full h-2 rounded-full" style="background:rgba(0,0,0,0.35)"><div class="h-full rounded-full" style="width:42%;background:var(--red-primary)"></div></div></div>
<div class="sidebar-section" style="border-bottom:none"><div class="sidebar-item"><i class="fa-solid fa-palette"></i><span>外观设置</span><i class="fa-solid fa-chevron-right text-[9px] ml-auto opacity-30"></i></div><div class="sidebar-item"><i class="fa-solid fa-bell"></i><span>通知偏好</span><i class="fa-solid fa-chevron-right text-[9px] ml-auto opacity-30"></i></div><div class="sidebar-item"><i class="fa-solid fa-cloud-arrow-up"></i><span>数据同步</span><i class="fa-solid fa-chevron-right text-[9px] ml-auto opacity-30"></i></div><div class="sidebar-item"><i class="fa-solid fa-circle-info"></i><span>关于应用</span><i class="fa-solid fa-chevron-right text-[9px] ml-auto opacity-30"></i></div></div>
<div class="sidebar-section" style="border-bottom:none;margin-top:auto;padding-bottom:20px"><div class="sidebar-item" style="color:var(--red-primary)"><i class="fa-solid fa-arrow-right-from-bracket"></i><span>退出登录</span></div></div>
</div>
</div>
<script>
const libDataMap = new Map();
function initLibData(){
libDataMap.set('lib-mine',[
{title:'晴天',artist:'周杰伦'},{title:'十年',artist:'陈奕迅'},{title:'修炼爱情',artist:'林俊杰'},{title:'光年之外',artist:'邓紫棋'},{title:'突然好想你',artist:'五月天'}
]);
['lib-1','lib-2','lib-3','lib-4','lib-5'].forEach(id=>{ libDataMap.set(id,[]); });
}
function getLibData(libId){ if(!libDataMap.has(libId)) libDataMap.set(libId,[]); return libDataMap.get(libId); }
initLibData();
let manageMode = false;
let dragCard=null,dragGhost=null,dragStartX=0,dragStartY=0,dragOrigRect=null;
let currentOpenLibId=null;
function switchTab(i){const p=[document.getElementById('tab-panel-0'),document.getElementById('tab-panel-1')],n=[document.getElementById('nav-home'),document.getElementById('nav-library')];p.forEach((e,x)=>{if(x===i){e.classList.remove('hidden-panel');e.classList.add('visible-panel')}else{e.classList.remove('visible-panel');e.classList.add('hidden-panel')}});n.forEach((e,x)=>{if(e){if(x===i)e.classList.add('active');else e.classList.remove('active')}});closeSubCollection();exitManageMode();closeSearchHistory()}
function handleLibCardClick(cardEl){if(manageMode)return;const name=cardEl.getAttribute('data-lib')||'曲库';const cover=cardEl.getAttribute('data-cover')||'';const coverImg=cardEl.querySelector('.card-cover img');const coverSrc=coverImg?coverImg.src:cover;openSubCollection(name,coverSrc,cardEl)}
function openSubCollection(title,coverSrc,cardEl){
if(manageMode&&cardEl)return;
const sv=document.getElementById('sub-collection-view');
const nameEl=document.getElementById('sub-lib-name');
const coverImg=document.getElementById('sub-cover-img');
nameEl.textContent=title||'曲库';
if(coverSrc){coverImg.src=coverSrc}
hideInlineSearch();
if(cardEl){
currentOpenLibId=cardEl.id;
nameEl.setAttribute('contenteditable',cardEl.getAttribute('data-locked')==='true'?'false':'true');
if(cardEl.getAttribute('data-locked')==='true'){nameEl.classList.add('locked-name')}else{nameEl.classList.remove('locked-name')}
}else{currentOpenLibId=null;nameEl.setAttribute('contenteditable','true');nameEl.classList.remove('locked-name')}
sv.classList.remove('hidden-sub');sv.classList.add('visible-sub');
if(cardEl){syncCardToSub(cardEl)}
renderSongList();
}
function syncCardToSub(cardEl){
const coverImg=document.getElementById('sub-cover-img');
const cardCover=cardEl.querySelector('.card-cover img');
if(cardCover){coverImg.src=cardCover.src}
document.getElementById('sub-lib-name').textContent=cardEl.getAttribute('data-lib')||'曲库';
}
function syncSubToCard(){
if(!currentOpenLibId)return;const card=document.getElementById(currentOpenLibId);if(!card)return;
const name=document.getElementById('sub-lib-name').textContent.trim();
const cover=document.getElementById('sub-cover-img').src;
card.setAttribute('data-lib',name);card.setAttribute('data-cover',cover);
const cn=card.querySelector('.card-name');if(cn)cn.textContent=name;
const cc=card.querySelector('.card-cover img');if(cc)cc.src=cover;
const list=getLibData(currentOpenLibId);
const ccount=card.querySelector('.card-count');if(ccount)ccount.textContent=list.length+' 首曲目';
}
function renderSongList(){
const listEl=document.getElementById('sub-song-list');
listEl.innerHTML='';
if(!currentOpenLibId){updateTrackCount();return}
const list=getLibData(currentOpenLibId);
list.forEach((item,i)=>{
const row=document.createElement('div');
row.className='song-row';row.setAttribute('data-title',item.title);row.setAttribute('data-time',String(i+1));
row.innerHTML=`<span class="song-index">${i+1}</span><div class="song-body"><div class="song-title">${item.title}</div><div class="song-artist">${item.artist}</div></div><div class="song-more-btn" onclick="event.stopPropagation();toggleSongPopup(event)">···</div>`;
listEl.appendChild(row);
});
updateTrackCount();
}
function closeSubCollection(){const sv=document.getElementById('sub-collection-view');sv.classList.remove('visible-sub');sv.classList.add('hidden-sub');closeAllPopups();closeSortDropdown();hideInlineSearch();closeCoverModal();closeImportPanel();currentOpenLibId=null}
function toggleManageMode(){manageMode=!manageMode;const btn=document.getElementById('btn-manage');if(manageMode){btn.classList.add('active-manage');document.querySelectorAll('.lib-card[data-locked="false"] .del-btn').forEach(b=>b.classList.add('show-del'));document.querySelectorAll('.lib-card[data-locked="false"] .drag-handle').forEach(b=>b.classList.add('show-handle'));document.querySelectorAll('.lib-card[data-locked="false"] .cover-overlay-card').forEach(b=>b.classList.add('show-cover'))}else{exitManageMode()}}
function exitManageMode(){manageMode=false;document.getElementById('btn-manage').classList.remove('active-manage');document.querySelectorAll('.del-btn').forEach(b=>b.classList.remove('show-del'));document.querySelectorAll('.drag-handle').forEach(b=>b.classList.remove('show-handle'));document.querySelectorAll('.cover-overlay-card').forEach(b=>b.classList.remove('show-cover'));cleanupDrag()}
function deleteLib(id){const c=document.getElementById(id);if(c){c.style.transition='all .3s ease';c.style.opacity='0';c.style.transform='scale(0.8)';setTimeout(()=>c.remove(),300);libDataMap.delete(id)}}
function changeCover(libId){const url=prompt('请输入封面图片URL(留空恢复默认):');const img=document.getElementById('cover-img-'+libId);if(!img)return;if(url&&url.trim()){img.src=url.trim()}else{const def=document.getElementById('lib-'+libId)?.getAttribute('data-cover');img.src=def||''}}
function addNewLib(){const name=prompt('请输入新曲库名称:');if(name&&name.trim()){const grid=document.getElementById('lib-grid');const newId='lib-'+Date.now();libDataMap.set(newId,[]);const div=document.createElement('div');div.className='lib-card';div.id=newId;div.setAttribute('data-lib',name.trim());div.setAttribute('data-locked','false');div.setAttribute('data-cover','');div.setAttribute('onclick','handleLibCardClick(this)');div.innerHTML=`<div class="drag-handle">⠿</div><div class="del-btn" id="del-${newId}" onclick="event.stopPropagation();deleteLib('${newId}')"><i class="fa-solid fa-xmark"></i></div><div class="cover-overlay-card" id="cover-overlay-${newId}" onclick="event.stopPropagation();changeCover('${newId}')"><i class="fa-solid fa-camera"></i></div><div class="card-cover"><div class="cover-placeholder"></div></div><div class="vinyl-peek"><div class="vinyl-mini"><div class="vinyl-shine"></div></div></div><div class="card-info"><div class="card-name">${name.trim()}</div><div class="card-count">0 首曲目</div></div>`;grid.appendChild(div);bindDragEvents(div);if(manageMode){div.querySelector('.del-btn').classList.add('show-del');div.querySelector('.drag-handle').classList.add('show-handle');div.querySelector('.cover-overlay-card').classList.add('show-cover')}}}
function bindDragEvents(card){const h=card.querySelector('.drag-handle');if(!h)return;h.addEventListener('touchstart',onDragStart,{passive:false});h.addEventListener('mousedown',onDragStart)}
function hideAllDelButtons(){document.querySelectorAll('.del-btn.show-del').forEach(b=>b.classList.remove('show-del'))}
function restoreAllDelButtons(){if(!manageMode)return;document.querySelectorAll('.lib-card[data-locked="false"] .del-btn').forEach(b=>b.classList.add('show-del'))}
function onDragStart(e){if(!manageMode)return;e.preventDefault();const h=e.target.closest('.drag-handle');if(!h||!h.classList.contains('show-handle'))return;dragCard=h.closest('.lib-card');if(!dragCard||dragCard.getAttribute('data-locked')==='true'){dragCard=null;return};hideAllDelButtons();const t=e.touches?e.touches[0]:e;dragStartX=t.clientX;dragStartY=t.clientY;dragOrigRect=dragCard.getBoundingClientRect();dragGhost=dragCard.cloneNode(true);const gd=dragGhost.querySelector('.del-btn');if(gd)gd.classList.remove('show-del');const gh=dragGhost.querySelector('.drag-handle');if(gh)gh.classList.remove('show-handle');const gc=dragGhost.querySelector('.cover-overlay-card');if(gc)gc.classList.remove('show-cover');dragGhost.classList.add('drag-ghost');dragGhost.style.width=dragOrigRect.width+'px';dragGhost.style.height=dragOrigRect.height+'px';dragGhost.style.left=dragOrigRect.left+'px';dragGhost.style.top=dragOrigRect.top+'px';document.body.appendChild(dragGhost);dragCard.classList.add('dragging');document.addEventListener('touchmove',onDragMove,{passive:false});document.addEventListener('touchend',onDragEnd);document.addEventListener('mousemove',onDragMove);document.addEventListener('mouseup',onDragEnd)}
function onDragMove(e){if(!dragCard||!dragGhost)return;e.preventDefault();const t=e.touches?e.touches[0]:e;dragGhost.style.left=(dragOrigRect.left+(t.clientX-dragStartX))+'px';dragGhost.style.top=(dragOrigRect.top+(t.clientY-dragStartY))+'px'}
function onDragEnd(e){document.removeEventListener('touchmove',onDragMove);document.removeEventListener('touchend',onDragEnd);document.removeEventListener('mousemove',onDragMove);document.removeEventListener('mouseup',onDragEnd);if(!dragCard||!dragGhost){cleanupDrag();return};const gr=dragGhost.getBoundingClientRect();const gcx=gr.left+gr.width/2,gcy=gr.top+gr.height/2;const grid=document.getElementById('lib-grid');const cards=Array.from(grid.querySelectorAll('.lib-card')).filter(c=>c!==dragCard);let target=null,min=Infinity;cards.forEach(c=>{const r=c.getBoundingClientRect();const d=Math.hypot(gcx-(r.left+r.width/2),gcy-(r.top+r.height/2));if(d<min){min=d;target=c}});if(target&&min<130){const all=Array.from(grid.children);const iD=all.indexOf(dragCard),iT=all.indexOf(target);if(iD<iT)grid.insertBefore(dragCard,target.nextSibling);else grid.insertBefore(dragCard,target)};cleanupDrag()}
function cleanupDrag(){restoreAllDelButtons();if(dragCard)dragCard.classList.remove('dragging');if(dragGhost){dragGhost.remove();dragGhost=null};dragCard=null;dragOrigRect=null}
function toggleSearchHistory(){if(manageMode)return;const dd=document.getElementById('search-dropdown'),sb=document.getElementById('search-bar');if(dd.classList.contains('hidden-dropdown')){dd.classList.remove('hidden-dropdown');sb.classList.add('focused')}else{closeSearchHistory()}}
function closeSearchHistory(){document.getElementById('search-dropdown').classList.add('hidden-dropdown');document.getElementById('search-bar').classList.remove('focused')}
function selectHistory(t){document.getElementById('search-placeholder').textContent=t;closeSearchHistory()}
function clearSearchHistory(){document.getElementById('history-list').innerHTML='';closeSearchHistory()}
function openCoverModal(){document.getElementById('cover-modal').classList.remove('hidden-modal');document.getElementById('cover-url-input').value='';const img=document.getElementById('sub-cover-img');document.getElementById('cover-preview-img').src=img?.src||''}
function closeCoverModal(e){if(e&&e.target!==document.getElementById('cover-modal'))return;document.getElementById('cover-modal').classList.add('hidden-modal')}
function confirmCoverChange(){const url=document.getElementById('cover-url-input').value.trim();const img=document.getElementById('sub-cover-img');const preview=document.getElementById('cover-preview-img');if(url){img.src=url;preview.src=url};closeCoverModal();syncSubToCard()}
function openImportPanel(){document.getElementById('import-panel-overlay').classList.remove('hidden-modal');document.getElementById('import-panel').classList.remove('hidden-panel');document.getElementById('import-panel').classList.add('visible-panel')}
function closeImportPanel(){document.getElementById('import-panel-overlay').classList.add('hidden-modal');document.getElementById('import-panel').classList.add('hidden-panel');document.getElementById('import-panel').classList.remove('visible-panel')}
function confirmImport(){
if(!currentOpenLibId)return;
const name=document.getElementById('import-name').value.trim();if(!name){alert('请输入曲谱名称');return}
const author=document.getElementById('import-author').value.trim()||'未知';
const list=getLibData(currentOpenLibId);list.push({title:name,artist:author});
renderSongList();closeImportPanel();syncSubToCard();
document.getElementById('import-name').value='';document.getElementById('import-author').value='未知';
}
function saveLibName(el){
const v=el.textContent.trim();if(!v){el.textContent=el._prev||'未命名曲库'}
if(currentOpenLibId&&el.getAttribute('contenteditable')!=='false'){syncSubToCard()}el.scrollLeft=0
}
function updateTrackCount(){
const listEl=document.getElementById('sub-song-list');const n=listEl.querySelectorAll('.song-row').length;
document.getElementById('sub-lib-meta').textContent='共 '+n+' 首曲目';
if(currentOpenLibId){const card=document.getElementById(currentOpenLibId);if(card){const cn=card.querySelector('.card-count');if(cn)cn.textContent=n+' 首曲目'}}
}
function renumberSongs(){
const listEl=document.getElementById('sub-song-list');const rows=listEl.querySelectorAll('.song-row');
rows.forEach((r,i)=>{const idx=r.querySelector('.song-index');if(idx)idx.textContent=i+1;r.setAttribute('data-time',String(i+1))});
if(currentOpenLibId){
const list=getLibData(currentOpenLibId);
const newList=[];rows.forEach(r=>{newList.push({title:r.getAttribute('data-title'),artist:r.querySelector('.song-artist')?.textContent||'未知'})});
libDataMap.set(currentOpenLibId,newList);
}
}
function pinTrack(row){
const listEl=document.getElementById('sub-song-list');listEl.insertBefore(row,listEl.firstChild);renumberSongs();updateTrackCount()
}
function deleteTrack(row){
row.style.opacity='0';row.style.transform='translateX(20px)';row.style.transition='all .25s ease';
setTimeout(()=>{row.remove();renumberSongs();updateTrackCount()},250)
}
function shareTrack(){alert('分享功能(模拟)')}
function toggleSortDropdown(){const existing=document.querySelector('.sort-dropdown');if(existing){existing.remove();return}closeAllPopups();const wrap=document.querySelector('.sort-dropdown-wrap');const dd=document.createElement('div');dd.className='sort-dropdown';dd.innerHTML=`<div class="sort-opt" onclick="applySort('名称正序','title','asc')"><i class="fa-solid fa-arrow-up-a-z"></i>名称正序</div><div class="sort-opt" onclick="applySort('名称倒序','title','desc')"><i class="fa-solid fa-arrow-down-z-a"></i>名称倒序</div><div class="sort-opt" onclick="applySort('时间正序','time','asc')"><i class="fa-regular fa-clock"></i>时间正序</div><div class="sort-opt" onclick="applySort('时间倒序','time','desc')"><i class="fa-regular fa-clock"></i>时间倒序</div>`;wrap.appendChild(dd);setTimeout(()=>document.addEventListener('click',function f(e){if(!e.target.closest('.sort-dropdown-wrap')){dd.remove();document.removeEventListener('click',f)}},{once:false}),10)}
function closeSortDropdown(){const d=document.querySelector('.sort-dropdown');if(d)d.remove()}
function applySort(label,key,dir){
document.getElementById('sort-label').textContent=label;
if(!currentOpenLibId)return;
const list=getLibData(currentOpenLibId);
list.sort((a,b)=>{const va=(a[key]||'').toLowerCase();const vb=(b[key]||'').toLowerCase();if(key==='time'){return dir==='asc'?parseInt(va)-parseInt(vb):parseInt(vb)-parseInt(va)}return dir==='asc'?va.localeCompare(vb,'zh'):vb.localeCompare(va,'zh')});
renderSongList();closeSortDropdown()
}
function toggleInlineSearch(){const inp=document.getElementById('search-input-inline');const btn=document.getElementById('btn-search-toggle');if(inp.classList.contains('show-input')){hideInlineSearch()}else{inp.classList.add('show-input');inp.focus();btn.style.background='rgba(227,59,13,0.10)';btn.style.color='var(--red-primary)'}}
function hideInlineSearch(){const inp=document.getElementById('search-input-inline');const btn=document.getElementById('btn-search-toggle');inp.classList.remove('show-input');inp.value='';btn.style.background='';btn.style.color='';filterSongRows()}
function filterSongRows(){const q=document.getElementById('search-input-inline').value.trim().toLowerCase();document.querySelectorAll('#sub-song-list .song-row').forEach(r=>{const title=r.querySelector('.song-title')?.textContent.toLowerCase()||'';if(!q||title.includes(q)){r.classList.remove('hidden-row')}else{r.classList.add('hidden-row')}})}
function toggleSongPopup(e){
const btn=e.target.closest('.song-more-btn');if(!btn)return;
const ex=document.querySelector('.song-action-popup');if(ex&&ex.parentElement===btn.parentElement){ex.remove();return}
closeAllPopups();closeSortDropdown();const row=btn.closest('.song-row');
const popup=document.createElement('div');popup.className='song-action-popup';
popup.innerHTML=`<div class="action-item" onclick="event.stopPropagation();pinTrack(this.closest('.song-row'));closeAllPopups();"><i class="fa-solid fa-thumbtack"></i><span>置顶</span></div><div class="action-item danger" onclick="event.stopPropagation();deleteTrack(this.closest('.song-row'));closeAllPopups();"><i class="fa-regular fa-trash-can"></i><span>删除</span></div><div class="action-item" onclick="event.stopPropagation();shareTrack();closeAllPopups();"><i class="fa-solid fa-share-nodes"></i><span>分享</span></div>`;
btn.parentElement.appendChild(popup);setTimeout(()=>document.addEventListener('click',closeAllPopupsOnce,{once:true}),10)
}
function closeAllPopups(){document.querySelectorAll('.song-action-popup').forEach(p=>p.remove())}
function closeAllPopupsOnce(){closeAllPopups()}
function openSidebar(){document.getElementById('sidebar-overlay').classList.remove('hidden-overlay');document.getElementById('sidebar-panel').classList.remove('hidden-sidebar');document.getElementById('sidebar-panel').classList.add('visible-sidebar')}
function closeSidebar(){document.getElementById('sidebar-overlay').classList.add('hidden-overlay');document.getElementById('sidebar-panel').classList.remove('visible-sidebar');document.getElementById('sidebar-panel').classList.add('hidden-sidebar')}
document.addEventListener('DOMContentLoaded',()=>{document.querySelectorAll('.lib-card[data-locked="false"]').forEach(bindDragEvents);document.getElementById('tab-panel-1').addEventListener('click',function(e){if(!e.target.closest('#search-wrapper'))closeSearchHistory()})});
</script>
</body>
</html>