:root{
  --bg:#000;
  --text:#f5f5f7;
  --text2:#86868b;
  --surface:rgba(255,255,255,.07);
  --surface2:rgba(255,255,255,.12);
  --hair:rgba(255,255,255,.10);
  --accent:#c8c8cc;
  --accent-soft:rgba(200,200,204,.22);
  --ease:cubic-bezier(.22,.61,.36,1);
  --soft:cubic-bezier(.25,.9,.3,1);
}

*{box-sizing:border-box;margin:0;padding:0}
/* .sheet/.bigplay 의 display 선언이 hidden 속성을 이기지 못하도록 */
[hidden]{display:none !important}
html,body{height:100%}
body{
  background:var(--bg);
  color:var(--text);
  font-family:"Pretendard Variable",Pretendard,-apple-system,BlinkMacSystemFont,"SF Pro Text",system-ui,sans-serif;
  -webkit-font-smoothing:antialiased;
  display:flex;flex-direction:column;
  overflow:hidden;
  overscroll-behavior:none;
}
button{font:inherit;color:inherit;background:none;border:0;cursor:pointer}
/* 손으로 끌 때 글자가 파랗게 잡히지 않게. 앱처럼 쓰려면 이게 없어야 한다.
   대신 입력칸·가사·약관처럼 실제로 긁어 갈 만한 곳은 열어 둔다. */
body{-webkit-user-select:none;user-select:none;-webkit-touch-callout:none}
input,textarea,.lines,.legal,.info-body,.albumstory,.offset,.code{
  -webkit-user-select:text;user-select:text}
svg{width:100%;height:100%;fill:none;stroke:currentColor;stroke-width:1.7;stroke-linecap:round;stroke-linejoin:round}

/* 애플 뮤직처럼 표지에서 뽑은 여러 색이 층을 이루며 천천히 흐릅니다 */
/* 재생 화면의 배경. 앨범에서 뽑은 네 색을 크게 번지게 깔아 애플뮤직처럼 만든다.
   시트(.player) 안에 있어야 한다 — 밖에 두면 시트의 불투명 배경에 덮인다(실측). */
.glow{
  position:absolute;inset:-25%;z-index:0;pointer-events:none;
  background:
    radial-gradient(42% 42% at 20% 24%, var(--c1,transparent), transparent 68%),
    radial-gradient(38% 38% at 80% 18%, var(--c2,transparent), transparent 66%),
    radial-gradient(46% 46% at 26% 80%, var(--c3,transparent), transparent 70%),
    radial-gradient(40% 40% at 78% 76%, var(--c4,transparent), transparent 66%);
  filter:blur(46px) saturate(1.25);
  opacity:0;
  transition:opacity 1.4s var(--ease);
  animation:drift 28s ease-in-out infinite alternate;
}
.glow.on{opacity:1}
@keyframes drift{
  from{transform:translate3d(-2%,-1.5%,0) scale(1.04)}
  to  {transform:translate3d(2.5%,2%,0) scale(1.12)}
}
/* 색 위에서도 글씨가 읽히도록 위·아래를 눌러줍니다 */
.glow::after{
  content:'';position:absolute;inset:0;
  background:linear-gradient(180deg,rgba(0,0,0,.55),rgba(0,0,0,.15) 32%,rgba(0,0,0,.30) 64%,rgba(0,0,0,.72));
}

.topbar{
  position:relative;z-index:3;
  display:flex;align-items:center;justify-content:space-between;
  padding:max(18px,env(safe-area-inset-top)) 22px 0;
}
.player-back{width:36px;height:36px;padding:0;border-radius:18px;flex:none}
.player-back svg{width:20px;height:20px}
.wordmark{
  font-size:13px;font-weight:700;letter-spacing:.22em;color:var(--text2);
}

.chip{
  display:inline-flex;align-items:center;gap:7px;
  height:34px;padding:0 14px;border-radius:17px;
  background:var(--surface);backdrop-filter:blur(20px);
  font-size:13px;font-weight:600;color:var(--text);
  transition:background .2s var(--ease),transform .2s var(--ease);
}
.chip svg{width:15px;height:15px}
.chip:hover{background:var(--surface2)}
.chip:active{transform:scale(.96)}
.chip.ghost{width:34px;padding:0;justify-content:center;color:var(--text2)}
.chip.ghost[aria-pressed="true"]{color:var(--text);background:var(--surface2)}

/* ── 턴테이블 ── */
/* 가사를 열면 이 행이 판과 가사로 갈린다. 판이 줄어들면 ResizeObserver가
   캔버스를 다시 재고 그리므로 별도 처리가 필요 없다. */
.main-row{
  position:relative;z-index:1;
  flex:1;min-height:0;display:flex;
}
.stage{
  position:relative;
  flex:1;min-width:0;min-height:0;
  touch-action:none;
}
#deck{position:absolute;inset:0;width:100%;height:100%;display:block}

.label{
  position:absolute;z-index:2;
  border-radius:50%;
  overflow:hidden;
  will-change:transform;
  box-shadow:0 0 0 1px rgba(0,0,0,.55), 0 10px 40px rgba(0,0,0,.5);
  /* 스핀들 구멍을 뚫어 캔버스의 축이 보이게 */
  -webkit-mask-image:radial-gradient(circle at 50% 50%, transparent 0 var(--hole,7px), #000 var(--hole,7px));
  mask-image:radial-gradient(circle at 50% 50%, transparent 0 var(--hole,7px), #000 var(--hole,7px));
  background:#0e0e10;
}
/* iframe은 자체 합성 레이어를 만들어 z-index:auto 형제를 이길 수 있다.
   표지가 확실히 위로 오도록 쌓임 순서를 명시한다. */
.label{isolation:isolate}
.label-inner{position:absolute;inset:0;overflow:hidden;z-index:1}
/* 16:9 영상을 정사각 라벨에 가운데 크롭. 너비 = 16/9 = 177.778%.
   pointer-events를 끊어 YouTube의 제목 바·일시정지 표시가 뜨지 않게 한다.
   어차피 위에 고해상도 표지 이미지를 덮으므로 화면에는 보이지 않는다. */
.label-inner iframe{
  position:absolute;top:50%;left:50%;
  transform:translate(-50%,-50%);
  width:177.778%;height:100%;
  border:0;pointer-events:none;
}
/* 16:9 썸네일을 정사각에 cover → 아트 트랙이면 앨범 표지만 남는다.
   항상 덮어둔다. 영상 스트림보다 해상도가 높고, YouTube UI가 비칠 일도 없다. */
.labelart{
  position:absolute;inset:0;z-index:3;
  width:100%;height:100%;object-fit:cover;
  pointer-events:none;
  animation:artin .5s var(--ease);
}
@keyframes artin{from{opacity:0}}

.label.idle{background:
  radial-gradient(circle at 50% 50%, #1c1c1f 0%, #121215 60%, #0b0b0d 100%);}
/* 판이 없을 땐 YouTube 기본 화면이 라벨에 비치지 않도록 가린다 */
.label.idle .label-inner{opacity:0;pointer-events:none}

.spindle{
  position:absolute;z-index:3;border-radius:50%;pointer-events:none;
  background:linear-gradient(150deg,#e8e8ea,#9a9aa0 45%,#6e6e74 60%,#c9c9cf);
  box-shadow:0 1px 3px rgba(0,0,0,.8), inset 0 0 2px rgba(255,255,255,.6);
}

.bigplay{
  position:absolute;z-index:4;left:50%;top:50%;
  width:76px;height:76px;margin:-38px 0 0 -38px;
  border-radius:50%;
  background:rgba(20,20,22,.55);backdrop-filter:blur(24px) saturate(1.6);
  box-shadow:0 0 0 1px var(--hair), 0 12px 40px rgba(0,0,0,.6);
  display:grid;place-items:center;
  transition:transform .22s var(--ease),opacity .22s var(--ease);
}
.bigplay svg{width:34px;height:34px;fill:var(--text);stroke:none;margin-left:3px}
.bigplay:active{transform:scale(.93)}

/* ── 하단 패널 ── */
.panel{
  position:relative;z-index:3;
  padding:0 22px max(20px,env(safe-area-inset-bottom));
  display:flex;flex-direction:column;gap:14px;
}
.meta{text-align:center;min-height:42px}
.title{
  font-size:17px;font-weight:600;letter-spacing:-.01em;
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis;
}
.artist{font-size:13px;color:var(--text2);margin-top:3px;
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis}

.scrub{cursor:pointer;padding:6px 0}
.scrub-track{height:4px;border-radius:2px;background:rgba(255,255,255,.14);overflow:hidden}
.scrub-fill{height:100%;width:0;border-radius:2px;background:var(--accent);
  transition:background 1s var(--ease)}
.times{display:flex;justify-content:space-between;
  font-size:11px;color:var(--text2);margin-top:7px;
  font-variant-numeric:tabular-nums}

.transport{display:flex;align-items:center;gap:10px}
.tbtn{
  width:40px;height:40px;border-radius:20px;display:grid;place-items:center;
  color:var(--text2);transition:color .18s var(--ease),transform .18s var(--ease),background .18s var(--ease);
}
.tbtn svg{width:22px;height:22px;fill:currentColor;stroke:none}
/* 선으로 그린 아이콘(셔플·반복)은 채우면 삼각형 조각만 남는다.
   CSS가 인라인 fill="none" 속성을 이기므로 여기서 되돌려 준다. */
.tbtn svg[fill="none"]{fill:none;stroke:currentColor;stroke-linecap:round;stroke-linejoin:round}
.tbtn:hover{color:var(--text)}
.tbtn:active{transform:scale(.9)}
.tbtn.play{width:52px;height:52px;border-radius:26px;color:var(--text);background:var(--surface)}
.tbtn.play svg{width:26px;height:26px}
.spacer{flex:1}

.seg{display:flex;background:var(--surface);border-radius:15px;padding:2px;height:30px}
.seg button{
  padding:0 11px;border-radius:13px;font-size:11px;font-weight:700;
  color:var(--text2);transition:.18s var(--ease);
  font-variant-numeric:tabular-nums;
}
.seg button.on{background:var(--surface2);color:var(--text)}

/* ── 검색 화면 ── */
@keyframes fade{from{opacity:0}}
@keyframes rise{from{transform:translateY(14px);opacity:0}}

/* ── 둘러보기 ──
 * 홈·라디오·검색·보관함이 각각 따로 뜨면 지금 어디에 있는지 헷갈린다.
 * 한 껍데기 안에서 탭으로만 오간다. 판(재생 화면)은 이 뒤에 있다.
 */
/* 둘러보기가 바닥이다. 언제나 여기 있고, 탭바도 늘 보인다. */
.browse{
  position:fixed;inset:0;z-index:20;
  background:var(--bg);
  display:flex;flex-direction:column;
}
/* 재생 화면은 그 위로 올라오는 시트. 내리면 보던 탭이 그대로 남아 있다. */
.player{
  position:fixed;inset:0;z-index:40;
  display:flex;flex-direction:column;
  background:var(--bg);
  /* 광원이 inset:-25% 로 시트보다 크다. 안 자르면 시트가 내려가 있어도
     위쪽 25%가 화면 아래에 비쳐 보인다(실측). */
  overflow:hidden;
  transform:translateY(100%);
  transition:transform .34s var(--ease);
  will-change:transform;
}
body.player-open .player{transform:translateY(0)}
body:not(.player-open) .player{pointer-events:none}
/* 시트 안의 내용은 광원 위에 온다 */
.player > *:not(.glow){position:relative;z-index:1}
.tabpane{flex:1;min-height:0;min-width:0;display:flex;flex-direction:column;overflow-x:hidden}
.tabpane[hidden]{display:none !important}

.tabbar{
  flex:none;display:flex;align-items:stretch;
  border-top:1px solid var(--hair);
  /* 화면 맨 아래까지 붙인다. 홈 인디케이터가 지나가는 만큼만 아주 얇게 남긴다 —
     그마저 없애면 탭 글씨가 인디케이터에 깔린다. */
  padding-bottom:calc(env(safe-area-inset-bottom) * 0.28);
  background:var(--bg);
}
.tab{
  flex:1;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:4px;
  padding:9px 4px 6px;color:var(--text2);
  font-size:10.5px;font-weight:600;letter-spacing:-.01em;
  transition:color .15s var(--ease);
}
.tab svg{width:22px;height:22px;fill:currentColor;stroke:none}
.tab svg[fill="none"]{fill:none;stroke:currentColor;stroke-linecap:round;stroke-linejoin:round}
.tab.on{color:var(--text)}
.tab:active{transform:scale(.94)}
.side-mark{display:none}



/* 재생 막대는 화면 맨 아래에 고정돼 있다. 둘러보기가 열려 있으면 탭바를 덮어
   가운데 탭 두 개가 통째로 가려진다(실측). 탭바 높이만큼 올려 붙인다. */
:root{--tabh:64px}
/* 재생 화면에는 이미 아래에 조작 막대가 있다. 시트가 올라와 있으면 미니바는 숨긴다. */
body.player-open .mini{display:none !important}
/* 마지막 줄이 재생 막대 뒤로 숨지 않게 */
body.mini-on .tabpane .lib-body,
body.mini-on .tabpane .results{padding-bottom:104px}
.search-bar{
  /* 탭 안에 있으므로 제목 줄은 위(.lib-bar)가 맡는다. 여기는 입력칸만. */
  display:flex;align-items:center;gap:12px;flex:none;
  width:100%;max-width:var(--pane);margin:0 auto;
  padding:6px 20px 12px;
}
.field{
  flex:1;display:flex;align-items:center;gap:10px;
  height:44px;padding:0 14px;border-radius:13px;
  background:var(--surface2);
  transition:background .2s var(--ease);
}
.field:focus-within{background:var(--surface)}
.field .mag{color:var(--text2)}
.field .mag{width:17px;height:17px;flex:none;color:var(--text2)}
.field input{
  flex:1;min-width:0;background:none;border:0;outline:none;
  color:var(--text);font-size:16px;
}
.field input::placeholder{color:var(--text2)}
.field input::-webkit-search-cancel-button{display:none}
.clear{width:19px;height:19px;flex:none;color:var(--text2);padding:0}
.clear svg{stroke-width:2.2}
.txtbtn{font-size:15px;color:var(--text);flex:none}
.txtbtn:active{opacity:.5}

.results{
  flex:1;overflow-y:auto;-webkit-overflow-scrolling:touch;
  padding:8px 10px 24px;
}
.note{
  text-align:center;color:var(--text2);font-size:14px;line-height:1.6;
  padding:56px 24px;
}
.note span{font-size:12.5px;opacity:.65}
.note.err{color:#ff6b6b}

.row{
  display:grid;width:100%;
  grid-template-columns:52px 1fr auto auto;
  grid-template-rows:auto auto;
  column-gap:13px;row-gap:2px;align-items:center;
  padding:8px 12px;border-radius:12px;
  transition:background .15s var(--ease);
}
.row:hover{background:rgba(255,255,255,.07)}
/* mqdefault·iTunes 표지 모두 정사각으로 */
.row .rart{
  grid-row:1/3;grid-column:1;
  width:52px;height:52px;border-radius:6px;object-fit:cover;background:#1a1a1d;
  box-shadow:0 1px 6px rgba(0,0,0,.5);cursor:pointer;
}
.row .rt{
  grid-row:1;grid-column:2;text-align:left;
  font-size:15px;font-weight:500;letter-spacing:-.01em;
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis;
}
.row .rs{
  grid-row:2;grid-column:2;
  font-size:12.5px;color:var(--text2);
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis;
}
.row .lnk{
  color:var(--text2);font:inherit;
  border-bottom:1px solid transparent;transition:.15s var(--ease);
}
.row .lnk:hover{color:var(--text);border-bottom-color:rgba(255,255,255,.35)}
.row .rd{
  grid-row:1/3;grid-column:3;
  font-size:12px;color:var(--text2);font-variant-numeric:tabular-nums;
}
.row .addbtn{grid-row:1/3;grid-column:4}

/* 둘러보기 머리말 */
.browse-head{
  display:flex;align-items:baseline;gap:12px;
  padding:6px 12px 14px;margin-bottom:2px;
  border-bottom:1px solid var(--hair);
}
.bh-t{flex:1;font-size:17px;font-weight:700;letter-spacing:-.015em;
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.bh-c{font-size:12px;color:var(--text2);flex:none}

.row.playing .rt{color:var(--accent)}

.skel{display:flex;align-items:center;gap:13px;padding:8px 12px}
.skel i{display:block;border-radius:6px;background:rgba(255,255,255,.07);
  animation:pulse 1.3s ease-in-out infinite}
.skel .sa{width:52px;height:52px;flex:none}
.skel .sb{flex:1;height:11px;max-width:230px}
@keyframes pulse{50%{opacity:.42}}

.morebtn{
  display:block;margin:14px auto 0;padding:9px 18px;border-radius:19px;
  background:var(--surface);font-size:13px;font-weight:600;color:var(--text);
}
.morebtn:hover{background:var(--surface2)}

/* ── 가사 ──
 * 넓은 화면에서는 판 옆에 나란히(애플 뮤직 전체화면 플레이어),
 * 좁은 화면에서는 전체를 덮는다. 아래 미디어쿼리에서 갈린다.
 */
.lyrics{
  flex:none;width:min(46%,540px);
  display:flex;flex-direction:column;min-height:0;
  animation:lyrin .38s var(--ease);
}
@keyframes lyrin{from{opacity:0;transform:translateX(24px)}}
@keyframes lyrup{from{opacity:0;transform:translateY(18px)}}

.lyr-head{
  display:flex;align-items:flex-end;justify-content:flex-end;gap:14px;flex:none;
  padding:18px 26px 10px;
}
/* 판 옆에 설 때는 아래 패널에 제목·가수가 이미 있다 — 한 화면에 두 번 쓰지 않는다.
   좁은 화면에서는 가사가 아래 패널을 덮으므로 그때만 되살린다. */
.lyr-meta{display:none}
.lyr-meta{min-width:0}
/* 가사 타이밍 미세조정 — LRCLIB 가사는 특정 발매반 기준이라
   유튜브 음원과 인트로 길이가 다르면 통째로 어긋난다 */
.lyr-tools{display:flex;align-items:center;gap:6px;flex:none}
.nudge{
  width:26px;height:26px;border-radius:13px;flex:none;
  background:var(--surface);color:var(--text2);
  font-size:15px;line-height:1;font-weight:600;
  transition:.16s var(--ease);
}
.nudge:hover{background:var(--surface2);color:var(--text)}
.nudge:active{transform:scale(.9)}
.offset{
  font-size:11px;color:var(--text2);min-width:34px;text-align:center;
  font-variant-numeric:tabular-nums;
}
.offset.set{color:var(--accent)}
.lyr-title{font-size:19px;font-weight:600;letter-spacing:-.015em;
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.lyr-artist{font-size:13px;color:var(--text2);margin-top:2px;
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis}

.lines{
  flex:1;overflow-y:auto;-webkit-overflow-scrolling:touch;
  --anchor:.40;                                   /* 강조 줄이 앉을 높이(0=위, 1=아래) */
  min-height:0;
  padding:0 26px;
  scrollbar-width:none;
  /* 위아래로 자연스럽게 사라지도록 */
  /* 또렷한 구간의 위아래는 place() 의 fadeToArt() 가 왼쪽 판(또는 표지)에 맞춰
     픽셀로 넣어 준다. 아래 값은 나란히 놓지 않을 때(좁은 화면) 쓰는 기본값이다. */
  --fa:17%; --fb:83%; --fade:72px;
  -webkit-mask-image:linear-gradient(180deg,
    transparent calc(var(--fa) - var(--fade)), #000 var(--fa),
    #000 var(--fb), transparent calc(var(--fb) + var(--fade)));
  mask-image:linear-gradient(180deg,
    transparent calc(var(--fa) - var(--fade)), #000 var(--fa),
    #000 var(--fb), transparent calc(var(--fb) + var(--fade)));
}
.lines::-webkit-scrollbar{display:none}
/* 스크롤 여백은 의사요소(=내용)로 준다. 패딩으로 주면 요소가 줄어들지 못한다. */
.lines::before,.lines::after{content:'';display:block;flex:none}
.lines::before{height:calc(var(--anchor) * 100vh)}
.lines::after{height:calc((1 - var(--anchor)) * 100vh + 8vh)}
.lines p{
  font-size:26px;font-weight:700;letter-spacing:-.022em;line-height:1.46;
  color:rgba(255,255,255,.26);
  padding:9px 0;cursor:pointer;
  /* 화면이 좁아도 글자는 줄이지 않는다. 대신 줄을 넘긴다.
     한국어는 단어 중간에서 자르면 읽기 나쁘므로 띄어쓰기에서만 끊고,
     끊을 데가 없는 긴 영어 단어만 예외로 쪼갠다. */
  word-break:keep-all;
  overflow-wrap:break-word;
  transform-origin:left center;
  filter:blur(1.4px);
  text-shadow:0 0 0 rgba(0,0,0,0);
  transition:color .6s var(--soft), transform .6s var(--soft),
             filter .6s var(--soft), text-shadow .6s var(--soft);
  will-change:transform,filter;
}
.lines p.done{color:rgba(255,255,255,.19)}
.lines p.now{
  color:var(--text);
  transform:scale(1.05) translateX(3px);
  filter:blur(0);
  text-shadow:0 0 30px var(--accent-soft);
}
.lines p:hover{color:rgba(255,255,255,.62)}
.lines .plain{font-size:16px;font-weight:500;color:rgba(255,255,255,.72);
  filter:none;cursor:default;padding:4px 0;letter-spacing:normal}
.lines .plain:hover{color:rgba(255,255,255,.72)}
.lyr-note{text-align:center;color:var(--text2);font-size:14px;line-height:1.6;
  filter:none;font-weight:500;letter-spacing:0;cursor:default}
/* 안내문 한 줄만 있을 때는 가사처럼 굴지 않는다 —
   스크롤 여백도, 위아래 흐림도, 글자 흐림도 없이 가운데 한 줄로 둔다. */
.lines.only-note{
  overflow:hidden;display:flex;align-items:center;justify-content:center;
  -webkit-mask-image:none;mask-image:none;
}
.lines.only-note::before,.lines.only-note::after{content:none}
.lines.only-note p{filter:none;transform:none}

.plainnote{padding:0 0 18px !important;font-size:12.5px !important;
  text-align:left !important;color:var(--text2) !important}

/* 좁은 화면에서는 옆에 세울 자리가 없다 → 전체를 덮는다 */
@media (max-width:900px){
  .lyrics{
    position:fixed;inset:0;z-index:18;width:auto;
    background:rgba(8,8,10,.72);backdrop-filter:blur(40px) saturate(1.6);
    animation:lyrup .32s var(--ease);
  }
  .lyr-head,.lines{width:100%;max-width:720px;margin:0 auto}
  .lyr-head{padding:max(20px,env(safe-area-inset-top)) 24px 14px;
    justify-content:space-between}
  .lyr-meta{display:block}
}
@media (max-width:520px){
  /* 여기서 19px 로 줄이고 있었다. 글자는 그대로 두고 줄을 넘긴다. */
  .lines{padding:0 20px}
}

.toast{
  position:fixed;z-index:30;left:50%;bottom:118px;transform:translateX(-50%);
  background:rgba(40,40,42,.92);backdrop-filter:blur(20px);
  border:1px solid var(--hair);
  padding:11px 18px;border-radius:22px;font-size:13px;
  animation:rise .24s var(--ease);max-width:88vw;text-align:center;
}

@media (max-width:520px){
  .panel{gap:12px}
  .title{font-size:15px}
  .bigplay{width:64px;height:64px;margin:-32px 0 0 -32px}
}
@media (prefers-reduced-motion:reduce){
  *{animation-duration:.01ms !important;transition-duration:.01ms !important}
}

.topright{display:flex;align-items:center;gap:8px}

.glow.on{opacity:1}

/* ── 모바일 ── */
/* iOS 사파리는 주소창이 접혔다 펴지며 100vh가 튄다. dvh가 실제 보이는 높이를 따라간다. */
@supports (height:100dvh){ html,body{height:100dvh} }

@media (pointer:coarse){
  /* 손가락으로 누를 만큼 키운다 */
  .tbtn{width:46px;height:46px;border-radius:23px}
  .tbtn.play{width:58px;height:58px;border-radius:29px}
  .chip.ghost{width:38px;height:38px;border-radius:19px}
  .seg{height:34px;border-radius:17px}
  .seg button{padding:0 13px;border-radius:15px;font-size:12px}
  .scrub{padding:10px 0}          /* 얇은 막대를 잡기 쉽게 */
  .row{padding:10px 12px}
  .nudge{width:32px;height:32px;border-radius:16px;font-size:17px}
}

@media (max-width:430px){
  .topbar{padding-top:max(14px,env(safe-area-inset-top))}
  .chip{height:32px;padding:0 12px;font-size:12.5px}
  .transport{gap:6px}
  .panel{gap:10px;padding-left:18px;padding-right:18px}
  .title{font-size:16px}
  .lyr-head{padding-left:20px;padding-right:20px}
}
/* 가로로 누운 폰 — 세로 공간이 없어 패널을 바짝 붙인다 */
@media (max-height:460px) and (orientation:landscape){
  .panel{gap:8px;padding-bottom:max(10px,env(safe-area-inset-bottom))}
  .meta{min-height:34px}
  .title{font-size:15px}
  .artist{font-size:12px}
  .times{margin-top:4px}
}

/* 좁은 화면에서 가사는 '판 대신' 보는 화면이다.
   반투명으로 두면 상단바와 하단 컨트롤이 가사에 겹쳐 읽을 수 없다.
   → 배경을 불투명하게 덮고, 재생 컨트롤만 가사 위로 올린다. */
@media (max-width:900px){
  .lyrics{background:rgba(7,7,9,.94);backdrop-filter:blur(30px) saturate(1.4)}
  body.lyr-open .topbar{opacity:0;pointer-events:none}
  body.lyr-open .meta{display:none}          /* 제목은 가사 헤더에 이미 있다 */
  /* 판이 안 보이는데 회전 속도·표지 회전만 남으면 뜻이 없다 (표지 보기와 같은 이유) */
  body.lyr-open #rpm,
  body.lyr-open #spinToggle{display:none}
  body.lyr-open .panel{
    z-index:19;                              /* 컨트롤은 가사 위로 */
    /* 위쪽부터 투명하게 시작하면 진행바 근처에서 가사가 비쳐 겹쳐 보인다.
       빠르게 불투명해지게 하고, 페이드 구간은 blur로 뭉갠다. */
    background:linear-gradient(180deg,
      rgba(7,7,9,0), rgba(7,7,9,.97) 34%, rgba(7,7,9,1) 56%);
    backdrop-filter:blur(16px);
    padding-top:34px;
  }
  /* 가사는 패널에 닿기 전에 사라지게 한다 — 겹침을 근본적으로 없앤다 */
  body.lyr-open .lines{
    -webkit-mask-image:linear-gradient(180deg,transparent,#000 11%,#000 48%,transparent 70%);
    mask-image:linear-gradient(180deg,transparent,#000 11%,#000 48%,transparent 70%);
  }
  .lines{--anchor:.32}                       /* 하단 컨트롤을 피해 위쪽에 앉힌다 */
}

/* ── 보관함 ── */
.library{                       /* 남아 있는 규칙 — 지금은 .tabpane 이 자리를 잡는다 */
  display:flex;flex-direction:column;
}
.lib-bar{
  display:flex;align-items:center;gap:12px;flex:none;
  width:100%;max-width:var(--pane);margin:0 auto;
  padding:max(16px,env(safe-area-inset-top)) 20px 12px;
  border-bottom:1px solid var(--hair);
}
.lib-title{flex:1;font-size:17px;font-weight:700;letter-spacing:-.01em;
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.txtbtn.back{flex:none;color:var(--text2)}
.lib-body{
  flex:1;overflow-y:auto;-webkit-overflow-scrolling:touch;
  width:100%;max-width:min(1240px,94vw);margin:0 auto;padding:6px 0 30px;
}
.lib-sec{padding:18px 20px 6px;display:flex;align-items:center;justify-content:space-between}
.lib-sec h3{font-size:13px;font-weight:700;color:var(--text2);letter-spacing:.02em}
.lib-empty{padding:44px 24px;text-align:center;color:var(--text2);font-size:14px;line-height:1.7}

/* 빈 플레이리스트 — 화면 가운데로 모으고 빈 슬리브를 하나 세워둔다 */
.empty-crate{
  min-height:58vh;display:flex;flex-direction:column;
  align-items:center;justify-content:center;gap:4px;padding:24px;
}
.ec-art{
  position:relative;display:block;width:132px;aspect-ratio:1;border-radius:6px;
  background:linear-gradient(150deg,#2a2a30,#191920 46%,#131318);
  box-shadow:0 10px 30px rgba(0,0,0,.55),
             inset 0 1px 0 rgba(255,255,255,.10),
             inset 0 -16px 26px rgba(0,0,0,.45);
  margin-bottom:22px;
}
.ec-art::after{content:'';position:absolute;left:9%;right:9%;top:7%;height:2px;border-radius:2px;
  background:linear-gradient(90deg,transparent,rgba(255,255,255,.16),transparent)}
.ec-disc{
  position:absolute;right:-22%;top:10%;width:82%;aspect-ratio:1;border-radius:50%;z:-1;
  background:radial-gradient(circle at 50% 50%, #0d0d10 0 4%, #6d6d78 4.5% 6%,
             #2e2e35 7% 30%, #43434c 31% 33%, #2a2a31 34% 60%, #45454e 61% 63%, #232329 64% 100%);
  box-shadow:0 6px 18px rgba(0,0,0,.6), inset 0 0 0 1px rgba(255,255,255,.12);
  z-index:-1;
}
.ec-t{font-size:15.5px;font-weight:600;color:var(--text)}
.ec-s{font-size:13px;color:var(--text2);margin-top:2px}
.empty-crate .lib-actions{padding-top:22px;justify-content:center}

/* 플레이리스트 = 레코드 슬리브. 판이 살짝 삐져나온 모습으로 그린다. */
.sleeves{display:grid;grid-template-columns:repeat(auto-fill,minmax(150px,1fr));
  gap:26px 22px;padding:8px 22px 12px}
.plcard{text-align:left}
/* 슬리브 밖으로 판이 삐져나온 모습. 판이 잘리면 안 되므로
   자르기(overflow:hidden)는 표지에만 걸고 바깥 wrap은 열어 둔다. */
.plcard .pl-wrap{position:relative;display:block;aspect-ratio:1;
  transition:transform .22s var(--soft)}
.plcard:hover .pl-wrap{transform:translateY(-3px)}
.plcard .pl-art{
  position:relative;z-index:1;display:block;height:100%;border-radius:5px;
  background:linear-gradient(150deg,#232327,#141417);
  box-shadow:0 6px 22px rgba(0,0,0,.5);overflow:hidden;
  display:grid;place-items:center;
}
.plcard .pl-art img{width:100%;height:100%;object-fit:cover;display:block}
.plcard .pl-n{display:block;font-size:13.5px;font-weight:600;margin-top:9px;
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.plcard .pl-c{display:block;font-size:11.5px;color:var(--text2);margin-top:1px}
/* 곡이 없으면 <img>가 없다 → :empty. 검은 상자가 아니라 빈 슬리브로 읽히게. */
.plcard .pl-art:empty{
  background:
    linear-gradient(150deg,#2a2a30,#191920 46%,#131318),
    #16161a;
  box-shadow:0 6px 22px rgba(0,0,0,.5),
             inset 0 1px 0 rgba(255,255,255,.10),
             inset 0 -14px 22px rgba(0,0,0,.45);
}
.plcard .pl-art:empty::after{      /* 슬리브 입구 */
  content:'';position:absolute;left:9%;right:9%;top:7%;height:2px;border-radius:2px;
  background:linear-gradient(90deg,transparent,rgba(255,255,255,.16),transparent);
}
.plnew .pl-art{border:1px dashed rgba(255,255,255,.18);background:rgba(255,255,255,.03)}
.plnew .pl-art:empty{box-shadow:none}
.plnew .pl-art svg{width:26px;height:26px;color:var(--text2);stroke-width:1.6}

/* ── LP 크레이트 ──
   선반에 세로로 꽂힌 판을 위에서 내려다본 모습.
   표지는 뒤로 눕혀 노출된 윗변만 남기고, 그 띠에 제목·가수를 얹는다.
   글자가 있어야 전부 식별되고 한 번에 고를 수 있다.

   3D는 .sl-card 안에서 perspective()로 끝낸다 — 조상에 perspective/preserve-3d를
   걸면 변환된 표지가 3D 정렬로 글자 위에 올라와 제목이 통째로 가려진다. */
.crate{
  width:100%;max-width:440px;margin:0 auto;
  padding:10px 0 300px;              /* 마지막 판이 아래로 길게 눕는 만큼 */
}
.sleeve{position:relative;height:62px}   /* 옆면으로 드러나는 높이 = 목록 한 줄 */

.sleeve .sl-card{
  position:absolute;left:0;right:0;top:0;
  aspect-ratio:1;
  transform-origin:50% 0%;
  /* 윗변을 축으로 아랫변만 뒤로 물러나게 → 아래가 조금 좁아진다.
     윗변 폭은 변하지 않으므로 딱지와 정확히 일치한다. */
  transform:perspective(2000px) rotateX(-56deg);
  border-radius:5px;overflow:hidden;
  pointer-events:none;               /* 클릭은 위의 버튼이 받는다 */
  box-shadow:0 -1px 0 rgba(255,255,255,.24),      /* 윗변 = 슬리브 두께 */
             0 16px 28px rgba(0,0,0,.66);
  transition:transform .3s var(--soft),filter .3s var(--soft);
  filter:brightness(.72) saturate(.95);
}
.sleeve .sl-card img{width:100%;height:100%;object-fit:cover;display:block}

/* 노출된 띠 위의 글자 — 3D 밖이라 항상 또렷하다 */
.sleeve .sl-main{
  position:absolute;left:0;right:0;top:0;height:62px;z-index:2;
  display:flex;flex-direction:column;justify-content:center;gap:2px;
  padding:0 48px 0 15px;text-align:left;   /* 오른쪽은 × 자리만 비운다 */
  background:linear-gradient(180deg,rgba(0,0,0,.62),rgba(0,0,0,.12));
  border-radius:5px 5px 0 0;
  transition:background .2s var(--soft),transform .3s var(--soft);
}
.sleeve .sl-t{
  font-size:14.5px;font-weight:600;letter-spacing:-.01em;
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis;
  text-shadow:0 1px 4px rgba(0,0,0,.9);
}
.sleeve .sl-a{
  font-size:11.5px;color:rgba(255,255,255,.74);
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis;
  text-shadow:0 1px 4px rgba(0,0,0,.9);
}
.sleeve .sl-x{
  position:absolute;right:4px;top:16px;z-index:3;
  width:30px;height:30px;border-radius:15px;
  display:grid;place-items:center;color:rgba(255,255,255,.6);
  opacity:0;transition:opacity .18s var(--soft),background .18s var(--soft),transform .3s var(--soft);
}
.sleeve .sl-x svg{width:15px;height:15px;stroke-width:2}
.sleeve .sl-x:hover{background:rgba(255,255,255,.16);color:#fff}

/* 짚은 판은 살짝 일어서며 떠오른다.
   무엇을 '짚은' 것으로 볼지는 기기에 따라 다르다 —
   마우스가 있으면 커서를 올린 판, 없으면 스크롤 위치에 걸린 판(.at).
   둘을 동시에 켜면 데스크톱에서 두 개가 같이 떠올라 서로 부딪힌다. */
@media (hover:hover){                 /* 데스크톱 — 마우스 오버 */
  .sleeve:hover .sl-card,.sleeve:focus-within .sl-card{
    transform:perspective(2000px) rotateX(-50deg) translateY(-15px);
    filter:brightness(1) saturate(1);
  }
  .sleeve:hover .sl-main,.sleeve:focus-within .sl-main{
    background:linear-gradient(180deg,rgba(0,0,0,.4),rgba(0,0,0,.04));
    transform:translateY(-15px);          /* 표지와 같은 양 — 안 맞추면 딱지만 남는다 */
  }
  .sleeve:hover .sl-x,.sleeve:focus-within .sl-x{opacity:1;transform:translateY(-15px)}
}

/* .at 은 터치 기기에서만 JS가 붙인다. 미디어쿼리로 한 번 더 감싸면
   브라우저마다 hover 판정이 갈려 조용히 안 먹는 일이 생기므로 클래스만 본다. */
.sleeve.at .sl-card{
  transform:perspective(2000px) rotateX(-50deg) translateY(-15px);
  filter:brightness(1) saturate(1);
}
.sleeve.at .sl-main{
  background:linear-gradient(180deg,rgba(0,0,0,.4),rgba(0,0,0,.04));
  transform:translateY(-15px);            /* 표지와 같은 양 */
}
.sleeve.at .sl-x{opacity:1;transform:translateY(-15px)}
/* 누르면 뽑혀 나간다 */
.sleeve.pull .sl-card{
  transform:perspective(2000px) rotateX(-12deg) translateY(-30px);
  opacity:.2;transition:transform .22s var(--ease),opacity .22s var(--ease);
}
.sleeve.pull .sl-main,.sleeve.pull .sl-x{
  transform:translateY(-30px);opacity:.2;
  transition:transform .22s var(--ease),opacity .22s var(--ease);
}

/* 고른 판 */
.pick{text-align:center;padding:6px 20px 0}
.pick-t{font-size:17px;font-weight:600;letter-spacing:-.01em;
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.pick-a{font-size:13px;color:var(--text2);margin-top:3px;
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.pick .lib-actions{justify-content:center;padding-top:14px}
.lib-actions.sub{justify-content:center;padding-top:22px;opacity:.75}
.lib-actions.sub .btn{height:32px;padding:0 14px;font-size:12.5px}



/* 곡 목록 (플레이리스트 안) */
.tlist{padding:4px 12px 24px}
/* 넓은 화면에서 한 줄이 화면 끝까지 늘어나면 읽기 나쁘다 → 여러 칸으로 접는다 */
@media (min-width:820px){
  .lib-body > .tlist{
    display:grid;grid-template-columns:repeat(auto-fill,minmax(330px,1fr));
    gap:2px 14px;
  }
}
.trow .td{flex:none;font-size:12px;color:var(--text2);font-variant-numeric:tabular-nums;margin-right:2px}
.trow{display:flex;align-items:center;gap:12px;width:100%;padding:8px 10px;border-radius:11px}
.trow:hover{background:rgba(255,255,255,.06)}
.trow img{width:44px;height:44px;border-radius:5px;object-fit:cover;flex:none;background:#1a1a1d}
.trow .tb{flex:1;min-width:0;text-align:left}
.trow .tt{display:block;font-size:14.5px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.trow .ta{display:block;font-size:12px;color:var(--text2);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.trow .tx{flex:none;width:30px;height:30px;border-radius:15px;color:var(--text2);
  display:grid;place-items:center}
.trow .tx:hover{background:rgba(255,255,255,.1);color:var(--text)}
.trow .tx svg{width:15px;height:15px}

.lib-actions{display:flex;gap:9px;padding:10px 20px 4px}
.btn{height:38px;padding:0 18px;border-radius:19px;font-size:14px;font-weight:600;
  background:var(--text);color:#000;transition:.18s var(--ease);
  display:inline-flex;align-items:center;gap:7px}
.btn svg{width:16px;height:16px;stroke-width:2}
.btn:active{transform:scale(.96)}
.btn.ghost{background:var(--surface);color:var(--text)}

/* 검색 결과에서 바로 담기 */
.row .addbtn{flex:none;width:30px;height:30px;border-radius:15px;color:var(--text2);
  display:grid;place-items:center;transition:.16s var(--ease)}
.row .addbtn:hover{background:rgba(255,255,255,.12);color:var(--text)}
.row .addbtn svg{width:16px;height:16px;stroke-width:2}

@media (max-width:520px){
  .sleeves{grid-template-columns:repeat(auto-fill,minmax(128px,1fr));gap:16px 12px;padding:6px 16px 10px}
  .crate{padding:8px 14px 34px}

}
.rmain{display:flex;align-items:center;gap:13px;flex:1;min-width:0;text-align:left}


/* 스크롤 막대는 어디서도 보이지 않게 한다 */
.lib-body,.results,.lines,.crate,.sheet,.library{scrollbar-width:none;-ms-overflow-style:none}
.lib-body::-webkit-scrollbar,.results::-webkit-scrollbar,
.lines::-webkit-scrollbar,.crate::-webkit-scrollbar{display:none;width:0;height:0}

/* 목록 위아래 끝을 부드럽게 — 잘린 느낌을 없앤다 */
/* 넓은 화면에서 목록이 좌우 끝까지 늘어지면 눈이 줄을 따라가기 힘들다.
   모든 탭이 같은 폭을 쓰도록 한 값으로 묶는다. */
:root{--pane:min(980px,94vw);--side:232px}
.lib-body,.results{width:100%;max-width:var(--pane);margin:0 auto}
.lib-body{
  -webkit-mask-image:linear-gradient(180deg,transparent,#000 22px,#000 calc(100% - 26px),transparent);
  mask-image:linear-gradient(180deg,transparent,#000 22px,#000 calc(100% - 26px),transparent);
}

/* ── 가사 싱크: 평소엔 접어둔다 ── */
.nudges{display:inline-flex;align-items:center;gap:6px}
.chip.ghost[aria-pressed="true"]#syncBtn{color:var(--accent)}

/* ── 앨범 표지 보기 ──
   판·톤암을 감추고 표지를 정사각으로 크게 세운다.
   .label 은 원형 마스크와 크기를 JS(place)가 잡으므로 여기선 모양만 바꾼다. */
body.cover #deck,
body.cover .spindle,
body.cover #rpm,
body.cover #spinToggle{display:none !important}
body.cover .label{
  border-radius:16px;
  -webkit-mask-image:none;mask-image:none;      /* 스핀들 구멍 제거 */
  box-shadow:0 30px 70px rgba(0,0,0,.6), 0 0 0 1px rgba(255,255,255,.06);
}
body.cover .label.idle{
  background:linear-gradient(150deg,#232329,#141418);
}
body.cover .labelart{border-radius:16px}

/* 가사 헤더의 작은 표지 — 넓은 화면에선 옆에 큰 표지가 이미 있으므로 감춘다 */
.lyr-art{display:none}

@media (max-width:900px){
  /* 가사만 볼 때는 앨범이 아니라 '그 뒤의 배경'이 비쳐야 한다.
     .lyrics 는 .main-row 안에 있으므로 .main-row 대신 .stage 만 숨긴다. */
  body.lyr-open .stage{visibility:hidden}
  .lyrics{background:rgba(8,8,10,.46);backdrop-filter:blur(26px) saturate(1.5)}

  .lyr-head{align-items:center;gap:12px}
  .lyr-art{
    display:block;flex:none;width:46px;height:46px;border-radius:7px;
    object-fit:cover;background:#1a1a1d;
    box-shadow:0 4px 14px rgba(0,0,0,.5);
  }
  .lyr-meta{flex:1;min-width:0}
  .lyr-title{font-size:16px}
  .lyr-artist{font-size:12px}
}

/* ── 판/표지 + 가사를 한 화면에 둘 때의 균형 ──
   판·표지는 제 칸 가운데에 오는데 가사는 왼쪽 정렬이라 오른쪽 끝에 붙어 있었다.
   실측: 왼쪽 여백 142px / 오른쪽 23px. 두 칸 모두 '내용이 칸 가운데'에 오게 맞춘다. */
@media (min-width:901px){
  body.lyr-open .main-row{
    padding:0 clamp(24px,4.5vw,76px);
    gap:clamp(28px,5.2vw,110px); /* 판/표지와 가사 사이 */
    justify-content:center;      /* 칸 폭을 JS가 잡으므로 남는 폭은 양쪽으로 */
  }
  body.lyr-open .lyrics{width:min(52%,580px)}
  body.lyr-open .lines{max-width:520px;margin:0 auto}   /* 글자 덩어리를 칸 가운데로 */
  /* 넓은 화면의 가사 헤더에는 싱크 아이콘뿐이다. 흐름에서 빼야 글자 영역이
     칸 맨 위에서 시작하고, 또렷한 구간의 윗끝을 판/표지 위끝에 맞출 수 있다. */
  body.lyr-open .lyrics{position:relative}
  body.lyr-open .lyr-head{
    position:absolute;top:0;right:0;z-index:3;
    padding:12px 16px;margin:0;width:auto;
  }
}

/* ── 미니 플레이어 ──
   검색·보관함이 화면을 덮어도 재생 중인 곡이 보이고 조작이 된다.
   이게 없으면 소리는 나는데 멈출 방법이 없어진다. */
.mini{
  /* 탭바가 늘 아래에 있으므로 그 위에 얹는다 — bottom:0 이면 탭을 덮는다 */
  position:fixed;left:0;right:0;z-index:24;
  bottom:calc(var(--tabh) + env(safe-area-inset-bottom));
  display:flex;align-items:center;gap:10px;
  width:100%;margin:0 auto;
  padding:10px calc((100vw - var(--pane)) / 2 + 14px);
  background:rgba(22,22,25,.92);backdrop-filter:blur(30px) saturate(1.6);
  border-top:1px solid var(--hair);
  animation:rise .26s var(--ease);
}
.mini-info{display:flex;align-items:center;gap:11px;flex:1;min-width:0;text-align:left}
.mini-info img{
  width:42px;height:42px;flex:none;border-radius:6px;object-fit:cover;background:#1a1a1d;
  box-shadow:0 2px 10px rgba(0,0,0,.5);
}
.mini-txt{flex:1;min-width:0}
.mini-t{display:block;font-size:13.5px;font-weight:600;
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.mini-a{display:block;font-size:11.5px;color:var(--text2);margin-top:1px;
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.mini-btn{
  flex:none;width:38px;height:38px;border-radius:19px;display:grid;place-items:center;
  color:var(--text);transition:background .16s var(--ease),transform .16s var(--ease);
}
.mini-btn svg{width:20px;height:20px;fill:currentColor;stroke:none}
.mini-btn:hover{background:rgba(255,255,255,.1)}
.mini-btn:active{transform:scale(.9)}

/* 막대에 마지막 줄이 가리지 않게 */
body.mini-on .results,
body.mini-on .lib-body{padding-bottom:96px}

/* ── 버튼 이름표 ──
 * 아이콘만 있는 버튼은 무슨 기능인지 알기 어렵다. 브라우저 기본 title 은
 * 1초쯤 지나야 뜨고 손가락으로 쓰는 기기에선 아예 안 뜬다. 직접 그린다.
 * ::after 는 셔플·반복의 켜짐 점이 이미 쓰고 있어 ::before 를 쓴다. */
[data-tip]{position:relative}
[data-tip]::before{
  content:attr(data-tip);
  position:absolute;bottom:calc(100% + 9px);left:50%;
  transform:translateX(-50%) translateY(3px);
  padding:6px 10px;border-radius:9px;
  background:rgba(30,30,34,.97);color:#fff;
  font-size:11.5px;font-weight:600;letter-spacing:-.01em;white-space:nowrap;
  box-shadow:0 8px 24px rgba(0,0,0,.45);
  opacity:0;pointer-events:none;z-index:60;
  transition:opacity .15s var(--ease), transform .15s var(--ease);
}
[data-tip]:hover::before,[data-tip]:focus-visible::before{
  opacity:1;transform:translateX(-50%) translateY(0);
}
/* 화면 맨 위 버튼은 이름표가 위로 나가면 화면 밖으로 잘린다 — 버튼 아래에 띄운다 */
.topbar [data-tip]::before{bottom:auto;top:calc(100% + 9px);transform:translateX(-50%) translateY(-3px)}
.topbar [data-tip]:hover::before,.topbar [data-tip]:focus-visible::before{transform:translateX(-50%) translateY(0)}
/* 맨 왼쪽·오른쪽 버튼은 이름표가 화면 옆으로 넘칠 수 있어 안쪽으로 붙인다 */
.topbar > [data-tip]:first-child::before{left:0;transform:translateX(0) translateY(-3px)}
.topbar > [data-tip]:first-child:hover::before{transform:translateX(0) translateY(0)}
.topright > [data-tip]:last-child::before{left:auto;right:0;transform:translateX(0) translateY(-3px)}
/* 곡 줄 오른쪽 끝 버튼 — 이름표가 화면 밖으로 나가지 않게 안쪽으로 편다 */
.trk-acts > [data-tip]:last-child::before{left:auto;right:0;transform:translateX(0) translateY(3px)}
.trk-acts > [data-tip]:last-child:hover::before{transform:translateX(0) translateY(0)}
.topright > [data-tip]:last-child:hover::before{transform:translateX(0) translateY(0)}
/* 손가락으로 쓰는 기기에는 이름표 대신 눌렀을 때 뜨는 안내(토스트)가 있다 */
@media (hover:none){[data-tip]::before{content:none}}

.nextbtn{width:32px;height:32px;flex:none;border-radius:16px;color:var(--text2);
  opacity:0;transition:opacity .14s var(--ease), color .14s var(--ease)}
.nextbtn svg{width:17px;height:17px}
.row:hover .nextbtn{opacity:1}
.nextbtn:hover{color:var(--text)}
@media (hover:none){.nextbtn{opacity:1}}
/* 추천을 불러오는 동안 자리를 잡아 둔다 — 갑자기 튀어나오지 않게 */
.skel-card{flex:none;width:132px;height:132px;border-radius:11px;background:var(--surface2);
  animation:pulse 1.3s ease-in-out infinite}
@keyframes pulse{0%,100%{opacity:.5}50%{opacity:.85}}

.mini-bar{position:absolute;left:0;right:0;top:0;height:2px;background:rgba(255,255,255,.1)}
.mini-fill{height:100%;width:0;background:var(--accent);transition:width .25s linear}
.mini{position:fixed}

/* 목록 머리 — 재생 · 셔플 */
.listhead{display:flex;align-items:center;gap:9px;padding:6px 12px 12px}
.lh-c{flex:1;font-size:12.5px;font-weight:600;color:var(--text2)}
.lh-btn{display:inline-flex;align-items:center;gap:6px;padding:8px 15px;border-radius:14px;
  background:var(--surface2);font-size:13px;font-weight:700;transition:.15s var(--ease)}
.lh-btn svg{width:15px;height:15px}
.lh-btn.go{background:var(--text);color:#000}
.lh-btn.go svg{fill:#000;stroke:none}
.lh-btn:hover{opacity:.85}
.lh-btn:active{transform:scale(.96)}

.likebtn{width:32px;height:32px;flex:none;border-radius:16px;color:var(--text2);
  opacity:0;transition:opacity .14s var(--ease), color .14s var(--ease)}
.likebtn svg{width:18px;height:18px;fill:none;stroke:currentColor;stroke-width:1.8}
.row:hover .likebtn,.likebtn.on{opacity:1}
.likebtn.on{color:#ff4d6a}
.likebtn.on svg{fill:#ff4d6a;stroke:#ff4d6a}
@media (hover:none){.likebtn{opacity:1}}
.chip.like.on{color:#ff4d6a}
.chip.like.on svg{fill:#ff4d6a;stroke:#ff4d6a}

/* ── 더보기 ──
   판 뒤집기·회전 속도 같은 건 자주 쓰지 않는다. 늘 꺼내놓으면 화면만 복잡해진다. */
.menu{
  position:absolute;bottom:calc(100% + 10px);right:0;z-index:50;
  min-width:230px;padding:7px;border-radius:15px;
  /* var(--surface) 는 rgba(255,255,255,.07) 이라 거의 투명하다. 그 뒤로 판이 돌고
     있어서 글씨가 묻혔다. 메뉴는 읽으라고 있는 것이므로 바탕을 제 색으로 깐다. */
  background:rgba(26,26,30,.96);
  backdrop-filter:blur(24px) saturate(1.4);
  box-shadow:0 18px 50px rgba(0,0,0,.6);
  border:1px solid rgba(255,255,255,.14);
  animation:lyrup .18s var(--ease);
}
.menu-row{
  display:flex;align-items:center;justify-content:space-between;gap:12px;
  padding:9px 11px;border-radius:10px;font-size:13.5px;font-weight:600;
  cursor:pointer;                       /* 줄 아무 데나 눌러도 켜지고 꺼진다 */
}
.menu-row:hover{background:rgba(255,255,255,.10)}
.menu-row:active{background:rgba(255,255,255,.15)}
/* 회전 속도처럼 고를 것이 여럿인 줄은 줄 전체를 누르는 게 뜻이 없다 */
.menu-row.pick{cursor:default}
.menu-row.pick:hover{background:none}
.menu-row .chip.ghost{width:32px;height:32px;flex:none}
.menu-row .seg{flex:none}
.transport{position:relative}

/* 셔플·반복 — 한 버튼이 모드에 따라 아이콘을 갈아 낀다 */
#modeBtn .ic-shuf{display:none}
#modeBtn[data-mode="shuffle"] .ic-rep{display:none}
#modeBtn[data-mode="shuffle"] .ic-shuf{display:block}

/* 켜져 있으면 강조색으로 상태를 알린다 */
.tbtn.small{width:34px;height:34px}
.tbtn.small svg{width:17px;height:17px}
.tbtn[aria-pressed="true"]{color:var(--accent)}
.tbtn[aria-pressed="true"]::after{
  content:'';position:absolute;bottom:2px;left:50%;transform:translateX(-50%);
  width:4px;height:4px;border-radius:2px;background:currentColor;
}
.tbtn{position:relative}
.rep1{position:absolute;right:6px;bottom:5px;font-size:9px;font-weight:800;
  color:var(--accent);pointer-events:none}

.acct-card{width:min(400px,100%)}
.acct-sub{font-size:13px;line-height:1.65;color:var(--text2);margin-top:10px}
#acctForm{display:flex;flex-direction:column;gap:9px;margin-top:20px}
#acctForm input{
  width:100%;padding:13px 15px;border-radius:12px;
  background:var(--surface2);color:var(--text);font-size:15px;
  border:1px solid transparent;transition:border-color .15s var(--ease);
}
#acctForm input:focus{outline:none;border-color:var(--accent)}
.acct-go{margin-top:6px;padding:13px;border-radius:12px;background:var(--text);color:#000;
  font-size:15px;font-weight:700;transition:opacity .15s var(--ease)}
.acct-go:disabled{opacity:.45}
.acct-alt{padding:8px;font-size:13px;font-weight:600;color:var(--text2)}
.acct-alt:hover{color:var(--text)}
.acct-msg{font-size:13px;line-height:1.5;color:#ff6b6b;padding:2px 2px 0}
.acct-msg.ok{color:var(--accent)}

/* ── 곡 이야기 ──
   위키백과에서 받아 온 곡·아티스트 설명. 화면 가운데 카드로 띄운다. */
.info{
  position:fixed;inset:0;z-index:80;
  display:flex;align-items:center;justify-content:center;padding:24px;
  background:rgba(0,0,0,.72);backdrop-filter:blur(18px);
  animation:fade .2s var(--ease);
}
@keyframes fade{from{opacity:0}}
.info-card{
  position:relative;width:min(640px,100%);max-height:min(78vh,720px);overflow-y:auto;
  padding:30px 30px 26px;border-radius:20px;
  /* --surface 는 반투명이다. 카드에 그대로 쓰면 뒤의 앨범 표지가 비쳐
     글씨를 못 읽는다(실측). 카드만은 불투명하게 둔다. */
  background:#141417;box-shadow:0 24px 70px rgba(0,0,0,.6);
  animation:lyrup .28s var(--ease);scrollbar-width:none;
}
.info-card::-webkit-scrollbar{display:none}
.info-x{position:absolute;top:14px;right:14px;width:32px;height:32px;border-radius:16px;
  color:var(--text2);background:transparent}
.info-x:hover{background:var(--surface2);color:var(--text)}
.info-x svg{width:17px;height:17px}
.info-t{font-size:23px;font-weight:800;letter-spacing:-.02em;padding-right:34px}
.info-a{font-size:14px;color:var(--text2);margin-top:5px}
.info-facts{display:flex;flex-wrap:wrap;gap:7px;margin:18px 0 4px}
.info-facts span{padding:6px 11px;border-radius:13px;background:rgba(255,255,255,.1);
  font-size:12px;font-weight:600;color:rgba(255,255,255,.72)}
.info-h{font-size:12.5px;font-weight:700;color:var(--text2);margin:22px 0 8px}
.info-p{font-size:15px;line-height:1.72;color:rgba(255,255,255,.86);word-break:keep-all}
.info-tr{margin-top:12px;font-size:12px;color:var(--text2)}
.info-orig{font-size:12px;font-weight:700;color:var(--accent);text-decoration:underline;
  text-underline-offset:2px;background:none;padding:0}
.info-src{display:inline-block;margin-top:16px;font-size:12.5px;font-weight:600;color:var(--accent)}
.info-none{font-size:14px;line-height:1.7;color:rgba(255,255,255,.66);margin-top:18px}
.sim{display:flex;flex-direction:column;gap:2px}
.sim-row{display:flex;align-items:center;gap:12px;width:100%;padding:8px;border-radius:12px;
  text-align:left;transition:background .14s var(--ease)}
.sim-row:hover{background:var(--surface2)}
.sim-row:active{transform:scale(.99)}
.sim-row img{width:44px;height:44px;border-radius:7px;object-fit:cover;flex:none;
  background:var(--surface2)}
.sim-txt{min-width:0;display:flex;flex-direction:column;gap:2px}
.sim-t{font-size:14.5px;font-weight:600;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.sim-a{font-size:12.5px;color:var(--text2);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
@media (max-width:520px){
  .info{padding:0;align-items:flex-end}
  .info-card{max-height:86vh;border-radius:20px 20px 0 0;padding:26px 22px calc(22px + env(safe-area-inset-bottom))}
}

/* ── 홈 ──
   처음 들어왔을 때 빈 판만 도는 대신, 들을 거리를 먼저 보여준다. */
.home-hero{padding:26px 4px 4px}
.home-hi{font-size:27px;font-weight:800;letter-spacing:-.03em}
.home-sub{font-size:14px;color:var(--text2);margin-top:7px}
.home-acct{display:flex;align-items:center;gap:8px;flex:none}
/* 홈 머리말 왼쪽은 서비스 이름 — 인사말은 아래 큰 글씨가 맡는다 */
.home-mark{flex:1;font-size:13px;font-weight:700;letter-spacing:.22em;color:var(--text2)}
.ha-btn{padding:7px 14px;border-radius:13px;background:var(--surface2);
  font-size:13px;font-weight:700;transition:.15s var(--ease)}
.ha-btn.go{background:var(--text);color:#000}
.ha-btn:hover{opacity:.85}
.ha-id{font-size:14px;font-weight:700}
.ha-note{font-size:12px;color:var(--text2)}
@media (max-width:520px){.ha-note{display:none}}

/* 다음 재생 */
.qrow{display:flex;align-items:center;gap:4px;border-radius:12px;padding:2px}
.qrow.now{background:var(--surface2)}
.qrow-main{display:flex;align-items:center;gap:12px;flex:1;min-width:0;padding:7px;
  text-align:left;border-radius:10px}
.qrow-main img{width:42px;height:42px;border-radius:7px;object-fit:cover;flex:none;
  background:var(--surface2)}
.qmini{width:30px;height:30px;border-radius:9px;flex:none;color:var(--text2);
  font-size:14px;font-weight:700}
.qmini:hover{background:var(--surface2);color:var(--text)}

/* 지금 재생 중 — 홈에서 바로 재생 화면으로 들어가는 문 */
.now-card{
  display:flex;align-items:center;gap:14px;width:100%;
  padding:12px;border-radius:14px;background:var(--surface2);
  text-align:left;transition:transform .14s var(--ease), background .14s var(--ease);
}
.now-card:hover{background:var(--surface)}
.now-card:active{transform:scale(.99)}
.now-card img{width:56px;height:56px;border-radius:9px;object-fit:cover;flex:none;
  background:var(--surface)}
.nc-txt{flex:1;min-width:0;display:flex;flex-direction:column;gap:3px}
.nc-t{font-size:15px;font-weight:700;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.nc-a{font-size:12.5px;color:var(--text2);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
/* 재생 중이면 막대가 움직인다 — 멈춰 있으면 가만히 */
.nc-eq{display:flex;align-items:flex-end;gap:3px;height:16px;flex:none;padding-right:4px}
.nc-eq i{width:3px;height:5px;border-radius:2px;background:var(--accent);display:block}
.nc-eq.on i{animation:eq .9s var(--ease) infinite}
.nc-eq.on i:nth-child(2){animation-delay:.3s}
.nc-eq.on i:nth-child(3){animation-delay:.6s}
@keyframes eq{0%,100%{height:5px}50%{height:15px}}

/* 플레이리스트는 가로로 흐르지 않고 줄이 바뀐다 — 몇 개인지 한눈에 보여야 한다 */
.hgrid{display:grid;grid-template-columns:repeat(auto-fill,minmax(126px,1fr));gap:18px 14px;padding:4px 2px 8px}
.hgrid .hcard,.hgrid .hcard img{width:100%}

/* 가로로 훑는 카드 줄 */
.hrow{display:flex;gap:14px;overflow-x:auto;padding:4px 2px 8px;scrollbar-width:none}
.hrow::-webkit-scrollbar{display:none}
.hcard{flex:none;width:132px;text-align:left}
.hcard img{width:132px;height:132px;border-radius:11px;object-fit:cover;
  background:var(--surface2);box-shadow:0 8px 24px rgba(0,0,0,.42);
  transition:transform .18s var(--ease)}
.hcard:hover img{transform:translateY(-3px)}
.hcard-t{display:block;margin-top:9px;font-size:13.5px;font-weight:600;
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.hcard-a{display:block;margin-top:2px;font-size:12px;color:var(--text2);
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis}

/* 장르 버튼 — 검색창 바로 아래에서 가로로 훑는다 */
.gchips{display:flex;gap:8px;overflow-x:auto;padding:2px 2px 4px;scrollbar-width:none}
.gchips::-webkit-scrollbar{display:none}
.gchip{
  flex:none;padding:8px 15px;border-radius:17px;
  background:linear-gradient(135deg,color-mix(in srgb,var(--gc1) 26%,transparent),
    color-mix(in srgb,var(--gc2) 26%,transparent));
  box-shadow:inset 0 0 0 1px color-mix(in srgb,var(--gc1) 30%,transparent);
  color:var(--text);
  font-size:13.5px;font-weight:600;white-space:nowrap;
  transition:background .16s var(--ease), transform .12s var(--ease);
}
.gchip:hover{filter:brightness(1.25)}
.gchip.on{background:linear-gradient(135deg,var(--gc1),var(--gc2));color:#fff}
.gchip:active{transform:scale(.95)}

/* ── 바로 듣기 타일 ──
   검색어가 없을 때 보여준다. 스포티파이 홈의 바로가기와 같은 자리. */
.qwrap{padding:14px 12px 8px}
.qh{font-size:13px;font-weight:700;color:var(--text2);padding:0 4px 12px}
.qgrid{display:grid;grid-template-columns:repeat(auto-fill,minmax(220px,1fr));gap:10px}
.qtile{
  display:flex;align-items:center;gap:12px;
  background:rgba(255,255,255,.07);border-radius:8px;overflow:hidden;
  transition:background .16s var(--ease),transform .16s var(--ease);
}
.qtile:hover{background:rgba(255,255,255,.13)}
.qtile:active{transform:scale(.98)}
.qtile img{width:56px;height:56px;flex:none;object-fit:cover;background:#1a1a1d}
.qt-txt{flex:1;min-width:0;padding-right:12px;text-align:left}
.qt-n{display:block;font-size:14px;font-weight:600;
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.qt-s{display:block;font-size:11.5px;color:var(--text2);margin-top:2px;
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis}

/* ── 넓은 화면은 사이드바 ──
 * 아래 탭바는 엄지로 쓰는 폰의 방식이다. 스포티파이·애플뮤직도 데스크톱에서는
 * 왼쪽 사이드바를 쓴다. 1600px 화면에 폰 UI 를 그대로 두면 허전하고 헷갈린다.
 */
@media (min-width:900px){
  :root{--tabh:0px}
  .browse{flex-direction:row}
  .tabbar{
    order:-1;width:var(--side);                       /* 목록보다 앞 = 왼쪽 */
    flex-direction:column;justify-content:flex-start;gap:3px;
    flex:none;
    border-top:0;border-right:1px solid var(--hair);
    padding:20px 12px calc(20px + env(safe-area-inset-bottom));
  }
  .side-mark{
    display:block;padding:6px 14px 20px;
    font-size:13px;font-weight:700;letter-spacing:.22em;color:var(--text2);
  }
  .tab{
    flex:none;flex-direction:row;justify-content:flex-start;gap:13px;
    padding:11px 14px;border-radius:11px;font-size:14.5px;letter-spacing:-.01em;
  }
  .tab svg{width:21px;height:21px}
  .tab.on{background:var(--surface2)}
  .tab:hover{color:var(--text)}
  .tab:active{transform:none}
  .tabpane{order:2;min-width:0}

  /* 재생 막대는 사이드바를 침범하지 않는다 — 사이드바는 위에서 아래까지 온전히 서 있고,
     막대는 목록이 있는 쪽에서만 가로지른다(애플뮤직과 같은 방식). */
  .mini{left:var(--side);right:0;bottom:0;width:auto;
    padding:10px calc((100vw - var(--side) - var(--pane)) / 2 + 14px)}
  body.mini-on .tabpane{padding-bottom:72px}

  /* 사이드바에 이미 VINYL 이 있다 — 본문 머리말의 것은 숨긴다(자리는 남겨 버튼 정렬 유지) */
  .home-mark{visibility:hidden}
}

/* ══════════════════════════════════════════════════════════════
   공통 컴포넌트 — 모든 탭이 이것만 쓴다 (js/ui.js 와 짝)
   화면마다 패딩·글자 크기·표지 비율이 달라 보이던 문제를 여기서 끝낸다.
   ══════════════════════════════════════════════════════════════ */
:root{
  --trk-art:48px;      /* 곡 줄 표지 */
  --card-w:150px;      /* 표지 카드 */
  --gap:14px;
}

/* ── 곡 한 줄 ── */
.trk{display:flex;align-items:center;gap:6px;border-radius:12px;padding:0 6px;
  transition:background .14s var(--ease)}
.trk:hover{background:rgba(255,255,255,.05)}
.trk.now{background:var(--surface2)}
.trk-main{display:flex;align-items:center;gap:13px;flex:1;min-width:0;
  padding:9px 4px;text-align:left}
.trk-art,.trk-main .art-none{width:var(--trk-art);height:var(--trk-art);flex:none;
  border-radius:8px;object-fit:cover;background:var(--surface2);display:block}
.trk-txt{min-width:0;display:flex;flex-direction:column;gap:3px}
.trk-t{font-size:15px;font-weight:600;letter-spacing:-.01em;
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.trk-s{font-size:12.5px;color:var(--text2);
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
/* 순서: 제목 … [다음에 재생 · 좋아요 · 담기] · 길이
   버튼이 길이 왼쪽에 오는 게 손이 가는 순서다(스포티파이도 같은 배치). */
.trk-d{flex:none;font-size:12.5px;color:var(--text2);font-variant-numeric:tabular-nums;
  padding:0 8px 0 6px;min-width:42px;text-align:right}
.trk-acts{display:flex;align-items:center;gap:2px;flex:none}
.trk-a{width:32px;height:32px;border-radius:16px;flex:none;color:var(--text2);
  font-size:14px;font-weight:700;opacity:0;
  transition:opacity .14s var(--ease), color .14s var(--ease), background .14s var(--ease)}
.trk-a svg{width:17px;height:17px;fill:none;stroke:currentColor;stroke-width:1.9}
.trk:hover .trk-a,.trk-a.on{opacity:1}
.trk-a:hover{background:var(--surface2);color:var(--text)}
.trk-a.like.on{color:#ff4d6a}
.trk-a.like.on svg{fill:#ff4d6a;stroke:#ff4d6a}
@media (hover:none){.trk-a{opacity:1}.trk-d{display:none}}

/* ── 표지 카드 ── */
.card{flex:none;width:var(--card-w);text-align:left}
.card-art{position:relative;display:block;width:var(--card-w);height:var(--card-w);
  border-radius:10px;overflow:visible}
.card-art img,.card-art .art-none{width:100%;height:100%;border-radius:10px;object-fit:cover;
  background:var(--surface2);display:block;position:relative;z-index:1;
  box-shadow:0 8px 22px rgba(0,0,0,.45);transition:transform .18s var(--ease)}
/* LP 가 슬리브에서 반쯤 나온 모습 — 표지 오른쪽 뒤로 판 가장자리가 보인다 */
.card-disc{position:absolute;top:8%;right:-9px;width:84%;height:84%;border-radius:50%;z-index:0;
  background:radial-gradient(circle at 50% 50%,#2a2a2e 0 22%,#141416 23% 100%);
  box-shadow:inset 0 0 0 1px rgba(255,255,255,.05);
  transition:transform .18s var(--ease)}
.card:hover .card-art img{transform:translateY(-3px)}
.card:hover .card-disc{transform:translateX(5px)}
.card.round .card-art img,.card.round .card-art .art-none{border-radius:50%}
/* 아티스트 사진이 도착하기 전 — 회색 원만 두면 고장난 것처럼 보인다 */
.card.round .art-none{
  background:
    radial-gradient(circle at 50% 38%, rgba(255,255,255,.16) 0 13%, transparent 14%),
    radial-gradient(ellipse 34% 26% at 50% 82%, rgba(255,255,255,.16) 0 60%, transparent 61%),
    var(--surface2);
}
.card.round .card-disc{display:none}
/* 사진을 끝내 못 찾은 아티스트 — 앨범 표지를 대신 쓰면 바로 옆 앨범 카드와 같은 그림이
   되고, 회색 실루엣만 두면 고장난 것처럼 보인다. 이름을 새긴 판을 그린다.
   색을 이름에서 뽑으므로 같은 사람은 어느 화면에서 보든 같은 판이 나온다. */
.card-art .ar-face,.card.round .card-art .ar-face,.hero-art .ar-face,.st-disc .ar-face{
  position:relative;display:flex;align-items:center;justify-content:center;
  border-radius:50%;overflow:hidden;
  background:
    repeating-radial-gradient(circle at 50% 50%,rgba(255,255,255,.05) 0 1px,transparent 1px 4px),
    radial-gradient(circle at 34% 26%,rgba(255,255,255,.10),transparent 52%),
    #121214}
.ar-face::before{content:'';position:absolute;left:50%;top:50%;transform:translate(-50%,-50%);
  width:47%;height:47%;border-radius:50%;
  background:radial-gradient(circle at 36% 28%,hsl(var(--h) 60% 60%),hsl(var(--h) 56% 36%))}
.ar-face i{position:relative;z-index:1;font-style:normal;font-weight:700;color:#fff;
  letter-spacing:-.02em;text-shadow:0 1px 2px rgba(0,0,0,.35);
  font-size:calc(var(--card-w) * .21)}
.hero-art .ar-face i{font-size:42px}
.st-disc .ar-face i{font-size:17px}
.card-t{display:block;margin-top:11px;font-size:13.5px;font-weight:600;
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.card-s{display:block;margin-top:2px;font-size:12px;color:var(--text2);
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis}

/* ── 구역 · 그릇 ── */
.sec{padding:8px 0 18px}
.sec-h{display:flex;align-items:baseline;gap:10px;padding:0 12px 12px}
.sec-h h3{flex:1;font-size:15.5px;font-weight:700;letter-spacing:-.02em}
.sec-more{font-size:12.5px;font-weight:600;color:var(--text2)}
.sec-more:hover{color:var(--text)}
/* 가로 레일은 overflow-x:auto 라 세로도 같이 잘린다(CSS 규칙상 visible 이 안 된다).
   카드가 호버에서 3px 뜨고 판 가장자리가 오른쪽으로 9px 삐져나오므로,
   그만큼 안쪽 여백을 둬서 잘리지 않게 한다. */
.rail{display:flex;gap:var(--gap);overflow-x:auto;overflow-y:hidden;
  padding:8px 12px 14px;scrollbar-width:none}
.rail::-webkit-scrollbar{display:none}
.grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(var(--card-w),1fr));
  gap:24px var(--gap);padding:8px 12px 14px}
/* 격자의 마지막 칸은 판 가장자리가 오른쪽 끝을 넘어간다 — 칸 안에서 끊기게 */
.grid .card-art{overflow:visible}
.grid .card:last-child .card-disc,.rail .card:last-child .card-disc{right:-6px}

/* ── 라디오 스테이션 ── */
.station{display:flex;align-items:center;gap:14px;width:100%;padding:12px;
  border-radius:16px;background:var(--surface2);text-align:left;
  transition:background .15s var(--ease), transform .12s var(--ease)}
.station:hover{background:var(--surface)}
.station:active{transform:scale(.99)}
.st-disc{position:relative;width:64px;height:64px;flex:none;border-radius:50%;overflow:hidden;
  box-shadow:0 6px 18px rgba(0,0,0,.5), inset 0 0 0 1px rgba(255,255,255,.07)}
.st-disc img,.st-disc .art-none{width:100%;height:100%;object-fit:cover;display:block;
  background:var(--surface)}
.st-disc::after{content:'';position:absolute;left:50%;top:50%;width:12px;height:12px;
  margin:-6px 0 0 -6px;border-radius:50%;background:var(--bg);
  box-shadow:0 0 0 1px rgba(255,255,255,.12)}
.st-txt{min-width:0;display:flex;flex-direction:column;gap:3px}
.st-t{font-size:15px;font-weight:700;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.st-s{font-size:12.5px;color:var(--text2);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.st-rail .station{width:270px;flex:none}

/* ── 빈 상태 ── */
.empty{display:flex;flex-direction:column;align-items:center;gap:14px;
  padding:56px 24px;text-align:center}
.empty-art{width:74px;height:74px;border-radius:50%;
  background:radial-gradient(circle at 50% 50%,#232327 0 20%,#131315 21% 100%);
  box-shadow:inset 0 0 0 1px rgba(255,255,255,.06)}
.empty-t{font-size:14px;line-height:1.65;color:var(--text2)}
.empty-btn{padding:10px 18px;border-radius:14px;background:var(--text);color:#000;
  font-size:13.5px;font-weight:700}
.empty-btn:hover{opacity:.85}

/* ── 골격 ── */
.skel-card{flex:none;width:var(--card-w);height:var(--card-w);border-radius:10px;
  background:var(--surface2);animation:pulse 1.3s ease-in-out infinite}
.skel-rows{display:flex;flex-direction:column;gap:10px;padding:6px 12px}
.skel-row{height:var(--trk-art);border-radius:10px;background:var(--surface2);
  animation:pulse 1.3s ease-in-out infinite}

@media (max-width:520px){
  :root{--card-w:132px;--trk-art:46px}
  .sec-h{padding:0 4px 10px}
  .rail,.grid{padding-left:4px;padding-right:4px}
  .trk{padding:0}
}

/* ── 장르 색 ──
 * 장르 타일·칩·스테이션이 전부 회색이라 로딩 중인 것처럼 보였다.
 * 장르마다 고정 색을 준다(같은 장르는 어디서든 같은 색이라 눈에 익는다). */
[data-genre="K-팝"],[data-hgenre="K-팝"],[data-gradio="K-팝"]{--gc1:#ff5f8f;--gc2:#7b3bff}
[data-genre="힙합"],[data-hgenre="힙합"],[data-gradio="힙합"]{--gc1:#ffb03a;--gc2:#c8461f}
[data-genre="R&B"],[data-hgenre="R&B"],[data-gradio="R&B"]{--gc1:#8f6bff;--gc2:#3a2b7a}
[data-genre="발라드"],[data-hgenre="발라드"],[data-gradio="발라드"]{--gc1:#5fa8ff;--gc2:#274a8f}
[data-genre="댄스"],[data-hgenre="댄스"],[data-gradio="댄스"]{--gc1:#25e0c0;--gc2:#0f7a8f}
[data-genre="록"],[data-hgenre="록"],[data-gradio="록"]{--gc1:#ff4d4d;--gc2:#5a1414}
[data-genre="인디"],[data-hgenre="인디"],[data-gradio="인디"]{--gc1:#9fd35c;--gc2:#2f6b3a}
[data-genre="일렉트로닉"],[data-hgenre="일렉트로닉"],[data-gradio="일렉트로닉"]{--gc1:#39c6ff;--gc2:#6b2bd6}
[data-genre="팝"],[data-hgenre="팝"],[data-gradio="팝"]{--gc1:#ff8bd0;--gc2:#8f2f7a}
[data-genre="J-팝"],[data-hgenre="J-팝"],[data-gradio="J-팝"]{--gc1:#ffd166;--gc2:#c2456b}
[data-genre="OST"],[data-hgenre="OST"],[data-gradio="OST"]{--gc1:#c9b18c;--gc2:#4a3b28}
[data-genre="재즈"],[data-hgenre="재즈"],[data-gradio="재즈"]{--gc1:#e0a45c;--gc2:#3a2a1c}
/* 값이 없을 때만 쓰는 기본값. :where 는 우선순위가 0이라 위의 장르 색을 덮지 않는다
   (평범하게 쓰면 뒤에 있는 이 규칙이 이겨서 전부 회색이 된다 — 실측). */
:where(.cat,.gchip,.gstation){--gc1:#8a8a92;--gc2:#3a3a42}

/* 검색 첫 화면 · 보관함에서 쓰는 작은 조각들 */
.chips{gap:8px}
.qchip{display:inline-flex;align-items:center;flex:none;border-radius:16px;background:var(--surface2)}
.qchip button{padding:8px 6px 8px 14px;font-size:13px;font-weight:600;color:var(--text)}
.qchip .qx{padding:8px 12px 8px 4px;color:var(--text2);font-size:15px}
.qchip .qx:hover{color:var(--text)}
.cat{position:relative;aspect-ratio:16/10;border-radius:13px;overflow:hidden;
  display:flex;align-items:flex-end;padding:13px;
  background:linear-gradient(135deg,var(--gc1),var(--gc2));
  transition:transform .14s var(--ease), filter .14s var(--ease)}
.cat:hover{transform:translateY(-2px);filter:brightness(1.12)}
/* 판이 반쯤 걸친 모습 — 장르 타일에도 LP 결을 남긴다 */
.cat::after{content:'';position:absolute;right:-22px;top:50%;width:74px;height:74px;
  margin-top:-37px;border-radius:50%;
  background:radial-gradient(circle at 50% 50%,rgba(0,0,0,.55) 0 19%,rgba(0,0,0,.28) 20% 100%);
  box-shadow:inset 0 0 0 1px rgba(255,255,255,.14)}
.cat-n{position:relative;z-index:1;font-size:15px;font-weight:800;letter-spacing:-.02em;
  color:#fff;text-shadow:0 1px 8px rgba(0,0,0,.35)}
.card-new .art-none{display:flex;align-items:center;justify-content:center;
  font-size:30px;font-weight:300;color:var(--text2)}
/* 좋아하는 곡 — 회색 네모 한가운데 판 하나 */
.disc-mark{position:relative;display:block}
.disc-mark::before{
  content:'';position:absolute;left:50%;top:50%;width:62%;height:62%;
  transform:translate(-50%,-50%);border-radius:50%;
  background:
    radial-gradient(circle at 50% 50%, var(--surface2) 0 15%, transparent 16%),
    radial-gradient(circle at 50% 50%, rgba(255,255,255,.05) 0 17%, transparent 18%),
    conic-gradient(from 210deg, #2b2b30, #191920 25%, #33333a 50%, #191920 75%, #2b2b30);
  box-shadow:inset 0 0 0 1px rgba(255,255,255,.07), 0 4px 14px rgba(0,0,0,.45);
}
.disc-mark::after{
  content:'';position:absolute;left:50%;top:50%;width:8%;height:8%;
  transform:translate(-50%,-50%);border-radius:50%;background:var(--bg);
  box-shadow:0 0 0 1px rgba(255,255,255,.12);
}
.card-liked .card-disc{display:none}
/* 스테이션 판에도 장르 색을 입힌다 — 가운데 홈은 그대로 둔다 */
.gstation .gdisc{background:
  radial-gradient(circle at 50% 50%,rgba(0,0,0,.9) 0 19%,transparent 20%),
  linear-gradient(135deg,var(--gc1),var(--gc2))}
.gstation{background:linear-gradient(120deg,color-mix(in srgb,var(--gc1) 16%,var(--surface2)),var(--surface2))}
.gstation:hover{background:linear-gradient(120deg,color-mix(in srgb,var(--gc1) 26%,var(--surface2)),var(--surface2))}
/* 지금 이 스테이션이 재생 중이면 확실히 구분되게 */
.station.on{box-shadow:inset 0 0 0 1.5px var(--accent)}
.station.on .st-t::after{content:' · 재생 중';font-size:11.5px;color:var(--accent);font-weight:700}
.gstation{padding:10px}

/* ── 상세 페이지 머리 ── */
.hero{display:flex;gap:26px;align-items:flex-end;padding:14px 12px 26px}
.hero-art{position:relative;flex:none;width:200px;height:200px}
.hero-art img,.hero-art .art-none{width:100%;height:100%;border-radius:12px;object-fit:cover;
  background:var(--surface2);display:block;position:relative;z-index:1;
  box-shadow:0 18px 44px rgba(0,0,0,.55)}
.hero-disc{position:absolute;top:7%;right:-16px;width:86%;height:86%;border-radius:50%;z-index:0;
  background:radial-gradient(circle at 50% 50%,#2a2a2e 0 20%,#141416 21% 100%);
  box-shadow:inset 0 0 0 1px rgba(255,255,255,.06)}
.hero.round .hero-art img,.hero.round .hero-art .art-none{border-radius:50%}
.hero-txt{flex:1;min-width:0;padding-bottom:6px}
.hero-t{font-size:32px;font-weight:800;letter-spacing:-.035em;line-height:1.15;
  word-break:keep-all}
.hero-s{margin-top:8px;font-size:15px;font-weight:600}
.hero-link{font-size:15px;font-weight:600;color:var(--text)}
.hero-link:hover{text-decoration:underline;text-underline-offset:3px}
.hero-m{margin-top:5px;font-size:12.5px;color:var(--text2)}
.hero-acts{display:flex;gap:9px;margin-top:18px}
@media (max-width:640px){
  .hero{flex-direction:column;align-items:center;text-align:center;gap:18px;padding-top:8px}
  .hero-art{width:min(64vw,240px);height:min(64vw,240px)}
  .hero-t{font-size:24px}
  .hero-acts{justify-content:center}
  .hero-disc{right:-12px}
}

/* 앨범 상세의 트랙 번호 — 표지 자리를 대신한다 */
.trk-n{width:var(--trk-art);flex:none;text-align:center;font-size:13px;color:var(--text2);
  font-variant-numeric:tabular-nums}

/* 보관함 도구 — 정렬 · 보기 전환 */
.libtools{display:flex;align-items:center;gap:7px;padding:0 12px 12px}
.lt-btn{padding:7px 13px;border-radius:12px;background:var(--surface2);
  font-size:12.5px;font-weight:700;color:var(--text2);transition:.14s var(--ease)}
.lt-btn:hover{color:var(--text)}
.lt-btn.ico{width:34px;height:32px;padding:0;display:inline-flex;align-items:center;justify-content:center}
.lt-btn.ico svg{width:16px;height:16px}
.lt-btn.on{background:var(--text);color:#000}
@media (max-width:520px){.libtools{padding-left:4px;padding-right:4px}}

/* 앨범 이야기 — 곡 이야기 카드와 같은 결로 */
.albumstory{padding:0 12px 6px;font-size:14.5px;line-height:1.75;
  color:rgba(255,255,255,.82);word-break:keep-all;max-width:760px}
@media (max-width:520px){.albumstory{padding-left:4px;padding-right:4px;font-size:14px}}

/* 약관·정책 */
.legal{padding:4px 12px 40px;max-width:720px}
.legal h4{font-size:14.5px;font-weight:700;margin:28px 0 9px;letter-spacing:-.02em;
  color:var(--text)}
.legal-lead{font-size:13.5px;line-height:1.8;color:var(--text2);
  padding-bottom:18px;border-bottom:1px solid var(--hair);margin-bottom:6px}
.legal h4:first-child{margin-top:6px}
.legal p{font-size:14px;line-height:1.8;color:rgba(255,255,255,.78);word-break:keep-all}
.legal b{color:var(--text)}
.legal-t{width:100%;border-collapse:collapse;margin:10px 0 4px;font-size:13px}
.legal-t th,.legal-t td{text-align:left;padding:9px 10px;border-bottom:1px solid var(--hair);
  color:rgba(255,255,255,.78);vertical-align:top}
.legal-t th{color:var(--text2);font-weight:700;font-size:12px}
.legal-note{display:block;margin-top:4px;font-size:11.5px;line-height:1.6;
  color:var(--text2);font-weight:400}
.legal-foot{margin-top:32px;padding-top:16px;border-top:1px solid var(--hair);
  font-size:12.5px;color:var(--text2)}
.legal-foot a{color:var(--accent)}
.acct-legal{margin-top:16px;font-size:12px;color:var(--text2);text-align:center}
.acct-legal button{font-size:12px;color:var(--text2);text-decoration:underline;
  text-underline-offset:2px}
.acct-legal button:hover{color:var(--text)}
.ha-btn.danger{background:transparent;color:#ff6b6b;
  box-shadow:inset 0 0 0 1px rgba(255,107,107,.3)}
.ha-btn.danger:hover{background:rgba(255,107,107,.12)}

/* 복구 코드 */
.reccode{margin:18px 0 12px;padding:16px;border-radius:12px;background:var(--surface2);
  font-size:19px;font-weight:700;letter-spacing:.08em;text-align:center;
  font-variant-numeric:tabular-nums;user-select:all}
.recchk{display:flex;align-items:center;gap:9px;margin:14px 0 4px;
  font-size:13.5px;color:var(--text2);cursor:pointer}
.recchk input{width:17px;height:17px;accent-color:var(--accent)}
#acctCode{letter-spacing:.06em}

/* 쿼터 현황 */
.qmeter{height:10px;border-radius:5px;background:var(--surface2);overflow:hidden;margin:12px 0 10px}
.qmeter span{display:block;height:100%;background:var(--accent);transition:width .4s var(--ease)}
.qchart{display:flex;align-items:flex-end;gap:8px;height:140px;margin:12px 0 6px;
  padding:0 2px}
.qbar{flex:1;display:flex;flex-direction:column;justify-content:flex-end;align-items:center;
  height:100%;gap:7px}
.qbar span{display:block;width:100%;border-radius:5px 5px 2px 2px;background:var(--accent);
  opacity:.75;min-height:2px}
.qbar:last-child span{opacity:1}
.qbar em{font-size:10.5px;font-style:normal;color:var(--text2)}

/* ── 아래에서 올라오는 시트 ──
   '다음 재생'을 탭으로 넘기면 판이 사라져 지금 뭘 듣고 있었는지 감각이 끊긴다.
   곡 이야기처럼 재생 화면 위로 올라오게 한다.
   여닫는 동작은 hidden 을 껐다 켰다 하면 순간이동이 되므로, 항상 자리에 두고
   transform 만 움직인다(.on 이 붙으면 올라온다). */
.upsheet{
  position:fixed;inset:0;z-index:82;
  display:flex;align-items:flex-end;justify-content:center;
  background:rgba(0,0,0,0);backdrop-filter:blur(0px);
  transition:background .28s var(--ease), backdrop-filter .28s var(--ease),
             visibility 0s linear .32s;
  visibility:hidden;
}
.upsheet.on{
  background:rgba(0,0,0,.55);backdrop-filter:blur(14px);
  visibility:visible;transition-delay:0s;
}
.up-card{
  width:min(680px,100%);max-height:min(76vh,760px);
  display:flex;flex-direction:column;
  background:#141417;border-radius:20px 20px 0 0;
  box-shadow:0 -18px 60px rgba(0,0,0,.6);
  transform:translateY(100%);
  transition:transform .32s var(--ease);
}
.upsheet.on .up-card{transform:translateY(0)}
.up-bar{
  position:relative;flex:none;padding:16px 18px 10px;
  display:flex;align-items:center;justify-content:center;
}
.up-grip{
  position:absolute;top:7px;left:50%;transform:translateX(-50%);
  width:38px;height:4px;border-radius:2px;background:rgba(255,255,255,.22);
}
.up-title{font-size:15px;font-weight:700}
.up-bar .info-x{position:absolute;right:12px;top:12px}
.up-body{flex:1;min-height:0;overflow-y:auto;padding:0 12px 22px;scrollbar-width:none}
.up-body::-webkit-scrollbar{display:none}

/* 곡 이야기도 같은 결로 — 뜨고 사라지는 순간이 뚝 끊기지 않게.
   [hidden]{display:none!important} 이 이기므로 hidden 속성 대신 .on 으로 여닫는다. */
.info{
  opacity:0;visibility:hidden;pointer-events:none;
  transition:opacity .24s var(--ease), visibility 0s linear .26s;
  animation:none;
}
.info.on{opacity:1;visibility:visible;pointer-events:auto;transition-delay:0s}
.info .info-card{transform:translateY(16px);opacity:0;
  transition:transform .28s var(--ease), opacity .28s var(--ease);animation:none}
.info.on .info-card{transform:translateY(0);opacity:1}

/* ── 여닫는 동작을 전부 부드럽게 ──
   버튼을 눌렀을 때 화면이 툭 바뀌면 무엇이 무엇으로 변했는지 눈이 못 따라간다.
   나타나는 것과 사라지는 것에 같은 시간을 준다. */
/* hidden 속성으로 여닫으면 display 가 함께 바뀌어 전환이 통째로 날아간다.
   .info · .upsheet 와 같이 .on 클래스로 통일한다. */
.menu{
  transform-origin:100% 100%;animation:none;
  opacity:0;visibility:hidden;pointer-events:none;
  transform:scale(.94) translateY(6px);
  transition:opacity .18s var(--ease), transform .18s var(--ease),
             visibility 0s linear .18s;
}
.menu.on{opacity:1;visibility:visible;pointer-events:auto;transform:none;transition-delay:0s}

/* 큐·상세·약관 같은 큰 화면은 살짝 떠오르며 들어온다 */
.tabpane:not([hidden]) > .lib-body{animation:lyrup .26s var(--ease)}

/* 토스트도 같은 결로 */
.toast{transition:opacity .2s var(--ease), transform .2s var(--ease)}

/* 로그인해야 들을 수 있다는 안내 — 창을 왜 만났는지 한 줄로 */
.acct-why{margin:2px 0 12px;font-size:12.5px;line-height:1.5;color:var(--text2)}

/* ── 로그인 전 첫 화면 ──
   계정이 없으면 곡을 아예 안 보여준다. 화면 전체를 불투명하게 덮는다.
   계정 창(z 80)보다 아래, 나머지 전부보다 위에 둔다. */
.gate{
  position:fixed;inset:0;z-index:70;
  display:flex;align-items:center;justify-content:center;gap:min(7vw,80px);
  padding:32px;background:#08080a;overflow:hidden;
}
.gate::before{                       /* 판 색이 번지는 배경 */
  content:'';position:absolute;inset:-20%;
  background:
    radial-gradient(40% 40% at 22% 38%, rgba(178,62,50,.22), transparent 70%),
    radial-gradient(45% 45% at 78% 66%, rgba(58,64,120,.20), transparent 70%);
  filter:blur(30px);
}
.gate-disc{
  position:relative;flex:none;width:min(38vw,300px);height:min(38vw,300px);
  border-radius:50%;
  background:
    repeating-radial-gradient(circle at 50% 50%,rgba(255,255,255,.05) 0 1px,transparent 1px 4px),
    radial-gradient(circle at 34% 26%,rgba(255,255,255,.10),transparent 52%),
    #121214;
  box-shadow:0 30px 80px rgba(0,0,0,.6);
  animation:gspin 14s linear infinite;
}
.gate-disc i{
  position:absolute;left:50%;top:50%;transform:translate(-50%,-50%);
  width:34%;height:34%;border-radius:50%;
  background:radial-gradient(circle at 38% 30%,#c2513f,#8d2f24);
}
.gate-disc i::after{
  content:'';position:absolute;left:50%;top:50%;transform:translate(-50%,-50%);
  width:9%;height:9%;border-radius:50%;background:#08080a;
}
@keyframes gspin{to{transform:rotate(360deg)}}

.gate-txt{position:relative;max-width:380px}
.gate-logo{font-size:26px;font-weight:700;letter-spacing:.34em;margin:0 0 18px}
.gate-tag{font-size:clamp(26px,4.4vw,40px);font-weight:700;line-height:1.28;
  letter-spacing:-.02em;margin:0 0 14px}
.gate-sub{font-size:14px;line-height:1.6;color:var(--text2);margin:0 0 28px}
.gate-acts{display:flex;gap:10px;flex-wrap:wrap}
.gate-btn{
  padding:13px 22px;border-radius:24px;font-size:14.5px;font-weight:600;
  background:var(--surface2);transition:.18s var(--ease);
}
.gate-btn:hover{background:rgba(255,255,255,.2)}
.gate-btn.go{background:var(--text);color:#08080a}
.gate-btn.go:hover{background:#fff}
.gate-legal{margin:26px 0 0;font-size:12px;color:var(--text2)}
.gate-legal button{color:var(--text2);text-decoration:underline;text-underline-offset:3px}
.gate-legal button:hover{color:var(--text)}

@media (max-width:760px){
  .gate{flex-direction:column;justify-content:center;text-align:center;gap:34px}
  .gate-disc{width:min(52vw,220px);height:min(52vw,220px)}
  .gate-acts{justify-content:center}
}
/* 첫 화면이 떠 있는 동안에는 뒤에서 아무것도 굴러가지 않게 */
body.gated .tabbar,body.gated .mini{display:none}

/* 곡 줄의 가수·앨범 — 누를 수 있다는 걸 알아채게 */
.sub-l{cursor:pointer;border-radius:4px;transition:color .15s var(--ease)}
.sub-l:hover{color:var(--text);text-decoration:underline;text-underline-offset:2px}

/* 재생 화면의 가수·앨범도 누를 수 있다 — 목록과 같은 표시 */
.meta .sub-l:hover{color:var(--text)}

/* 곡 이야기 닫기 버튼 — 카드가 스크롤 칸(overflow:auto)이라 이름표가 위로 나가면
   카드 경계에서 잘린다. 아래·왼쪽으로 펴서 카드 안에 들어오게 한다. */
.info-x[data-tip]::before{
  bottom:auto;top:calc(100% + 8px);
  left:auto;right:0;transform:translateX(0) translateY(-3px);
}
.info-x[data-tip]:hover::before,.info-x[data-tip]:focus-visible::before{
  transform:translateX(0) translateY(0);
}

/* ── 약관·개인정보처리방침은 혼자 서는 문서 ──
   앱 화면 안의 한 칸이 아니라 문서 한 장으로 둔다. 로그인 전에도 봐야 하므로
   첫 화면(z 70)보다 위에 오고, 사이드바·탭바·재생바를 모두 덮는다. */
body.doc-open .tabbar,
body.doc-open .mini{display:none !important}
/* #page 는 .browse(z:20) 안에 있다. 그 안에서 z를 아무리 올려도 바깥의 첫 화면(z:70)을
   못 이긴다 — 쌓임 맥락은 조상 단위로 갈린다. 담는 그릇째 올려야 한다(실측으로 확인). */
body.doc-open .browse{z-index:95}
body.doc-open #page{
  position:fixed;inset:0;z-index:90;
  background:var(--bg);
  display:flex;flex-direction:column;
  animation:fade .2s var(--ease);
}
body.doc-open #page .lib-bar{
  flex:none;justify-content:flex-start;gap:10px;
  /* 화면 전체를 덮으므로 노치·상태바 자리를 직접 비켜야 한다.
     안 비키면 뒤로 버튼이 상태바 밑에 깔려 눌리지 않는다(실측). */
  padding:max(14px,env(safe-area-inset-top)) max(18px,env(safe-area-inset-left))
          14px max(18px,env(safe-area-inset-right));
  border-bottom:1px solid var(--hair);
  background:rgba(10,10,12,.92);backdrop-filter:blur(18px);
}
/* 뒤로 버튼은 손가락으로 눌러야 한다 — 과녁을 넉넉히 */
body.doc-open #page .lib-bar .back{
  min-width:40px;min-height:40px;display:flex;align-items:center;justify-content:center;
  margin-left:-8px;font-size:24px;line-height:1;
}
body.doc-open #page .lib-body{
  flex:1;min-height:0;overflow-y:auto;
  -webkit-overflow-scrolling:touch;
  padding:26px max(22px,env(safe-area-inset-left))
          calc(60px + env(safe-area-inset-bottom)) max(22px,env(safe-area-inset-right));
}
/* 글줄이 길면 눈이 줄을 놓친다 — 가운데로 모으고 폭을 묶는다 */
body.doc-open .legal{max-width:640px;margin:0 auto;padding:0}
body.doc-open .legal h4{margin-top:32px}
body.doc-open .legal p{font-size:14.5px;line-height:1.85}

@media (min-width:900px){
  body.doc-open #page .lib-bar{padding:16px 28px}
  body.doc-open #page .lib-body{padding:34px 28px 80px}
}

/* 보관함 맨 아래 약관 링크 — 눈에 띄지 않되 찾으면 있는 자리 */
.lib-foot{display:flex;gap:16px;justify-content:center;flex-wrap:wrap;
  margin:34px 0 8px;padding-top:20px;border-top:1px solid var(--hair)}
.lib-foot button{font-size:12.5px;color:var(--text2);
  text-decoration:underline;text-underline-offset:3px}
.lib-foot button:hover{color:var(--text)}

/* 판 번호 — 옛 화면을 보고 있는지 눈으로 확인하는 용도 */
.build{margin-left:8px;font-size:11px;color:rgba(255,255,255,.28);letter-spacing:.04em}

/* ── 모바일 여백 ──
   가장자리에 12px 만 두었더니 글자가 화면 끝에 붙어 답답했다.
   손가락으로 잡는 화면은 여백이 곧 읽기 편함이다. 좌우를 넓히고
   위아래로도 숨 쉴 자리를 준다. */
@media (max-width:760px){
  .lib-body,.tabpane > .lib-body{
    padding-left:max(18px,env(safe-area-inset-left));
    padding-right:max(18px,env(safe-area-inset-right));
    padding-top:14px;
  }
  .sec{margin-bottom:26px}
  .sec-h{padding-left:2px;padding-right:2px}
  .rail{gap:12px;padding-left:2px;padding-right:2px}
  .grid{gap:12px}
  .trk{padding-left:2px;padding-right:2px}
  .home-hero{padding:10px 2px 4px}
  .field{margin-left:2px;margin-right:2px}
  /* 마지막 줄이 탭바에 가려지지 않게 */
  .lib-body{padding-bottom:calc(var(--tabh) + 22px + env(safe-area-inset-bottom) * 0.28)}
}
