/*
|--------------------------------------------------------------------------
| app.css — search_song.php 에서 떼어낸 화면 스타일
|--------------------------------------------------------------------------
| 곡 페이지가 6만 장인데 같은 스타일 40KB 가 장마다 실려 나갔다.
| 밖으로 빼면 브라우저와 크롤러가 한 번만 받고 이후로는 캐시를 쓴다.
|
| 파일이 바뀌면 <link> 의 ?v= 값(수정시각)이 바뀌어 주소가 달라진다.
| 그래서 1년 캐시를 걸어도 낡은 스타일이 남지 않는다.
|--------------------------------------------------------------------------
*/

/*
|--------------------------------------------------------------------------
| Apple 디자인 언어 (라이트 모드)
|--------------------------------------------------------------------------
| - apple.com 스타일: #f5f5f7 배경 + 화이트 카드 + 은은한 그림자
| - Apple 시스템 컬러: #007aff(블루), #af52de(퍼플), #ff9500(오렌지)
| - 헤어라인 보더, 절제된 그림자, 부드러운 트랜지션
|--------------------------------------------------------------------------
*/

*, *::before, *::after { box-sizing: border-box; }

:root { /* 색은 theme.css 로 옮겼다 — 모든 화면이 그 파일을 먼저 읽는다 */ }

html, body {
    margin: 0; padding: 0; width: 100%;
    overflow-x: hidden;
    background: var(--bg);
    font-family: 'Pretendard', -apple-system, BlinkMacSystemFont, 'Apple SD Gothic Neo', sans-serif;
    color: var(--label);
    -webkit-text-size-adjust: 100%;
    -webkit-font-smoothing: antialiased;
}

.container {
    width: 100%; max-width: 680px;
    margin: 0 auto;
    padding: 8px 16px 56px;   /* 위쪽은 최상단 줄(홈·즐겨찾기)이 바로 오므로 좁게 */
}

/* ── 헤더 ── */

/* 앱 홍보 배너 (최상단) */
.top-banner { margin: 0 -4px 14px; cursor: pointer; -webkit-tap-highlight-color: transparent; }
.top-banner:active { opacity: 0.92; }
.top-banner:focus-visible { outline: 2px solid var(--blue); outline-offset: 3px; border-radius: var(--radius-m); }
.top-banner img,
.top-banner picture {
    display: block; width: 100%; height: auto;
    /*
    | 비율은 search_song.php 가 이미지 파일에서 읽어 인라인으로 준다.
    | 여기 숫자를 박아 두면 배너를 갈 때마다 늘어나 보인다 (실제로 그랬다 —
    | 650x244 로 굳어 있어서 650x156 배너가 세로로 늘어났다).
    | 값이 안 오면 아래 기본값으로 버틴다.
    */
    aspect-ratio: var(--banner-ratio, 650 / 244);
    border-radius: var(--radius-m);
    box-shadow: var(--card-shadow);
}
@media (max-width: 620px) { .top-banner { margin: 0 -4px 11px; } }

.search-box {
    position: sticky; top: 0;
    background: var(--glass);
    -webkit-backdrop-filter: saturate(180%) blur(20px);
    backdrop-filter: saturate(180%) blur(20px);
    padding-bottom: 10px;
    margin: 0 -16px; padding-left: 16px; padding-right: 16px;
    z-index: 100;
}

.header-row {
    display: flex; align-items: center;
    justify-content: space-between;
    gap: 12px;
    padding: 10px 0 14px;
}

.logo {
    display: inline-flex; align-items: center; gap: 7px;
    font-size: 21px; font-weight: 700;
    letter-spacing: -0.5px;
    color: var(--label);
    white-space: nowrap; flex-shrink: 0;
    text-decoration: none; cursor: pointer;
    -webkit-tap-highlight-color: transparent;
}

/* iOS 세그먼티드 컨트롤 */
.logo-ico { width: 26px; height: 26px; flex-shrink: 0; }

.sec-head {
    margin: 20px 0 10px; padding: 0 2px;
    font-size: 15.5px; font-weight: 700; letter-spacing: -0.3px; color: var(--label);
}
.sec-head span { font-size: 12.5px; font-weight: 500; color: var(--label-3); margin-left: 6px; }
.also-list { display: grid; grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); gap: 7px; }
/* 주제 이름은 곡 제목보다 길다.
   3열로 넓히고, 넘치면 자르지 말고 두 줄로 흐르게 한다. */
/* 목록 페이지 이동 */
.pager {
    display: flex; flex-wrap: wrap; align-items: center; justify-content: center;
    gap: 6px; margin: 18px 0 4px;
}
.pg {
    display: inline-flex; align-items: center; justify-content: center;
    min-width: 34px; height: 34px; padding: 0 10px;
    border: 1px solid var(--hairline); border-radius: 10px;
    background: var(--surface); color: var(--label-2);
    font-size: 13.5px; font-weight: 500; text-decoration: none;
    transition: all 0.15s var(--ease); -webkit-tap-highlight-color: transparent;
}
.pg:hover { background: var(--surface-2); color: var(--label); }
.pg-now {
    background: var(--blue-fill); border-color: var(--blue-line);
    color: var(--blue); font-weight: 700;
}
.pg-gap { color: var(--label-3); padding: 0 2px; }

.also-cell .ac-n {
    flex-shrink: 0; margin-left: auto;
    font-size: 11px; font-weight: 600; color: var(--label-3);
    font-family: 'Roboto', sans-serif;
}

/*
| 주제 이름 뒤의 곡 수 — '(59)'.
| .ac-n 은 오른쪽 끝으로 띄우는 모양이라 가운데 정렬한 주제 칸과 맞지 않는다.
| 괄호는 CSS 로 두른다 — 읽어 주는 기계에는 숫자만 들린다.
*/
.th-n {
    margin-left: 4px; font-size: 0.85em; font-weight: 600;
    color: var(--label-3); font-family: 'Roboto', sans-serif;
}
.th-n::before { content: '('; }
.th-n::after  { content: '곡)'; }   /* '(10)' 만으로는 무엇의 수인지 안 읽힌다 — '(10곡)' (2026-09-14) */

.theme-grid { grid-template-columns: repeat(3, 1fr) !important; }
/*
| 갈래 들머리의 펼친 카드 (그룹사운드처럼 하위 주제가 서너 개일 때)
|
| 격자(.theme-grid)와 달리 한 줄에 하나씩 세로로 쌓는다. 안내문이 두 줄쯤
| 되므로 두 칸으로 나누면 좁은 화면에서 글이 계단처럼 끊긴다.
|
| 이름·부제·안내문 세 줄의 굵기와 색을 뚜렷이 벌려 둔다 — 셋이 비슷하면
| 어디까지가 제목인지 눈이 매번 다시 재야 한다.
*/
.theme-cards { display: grid; gap: 9px; }
.theme-card {
    display: block; padding: 13px 15px 14px; text-decoration: none;
    background: var(--surface); border: 1px solid var(--line);
    border-radius: var(--radius-m); box-shadow: var(--card-shadow);
    transition: background 0.15s, border-color 0.15s;
}
.theme-card:hover { background: var(--surface-hover); border-color: var(--blue); }
.tc-head { display: flex; align-items: baseline; gap: 6px; }
.tc-name {
    font-size: 16px; font-weight: 700; color: var(--label);
    letter-spacing: -0.4px; word-break: keep-all;
}
/* 곡 수는 .th-n 이 '(27곡)' 로 그린다 — 0.85em 이라 기준 크기를 여기서 준다 */
.tc-cnt { flex: none; margin-left: auto; font-size: 14px; }
.tc-sub {
    margin-top: 3px;
    font-size: 13px; font-weight: 600; color: var(--blue);
    letter-spacing: -0.3px; word-break: keep-all;
}
.tc-desc {
    margin: 5px 0 0;
    font-size: 13px; line-height: 1.55; color: var(--label-3);
    letter-spacing: -0.3px; word-break: keep-all;
}

/*
| 표지가 붙은 펼친 카드 (2026-09-10)
|
| 안쪽을 span 으로 바꿨다 — a 안에 블록을 넣어도 되지만, 표지와 글을
| 좌우로 세우려면 어차피 display 를 다 지정해야 해서 한 가지로 통일했다.
| 그래서 여기서 display 를 반드시 준다. 빠뜨리면 여백이 통째로 안 먹는다.
*/
.tc-body { display: block; min-width: 0; flex: 1 1 auto; }
.tc-head, .tc-sub, .tc-desc { display: block; }
.tc-head { display: flex; }
.theme-card.has-cover { display: flex; align-items: flex-start; gap: 13px; }
/*
| 왼쪽 썸네일 = 재생 단추 (2026-09-15, 팝업 재생). 공용 .mv-facade 의 폭·최소 높이를 푼다.
| 128×72 — 유튜브 규정(재생을 시작하는 썸네일 120×70 이상). 폰에서도 좌우로 둔다.
*/
.tc-cover.mv-facade {
    flex: 0 0 auto; width: 128px; min-height: 0; aspect-ratio: 16 / 9;
    border-radius: 10px; margin-top: 2px;
}
.tc-cover .mv-play {
    left: auto; top: auto; right: 5px; bottom: 5px; transform: none;
    width: 30px; height: 22px; border-radius: 6px; --tri: 5px;   /* 반 픽셀이 생기면 세모가 1px 내려앉는다 — 짝수 여백으로 */
}
a.tc-body { text-decoration: none; color: inherit; -webkit-tap-highlight-color: transparent; }
.tc-song {
    display: block; margin-top: 6px;
    font-size: 12px; color: var(--label-3); letter-spacing: -0.2px; line-height: 1.4; word-break: keep-all;
}
.tc-song b { font-weight: 700; font-size: 11px; opacity: 0.7; }
.tc-song b::after { content: ':'; margin-right: 4px; }
.tc-song i { font-style: normal; opacity: 0.75; }
/*
| 갈래 카드 새 구성 (2026-09-15 저녁) — 이름·소개 / 구분선 / [썸네일 | 설명] / 대표곡.
| 썸네일은 폰에서 카드 폭의 절반(규정 120×70 이상), 넓은 화면에서는 260px.
| 세 덩이가 따로 눌리므로 카드 자체의 hover 반응은 끈다.
*/
.theme-card.tc2 { padding: 13px 15px 13px; }
.theme-card.tc2:hover { background: var(--surface); border-color: var(--line); }
.tc2-top { display: block; text-decoration: none; color: inherit; -webkit-tap-highlight-color: transparent; }
.tc2-top .tc-sub { display: block; }
.tc2-mid {
    display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: 12px; align-items: start;
    margin-top: 11px; padding-top: 12px; border-top: 1px solid var(--hairline);
}
.tc2-mid.no-cover { grid-template-columns: 1fr; }
.tc2-cover.mv-facade { width: 100%; min-height: 0; aspect-ratio: 16 / 9; border-radius: 10px; }
.tc2-desc {
    display: block; margin: 0; text-decoration: none;
    font-size: 13px; line-height: 1.55; color: var(--label-3); letter-spacing: -0.3px; word-break: keep-all;
}
.tc2-song {
    display: block; margin-top: 10px; text-decoration: none;
    font-size: 12.5px; color: var(--label-2); letter-spacing: -0.2px; line-height: 1.4; word-break: keep-all;
}
.tc2-song b { font-weight: 700; font-size: 11.5px; color: var(--label-3); }
.tc2-song b::after { content: ':'; margin-right: 5px; }
.tc2-song i { font-style: normal; color: var(--label-3); }
@media (min-width: 600px) { .tc2-mid { grid-template-columns: 260px minmax(0, 1fr); gap: 16px; } }
@media (hover: hover) and (pointer: fine) {
    .tc2-top:hover .tc-name, .tc2-desc:hover { color: var(--blue); }
    a.tc2-song:hover { color: var(--blue); }
}

/* 영상 팝업 (#mvSheet) — 플레이어는 폭을 다 쓴다. 곡 줄은 가수 시트의 .sgv-song 모양 */
.mv-sheet-slot { margin: 0 0 10px; }
.sgv-song[hidden] { display: none; }
/*
| 대표곡 플레이어가 붙은 갈래 카드 (2026-09-14, 남녀 인기곡·그룹사운드).
|
| 카드 자체는 링크가 아니다 — 플레이어가 링크 안에 들면 누를 때 재생과 이동이
| 엉킨다. 그래서 카드 테두리가 눌리는 것처럼 반응하지 않게 hover 를 되돌리고,
| 주제로 가는 길은 아래 줄(.tc-link) 한 곳에만 둔다.
| 플레이어 크기·모서리는 .mv-live .mv-frame 이 맡는다(최소 200px 규정 포함).
*/
.theme-card.has-player { display: block; padding: 12px 12px 0; overflow: hidden; }
.theme-card.has-player:hover { background: var(--surface); border-color: var(--line); }
.tc-live { margin: 0; }
.tc-rep {
    display: flex; align-items: baseline; flex-wrap: wrap; gap: 4px 7px;
    margin: 10px 2px 11px; font-size: 14px; letter-spacing: -0.3px; line-height: 1.4;
}
.tc-rep-tag {
    flex: none; align-self: center;
    padding: 2px 8px; border-radius: 999px;
    background: var(--fill); color: var(--label-2);
    font-size: 11px; font-weight: 700; letter-spacing: 0;
}
.tc-rep-s { color: var(--label-2); font-weight: 600; word-break: keep-all; }
.tc-rep-t { color: var(--label); font-weight: 800; text-decoration: none; word-break: keep-all; }
a.tc-rep-t:focus-visible { outline: 2px solid var(--blue); outline-offset: 2px; border-radius: 3px; }
.tc-link {
    display: flex; align-items: center; gap: 10px;
    margin: 0 -12px; padding: 12px 14px 13px 14px;
    border-top: 1px solid var(--line);
    text-decoration: none; color: inherit;
}
.tc-go { flex: none; font-size: 24px; line-height: 1; color: var(--label-3); }
.tc-link:focus-visible { outline: 2px solid var(--blue); outline-offset: -3px; border-radius: var(--radius-m); }
/*
| 플레이어가 아직 없는 카드 (2026-09-14 저녁) — 첫 카드만 플레이어를 심는다.
| 대표곡 줄이 카드 맨 위로 올라오므로 위 여백을 줄로 넘긴다. 단추를 누르면
| tc-idle 이 빠지고 원래 여백(12px)과 플레이어가 돌아온다.
| 단추는 줄 오른쪽 끝 — 제목이 길어 줄이 넘치면 다음 줄 오른쪽으로 내려간다.
*/
.theme-card.has-player.tc-idle { padding-top: 2px; }
/* 32px 단추가 줄을 키우면 baseline 글자는 위로 붙고 알약·단추만 가운데로 가 5px 어긋난다 — 단추가 있는 동안만 가운데 정렬 */
.theme-card.tc-idle .tc-rep { align-items: center; cursor: pointer; -webkit-tap-highlight-color: transparent; }
/* 단추는 모든 카드에 그려 두고 열린 카드에서만 숨긴다 — 닫히면 다시 보인다 (app.js tcPlay) */
.theme-card.has-player:not(.tc-idle) .tc-play { display: none; }
/*
| 카드를 여닫을 때 화면 위치는 app.js 가 직접 맞춘다 — 누른 카드가 손가락 밑에
| 그대로 있게. 브라우저의 스크롤 고정까지 겹치면 두 번 밀린다.
*/
.theme-cards { overflow-anchor: none; }
.tc-play {
    flex: none; align-self: center; margin-left: auto;
    display: inline-flex; align-items: center; gap: 5px;
    min-height: 32px; padding: 0 12px 0 10px;
    border: 1px solid var(--line); border-radius: 999px;
    background: var(--surface); color: var(--label);
    font: inherit; font-size: 12.5px; font-weight: 700; letter-spacing: -0.2px;
    cursor: pointer; -webkit-tap-highlight-color: transparent;
}
.tc-play-i { font-size: 9px; color: var(--blue); }
.tc-play:active { background: var(--surface-hover); }
.tc-play:focus-visible { outline: 2px solid var(--blue); outline-offset: 2px; }
@media (hover: hover) and (pointer: fine) {
    .tc-play:hover,
    .theme-card.tc-idle .tc-rep:hover .tc-play { background: var(--surface-hover); border-color: var(--blue); color: var(--blue); }
    /* 닫힌 카드의 곡 제목은 여는 자리라 링크처럼 밑줄을 긋지 않는다 */
    .theme-card.tc-idle a.tc-rep-t:hover { text-decoration: none; }
    a.tc-rep-t:hover { text-decoration: underline; text-underline-offset: 3px; }
    .tc-link:hover { background: var(--surface-hover); }
    .tc-link:hover .tc-name, .tc-link:hover .tc-go { color: var(--blue); }
}
/*
| 재생 단추 판 (2026-09-15, app.js mvFacadeHtml · search_song.php ssrMvFacade).
| 주제 목록의 영상 칸(.mv-box)과 같은 모양 — 그 영상의 썸네일 위에 반투명 재생 단추,
| 마우스를 올리면 단추가 빨개진다. 그림·단추 모양은 .mv-thumb · .mv-play 를 그대로 쓴다.
| 크기만 플레이어가 설 자리에 맞춘다 — 폭을 다 쓰고 16:9, 최소 200px.
*/
.mv-facade {
    position: relative; display: block;
    width: 100%; aspect-ratio: 16 / 9; min-height: 200px; padding: 0; margin: 0;
    border: 0; border-radius: var(--radius-m); overflow: hidden; cursor: pointer;
    background: #000; -webkit-tap-highlight-color: transparent;
}
.mv-facade .mv-thumb { position: absolute; inset: 0; }
.mv-facade:focus-visible { outline: 3px solid var(--blue); outline-offset: 2px; }
@media (hover: hover) and (pointer: fine) {
    .mv-facade:hover .mv-thumb { opacity: 1; }
    .mv-facade:hover .mv-play { background: #ff0000; }
}

/* 재생을 시작하기 전에는 띠를 숨긴다 — display 를 준 클래스라 [hidden] 을 따로 적는다 */
.mv-promo[hidden] { display: none; }

/*
| 좁은 화면에서도 좌우로 둔다 (2026-09-15, 사용자 요청) — 예전에는 420px 아래에서
| 썸네일을 위로 쌓았다. 대신 썸네일을 조금 줄여 글자 폭을 남긴다(120×68 은 규정
| 120×70 에 못 미쳐 안 된다 — 120px 폭이면 높이를 70 으로 둔다).
*/
@media (max-width: 420px) {
    .theme-card.has-cover { gap: 11px; }
    .tc-cover.mv-facade { width: 120px; aspect-ratio: auto; height: 70px; }
}

/*
|--------------------------------------------------------------------------
| 주제 격자 — 표지가 있는 타일 (2026-09-10)
|--------------------------------------------------------------------------
| 예전에는 이름과 곡 수만 있는 글자 칸이었다(.theme-grid .also-cell).
| 무엇을 고를지가 이름만으로 판가름났고, 네이버 검색 결과에서도 글자
| 덩어리로 나왔다. 대표곡의 유튜브 썸네일을 깔아 '아 그 노래' 가 먼저 오게 한다.
|
| 폭을 고정 3열이 아니라 auto-fill 로 둔다 — 옛 격자는 !important 로 3열을
| 못 박아 두었는데, 표지가 들어가면 좁은 화면에서 3열은 너무 작다.
| 150px 기준이면 폰에서 2열, 태블릿 3~4열, PC 5열로 알아서 접힌다.
*/
/*
|--------------------------------------------------------------------------
| 홈 맨 위의 주제 갈래 (2026-09-11)
|--------------------------------------------------------------------------
| 폰에서 두 칸, 넓어지면 네 칸. 몇 줄이면 끝나고 그 아래 TOP100 이 화면 안에
| 남는다 — 걷어내지 않고 위에 얹기만 하는 것이 요점이다.
*/
.home-topics { margin: 14px 0 4px; }
.ht-head {
    display: flex; align-items: baseline; gap: 8px;
    margin: 0 0 9px; font-size: 15px; font-weight: 700;
    color: var(--label); letter-spacing: -0.4px;
}
.ht-more {
    margin-left: auto; font-size: 12.5px; font-weight: 600;
    color: var(--label-3); text-decoration: none; letter-spacing: -0.2px;
}
.ht-more:hover { color: var(--blue); }
/* 격자 밑의 '전체 보기' — 아홉 번째 칸처럼 보이지 않게 한 줄로 눕힌다 */
.ht-all {
    display: block; margin: 9px 0 0; padding: 10px;
    border: 1px solid var(--hairline); border-radius: var(--radius-m);
    background: var(--surface);
    text-align: center; text-decoration: none;
    font-size: 13px; font-weight: 700; color: var(--label-2); letter-spacing: -0.3px;
    transition: border-color 0.15s, color 0.15s;
}
.ht-all:hover { border-color: var(--blue); color: var(--blue); }
/* TOP100 머리글 — 주제 격자와 목록 사이를 벌린다 */
.home-hit-head { margin-top: 20px; }
.theme-tiles {
    display: grid; gap: 10px;
    grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
}
.tt {
    display: block; text-decoration: none; color: inherit;
    background: var(--surface); border: 1px solid var(--line);
    border-radius: var(--radius-m); overflow: hidden;
    box-shadow: var(--card-shadow);
    transition: border-color 0.15s, transform 0.15s;
}
.tt:hover { border-color: var(--blue); transform: translateY(-2px); }
.tt:active { transform: none; }
/*
| 넓은 화면에서만 펴지는 타일 (2026-09-11).
|
| 홈 주제 격자는 열둘을 내려받고 폰에서는 여덟 장만 편다. 폰은 두 칸이라
| 여덟 장이 이미 네 줄이고, 더 깔면 TOP100 이 화면 밖으로 밀린다. 반대로
| PC 는 네 칸이라 여덟 장이 두 줄에서 끝나 아래가 허전하다 — 열둘이면
| 세 줄이 꽉 찬다.
|
| 폭만으로 가르지 않는다 (2026-09-11 고침).
|
| 처음에는 (min-width: 680px) 하나로 걸었다. 갤럭시 S26 울트라에서 열두 장이
| 다 보인다는 지적을 받았다 — 큰 폰은 가로로 눕히거나 '화면 크기' 를 작게
| 두면 CSS 폭이 680px 을 넘는다. 폭은 '마우스인지 손가락인지' 를 말해 주지
| 않는다. 그래서 그 질문을 직접 한다: (pointer: fine).
|
| 이 파일의 .genre-wrap::after 도 같은 이유로 pointer 를 쓴다. 네이버 앱
| 인앱 브라우저가 hover 를 거짓으로 답하는 것이 기기 실측으로 확인돼 있고,
| 자바스크립트의 isTouchDevice() 도 pointer 를 기준으로 삼는다.
|
| 폭 조건도 남겨 둔다. 마우스를 쓰더라도 창이 좁으면 격자가 네 칸이 안 돼
| 열두 장이 어긋난 줄로 깔린다. 680px 인 이유는 .container 의
| max-width 가 680px 이라, 이 폭을 넘으면 본문(648px)이 더 안 넓어지고
| 그 폭에서 격자가 정확히 네 칸이 되기 때문이다
| (150px 넷 + 10px 간격 셋 = 630px ≤ 648px). '레이아웃이 다 자란 지점' 이다.
|
| 감추는 쪽을 기본값으로 둔 것은 일부러다. pointer 를 모르는 브라우저가
| 있더라도 폰 쪽 배치(여덟 장)로 떨어지지, 폰에 열두 장이 깔리지 않는다.
|
| .tt 뒤에 두어야 한다. 처음에는 .theme-tiles 바로 밑, 곧 .tt 앞에 적었는데
| 둘 다 클래스 하나라 특정도가 같아서 뒤에 오는 .tt{display:block} 이 이겼다.
| 그래서 접기가 어느 기기에서도 안 먹었다 (갤럭시 S26 울트라에서 열두 장이
| 다 보인다는 지적으로 발견, 2026-09-11).
|
| 자바스크립트로 지우지 않는 이유는 그렸다 지우는 것이 눈에 보이기 때문이다.
| display:none 인 타일은 그 안의 loading="lazy" 이미지도 받지 않는다.
*/
.tt-fold { display: none; }
@media (min-width: 680px) and (pointer: fine) { .tt-fold { display: block; } }
.tt-thumb {
    display: block; position: relative;
    aspect-ratio: 16 / 9; background: var(--fill); line-height: 0;
}
.tt-thumb img {
    width: 100%; height: 100%; object-fit: cover; display: block;
    /*
    | 유튜브 썸네일은 원본 비율이 제각각이라 위아래에 띠가 남는 것이 있다.
    | 살짝 키워 잘라 내면 타일이 고르게 보인다.
    */
    transform: scale(1.02);
}
/*
| 표지 그림 없는 주제 타일 (2026-09-14).
|
| 유튜브 썸네일을 타일 배경으로 깔던 것을 걷어 냈다 — 눌러도 그 영상으로
| 가지 않는 자리라 남의 그림을 장식으로 쓰는 셈이었다. 대신 주제마다 고정된
| 색(ssrThemeHue)에 이름을 얹는다. 채도·밝기를 여기서 고정하므로 어떤 색이
| 나와도 흰 글자 대비가 같다(약 7:1). 밝게·어둡게 모두 같은 판을 쓴다.
*/
.tt-plain .tt-thumb {
    display: flex; align-items: flex-end; padding: 10px 11px; line-height: 1;
    background: linear-gradient(158deg, hsl(var(--h) 44% 36%), hsl(var(--h) 40% 26%));
}
.tt-cap {
    color: #fff; font-weight: 800; font-size: 17px; line-height: 1.2;
    letter-spacing: -0.4px; word-break: keep-all; text-wrap: balance;
    display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical; overflow: hidden;
}
.tt-badge {
    position: absolute; right: 8px; top: 8px;
    padding: 2px 7px; border-radius: 999px;
    background: rgba(0,0,0,0.28); color: #fff;
    font-size: 11px; font-weight: 700; font-variant-numeric: tabular-nums; line-height: 1.5;
}
.tt-plain .tt-song { padding-top: 9px; }
/*
| 대표곡 영상 타일 (2026-09-15, search_song.php ssrThemeTiles).
| 썸네일 판은 공용 .mv-facade 를 쓰되 타일 안이라 모서리·최소 높이를 푼다.
| 재생은 영상 팝업(#mvSheet)에서 한다 — 타일 모양은 누른 뒤에도 그대로다.
| display 는 건드리지 않는다 — .tt-fold(display:none) 를 덮어쓰면 접힌 타일이 폰에 나온다.
*/
.tt-vid .tt-face { min-height: 0; border-radius: 0; aspect-ratio: 16 / 9; }
/*
| 재생 단추는 오른쪽 아래 작게 (2026-09-15, 사용자 제안) — 가운데 큰 단추가 썸네일을
| 가려서. 폰에도 늘 보인다(마우스 올림에만 띄우면 폰에서는 안 보인다).
| 누를 수 있는 곳은 여전히 썸네일 전체다.
*/
.tt-vid .mv-play {
    left: auto; top: auto; right: 6px; bottom: 6px; transform: none;
    width: 34px; height: 24px; border-radius: 7px; --tri: 5px;
}

.tt-label {
    display: block; padding: 9px 10px 0 11px; text-decoration: none; color: inherit;
    -webkit-tap-highlight-color: transparent;
}
.tt-lrow { display: flex; align-items: center; gap: 6px; }
.tt-label .tt-song { padding: 3px 0 10px; }
.tt-lname { flex: 1 1 auto; min-width: 0; font-size: 14px; font-weight: 800; letter-spacing: -0.35px; line-height: 1.3; word-break: keep-all; color: var(--label); }
.tt-lcnt { flex: none; font-size: 11.5px; font-weight: 600; color: var(--label-3); font-variant-numeric: tabular-nums; }
.tt-lgo { flex: none; font-size: 18px; line-height: 1; color: var(--label-3); }
.tt-label:focus-visible { outline: 2px solid var(--blue); outline-offset: -3px; border-radius: var(--radius-m); }
.tt-vid:hover { transform: none; }
@media (hover: hover) and (pointer: fine) {
    .tt-label:hover .tt-lname, .tt-label:hover .tt-lgo { color: var(--blue); }
}
/*
| 주제 그림 (2026-09-15, theme_lib.php themeCardImg).
| 틀을 3:2 로 — 사용자가 만든 그림이 640×427·640×480 으로 섞여 있어 가장 덜 잘리는
| 비율이다. 그림 없는 색 판도 같은 비율로 맞춰야 한 줄의 타일 높이가 어긋나지 않는다.
| 그림 안에 주제 이름이 들어 있어 얹던 글자는 화면에서만 숨긴다.
*/
.tt-plain .tt-thumb { aspect-ratio: 3 / 2; }
.tt-img .tt-thumb img { position: absolute; inset: 0; transform: none; }
.tt-img .tt-cap {
    position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0;
    overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}
.tt-img .tt-badge { background: rgba(0,0,0,0.58); }

/* 표지를 못 찾은 주제 — 빈 칸 대신 결이 같은 자리를 둔다 */
.tt-none {
    position: absolute; inset: 0;
    display: flex; align-items: center; justify-content: center;
    font-size: 26px; color: var(--label-3); opacity: 0.45; line-height: 1;
    background: linear-gradient(135deg, var(--fill) 0%, var(--fill-3) 100%);
}
.tt-name {
    display: block; padding: 9px 11px 0;
    font-size: 14px; font-weight: 700; color: var(--label);
    letter-spacing: -0.35px; line-height: 1.35; word-break: keep-all;
}
/*
| 표지 밑의 한 줄.
|
| 앞에 '대표곡' 을 붙인다 — 안 붙이면 곡 이름 하나만 놓여 있어 '이 주제에는
| 이 곡뿐인가' 로 읽힌다. 이름 옆 괄호 안에 곡 수가 이미 있지만, 눈은
| 큰 글자부터 읽으므로 그 숫자보다 이 줄이 먼저 뜻을 만든다.
|
| 한 줄로 자르지 않고 두 줄까지 흐르게 둔다 — 타일이 150px 까지 좁아지는데
| '대표곡' 이 앞을 40px 쯤 먹어서, 한 줄로 묶으면 곡 이름이 서너 글자에서
| 잘린다. 두 줄을 넘기면 그때 자른다.
*/
.tt-song {
    display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;
    padding: 3px 11px 11px;
    font-size: 11.5px; color: var(--label-3);
    letter-spacing: -0.2px; line-height: 1.4;
    overflow: hidden;
}
.tt-song b {
    font-weight: 700; color: var(--label-3); opacity: 0.66;
    font-size: 10.5px; letter-spacing: 0;
}
/* 콜론과 사이 띄움은 CSS 로 둔다 — 읽어 주는 기계에는 '대표곡' 만 들린다 */
.tt-song b::after { content: ':'; margin-right: 4px; }
.tt-song i { font-style: normal; opacity: 0.72; }
/* 표지가 없으면 곡 이름 줄도 없다 — 아래 여백을 이름 쪽에서 낸다 */
.tt-thumb + .tt-name:last-child { padding-bottom: 11px; }

.theme-grid .also-cell {
    display: flex; align-items: center; justify-content: center;
    min-height: 46px; padding: 8px 10px;
    white-space: normal; overflow: visible; text-overflow: clip;
    text-align: center; line-height: 1.35;
    font-size: 13.5px; letter-spacing: -0.3px;
    word-break: keep-all;      /* 단어 중간에서 끊기지 않게 */
}
@media (max-width: 520px) { .theme-grid { grid-template-columns: repeat(2, 1fr) !important; } }
/*
| 제목은 줄이되 유튜브 표시는 남긴다.
|
| 예전에는 칸 전체가 display:block 에 overflow:hidden 이라, 제목과 아이콘이
| 한 흐름이었다. 제목이 길면 잘리는 자리에 아이콘이 걸려 통째로 사라졌다
| (2026-08-31). flex 로 나눠 제목만 줄이고 아이콘은 제 자리를 지키게 한다.
*/
.also-cell {
    display: flex; align-items: center; gap: 5px;
    padding: 11px 13px; text-decoration: none;
    background: var(--surface); border: 1px solid var(--line);
    border-radius: var(--radius-m); box-shadow: var(--card-shadow);
    font-size: 14.5px; font-weight: 500; color: var(--label); letter-spacing: -0.2px;
    transition: background 0.15s, color 0.15s;
    -webkit-tap-highlight-color: transparent;
}
/* 제목 — 여기만 줄인다 */
.also-cell .ac-t {
    flex: 1; min-width: 0;
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.also-cell:hover { background: var(--surface-hover); color: var(--blue); }
/*
|--------------------------------------------------------------------------
| 칸 오른쪽의 ▶ 단추 — '함께 본 곡' · '같은 제목의 다른 곡' (2026-09-11)
|--------------------------------------------------------------------------
| 영상이 있는 곡에만 붙는다. 단추는 <a> 밖에 형제로 두고(누를 것 안에 누를
| 것을 넣을 수 없다) 여기서 칸 오른쪽에 얹는다. .also-row 가 격자 칸이
| 되므로 줄 높이는 예전과 같다.
|
| 칸의 오른쪽 여백을 단추 폭만큼 넓혀 제목이 그 밑으로 들어가지 않게 한다.
| 30px + 좌우 7px·5px = 42px.
|
| 목록의 ▶(.yt-btn 33px)보다 작게 잡았다. 저쪽은 곡 한 줄의 주된 행동이고
| 여기는 '골라 보는 칸' 에 얹힌 곁가지다 — 같은 크기면 제목보다 단추가
| 먼저 읽힌다.
*/
.also-row { position: relative; min-width: 0; }
.also-row .also-cell { padding-right: 42px; }
.also-yt {
    position: absolute; right: 7px; top: 50%; transform: translateY(-50%);
    width: 30px; height: 26px; padding: 0; border: 0;
    border-radius: var(--radius-s);
    background: var(--red-fill); color: var(--red);
    display: inline-flex; align-items: center; justify-content: center;
    font-size: 10px; font-family: inherit; cursor: pointer;
    -webkit-tap-highlight-color: transparent;
    transition: background 0.15s, color 0.15s;
}
.also-yt:hover { background: var(--red); color: #fff; }
.also-yt:active { transform: translateY(-50%) scale(0.94); }

.site-foot {
    margin-top: 34px; padding-top: 20px;
    border-top: 1px solid var(--hairline);
}
.foot-nav { display: flex; flex-wrap: wrap; gap: 7px 14px; margin-bottom: 12px; }
.foot-nav a {
    font-size: 13px; color: var(--label-2); text-decoration: none; letter-spacing: -0.2px;
}
.foot-nav a:hover { color: var(--blue); }
.foot-sub a { font-weight: 600; }
.foot-copy { margin: 6px 0 0; font-size: 12px; color: var(--label-3); letter-spacing: -0.2px; }
.foot-note {
    margin: 10px 0 0; font-size: 11.5px; line-height: 1.65;
    color: var(--label-3); letter-spacing: -0.2px;
}
.foot-copyright {
    margin: 12px 0 0; padding-top: 12px;
    border-top: 1px solid var(--hairline);
    font-size: 11.5px; color: var(--label-3); letter-spacing: -0.2px;
}

/*
| 제목과 부제를 한 줄에 세운다.
|
| 예전에는 세로로 쌓았는데, 부제('금영 · 태진 번호 · 노래방 영상 · 뮤직비디오')
| 는 무엇을 볼 수 있는지 알려 주는 곁말이지 따로 읽을 문장이 아니다.
| 한 줄을 통째로 쓰면서 정작 아래 곡 목록을 화면 밖으로 밀어냈다.
|
| 좁아지면 부제만 아랫줄로 접힌다 (wrap). 억지로 붙여 '…' 로 자르면
| 무엇을 볼 수 있는지가 사라지므로, 자르지 않고 접는 쪽을 고른다.
| baseline 정렬이라 접히기 전까지는 제목 글자 밑선에 나란히 붙는다.
*/
.page-h1 {
    margin: 6px 0 12px; padding: 0 2px;
    font-size: 19px; font-weight: 700; letter-spacing: -0.4px; color: var(--label);
    display: flex; flex-wrap: wrap; align-items: baseline; gap: 2px 7px;
}
.page-h1 span { font-size: 12.5px; font-weight: 500; color: var(--label-3); letter-spacing: -0.2px; }
/*
| 좁은 화면에서는 곁말을 한 단계 줄여 한 줄에 들어갈 자리를 만든다.
| 그래도 안 들어가는 긴 제목('동요/만화 노래방 인기곡' 등)은 접힌다.
*/
@media (max-width: 430px) {
    .page-h1 { gap: 2px 6px; }
    .page-h1 span { font-size: 11.5px; }
}
.sr-only {
    position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
    overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}

.brand-sub {
    font-size: 12.5px; font-weight: 500; letter-spacing: -0.2px;
    color: var(--label-3); white-space: nowrap; flex-shrink: 0;
}

.vendor-tabs {
    display: flex; gap: 2px; flex-shrink: 0;
    background: var(--fill-2);   /* 선택된 흰 탭이 배경과 구분되도록 트랙을 조금 진하게 */
    border-radius: 10px;
    padding: 2px;
}

.vendor-tab {
    height: 32px; padding: 0 18px; border: none;
    display: inline-flex; align-items: center; justify-content: center;
    text-decoration: none;
    border-radius: 8px; font-size: 14px; font-weight: 600;
    letter-spacing: -0.2px;
    cursor: pointer;
    transition: background 0.25s var(--ease), color 0.25s var(--ease), box-shadow 0.25s var(--ease);
    background: transparent; color: var(--label-2);
    white-space: nowrap; -webkit-tap-highlight-color: transparent;
    font-family: inherit;
}

.vendor-tab.active-ky,
.vendor-tab.active-tj {
    background: var(--surface);
    color: var(--label);
    box-shadow: 0 1px 4px rgba(0,0,0,0.12);
}

/* ── 검색 입력 ── */

.search-wrap { position: relative; width: 100%; }

.search-input {
    width: 100%; height: 52px;
    /* 입력창은 눌러야 할 곳이므로 헤어라인보다 한 단계 진하게 — 밝은 화면에서도 테두리가 보인다 */
    border: 1px solid var(--line-3);
    border-radius: var(--radius-m);
    padding: 0 46px 0 46px; font-size: 18px;
    background: var(--surface);
    color: var(--label); outline: none;
    box-shadow: var(--card-shadow);
    transition: border-color 0.25s var(--ease), box-shadow 0.25s var(--ease);
    -webkit-appearance: none;
    font-family: inherit;
    letter-spacing: -0.3px;
    font-weight: 500;
}

.search-input:focus {
    border-color: var(--blue-line);
    box-shadow: 0 0 0 3px var(--blue-fill);
}
.search-input::placeholder { color: var(--label-3); font-weight: 400; }
.search-input::-webkit-search-cancel-button,
.search-input::-webkit-search-decoration { -webkit-appearance: none; }

/* 입력창임을 한눈에 알 수 있게 왼쪽에 돋보기를 둔다.
   아이콘 위를 눌러도 입력창이 포커스되도록 클릭은 통과시킨다. */
.search-ico {
    position: absolute;
    left: 15px; top: 50%; transform: translateY(-50%);
    width: 20px; height: 20px;
    color: var(--label-3);
    pointer-events: none;
    transition: color 0.25s var(--ease);
}
.search-input:focus ~ .search-ico { color: rgba(0,122,255,0.75); }

.clear-btn {
    display: none; position: absolute;
    right: 10px; top: 50%; transform: translateY(-50%);
    width: 28px; height: 28px;
    background: var(--fill-3); border: none;
    border-radius: 50%;
    color: var(--label-2);
    font-size: 12px; cursor: pointer; line-height: 1;
    z-index: 10; -webkit-tap-highlight-color: transparent;
    transition: background 0.15s;
}
.clear-btn:active { background: var(--fill-3); color: var(--label); }

/*
| 음성 검색 단추 (2026-09-09)
|
| 지우기 단추와 같은 자리를 쓴다 — 칸이 비었을 때만 보인다.
| 두 개를 나란히 두면 좁은 화면에서 입력 폭이 줄고, 어느 쪽인지 매번
| 재게 된다. 음성은 '처음 칠 때' 쓰는 것이라 겹쳐도 문제가 없다.
*/
.mic-btn {
    position: absolute;
    right: 10px; top: 50%; transform: translateY(-50%);
    width: 30px; height: 30px;
    display: flex; align-items: center; justify-content: center;
    background: none; border: none; padding: 0;
    color: var(--label-3); cursor: pointer;
    z-index: 10; -webkit-tap-highlight-color: transparent;
    transition: color 0.15s;
}
.mic-btn svg { width: 20px; height: 20px; }
.mic-btn:hover { color: var(--label-2); }
/*
| display 를 준 요소는 [hidden] 이 안 먹는다 — 브라우저 기본 규칙과
| 특정도가 같은데 이 파일이 뒤에 오기 때문이다. 그래서 감출 때를 따로 적는다.
| (이 파일의 .sp[hidden] · .hero-head-share[hidden] 과 같은 방식)
*/
.mic-btn[hidden] { display: none; }

/*
| 듣는 중 — 빨갛게 켜고 천천히 숨쉬게 한다.
| 마이크가 켜져 있다는 것은 반드시 눈에 보여야 한다.
*/
.mic-btn.on { color: #e0393e; }
.mic-btn.on svg { animation: micPulse 1.3s ease-in-out infinite; }
@keyframes micPulse {
    0%, 100% { opacity: 1;   transform: scale(1); }
    50%      { opacity: .55; transform: scale(1.14); }
}
/*
| 준비 중 — 눌렀지만 아직 못 듣는 동안.
|
| 네이버 앱 웹뷰에서 누른 뒤 실제로 듣기 시작할 때까지 3.3초가 걸렸다.
| 그동안 아무 표시가 없으면 누른 줄 모르고 말을 시작해 그 말을 잃는다.
| 회색으로 빠르게 깜빡여 '아직 아니다' 를 알린다 — 빨간 맥박(듣는 중)과
| 색도 속도도 달라야 두 상태가 구별된다.
*/
.mic-btn.warm { color: var(--label-3); }
.mic-btn.warm svg { animation: micWarm 0.7s ease-in-out infinite; }
@keyframes micWarm {
    0%, 100% { opacity: .35; }
    50%      { opacity: 1;   }
}
@media (prefers-reduced-motion: reduce) {
    .mic-btn.on svg, .mic-btn.warm svg { animation: none; }
    .mic-btn.warm { opacity: .55; }
}

/* ── 자동완성 ── */

.ac-dropdown {
    display: none; position: absolute;
    top: calc(100% + 8px); left: 0; right: 0;
    background: var(--glass-2);
    -webkit-backdrop-filter: saturate(180%) blur(24px);
    backdrop-filter: saturate(180%) blur(24px);
    border: 1px solid var(--hairline);
    border-radius: var(--radius-m);
    box-shadow: 0 12px 40px rgba(0,0,0,0.14);
    z-index: 200;
    /* 항목이 많아도 문서 높이를 크게 늘리지 않도록 제한한다.
       (제한이 없으면 짧은 페이지에서 스크롤이 생겼다 사라지며 화면이 흔들린다) */
    max-height: min(46vh, 340px);
    overflow-y: auto; overflow-x: hidden;
    overscroll-behavior: contain;
    -webkit-overflow-scrolling: touch;
}
.ac-dropdown.open { display: block; }

.ac-item {
    display: flex; align-items: center; gap: 11px;
    padding: 12px 15px; cursor: pointer;
    transition: background 0.12s;
    -webkit-tap-highlight-color: transparent;
    position: relative;
}
.ac-item + .ac-item::before {
    content: '';
    position: absolute; top: 0; left: 15px; right: 15px;
    height: 1px; background: var(--fill);
}
.ac-item:hover, .ac-item.active { background: var(--fill); }

/* 최근 검색어 */
.ac-head {
    display: flex; align-items: center; justify-content: space-between;
    padding: 10px 14px 6px; font-size: 12px; font-weight: 600;
    color: var(--label-2); letter-spacing: -0.2px;
}
.ac-clear {
    background: none; border: 0; padding: 2px 4px; cursor: pointer;
    font: inherit; font-weight: 500; color: var(--label-3);
}
.ac-clear:hover { color: var(--label-1); }
/*
| 머리줄 오른쪽 단추 묶음 — '전체 삭제' 와 '✕ 닫기'.
|
| 둘 사이를 넉넉히 벌리고 가는 금을 하나 넣는다. 붙여 놓으면 '전체 삭제'
| 옆의 ✕ 가 그 일의 연장(하나 더 지우기)처럼 읽힌다 — 하는 일이 다르니
| 눈으로도 갈라 놓아야 한다.
*/
.ac-head-btns { display: flex; align-items: center; gap: 10px; }
.ac-close {
    background: none; border: 0; cursor: pointer;
    display: flex; align-items: center; gap: 3px;
    padding: 5px 4px; margin-right: -4px;          /* 손가락이 닿을 높이(28px)를 padding 으로 준다 */
    font: inherit; font-weight: 500; line-height: 1;
    color: var(--label-3); border-radius: 6px;
    position: relative;                             /* 아래 금의 기준점 */
    -webkit-tap-highlight-color: transparent;
}
.ac-close::before {                                 /* 전체 삭제와 갈라 주는 가는 금 */
    content: ''; position: absolute; left: -5px; top: 50%;
    width: 1px; height: 11px; margin-top: -5.5px;
    background: var(--fill-3);
}
.ac-close-x { font-size: 11px; opacity: 0.85; }
.ac-close:hover { color: var(--label-1); background: var(--fill); }
.ac-close:active { background: var(--fill-3); }
.ac-recent + .ac-recent::before { content: none; }   /* 최근 목록은 줄을 긋지 않는다 */
/* 자동완성은 제목·가수 두 줄이라 12px 이 맞지만 여기는 한 줄이다 */
.ac-recent { padding: 0 15px; min-height: 40px; gap: 9px; }
.ac-recent .ac-icon { opacity: 0.5; font-size: 14px; }
.ac-recent .ac-main { color: var(--label-1); }
.ac-del {
    flex-shrink: 0; width: 24px; height: 24px; line-height: 1;
    background: none; border: 0; border-radius: 50%; cursor: pointer;
    font-size: 18px; color: var(--label-3);
}
.ac-del:hover { background: var(--fill-2); color: var(--label-1); }
.ac-recent:last-child { margin-bottom: 4px; }

.ac-icon { font-size: 16px; width: 26px; text-align: center; flex-shrink: 0; opacity: 0.85; }
.ac-text { flex: 1; min-width: 0; }
.ac-main { font-size: 15.5px; font-weight: 500; letter-spacing: -0.2px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.ac-sub  { font-size: 13px; color: var(--label-2); margin-top: 2px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.ac-badge {
    font-size: 11.5px; font-weight: 600;
    padding: 3px 9px; border-radius: 20px; flex-shrink: 0;
    letter-spacing: 0;
}
.ac-badge-singer { background: var(--blue-fill); color: var(--blue); }
.ac-badge-title  { background: var(--green-fill); color: var(--green); font-family: 'Roboto', sans-serif; }

/* ── 선택된 곡 (v & sn) ── */

.song-hero {
    position: relative;
    background: var(--surface);
    border: 1px solid var(--hairline);
    border-radius: 20px;
    padding: 15px 17px 14px;
    margin: 10px 0 13px;
    box-shadow: 0 4px 20px rgba(0,0,0,0.06);
    overflow: hidden;
}
/*
| 판넬 안 마지막 줄의 아래 여백은 지운다.
|
| 안내문(.song-hero-singer)은 곡 화면에서 아래에 번호 칸이 오므로
| margin-bottom: 16px 을 갖고 있다. 그런데 목록 들머리 판넬에서는
| 그게 마지막 줄이라, 판넬 자체의 아래 여백 14px 과 겹쳐 30px 이
| 됐다 — 위는 15px 인데 아래만 두 배로 벌어져 글이 떠 보였다.
|
| 마지막 줄에서만 지우면 곡 화면의 간격은 그대로다.
*/
.song-hero > :last-child { margin-bottom: 0; }

/* 상단 강조 라인 */
.song-hero::before {
    content: '';
    position: absolute; top: 0; left: 0; right: 0; height: 3px;
    background: linear-gradient(90deg, var(--blue), var(--purple));
}

.song-hero-head {
    display: flex; align-items: center; justify-content: space-between;
    gap: 8px;
    margin-bottom: 7px;
}
.song-hero-tag {
    font-size: 11.5px; font-weight: 600; letter-spacing: 0.2px;
    color: var(--blue);
    background: var(--blue-fill);
    padding: 3px 10px; border-radius: 20px;
}
.song-hero-close {
    width: 26px; height: 26px; flex-shrink: 0;
    display: flex; align-items: center; justify-content: center;
    border-radius: 50%; text-decoration: none;
    background: var(--fill); color: var(--label-3);
    font-size: 11px; transition: background 0.15s, color 0.15s;
    -webkit-tap-highlight-color: transparent;
}
.song-hero-close:hover { background: var(--fill-2); color: var(--label); }

.song-hero-title {
    margin: 0 0 4px;
    font-size: 25px; font-weight: 700; line-height: 1.25;
    letter-spacing: -0.7px; color: var(--label);
    word-break: keep-all;
}
/*
| 자동완성의 읽기 — 고르는 순간에 필요한 정보다.
| 제목/가수 바로 아래에 한 급 작게 둔다. 목록의 읽기와 같은 색을 써서
| '이건 읽는 법' 이라는 규칙이 화면마다 달라지지 않게 한다.
*/
.ac-yomi {
    margin: 1px 0 0;
    font-size: 11.5px; font-weight: 500;
    letter-spacing: -0.2px; color: var(--label-2);
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.ac-yomi-in { color: var(--label-2); font-weight: 500; }

/* 가수명 옆 읽기 — 같은 줄에 괄호 없이 붙인다 */
.s-yomi { color: var(--label-2); font-weight: 500; font-size: 0.92em; }
.s-yomi::before { content: '· '; color: var(--label-3); }

/* 목록 한 줄에 붙는 일본어 제목 읽기 */
.hit-yomi,
.song-yomi {
    margin: 1px 0 0;
    font-size: 12px; font-weight: 500;
    letter-spacing: -0.2px; color: var(--label-2);
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

/*
| 일본어 제목의 한글 읽기.
| 제목이 아니라 '읽는 법' 이므로 제목보다 작게 둔다.
|
| 처음에는 --label-3 (흰 배경 대비 4.4:1) 로 흐리게 깔았는데, 읽어야 하는
| 글자를 설명글처럼 다뤄 버린 것이었다. 일본어 제목을 못 읽는 사람에게는
| 이 줄이 곧 제목이다. --label-2 (7.0:1) 로 올리고 굵기도 한 단계 준다.
*/
.song-hero-yomi {
    margin: -2px 0 5px;
    font-size: 14px; font-weight: 500;
    letter-spacing: -0.2px; color: var(--label-2);
    word-break: keep-all;
}

/*
| 주제 안내문 — 제목과 '몇 곡 중 몇 위' 줄 사이.
|
| 읽히되 제목을 누르지 않아야 해서 본문보다 한 급 작게 두고, 부제만
| 굵게 올려 눈이 먼저 걸리게 한다. 부제와 안내문은 한 문단으로 흐르게
| 두었다 — 줄을 나누면 좁은 화면에서 판넬이 두 줄 더 길어진다.
|
| keep-all 은 '가창력 필살기' 같은 말이 글자 단위로 끊기지 않게 한다.
*/
.theme-lead {
    margin: -1px 0 11px;
    font-size: 13.5px; line-height: 1.5;
    letter-spacing: -0.3px; color: var(--label-3);
    word-break: keep-all;
}
.theme-lead b {
    font-weight: 700; color: var(--label-2);
}
.theme-lead b::after { content: ' — '; font-weight: 400; }

.song-hero-singer {
    margin: 0 0 16px;
    font-size: 15.5px; font-weight: 500;
    letter-spacing: -0.3px; color: var(--label-2);
}

/*
| 가수 줄 — [얼굴] [이름] ······ [가수 정보]
|
| 예전에는 그냥 글줄이라, 이름이 길면 '가수 정보' 단추가 아랫줄로
| 떨어져 나갔다. 단추가 어디 있는지 곡마다 달라지니 찾는 눈이 매번
| 헤맨다. 오른쪽 끝에 못박고, 모자라면 이름을 자른다 — 이름은 바로
| 위 제목 옆에도 있고 검색으로 들어온 사람은 이미 아는 이름이다.
|
| min-width: 0 이 있어야 자른다. flex 칸은 기본이 min-width: auto 라
| 내용보다 작아지지 않아, 이것 없이는 ellipsis 가 걸려도 안 줄어든다.
|
| 이 규칙은 .sg-line 이 붙은 줄에만 건다 — 같은 .song-hero-singer 를
| 주제·가수 목록 화면이 그냥 문장 줄로도 쓴다.
*/
.song-hero-singer.sg-line { display: flex; align-items: center; }
.song-hero-singer.sg-line .sg-name {
    min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.song-hero-singer.sg-line .sg-face-btn,
.song-hero-singer.sg-line .sg-face { flex: 0 0 auto; }
.song-hero-singer.sg-line .sp-btn { flex: 0 0 auto; margin-left: auto; }
/*
| 이름 자체도 시트를 여는 단추다 (소개가 있을 때만).
|
| 겉모습은 그냥 글자여야 한다 — 이름 자리에 단추 티가 나면 옆의
| '가수 정보' 와 둘이 경쟁해 어느 쪽을 눌러야 하는지 헷갈린다.
| 눌러 보면 열린다는 것만 밑줄로 살짝 알린다.
*/
.sg-name-btn {
    padding: 0; border: 0; background: none;
    font: inherit; color: inherit; letter-spacing: inherit;
    text-align: left; cursor: pointer;
    -webkit-tap-highlight-color: transparent;
}
.sg-name-btn:hover { text-decoration: underline; text-underline-offset: 3px; }

.song-hero-nums { display: flex; gap: 10px; }

/*
| 번호 아래 '이 아래에 뭐가 있는지' 줄.
| 목록이 아니라 개수만 알린다 — 여기서 펼치면 정작 보러 온 번호를 가린다.
*/
.hero-jump {
    display: flex; flex-wrap: wrap; gap: 6px;
    margin: 12px 0 0;
}
.jump-chip {
    display: inline-flex; align-items: center; gap: 5px;
    height: 30px; padding: 0 11px; border-radius: 16px;
    border: 1px solid var(--hairline);
    background: var(--surface-2); color: var(--label-2);
    font-size: 12.5px; font-weight: 600; letter-spacing: -0.2px;
    text-decoration: none; -webkit-tap-highlight-color: transparent;
    transition: background 0.15s, color 0.15s;
}
.jump-chip:hover { background: var(--blue-fill); color: var(--blue); }
.jump-chip b {
    min-width: 16px; height: 16px; padding: 0 4px; border-radius: 8px;
    background: var(--blue-fill); color: var(--blue);
    font-size: 11px; font-weight: 700;
    display: inline-flex; align-items: center; justify-content: center;
}

/* 눌러서 내려갔을 때 고정된 검색창이 제목을 가리지 않게 */
.sec-head { scroll-margin-top: 64px; }
html { scroll-behavior: smooth; }

/*
| 이름과 번호를 한 줄에 놓는다.
|
| 쌓아 두면 칸 하나가 74px 을 먹었다. 곡 화면 맨 위에 둘이 나란히 서
| 있으므로 그만큼 제목과 목록이 통째로 아래로 밀린다. '금영' 은 어느
| 노래방인지 알려 주는 딱지일 뿐 번호와 대등한 정보가 아니라, 옆에
| 붙여도 읽는 데 걸리지 않는다.
|
| baseline 으로 맞춰야 딱지가 번호 밑선에 앉는다 — center 로 두면
| 글자 크기 차이(11.5 vs 23) 때문에 딱지가 번호 한가운데 떠 보인다.
|
| wrap 은 '없음' 칸 때문에 있다. 그 칸에는 '아시나요?' 가 하나 더
| 붙는데, 셋을 한 줄에 밀어 넣으면 좁은 화면에서 넘친다. 아래 규칙이
| 그것만 둘째 줄로 내린다.
*/
.num-tile {
    flex: 1;
    display: flex; flex-wrap: wrap;
    align-items: baseline; justify-content: center;
    gap: 0 7px;
    padding: 9px 8px;
    border: 1px solid var(--hairline);
    border-radius: 13px;
    background: var(--surface-hover);
    transition: all 0.2s var(--ease);
}
.num-label {
    font-size: 11.5px; font-weight: 600; letter-spacing: 0.2px;
    color: var(--label-3);
}
.num-value {
    font-size: 23px; font-weight: 700;
    font-family: 'Roboto', sans-serif;
    letter-spacing: 0.5px; line-height: 1.1;
    font-variant-numeric: tabular-nums;
    color: var(--label);
}
/* 현재 보고 있는 벤더 강조 */
.num-tile.primary.num-ky {
    background: var(--blue); border-color: var(--blue);
    box-shadow: 0 4px 14px var(--blue-line);
}
.num-tile.primary.num-tj {
    background: var(--purple); border-color: var(--purple);
    box-shadow: 0 4px 14px rgba(175,82,222,0.28);
}
.num-tile.primary .num-label { color: rgba(255,255,255,0.75); }
.num-tile.primary .num-value { color: #ffffff; }
/*
| 번호가 여럿일 때는 한 급 줄인다.
|
| '223 · 89025' 는 한 번호보다 두 배 넘게 넓다. 23px 그대로 두면 320px
| 화면에서 칸을 넘치거나 줄이 바뀐다. 번호가 둘인 곡은 166곡뿐이라
| 그쪽만 줄이는 편이, 모든 곡의 번호를 미리 작게 두는 것보다 낫다.
*/
.num-tile.num-multi .num-value { font-size: 18px; letter-spacing: 0.2px; }

/* 대응 번호 없음 */
.num-tile.na .num-value { font-size: 17px; color: var(--label-3); font-weight: 500; }

/*
| 작사·작곡·발매
|
| 처음에는 한 덩어리라 'Andreas Carlsson,Erik Lidbom,…'(52자) 같은 이름에서
| '작곡' 과 이름이 다른 줄로 갈라졌다. 그래서 flex-wrap 으로 항목을 묶었는데,
| 이번에는 그 묶음이 너무 단단해서 탈이 났다.
|
| 2026-08-31. 작사와 작곡이 같으면 '작사·작곡 X' 로 합치게 했더니, 줄을
| 나눌 자리가 하나 사라졌다. 전에는
|     1줄  작사 로제,Bruno Mars,… ·
|     2줄  작곡 로제,Bruno Mars,… · 발매 2024.12.01
| 처럼 둘째 줄에 발매가 함께 붙었는데, 합친 뒤에는 첫 줄이 통째로 한 덩이라
|     1줄  작사·작곡 로제,Bruno Mars,… ·
|     2줄  발매 2024.12.01
| 이 되어 발매만 혼자 내려간다. 320px 화면에서 1,555곡 중 169곡(11%)이
| 여기 걸린다(390px 에서는 6곡).
|
| flex 를 걷고 보통 글줄로 되돌린다. 그러면 이름 안에서 접히면서 발매가
| 같은 줄에 남는다. 처음의 문제(라벨과 이름이 갈라짐)는 라벨과 이름 사이를
| 줄바꿈 없는 공백(&#160;)으로 붙여 막는다 — flex 로 묶을 필요가 없다.
|
| keep-all 은 한글을 낱말 단위로만 끊는다. 없으면 '로제,Bruno' 같은 데서
| 아무 글자 사이나 끊긴다.
*/
.song-hero-meta {
    margin-top: 15px;
    font-size: 13px; color: var(--label-2); letter-spacing: -0.1px;
    line-height: 1.75;
    word-break: keep-all; overflow-wrap: anywhere;
}
.song-hero-meta .mb { display: inline; }
.song-hero-meta b { font-weight: 600; color: var(--label); }
.song-hero-meta .dot { margin: 0 7px; color: var(--label-3); flex-shrink: 0; }

.song-hero-lyrics {
    margin-top: 14px; padding: 13px 15px;
    background: var(--surface-2);
    border-radius: 12px;
    font-size: 13.5px; line-height: 1.75;
    color: var(--label-2); letter-spacing: -0.2px;
}
.song-hero-lyrics .ly-more { color: var(--label-3); }

/*
| 버튼 줄 — 한 줄에 두 개씩만. 좁은 화면에서 네 개를 한 줄에 밀어 넣으면
| "○○ 곡 더보기" 처럼 긴 글자가 먼저 잘려 나가 뭘 누르는 버튼인지 안 보였다.
|   1줄: 유튜브 보기 / ○○ 곡 더보기   (곡을 듣거나 더 찾는 동작)
|   2줄: 담기 / 공유                  (곡을 챙기거나 건네는 동작)
*/
.song-hero-actions { display: flex; flex-direction: column; gap: 8px; margin-top: 16px; }
.hero-row { display: flex; gap: 8px; }
.hero-btn {
    flex: 1 1 0; min-width: 0;
    height: 40px; padding: 0 14px;
    display: inline-flex; align-items: center; justify-content: center;
    border: 1px solid var(--hairline); border-radius: 11px;
    background: var(--surface); color: var(--label);
    font-size: 13.5px; font-weight: 600; letter-spacing: -0.2px;
    font-family: inherit; cursor: pointer; text-decoration: none;
    transition: all 0.18s var(--ease);
    -webkit-tap-highlight-color: transparent;
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.hero-btn:hover { background: var(--surface-2); border-color: var(--line-2); }
/*
| 유튜브 버튼 — 곡 페이지에서 가장 많이 눌리는 동작인데 옅은 색이라 눈에 안 띄었다.
| 유튜브 고유의 빨강을 그대로 채워 다른 버튼과 위계를 벌린다.
*/
.hero-btn-yt {
    gap: 7px;
    background: #ff0000;
    border-color: #ff0000;
    color: #fff;
    box-shadow: 0 2px 8px rgba(255,0,0,0.24);
}
.hero-btn-yt:hover { background: #e00000; border-color: #e00000; box-shadow: 0 3px 12px rgba(255,0,0,0.32); }
.hero-btn-yt svg { width: 20px; height: 20px; flex-shrink: 0; }

/*
| 담기 버튼 — 노래방 가기 전에 부를 곡을 모아두는 자리.
| 공유와 마찬가지로 폭을 늘리지 않는다. 담긴 뒤에는 눌린 상태가
| 색으로 남아야 "담았나?" 하고 다시 누르는 일이 없다.
*/
.hero-btn-save { gap: 6px; padding: 0 16px; }
.hero-btn-save svg { width: 16px; height: 16px; flex-shrink: 0; }
.hero-btn-save.is-saved {
    background: var(--blue-fill);
    border-color: var(--blue-line);
    color: var(--blue-2);
}

/*
| 공유 버튼 — 곡 번호는 "이거 불러" 하고 건네는 정보라 공유가 자연스럽다.
| 다른 버튼과 달리 폭을 늘리지 않는다 (아이콘 + 두 글자면 충분)
*/
.hero-btn-share { gap: 6px; padding: 0 16px; }
.hero-btn-share svg { width: 15px; height: 15px; flex-shrink: 0; }
/* 복사된 직후 — 토스트를 못 봐도 여기서 알 수 있게 */
.hero-btn-share.is-copied {
    background: var(--green-fill);
    border-color: var(--green-line);
    color: var(--green-2);
}

/*
| 번호 복사 — 담기·공유와 한 줄에 선다.
|
| 노래방 번호는 일행에게 보내는 물건이라, 붙여넣기 한 번이면 끝나는
| 자리를 따로 둔다. 공유 시트는 보낼 곳을 고르게 하는데 대개는 이미
| 대화창이 열려 있다.
*/
.hero-btn-copy { gap: 6px; padding: 0 14px; }
.hero-btn-copy svg { width: 15px; height: 15px; flex-shrink: 0; }
.hero-btn-copy.is-copied {
    background: var(--green-fill);
    border-color: var(--green-line);
    color: var(--green-2);
}

/*
| 다시 찾아오는 길 — 히어로 맨 위, 제목보다도 앞.
|
| 네이버 앱 안의 브라우저에는 즐겨찾기도 홈 화면 추가도 없다. 그래서
| 다시 오는 길을 글자로 알려 주는 수밖에 없다. 초록은 네이버 색이다 —
| '어디서' 검색하라는 말이 글자보다 색으로 먼저 읽힌다.
|
| 회색 바탕에 회색 잔글씨로 두었더니 휴대폰에서 흐릿하게 뭉갰다.
| 11px 에 자간 -0.3px 은 한글에서 획이 서로 붙는다. 글자를 키우고
| 자간을 풀고, 색도 --label-3 에서 본문 색으로 올린다.
|
| 바탕은 회색 대신 네이버 초록을 아주 옅게 깐다. 다른 회색 부품들과
| 섞이지 않아 카드로 읽히고, '네이버' 라는 말이 바탕에서 먼저 온다.
| 진하게 칠하지는 않는다 — 제목 위에 서지만 제목을 이기면 안 된다.
*/
.hero-again {
    display: flex; flex-wrap: wrap; align-items: center;
    gap: 9px 10px; margin: 0 0 14px; padding: 12px 14px;   /* 세로 값은 도장이 아랫줄로 접혔을 때 쓴다 */
    border: 1px solid color-mix(in srgb, #03c75a 24%, transparent);
    border-radius: 13px;
    background: color-mix(in srgb, #03c75a 7%, var(--surface));
    text-decoration: none;
    -webkit-tap-highlight-color: transparent;
    transition: all 0.18s var(--ease);
}
.hero-again:hover {
    background: color-mix(in srgb, #03c75a 12%, var(--surface));
    border-color: color-mix(in srgb, #03c75a 40%, transparent);
}
/*
| 왼쪽 글, 오른쪽 도장.
|
| 글 칸의 기준 폭을 150px 로 둔다 — 360px 화면에서는 도장이 옆에 서고,
| 320px 에서는 자리가 모자라 도장이 아랫줄로 접힌다. 접혀도 margin-left:auto
| 가 오른쪽 끝에 붙여 두므로 '오른쪽 도장' 이라는 꼴은 그대로다.
| 억지로 한 줄에 밀어 넣으면 '네이버에 나만의노래방' 이 잘린다.
*/
.hero-again .ha-txt {
    flex: 1 1 150px; min-width: 0;
    display: flex; flex-direction: column; gap: 3px;
}
/*
| 첫 줄은 자르지 않고 접는다. '다음에도 노래방 번호/영상/뮤비가 필요하면'
| 은 좁은 화면에서 한 줄에 안 들어가는데, '…' 로 잘리면 무엇이 필요할
| 때인지가 사라져 문장이 뜻을 잃는다. 두 줄이 낫다.
*/
.hero-again .ha-t {
    font-size: 12.5px; font-weight: 500; letter-spacing: -0.1px; line-height: 1.4;
    color: var(--label-2); word-break: keep-all;
}
/*
| '네이버에' 와 '나만의노래방' 은 무게가 다르다. 앞은 어디서인지고 뒤는
| 외워 가야 할 낱말이다. 같은 크기로 두면 둘 다 그냥 한 줄로 읽히므로
| 외울 쪽만 키운다 — 글자를 통째로 키우는 것보다 이게 더 크게 보인다.
*/
.hero-again .ha-q {
    display: flex; align-items: center; gap: 4px; min-width: 0;
    font-size: 13.5px; font-weight: 600; letter-spacing: -0.2px; color: var(--label-2);
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.hero-again .ha-q b { font-size: 16.5px; color: #03c75a; font-weight: 800; letter-spacing: -0.4px; }
.hero-again .ha-q svg { flex: 0 0 auto; width: 15px; height: 15px; color: #03c75a; }

/*
| 주소 도장.
|
| 곡 카드 맨 위 강조선과 같은 그러데이션을 채운다 — 이 사이트에서 가장
| 눈에 띄는 색이고, 이미 이 카드 위에 한 번 쓰여 있어 낯설지 않다.
| 초록(네이버)과 색이 갈라져야 '어디서' 와 '무엇을' 이 안 섞인다.
|
| 로마자는 Roboto 다. 본문 한글 글꼴로 주소를 쓰면 자간이 벌어져
| 낱말이 아니라 글자 열한 개로 읽힌다.
*/
.hero-again .ha-brand {
    flex: 0 0 auto; margin-left: auto;
    padding: 6px 11px; border-radius: 9px;
    background: linear-gradient(135deg, var(--blue), var(--purple));
    color: #fff;
    font-family: 'Roboto', system-ui, sans-serif;
    font-size: 14px; font-weight: 700; letter-spacing: -0.2px; line-height: 1;
    white-space: nowrap;
    box-shadow: 0 2px 8px color-mix(in srgb, var(--purple) 32%, transparent);
}

/*
| 목록을 통째로 건네는 공유 (주제별 인기곡).
| "여름에 뭐 부르지?" 하는 사람에게는 곡 하나보다 목록 하나가 답이다.
|
| 곡 공유와 달리 제목 아래 버튼 줄을 새로 만들지 않는다. 버튼 하나 때문에
| 줄 하나가 통째로 생겨 여백만 벌어졌다. 원래 태그 하나와 닫기(✕) 뿐이라
| 가운데가 비어 있던 태그 줄로 올린다 — 새로 차지하는 세로 공간이 없다.
| 그래서 크기도 hero-btn(40px) 이 아니라 그 줄의 부품들(26px)에 맞춘다.
*/
.hero-head-share {
    margin-left: auto;                 /* 태그는 왼쪽, 공유·닫기는 오른쪽 */
    height: 26px; padding: 0 11px; gap: 5px;
    display: inline-flex; align-items: center;
    border: 1px solid var(--hairline); border-radius: 20px;
    background: var(--surface); color: var(--label-2);
    font-size: 12px; font-weight: 600; letter-spacing: -0.2px;
    font-family: inherit; cursor: pointer;
    transition: all 0.18s var(--ease);
    -webkit-tap-highlight-color: transparent;
}
.hero-head-share svg { width: 12px; height: 12px; flex-shrink: 0; }
/* inline-flex 를 지정했으므로 hidden 을 여기서 다시 눌러 준다 */
.hero-head-share[hidden] { display: none; }
.hero-head-share:hover { background: var(--surface-2); color: var(--label); border-color: var(--line-2); }
/* 복사된 직후 — hero-btn-share 와 같은 신호를 쓴다 */
.hero-head-share.is-copied {
    background: var(--green-fill);
    border-color: var(--green-line);
    color: var(--green-2);
}

/* 링크 복사처럼 되돌릴 것 없는 알림 — 잠깐 떴다 사라진다 */
.toast {
    position: fixed; left: 50%; bottom: 84px;
    transform: translateX(-50%) translateY(8px);
    background: rgba(28,28,30,0.94);
    -webkit-backdrop-filter: blur(12px); backdrop-filter: blur(12px);
    color: #fff; font-size: 13.5px; font-weight: 500; letter-spacing: -0.2px;
    padding: 11px 18px; border-radius: 22px;
    box-shadow: 0 8px 28px rgba(0,0,0,0.25);
    z-index: 400; pointer-events: none;
    opacity: 0; transition: opacity 0.22s var(--ease), transform 0.22s var(--ease);
}
.toast.show { opacity: 1; transform: translateX(-50%) translateY(0); }

/* 기본값의 -8px 은 곡 카드 바로 아래에 붙일 때를 위한 값이다.
   목록(그리드·리스트) 뒤에 올 때는 당겨 붙이면 안 되므로 되돌린다. */
/* 가수 소개 — 이름 오른쪽 여백 활용 */
.singer-hero-body { display: flex; align-items: flex-start; gap: 22px; }
.singer-hero-main { flex-shrink: 0; min-width: 0; }
.sp {
    flex: 1; min-width: 0;
    padding-left: 22px; border-left: 1px solid var(--hairline);
    animation: spIn 0.35s var(--ease);
}
.sp[hidden] { display: none; }
@keyframes spIn { from { opacity: 0; transform: translateY(4px); } to { opacity: 1; transform: none; } }
.sp-meta {
    display: flex; flex-wrap: wrap; align-items: baseline;
    font-size: 12px; font-weight: 600; color: var(--blue);
    letter-spacing: -0.1px; margin-bottom: 6px; line-height: 1.7;
}
.sp-meta .mb  { display: inline; }
.sp-meta .dot { margin: 0 6px; color: var(--label-3); flex-shrink: 0; }
.sp-intro {
    margin: 0; font-size: 13.5px; line-height: 1.62;
    color: var(--label-2); letter-spacing: -0.2px;
}
.sp-hits {
    margin-top: 9px; font-size: 12.5px; color: var(--label-2);
    letter-spacing: -0.2px;
}
.sp-hits span {
    display: inline-block; margin-right: 8px;
    font-size: 10.5px; font-weight: 700; color: var(--label-3);
    letter-spacing: 0.2px;
}
.sp-alias { margin-bottom: 7px; font-size: 12.5px; color: var(--label-2); letter-spacing: -0.2px; }
.sp-rel { margin-top: 9px; font-size: 12.5px; letter-spacing: -0.2px; }
.sp-rel a {
    display: inline-block; margin-right: 6px;
    color: var(--blue); text-decoration: none; font-weight: 500;
}
.sp-rel a:hover { text-decoration: underline; }
.sp-alias span, .sp-rel span {
    display: inline-block; margin-right: 8px;
    font-size: 10.5px; font-weight: 700; color: var(--label-3); letter-spacing: 0.2px;
}
.sp-note { margin-top: 9px; font-size: 11px; color: var(--label-3); }

/* 좁은 화면 — 아래로 흐르게 */
@media (max-width: 620px) {
    .singer-hero-body { flex-direction: column; gap: 14px; }
    .sp {
        padding-left: 0; border-left: none;
        padding-top: 14px; border-top: 1px solid var(--hairline);
        width: 100%;
    }
}

.hero-backlink { margin: -8px 0 20px; text-align: center; }
/* 목록 뒤에 올 때는 띄운다 — 작곡가의 다른 곡(.comp-list)이 나중에 생기면서 빠져 있었다 (2026-09-15) */
.also-list + .hero-backlink,
.comp-list + .hero-backlink,
.singer-songs + .hero-backlink { margin-top: 22px; }
.hero-backlink a {
    font-size: 13.5px; font-weight: 500;
    color: var(--label-2); text-decoration: none;
    letter-spacing: -0.2px;
    padding: 7px 14px; border-radius: 20px;
    transition: background 0.15s, color 0.15s;
    -webkit-tap-highlight-color: transparent;
}
.hero-backlink a:hover { background: var(--fill); color: var(--label); }

/* 곡을 찾지 못한 경우 */
.song-hero-miss { text-align: center; padding: 26px 22px; }
.song-hero-miss .miss-text { margin: 0 0 6px; font-size: 15.5px; font-weight: 600; }
.song-hero-miss .miss-sub  { margin: 0; font-size: 13.5px; color: var(--label-2); }

@media (max-width: 420px) {
    .song-hero { padding: 14px 14px 13px; border-radius: 17px; }
    .song-hero-title { font-size: 21px; }
    .num-value { font-size: 21px; }
    .num-tile.num-multi .num-value { font-size: 16px; }
    .hero-btn { min-width: 0; }
    /*
    | 복사·담기·공유 셋이 한 줄이다. 320px 에서는 칸이 94px 인데
    | '번호 복사' 는 그림까지 109px 라 '번호 복…' 으로 잘렸다.
    | 그림을 빼면 글자가 온전히 들어간다 — 잘린 글자보다 낫다.
    */
    .hero-btn-copy svg, .hero-btn-save svg, .hero-btn-share svg { display: none; }
    .hero-btn-copy, .hero-btn-save, .hero-btn-share { padding: 0 8px; }
}

/*
| 좁은 화면에서는 글자를 줄이지 않고 키운다.
|
| 도장을 글 옆에 붙여 두려니 360px 에서 남는 폭이 160px 뿐이라 글자를
| 계속 깎아야 했다. 첫 화면에 놓은 판인데 잔글씨로 뭉개지면 놓아 둔
| 뜻이 없다. 그래서 도장을 아랫줄로 내리고 — margin-left:auto 가
| 오른쪽 끝에 붙여 두므로 도장 자리는 그대로다 — 폭을 통째로 글에 준다.
|
| 줄이 하나 늘지만 넉 줄이라도 다 읽히는 편이 석 줄이 흐린 것보다 낫다.
*/
@media (max-width: 440px) {
    /*
    | 좁은 화면에서는 격자로 바꾼다.
    |
    | 넓은 화면의 '왼쪽 글 · 오른쪽 도장' 은 좁아지면 도장이 셋째 줄로
    | 밀려 카드가 쓸데없이 길어졌다. 안내문만 위에서 두 줄로 접고,
    | '네이버에 나만의노래방' 과 주소 도장은 같은 줄에 나란히 세운다.
    | .ha-txt 는 display:contents 로 껍데기만 지워 두 자식이 이 격자에
    | 직접 들어오게 한다 — 표시를 옮기려고 마크업을 흔들 필요가 없다.
    */
    .hero-again {
        display: grid; grid-template-columns: 1fr auto;
        align-items: center; gap: 4px 10px; padding: 10px 13px;
    }
    .hero-again .ha-txt { display: contents; }
    .hero-again .ha-t { grid-column: 1 / -1; font-size: 13.5px; line-height: 1.45; }
    .hero-again .ha-q { font-size: 14px; }
    .hero-again .ha-q b { font-size: 18px; }
    .hero-again .ha-q svg { width: 16px; height: 16px; }
    .hero-again .ha-brand { margin-left: 0; font-size: 14.5px; padding: 5px 10px; }
}

/*
| 검색창 밑의 가사 찾기 안내.
|
| 눈에 띄되 검색창을 이기면 안 된다. 이 줄은 '여기 말고 저기' 라는
| 뜻이라, 검색창보다 앞서 읽히면 정작 곡을 아는 사람까지 헷갈린다.
| 글자만 두고 테두리는 안 준다.
*/
/*
| 검색창 밑의 가사 찾기 문.
|
| 처음에는 회색 글줄로 뒀는데 아무도 못 볼 모양이었다. 이 줄이 말을
| 거는 상대는 '무엇을 넣어야 할지 몰라 검색창을 보고만 있는 사람' 이라,
| 눈에 안 들어오면 있으나 마나다.
|
| 그렇다고 검색창을 이기면 안 된다. 그래서 크기는 그대로 두고 '눌러지는
| 것' 이라는 꼴만 준다 — 테두리, 둥근 모서리, 화살표. 색은 파랑을 옅게
| 깔아 이 사이트의 것임을 보이되 채우지는 않는다.
*/
.lyr-hint {
    display: inline-flex; align-items: center; gap: 5px;
    margin: 9px 0 0; padding: 6px 12px;
    border: 1px solid var(--blue-line); border-radius: 999px;
    background: var(--blue-fill);
    font-size: 12.5px; letter-spacing: -0.3px; color: var(--label-2);
    text-decoration: none; -webkit-tap-highlight-color: transparent;
    transition: background 0.15s, border-color 0.15s;
}
/*
| 가사 알약과 가수 찾기를 한 줄에 (2026-09-11).
| 둘 다 '무엇을 넣을지 모르겠다' 에 답하는 길이라 나란히 둔다.
| 좁으면 접히게 두되, 접혀도 알약 모양은 그대로다.
*/
.hint-row { display: flex; flex-wrap: wrap; gap: 6px; align-items: center; }
.hint-row .lyr-hint { margin: 9px 0 0; }
/* 가수 쪽은 글이 짧아 색을 한 단 낮춘다 — 가사 쪽이 주된 길이다 */
.hint-singer { background: var(--fill); border-color: var(--hairline); }
.hint-singer b { color: var(--label-2); }
.hint-singer:hover { background: var(--label-2); border-color: var(--label-2); }
.hint-singer.active { background: var(--label-2); border-color: var(--label-2); color: #fff; }
.hint-singer.active b { color: #fff; }

.lyr-hint b { color: var(--blue); font-weight: 700; }
.lyr-hint:hover { background: var(--blue); border-color: var(--blue); color: rgba(255,255,255,0.82); }
.lyr-hint:hover b { color: #fff; }

/*
| 검색 결과가 없을 때 뜨는 다음 수.
|
| 여기는 화면에 다른 볼 것이 없는 자리라 크게 잡아도 방해가 안 된다.
| 오히려 '없습니다' 한 줄만 두고 끝내는 것이 손님을 내보내는 짓이다.
*/
.empty-lyr {
    display: block; margin: 10px 0 0; padding: 18px 18px 16px;
    border: 1px solid var(--blue-line); border-radius: 16px;
    background: linear-gradient(160deg, var(--blue-fill), transparent 70%), var(--surface);
    text-decoration: none; text-align: center;
    -webkit-tap-highlight-color: transparent;
}
.empty-lyr b {
    display: block; font-size: 16px; font-weight: 700; letter-spacing: -0.4px;
    color: var(--label); margin-bottom: 5px;
}
.empty-lyr span {
    display: block; font-size: 13px; color: var(--label-2); letter-spacing: -0.2px;
    margin-bottom: 13px;
}
.empty-lyr em {
    display: inline-flex; align-items: center; gap: 4px;
    padding: 9px 18px; border-radius: 999px;
    background: var(--blue); color: #fff;
    font-style: normal; font-size: 13.5px; font-weight: 700; letter-spacing: -0.2px;
}
.empty-lyr:active em { transform: translateY(0.5px); }

/* ── 인기곡 섹션 ── */

.hit-section { margin-top: 10px; }

.genre-wrap {
    position: relative;
    display: flex; align-items: center;
    margin-bottom: 14px;
    gap: 5px;
}

.genre-arrow {
    flex-shrink: 0;
    width: 28px; height: 32px;
    border: 1px solid var(--hairline);
    border-radius: var(--radius-s);
    background: var(--surface); color: var(--label-2);
    font-size: 14px; cursor: pointer;
    display: none;
    align-items: center; justify-content: center;
    -webkit-tap-highlight-color: transparent;
    transition: background 0.15s, color 0.15s;
}
.genre-arrow:hover { background: var(--surface-hover); color: var(--label); }

.genre-scroll {
    flex: 1;
    display: flex; gap: 7px;
    overflow-x: auto; padding-bottom: 4px;
    scrollbar-width: none;
    scroll-behavior: smooth;
}
.genre-scroll::-webkit-scrollbar { display: none; }

/* 주제 목록 위의 주제 바꾸기 줄 — 장르 칩과 같은 부품을 쓴다 */
/* 좌우 버튼과 높이를 맞추려면 장르 줄(.genre-wrap)과 같은 정렬이 필요하다 */
.theme-chips { margin: 0 0 13px; display: flex; align-items: center; gap: 5px; }
/*
| 장르 줄과 같이 가로로 흐른다.
|
| 처음에는 접어 내렸다 — 선택지가 한눈에 다 보이는 편이 낫다고 봤다.
| 그런데 휴대폰에서 네댓 줄을 차지해 곡 목록이 화면 밖으로 밀렸다.
| 목록을 보러 온 사람에게는 그게 더 나쁘다. 대신 열릴 때 선택된 주제가
| 화면 가운데로 오도록 자동으로 굴려 준다 (app.js centerActiveChip).
*/
.theme-chips .genre-scroll {
    flex-wrap: nowrap;
    overflow-x: auto;
    padding-bottom: 2px;
    scroll-behavior: smooth;
    -webkit-overflow-scrolling: touch;
    /* 끝에 닿았는지 알 수 있게 살짝 여백을 준다 */
    scroll-padding: 0 12px;
}
/* 좁은 화면에서 칩이 눌려 찌그러지지 않게 */
.theme-chips .genre-chip { flex: 0 0 auto; }

@media (hover: hover) {
    .genre-arrow { display: flex; }
}

/*
| 더 있다는 표시 — 손가락으로 미는 화면 전용.
|
| 좌우 버튼(.genre-arrow)은 (hover: hover) 안에 있어 PC 에만 나온다.
| 휴대폰에서는 칩 줄이 오른쪽으로 더 이어지는지 알 길이 아예 없었다.
| 화면 폭에 딱 맞게 잘린 줄은 '이게 전부' 로 보인다.
|
| 그래서 오른쪽 끝을 배경색으로 흐리고 겹화살표를 얹는다. 흐림이 있어야
| 칩이 잘린 게 아니라 이어진다는 뜻이 된다 — 화살표만 놓으면 그냥 칩
| 하나로 읽힌다. 끝까지 밀면 사라지므로 남았는지 아닌지가 늘 맞는다.
|
| pointer-events: none 이 꼭 필요하다. 이 띠는 마지막 칩 위를 덮으므로
| 안 그러면 눌러야 할 칩이 안 눌린다.
*/
/*
| 손가락 기기에서만 '» 더 있음' 을 띄운다.
|
| 원래 (hover: none) 으로 걸었는데, 네이버 앱 인앱 브라우저가 손가락뿐인
| 폰에서도 hover:hover 라고 답한다(기기 실측). 그래서 이 블록이 통째로
| 안 걸려, 주력 유입인 네이버 앱에서만 이 표시가 안 보이고 있었다.
| 자바스크립트의 isTouchDevice() 와 같은 기준(pointer)으로 맞춘다.
*/
@media (pointer: coarse) {
    .genre-wrap, .theme-chips { position: relative; }
    .genre-wrap::after, .theme-chips::after {
        content: '\00BB';
        position: absolute; top: 0; right: 0; bottom: 0;
        z-index: 2; pointer-events: none;
        width: 46px;
        display: flex; align-items: center; justify-content: flex-end;
        padding-right: 4px; padding-bottom: 4px;
        background: linear-gradient(to right,
            color-mix(in srgb, var(--bg) 0%, transparent), var(--bg) 62%);
        color: var(--label-2);
        font-size: 15px; font-weight: 700; line-height: 1;
        opacity: 0; transition: opacity 0.18s var(--ease);
    }
    .genre-wrap.chip-more::after, .theme-chips.chip-more::after { opacity: 1; }
}

.genre-chip {
    height: 33px; padding: 0 15px;
    display: inline-flex; align-items: center; justify-content: center;
    text-decoration: none;
    border: 1px solid var(--hairline);
    border-radius: 20px; font-size: 13.5px; font-weight: 500;
    letter-spacing: -0.2px;
    cursor: pointer; white-space: nowrap; flex-shrink: 0;
    background: var(--surface); color: var(--label-2);
    transition: background 0.2s var(--ease), color 0.2s var(--ease), border-color 0.2s var(--ease);
    -webkit-tap-highlight-color: transparent;
    font-family: inherit;
}
.genre-chip:hover { background: var(--surface-hover); color: var(--label); }
.genre-chip.active-ky { background: var(--blue); color: white; border-color: var(--blue); font-weight: 600; }
.genre-chip.active-tj { background: var(--purple); color: white; border-color: var(--purple); font-weight: 600; }
/*
| 눌린 칩 안의 곡 수도 흰색으로 (2026-09-11).
|
| .th-n 은 제 색(--label-3, 회색)을 직접 들고 있다. 직접 준 색은 물려받는
| 색을 언제나 이기므로, 칩이 파래지면서 이름만 희어지고 '(91)' 은 회색으로
| 남았다. 파란 바탕에 회색이라 읽히지가 않았다.
|
| 크기가 0.85em 이고 괄호를 두르고 있어, 같은 흰색이어도 이름이 앞선다.
| 색을 흐려서까지 순서를 만들 이유가 없다 — 읽히는 것이 먼저다.
*/
.genre-chip.active-ky .th-n,
.genre-chip.active-tj .th-n { color: #fff; }

.cls-btn-row { display: flex; gap: 7px; margin-bottom: 11px; flex-wrap: wrap; }
/*
| 인기곡 머리의 두 줄은 '버튼 → 칩' 순서다.
|
| 붙어 있는 두 줄이므로 사이 여백은 줄이고, 곡 목록과의 사이만 남긴다.
| 한때 칩을 위로 올려 봤으나 되돌렸다.
*/
#hitNav .cls-btn-row { margin-bottom: 8px; }
#hitNav .genre-wrap { margin-bottom: 13px; }
/*
| 검색 중에는 내비와 결과 사이를 좁힌다 (2026-09-11).
|
| 평소에는 이 아래로 제목(h2)이나 주제 격자가 오므로 14px 이 맞다. 그런데
| 검색 결과에서는 h1 도 제목도 없이 '12곡 검색됨' 한 줄이 바로 온다.
| 얇은 줄 위에 두꺼운 여백이 얹히면 그 줄이 떠 보인다.
|
| is-searching 은 showResultMode/showHitMode 가 <body> 에 붙인다.
*/
/* #hitNav .genre-wrap 이 ID 로 13px 을 박아 둬서(특정도 1,1,0) 클래스만으로는
   못 이긴다. 같은 ID 를 끼워 (1,2,1) 로 올린다. */
body.is-searching #hitNav .genre-wrap { margin-bottom: 8px; }
/*
| 칩 넷(가수 찾기·주제별·일본애니·7080)의 폭이 360px 화면의 328px 를
| 10px 넘겨 마지막 하나가 혼자 다음 줄로 넘어갔다. 글자는 그대로 두고
| 좌우 여백만 깎는다 — 글자를 줄이면 네 칩이 다 흐려진다.
|
| 2026-09-07: 넷째 칩이 '7080'(숫자 넉 자, 약 30px) 에서 '그룹사운드'
| (한글 다섯 자, 약 68px) 로 바뀌면서 다시 8px 쯤 넘쳤다. 같은 처방을
| 한 번 더 쓴다 — 여백 11→9px, 사이 7→6px 로 약 27px 을 돌려받는다.
| 360px 에서 10px 남는다. 320px(iPhone SE) 에서는 여전히 두 줄이 되는데,
| 넘치면 다음 줄로 흐르므로 깨지지는 않는다.
*/
/* <a> 와 <button> 이 섞여 있어 정렬·밑줄 규칙을 공통으로 둔다.
   (개별 클래스에만 두면 새 버튼을 추가할 때마다 어긋난다) */
.cls-btn {
    display: inline-flex; align-items: center; justify-content: center;
    height: 33px; padding: 0 16px;
    border: 1px solid var(--hairline);
    border-radius: 20px; font-size: 13.5px; font-weight: 500;
    letter-spacing: -0.2px; text-decoration: none;
    cursor: pointer; white-space: nowrap;
    background: var(--surface); color: var(--label-2);
    transition: all 0.2s var(--ease); -webkit-tap-highlight-color: transparent;
    font-family: inherit;
}
/*
| 좁은 화면 여백 — 위 주석의 처방. 이 규칙은 반드시 .cls-btn 기본값 '뒤' 에 둔다 (2026-09-15).
| 특정도가 같아 앞에 두면 기본값(16px)이 이긴다 — 실제로 이 규칙이 한 번도 안 먹고 있었다.
| KPOP 이 들어와 단추가 다섯이 되어(주제별·KPOP·남녀인기·그룹·일본애니) 여백을 더 줄였다.
| 390·360px 한 줄, 320px 은 글자까지 조금 줄여 한 줄.
*/
@media (max-width: 400px) {
    .cls-btn     { padding: 0 8px; }
    .cls-btn-row { gap: 5px; }
}
@media (max-width: 350px) {
    .cls-btn     { padding: 0 6px; font-size: 12.5px; letter-spacing: -0.4px; }
    .cls-btn-row { gap: 4px; }
}
.cls-btn:hover { border-color: var(--line-2); color: var(--label); }
.cls-btn.active {
    background: var(--green-fill);
    color: var(--green);
    border-color: var(--green-line);
    font-weight: 600;
}

.hit-list { }

/*
| 목록 한 줄 — 제목을 맨 윗줄에 통째로 준다.
|
| 예전에는 [순위][제목/가수][하트·유튜브·번호] 를 가로로 늘어놓았는데,
| 360px 화면에서 오른쪽 덩어리가 166px 을 가져가 제목에 84px(한글 5.5자)
| 밖에 남지 않았다. 곡의 65% 가 7자 이상이라 사실상 전부 잘렸다.
|
| 그래서 grid 로 바꾸고 제목을 첫 줄 전체에 깔았다.
|
|   [1] 좋은 날 (Good Day)
|   [ ] 아이유 · 가사 한 조각 …
|   [ ] KY 77713  TJ 32235              ♡  ▶
|
| .hit-right 는 display:contents 로 껍데기를 지워 그 안의 셋(하트·유튜브·
| 번호)이 각자 grid 칸에 놓이게 한다.
*/
.hit-item {
    position: relative;
    display: grid;
    grid-template-columns: auto minmax(0, 1fr) auto auto;
    grid-template-areas:
        "rank title info  sng"
        "rank sub   sub   sub"
        "rank nums  fav   yt";
    align-items: center;
    column-gap: 9px; row-gap: 5px;
    padding: 11px 13px; margin-bottom: 7px;
    background: var(--surface);
    border: 1px solid var(--line);
    border-radius: var(--radius-m);
    box-shadow: var(--card-shadow);
    -webkit-tap-highlight-color: transparent;
    transition: background 0.15s;
}
.hit-item:hover { background: var(--surface-hover); }

.hit-rank {
    grid-area: rank;
    font-size: 15px; font-weight: 600;
    font-family: 'Roboto', sans-serif;
    width: 24px; text-align: center;
    color: var(--label-3);
    font-variant-numeric: tabular-nums;
}
.hit-rank.top3 { color: var(--orange); font-weight: 700; }

/* 곡 상세(?v=&sn=)로 가는 링크 — 크롤러 내부 링크 겸용.
   ::after 로 카드 전체를 덮어 여백을 눌러도 넘어가게 한다. 링크는 여전히
   하나라 색인에 군더더기가 생기지 않는다. */
.hit-link { grid-area: title; display: block; min-width: 0; text-decoration: none; color: inherit; }
.hit-link::after { content: ''; position: absolute; inset: 0; border-radius: inherit; }

.hit-title  { font-size: 15.5px; font-weight: 600; letter-spacing: -0.2px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.hit-sub    { grid-area: sub; min-width: 0; }
.hit-singer { font-size: 14px; font-weight: 600; color: var(--label-2); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }

.hit-singer-row {
    display: flex; align-items: baseline; gap: 7px;
    min-width: 0;
}
.hit-singer-row .hit-singer { flex-shrink: 0; max-width: 45%; }
.hit-lyrics {
    color: var(--label-2); font-size: 13px; font-weight: 500;
    letter-spacing: -0.1px;
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
    flex: 1; min-width: 0;
}

/* 껍데기를 지워 자식 셋이 직접 grid 항목이 된다 */
.hit-item .hit-right { display: contents; }
/* 카드를 덮은 ::after 위로 올려야 눌린다.
   justify-self:center 는 칸 안에서 가운데로 놓는 것 — 위 줄의 '곡정보'·'가수정보'
   단추가 칸 너비를 정하는데 이 둘은 33px 고정이라, 그냥 두면 칸 왼쪽에 붙어
   위아래 가운데선이 어긋난다. */
.hit-item .fav-btn { grid-area: fav; position: relative; z-index: 1; justify-self: center; }
.hit-item .yt-btn  { grid-area: yt;  position: relative; z-index: 1; justify-self: center; }

/* 세로 쌓기 → 가로 나란히. min-width:86px 는 세로일 때 자릿수를 맞추려던
   값이라 가로에서는 빈칸만 만든다. */
.hit-item .num-pair { grid-area: nums; flex-direction: row; gap: 13px; }
.hit-item .np       { min-width: 0; gap: 4px; }
.hit-item .np-value { flex: none; text-align: left; }



/* ── 검색 결과 ── */

/*
| 위 간격은 내비(.genre-wrap)가 이미 내고 있다. 여기서 또 주면 겹친다
| — 인접 형제라 margin 은 큰 쪽으로 합쳐지지만, 0 으로 두는 편이 뜻이 맞다.
*/
.result-list { margin-top: 0; }

/*
| 곡 수 줄 — 얇게 (2026-09-11).
|
| 글자는 13px 한 줄인데 줄 키는 29px 이었다. 옆 단추 둘이 키를 정하기
| 때문이다. 글자 위아래로 8px 씩 빈 것처럼 보여, 결과 목록이 시작되기 전에
| 한 뼘이 비었다. 단추를 25px 로 낮추고 아래 여백도 11 → 7px 로 줄인다.
|
| 단추 글자(12.5px)는 그대로다. 누를 것은 여전히 누를 만해야 한다 —
| 25px 이면 손가락 목표로 작지만, 이 둘은 곁가지고 본체는 아래 목록이다.
*/
.result-stat {
    display: flex; align-items: center; justify-content: space-between;
    gap: 8px;
    font-size: 13px; color: var(--label-3);
    margin-bottom: 7px; padding: 0 4px;
    letter-spacing: -0.1px;
}
/*
| 곡 수는 줄어들 수 있고 단추는 줄어들면 안 된다.
| 좁은 화면에서 'AI 추천 39곡 검색됨 · 0.21초' 가 길어져도 단추를 밀어내지
| 않도록, 글자 쪽만 말줄임으로 접는다.
*/
.result-stat .rs-count { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/*
| '가사만 검색' 과 '공유' 를 한 덩이로 묶는다 (2026-09-11).
|
| 공유 버튼은 원래 제목 줄에 홀로 있었다. 검색 결과에서 제목을 내리자 그
| 줄을 통째로 먹길래 여기로 내렸다. 둘 다 '이 결과를 어떻게 할까' 를 묻는
| 단추라 나란히 두는 편이 읽기도 낫다.
*/
.result-stat .rs-btns { display: flex; align-items: center; gap: 6px; flex-shrink: 0; }
/* 제목 줄에서는 오른쪽 끝으로 밀려나야 했지만, 여기서는 묶음이 이미 오른쪽이다 */
.result-stat .hero-head-share { margin-left: 0; height: 25px; }

.lyrics-search-btn {
    font-size: 12.5px; font-weight: 500;
    padding: 4px 12px;          /* 옆 공유 단추와 같은 25px 이 되게 */
    border: 1px solid var(--hairline);
    border-radius: 20px; cursor: pointer;
    background: var(--surface); color: var(--label-2);
    white-space: nowrap; flex-shrink: 0;
    -webkit-tap-highlight-color: transparent;
    transition: all 0.2s var(--ease);
    font-family: inherit;
}
.lyrics-search-btn:active { background: var(--surface-hover); }
.lyrics-search-btn.active {
    background: var(--blue); color: white;
    border-color: var(--blue); font-weight: 600;
}

/*
| 검색 결과 한 장 — 목록(.hit-item)과 같은 규칙으로 제목을 첫 줄 전체에 준다.
| 예전 가로 배치에서는 360px 화면에서 제목에 118px(한글 7자)밖에 남지 않았다.
|
|   [제목 ─────────────────────────────────]
|   [가수 · 가사 한 조각 ───────────────────]
|   [KY 77713  TJ 32235              ♡  ▶ ]
|   [작곡 : … | 작사 : …]
*/
.song-item {
    position: relative;
    display: grid;
    grid-template-columns: minmax(0, 1fr) auto auto;
    grid-template-areas:
        "title info  sng"
        "sub   sub   sub"
        "nums  fav   yt"
        "meta  meta  meta";
    align-items: center;
    column-gap: 10px; row-gap: 5px;
    background: var(--surface);
    border: 1px solid var(--line);
    border-radius: var(--radius-l);
    padding: 15px 16px; margin-bottom: 9px;
    box-shadow: var(--card-shadow);
    -webkit-tap-highlight-color: transparent;
    transition: background 0.15s;
}
.song-item:hover { background: var(--surface-hover); }

.song-item > .hit-link { grid-area: title; }
.song-title  { font-size: 17px; font-weight: 600; letter-spacing: -0.3px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.song-sub    { grid-area: sub; min-width: 0; }
.song-singer { color: var(--label-2); font-size: 15px; font-weight: 600; letter-spacing: -0.2px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }

.song-singer-row {
    display: flex; align-items: baseline; gap: 8px;
    min-width: 0;
}
.song-lyrics {
    color: var(--label-2); font-size: 13.5px; font-weight: 500;
    letter-spacing: -0.1px;
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
    flex: 1; min-width: 0;
}

.song-item .song-right { display: contents; }
.song-item .fav-btn { grid-area: fav; position: relative; z-index: 1; justify-self: center; }
.song-item .yt-btn  { grid-area: yt;  position: relative; z-index: 1; justify-self: center; }
.song-item .num-pair { grid-area: nums; flex-direction: row; gap: 13px; }
.song-item .np       { min-width: 0; gap: 4px; }
.song-item .np-value { flex: none; text-align: left; }


.song-number {
    min-width: 76px; text-align: center;
    padding: 8px 11px; border-radius: 10px;
    font-size: 15px; font-weight: 700;
    font-family: 'Roboto', sans-serif;
    letter-spacing: 0.3px;
    font-variant-numeric: tabular-nums;
}
.song-number-ky { background: var(--blue); color: white; }
.song-number-tj { background: var(--purple); color: white; }

.song-meta {
    grid-area: meta;
    margin-top: 7px; padding-top: 10px;
    border-top: 1px solid var(--hairline);
    font-size: 12.5px; color: var(--label-3);
    letter-spacing: -0.1px;
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}

.empty   { text-align: center; padding: 64px 20px; color: var(--label-3); font-size: 15px; }
.loading { text-align: center; padding: 28px; color: var(--label-3); font-size: 14px; }

/* 가수 페이지 / 가수 목록 */
.singer-hero { margin-bottom: 10px; }
.singer-songs { margin-bottom: 6px; }

.singer-more { margin: 10px 0 0; text-align: center; font-size: 12.5px; color: var(--label-3); }

.hub-grid {
    display: grid; grid-template-columns: repeat(auto-fill, minmax(72px, 1fr));
    gap: 8px; margin-bottom: 18px;
}
.hub-cell {
    display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 2px;
    padding: 12px 6px; text-decoration: none;
    background: var(--surface); border: 1px solid var(--hairline);
    border-radius: var(--radius-m); box-shadow: var(--card-shadow);
    transition: background 0.15s, border-color 0.15s;
    -webkit-tap-highlight-color: transparent;
}
.hub-cell:hover { background: var(--surface-hover); border-color: var(--line-2); }
.hub-key { font-size: 17px; font-weight: 700; color: var(--label); letter-spacing: -0.3px; }
.hub-cnt { font-size: 11.5px; color: var(--label-3); font-family: 'Roboto', sans-serif; }

.hub-nav { display: flex; flex-wrap: wrap; gap: 6px; margin-bottom: 14px; }
.hub-chip {
    display: inline-flex; align-items: center; justify-content: center;
    min-width: 32px; height: 30px; padding: 0 9px;
    border: 1px solid var(--hairline); border-radius: 8px;
    background: var(--surface); color: var(--label-2);
    font-size: 13px; font-weight: 600; text-decoration: none;
    transition: all 0.15s; -webkit-tap-highlight-color: transparent;
}
.hub-chip:hover { background: var(--surface-hover); color: var(--label); }
.hub-chip.active { background: var(--blue); border-color: var(--blue); color: #fff; }
/* KPOP '전체·남자·여자' — 단추로 쓰는 칩 (2026-09-15) */
button.hub-chip { font-family: inherit; cursor: pointer; gap: 4px; padding: 0 12px; }
.tt-filter { margin: 2px 0 12px; }
.tt-filter .hub-cnt { font-size: 11.5px; font-weight: 600; }
.tt-filter .hub-chip.active .hub-cnt { color: #fff; opacity: 0.85; }
.theme-tiles .tt[hidden] { display: none; }

.singer-list {
    display: grid; grid-template-columns: repeat(auto-fill, minmax(160px, 1fr));
    gap: 7px;
}
.singer-cell {
    display: flex; align-items: center; justify-content: space-between; gap: 8px;
    padding: 11px 13px; text-decoration: none;
    background: var(--surface); border: 1px solid var(--line);
    border-radius: var(--radius-m); box-shadow: var(--card-shadow);
    transition: background 0.15s;
    -webkit-tap-highlight-color: transparent;
}
.singer-cell:hover { background: var(--surface-hover); }
.sc-name {
    font-size: 14.5px; font-weight: 500; color: var(--label); letter-spacing: -0.2px;
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.sc-cnt {
    flex-shrink: 0; font-size: 11.5px; font-weight: 600;
    color: var(--label-3); font-family: 'Roboto', sans-serif;
    background: var(--fill); padding: 2px 7px; border-radius: 20px;
}

/* 차트 탭 */
.chart-tabs {
    display: flex; gap: 2px; margin: 4px 0 12px;
    background: var(--fill); border-radius: 11px; padding: 3px;
}
.chart-tab {
    flex: 1; height: 36px; border: none; border-radius: 9px;
    display: inline-flex; align-items: center; justify-content: center; gap: 6px;
    background: transparent; color: var(--label-2);
    font-size: 14px; font-weight: 600; letter-spacing: -0.2px;
    font-family: inherit; cursor: pointer;
    transition: background 0.2s var(--ease), color 0.2s var(--ease), box-shadow 0.2s var(--ease);
    -webkit-tap-highlight-color: transparent;
}
.chart-tab.active {
    background: var(--surface); color: var(--label);
    box-shadow: 0 1px 4px rgba(0,0,0,0.12);
}
.chart-sec.is-hidden { display: none; }
.hub-sec.is-hidden { display: none; }

/* 차트 섹션 제목 */
.chart-head {
    display: flex; align-items: center; gap: 7px;
    margin: 18px 0 10px; padding: 0 2px;
    font-size: 15.5px; font-weight: 700; letter-spacing: -0.3px; color: var(--label);
}
.chart-head:first-child { margin-top: 4px; }
.ch-dot { width: 7px; height: 7px; border-radius: 50%; flex-shrink: 0; }
/*
| 회사 이름 옆의 번호 앞글자 — 금영(KY) · 태진(TJ) (2026-09-11).
|
| 회사 이름이 주인공이고 KY·TJ 는 그것을 목록의 번호와 이어 주는 실마리다.
| 그래서 같은 크기로 나란히 두지 않고 한 급 작게, 흐리게 깐다. 그래도
| 읽히긴 해야 하므로 굵기는 살려 둔다.
|
| letter-spacing 을 0 으로 되돌리는 이유: 둘레 글자에 걸린 -0.2px 이
| 로마자에 그대로 먹으면 K 와 Y 가 붙어 보인다.
*/
/* 점과 라벨만 flex 항목이 되도록 묶는다 — 안쪽 (KY) 는 그냥 inline 이다 */
.ch-lab { white-space: nowrap; }
.ch-code {
    font-style: normal; font-size: 11.5px; font-weight: 700;
    letter-spacing: 0; opacity: 0.55; margin-left: 3px;
    font-family: 'Roboto', sans-serif;
}
/* 눌려 있는 탭에서는 글자색이 진해지므로 곁말도 같이 또렷해진다 */
.chart-tab.active .ch-code { opacity: 0.68; }
.ch-ky { background: var(--blue); }
.ch-tj { background: var(--purple); }

/* 가수 찾기 버튼 */
.cls-singer {
    background: var(--blue-fill) !important;
    border-color: var(--blue-line) !important;
    color: var(--blue) !important; font-weight: 600;
}
.cls-singer:hover { background: var(--blue-fill) !important; }
/* 눌린 상태 — 이 버튼은 평소에도 파란색이라 공통 초록(.cls-btn.active)을 쓰면
   오히려 정체성이 흐려진다. 같은 파랑을 진하게 채워 선택을 표현한다.
   (.cls-singer 가 !important 라 여기서도 맞춰 준다) */
.cls-singer.active {
    background: var(--blue) !important;
    border-color: var(--blue) !important;
    color: #fff !important;
}

/* 홈 버튼 — 아이콘 + 글자 */

/* 검색 결과 — 금영·태진 번호 병기 */
.num-pair { display: flex; flex-direction: column; gap: 4px; flex-shrink: 0; }
/* 노래방 번호 — 목록에서 100번 반복되므로 색을 쓰지 않는다.
   'KY/TJ' 글자가 이미 구분자 역할을 하므로 색은 중복이다.
   iOS 설정앱처럼 캡션(회색) + 값(진한색) 의 활자 위계로만 표현한다. */
.np {
    display: flex; align-items: baseline; gap: 5px;
    min-width: 86px;
}
/* 벤더별 색 — 같은 채도의 블루/틸 두 톤.
   목록에서 100번 반복되므로 원색을 피하고, 라벨은 같은 색을 옅게 써서
   라벨+번호가 한 덩어리로 읽히게 한다. */
.np-ky { --np-c: var(--np-ky-c); }
.np-tj { --np-c: var(--np-tj-c); }
.np-none { --np-c: var(--label-3); }

.np-label {
    font-size: 10.5px; font-weight: 600; letter-spacing: 0.3px;
    font-family: 'Roboto', sans-serif;
    color: var(--np-c); opacity: 0.6; flex-shrink: 0;
}
.np-value {
    flex: 1; text-align: right;
    font-size: 15px; font-weight: 600;
    font-family: 'Roboto', sans-serif;
    font-variant-numeric: tabular-nums;
    letter-spacing: 0.1px; color: var(--np-c);
}
.np-none .np-value { font-weight: 400; }

/* AI 보정 검색 */
.ai-loading { color: var(--blue); font-weight: 500; }
.ai-spinner {
    display: inline-block; vertical-align: -2px;
    width: 13px; height: 13px; margin-right: 8px;
    border: 2px solid var(--blue-line);
    border-top-color: var(--blue);
    border-radius: 50%;
    animation: ai-spin 0.7s linear infinite;
}
@keyframes ai-spin { to { transform: rotate(360deg); } }

.ai-badge {
    display: inline-block;
    font-size: 11px; font-weight: 600;
    padding: 2px 8px; border-radius: 20px;
    background: var(--blue-fill); color: var(--blue);
    vertical-align: 1px;
}

.highlight { color: var(--blue); }

.yt-btn {
    display: inline-flex; align-items: center; justify-content: center;
    border: none; font-family: inherit; cursor: pointer; padding: 0;
    width: 33px; height: 33px; border-radius: var(--radius-s);
    background: var(--red-fill); color: var(--red);
    font-size: 11px;
    text-decoration: none; flex-shrink: 0;
    -webkit-tap-highlight-color: transparent;
    transition: background 0.15s;
}
.yt-btn:hover  { background: var(--red-fill); }
.yt-btn:active { background: var(--red-fill-2); }

/*
| 즐겨찾기 하트 — 목록에서 바로 담는다.
| 전에는 곡 상세로 들어가야만 담을 수 있어, 기능이 있는 줄도 모르고
| 지나치는 사람이 대부분이었다. 유튜브 버튼 왼쪽에 둔다.
*/
.fav-btn {
    display: inline-flex; align-items: center; justify-content: center;
    border: none; font-family: inherit; cursor: pointer; padding: 0;
    width: 33px; height: 33px; border-radius: var(--radius-s);
    background: var(--fill); color: var(--label-3);
    text-decoration: none; flex-shrink: 0;
    -webkit-tap-highlight-color: transparent;
    transition: background 0.15s, color 0.15s, transform 0.12s var(--ease);
}
.fav-btn svg { width: 17px; height: 17px; fill: none; stroke: currentColor; stroke-width: 1.9; }
.fav-btn:hover  { background: var(--pink-fill); color: var(--pink); }
.fav-btn:active { transform: scale(0.88); }
/* 담긴 상태 — 하트를 채운다 */
.fav-btn.is-saved { background: var(--pink-fill); color: var(--pink); }
.fav-btn.is-saved svg { fill: currentColor; stroke: currentColor; }

/* 최상단 즐겨찾기 — 담아둔 곡으로 가는 문 */
/*
| 최상단 줄 — 홈과 즐겨찾기.
| 내비 줄(주제 버튼들)에 있던 둘을 여기로 올렸다. 주제와 성격이 달라
| 같은 줄에 두면 섞여 보였고, 어느 페이지에서나 같은 자리에 있어야
| 손이 기억한다.
*/
.top-bar { display: flex; flex-wrap: wrap; align-items: center; justify-content: flex-end; gap: 7px; margin: 0 0 8px; }

/*
| 화면 밝기 고르기 — 자동(폰 설정) · 밝게 · 어둡게
|
| 셋을 다 펼쳐 둔다. 눌러야 다음이 뭔지 아는 순환 버튼과 달리, 지금 무엇이
| 골라져 있고 무엇을 고를 수 있는지가 한눈에 보인다. 한 번에 원하는 곳으로
| 갈 수 있으므로 '어둡게' 로 가려고 두 번 누를 일도 없다.
|
| 지금 상태는 CSS 가 직접 칠한다 — data-theme 은 <head> 에서 이미 붙으므로
| JS 가 화면을 손대기 전에 올바른 칸이 켜져 있다. 켜졌다 바뀌는 깜빡임이 없다.
*/
.theme-seg {
    margin-right: auto;                 /* 나머지(홈·즐겨찾기)는 오른쪽 */
    display: inline-flex; align-items: center; gap: 2px;
    padding: 3px;
    border-radius: 22px;
    border: 1px solid var(--hairline);
    background: var(--surface-2);
}
/*
| 아이콘만 남은 밝기 단추 (2026-09-11).
|
| '밝게'·'어둡게' 글자를 지우고 그 자리를 홈 버튼의 도메인에 내줬다.
| 해와 달은 설명이 필요 없는 그림이고, 이름은 aria-label·title 에 남겼다.
|
| 글자가 없으니 좌우 여백을 줄여 네모에 가깝게 만든다 — 13px 을 그대로
| 두면 아이콘 하나를 놓고 폭만 넓은 칸이 된다.
*/
.seg-btn {
    display: inline-flex; align-items: center; justify-content: center;
    height: 34px; width: 38px; padding: 0;
    border: 0; border-radius: 19px;
    background: transparent; color: var(--label-2);
    font-family: inherit; font-size: 13.5px; font-weight: 600; letter-spacing: -0.3px;
    cursor: pointer; -webkit-tap-highlight-color: transparent;
    transition: background 0.15s, color 0.15s, box-shadow 0.15s;
}
.seg-btn svg { width: 16px; height: 16px; }
.seg-btn:hover { color: var(--label); }

/* 골라진 칸 — 배경을 띄우고 파랑으로 못 박는다 */
:root:not([data-theme]) .seg-btn[data-mode="auto"],
:root[data-theme="light"] .seg-btn[data-mode="light"],
:root[data-theme="dark"]  .seg-btn[data-mode="dark"] {
    background: var(--surface);
    color: var(--blue);
    box-shadow: var(--card-shadow);
}

/*
| 홈 — 맨 앞자리. 어느 쪽에서든 돌아올 곳이라 다른 것보다 진하게 둔다.
| (밝기 단추는 회색 글자, 즐겨찾기는 분홍, 공유는 파랑 — 홈은 검정 글자로
|  구분된다)
*/
/*
| 키를 밝기 묶음에 맞춘다 — 40 + 테두리 2 = 42px (2026-09-11).
|
| .theme-seg 는 안쪽 단추 34 + 여백 3·3 + 테두리 1·1 로 42px 이다. 홈이
| 30(+2) 이라 나란히 두면 8px 이 낮았다. '홈' 한 글자일 때는 눈에 안 띄었는데,
| 도메인이 들어오면서 바에서 제일 작은 칸이 이름을 달고 있는 꼴이 됐다.
|
| 글자는 13px 그대로 둔다. 키우는 것은 칸이지 글자가 아니다 — 도메인이
| 커지면 밝기·공유보다 목소리가 커져서 최상단 줄이 광고처럼 읽힌다.
| 아이콘만 15 → 17px 로 함께 올린다. 칸만 키우고 그림을 두면 가운데가 빈다.
*/
.top-link {
    display: inline-flex; align-items: center; gap: 6px;
    height: 40px; padding: 0 14px; border-radius: 21px;
    border: 1px solid var(--label-3);
    background: var(--surface); color: var(--label);
    font-size: 13px; font-weight: 700; letter-spacing: -0.2px;
    text-decoration: none; -webkit-tap-highlight-color: transparent;
    transition: background 0.15s, color 0.15s;
}
.top-link:hover { background: var(--surface-3); }
.top-link svg { width: 17px; height: 17px; stroke-width: 2.2; }
/*
| 홈 버튼 안의 도메인 — 이름표다 (2026-09-12).
|
| 굵기로 간다. Roboto 700 으로 바꿔 봤는데 화면에서 티가 안 났다 —
| 두 글꼴의 로마자를 실제 파일에서 재 보니 글자당 최대 0.77px, 대부분
| 0.3px 이하 차이였다. Pretendard 로마자와 Roboto 는 같은 계열의 중립
| 그로테스크라 13px 에서는 같은 글자다. 글꼴 교체는 지렛대가 아니었다.
|
| 900(Black) 은 다르다. 'N' 왼쪽 세로획이 13px 에서
|     700 = 1.68px  →  900 = 2.06px   (+23%)
| 두께가 바뀌는 것은 눈이 바로 잡는다.
|
| 값은 정직하게 적는다 — 공짜가 아니다. Pretendard 로마자 묶음은
| subset.91 이고(subset.0 은 전각이다) 굵기마다 한 벌이다.
|     Black subset.91 = 19,932 B
| 최상단 줄은 모든 쪽에 있으므로 이 19.9 KB 가 모든 쪽에 붙는다.
| 대신 아래 .mvp-dom 을 800 에서 같은 900 으로 옮겨, 예전에 재생 경로에서
| 따로 받던 ExtraBold subset.91(20,064 B)이 사라진다. 재생을 누르는
| 사람에게는 실질 0 이고, 안 누르는 사람에게는 +19.9 KB 다.
|
| 자간 +0.2px. 이 파일의 한글은 전부 음수 자간이고 양수는 이름표에만
| 붙어 있다 — .num-label(0.2) .np-label(0.3) .mvp-dom(0.3). 양수 자간 자체가
| 이 사이트에서 '이건 글월이 아니라 이름이다' 라는 표시다. 900 은 획이
| 굵어 글자끼리 붙어 보이므로 조금 풀어 주는 쪽이 읽기도 낫다.
|
| 폭: 85.54 → 90.32px (13px), 78.96 → 83.54px (좁은 화면 12px).
| 360px 최상단 줄 여유가 37px 이라(담은 곡 배지가 떠도 16px) 들어간다.
| 키(40+2px)는 안 건드린다.
*/
.tl-brand {
    font-weight: 900;
    letter-spacing: 0.2px;
    /*
    | 크기는 화면 폭을 따라간다 (2026-09-12).
    |
    | 13px 에서 17px 로 키우고 싶은데(+30%) 360px 폰에서는 안 들어간다.
    | 실제 글꼴 파일로 최상단 줄 예산을 재 보면, 담은 곡 배지까지 떴을 때
    | 글자에 쓸 수 있는 폭이
    |     360px 폰  93px      412px 폰  124px      430px 이상  142px+
    | 이고 17px 짜리 'MyNorae.com' 은 115.9px 다. 큰 화면에서만 들어간다.
    |
    | 그래서 한 값으로 못 정한다. 단계로 끊으면(미디어쿼리) 경계에서 글자가
    | 툭 뛰므로 폭을 따라 이어지게 둔다.
    |     360px → 13.0px   390px → 15.0px   412px → 16.4px   430px↑ → 17px
    |
    | 아래 @media (max-width:400px) 에 있던 .tl-brand{font-size:12px} 는 지웠다.
    | 그 덩이가 이 규칙보다 파일 뒤에 있어(특정도가 같아 뒤가 이긴다) 남겨 두면
    | clamp 를 덮어쓴다 — 2026-09-09 에 같은 자리에서 한 번 겪은 일이다.
    |
    | 320px 은 여기서도 넘친다. 다만 오늘도 이미 넘치고 있다(12px 짜리가
    | 79px 인데 예산이 53px). .top-bar 가 flex-wrap 이라 두 줄이 될 뿐 안 깨진다.
    */
    font-size: clamp(13px, calc(6.4vw - 10px), 17px);
}
/*
| .com 은 주소지 이름이 아니다. 두 겹 뒤로 물린다 — 굵기를 900 에서 700 으로
| 내리고 투명도도 준다. 700 은 본문이 이미 받아 오므로 여기서 드는 값은 0 이다.
| 대문자 둘(M·N)이 앞으로 나오면서 My + Norae 로 갈라져 읽힌다.
|
| 0.62 가 아니라 0.64 인 이유 — .mvp-item 이 쓰는 0.62 를 가져오려 했는데
| 눌렀을 때(--surface-3 #ececf1) 명암비가 4.45:1 로 AA 문턱(4.5) 아래였다.
| 네이버 인앱이 hover 를 거짓으로 답하는 것이 기기 실측으로 확인돼 있어
| (memory: naver-inapp-webview) 주력 유입에서 그 상태가 실제로 보인다.
|   0.64  평상 5.09:1 · 눌림 4.72:1 · 어두울 때 7.08:1   셋 다 통과
*/
.tl-tld { font-weight: 700; opacity: 0.64; }
.fav-link {
    display: inline-flex; align-items: center; gap: 5px;
    height: 30px; padding: 0 12px; border-radius: 20px;
    border: 1px solid var(--pink-line);
    background: var(--pink-fill); color: var(--pink-2);
    font-size: 13px; font-weight: 600; letter-spacing: -0.2px;
    text-decoration: none; -webkit-tap-highlight-color: transparent;
    transition: background 0.15s;
}
.fav-link:hover { background: var(--pink-fill); }
.fav-link svg { width: 16px; height: 16px; fill: currentColor; }

/*
| 좁은 화면에서는 '즐겨찾기' 글자를 접고 하트만 남긴다.
|
| 밝기 선택기(세 칸)가 들어오면서 최상단 줄이 360px 폰에서 한 줄에 안
| 들어갔다. 즐겨찾기가 아래로 떨어지면 최상단 줄이 두 줄이 되어, 정작
| 곡을 찾으러 온 사람의 검색창이 그만큼 밀린다.
|
| 하트는 그 자체로 뜻이 통하는 몇 안 되는 기호다. 글자를 접는 대신
| 하트를 키워서 누르기 쉽게 한다 (16 → 19px). 읽어 주는 기기에는
| aria-label 로 이름이 남으므로 글자를 접어도 뜻이 사라지지 않는다.
*/
@media (max-width: 560px) {
    .fav-link .fav-txt { display: none; }
    .fav-link { padding: 0 11px; gap: 4px; }
    .fav-link svg { width: 19px; height: 19px; }
}
/*
| 좁은 화면 — 최상단 줄의 여백만 조인다.
|
| 홈 버튼이 '홈'(한 글자)에서 'MyNorae.com'(열한 글자)으로 길어졌다.
| 밝기 단추 두 개에서 글자를 지워 벌어 온 자리를 거기에 쓰는 셈인데,
| 벌어 온 것보다 쓰는 쪽이 조금 더 크다. 그래서 좁은 화면에서는 도메인만
| 한 급 줄인다 — 칸을 없애거나 .com 을 떼지 않는다. 도메인을 반만 보여
| 주면 적어 둔 뜻이 없다.
|
| 그래도 안 들어가면 .top-bar 가 flex-wrap 이라 두 줄이 된다. 깨지지는
| 않는다.
|
| 이 덩이를 .top-link·.fav-link 정의보다 뒤에 둬야 한다. 예전에는 앞에
| 있었는데, 클래스 하나끼리라 특정도가 같아서 뒤에 오는 기본 규칙이 이겼다
| — 좁은 화면용 여백이 한 번도 안 먹고 있었다(2026-09-09부터, 2026-09-11
| 발견). 미디어쿼리는 특정도를 올려 주지 않는다.
*/
@media (max-width: 400px) {
    .top-bar  { gap: 5px; }
    .seg-btn  { width: 34px; }
    .top-link { padding: 0 11px; gap: 5px; }   /* 키는 안 줄인다 — 좁은 것은 가로지 세로가 아니다 */
    .fav-link { padding: 0 10px; }
}
.fav-cnt {
    min-width: 17px; height: 17px; padding: 0 5px; border-radius: 9px;
    background: var(--pink); color: #fff; font-size: 10.5px; font-weight: 700;
    display: inline-flex; align-items: center; justify-content: center;
}
/*
| display 를 클래스에 주면 브라우저 기본값인 [hidden]{display:none} 을 이긴다.
| 그래서 담은 곡이 0개여도 빈 분홍 동그라미가 남았다 — 따로 눌러 준다.
*/
.fav-cnt[hidden] { display: none; }



/* ── 가수 사진 ── */

.sg-photos { margin: 12px 0 4px; }
.sg-main {
    display: block; width: 100%; max-width: 320px; height: auto;
    border-radius: var(--radius-m); background: var(--surface-2);
}
.sg-cap { margin: 6px 0 0; font-size: 12px; color: var(--label-3); letter-spacing: -0.2px; }
.sg-cap[hidden] { display: none; }
.sg-strip { display: flex; gap: 6px; margin-top: 8px; flex-wrap: wrap; }
.sg-th {
    width: 56px; height: 56px; padding: 0; cursor: pointer; overflow: hidden;
    border: 2px solid transparent; border-radius: 9px; background: none;
    -webkit-tap-highlight-color: transparent;
}
.sg-th img { width: 100%; height: 100%; object-fit: cover; display: block; border-radius: 7px; }
.sg-th.on { border-color: var(--blue); }

/*
| 가수 사진 자리의 영상 (2026-09-15, search_song.php $sgVids).
| 넓은 화면에서는 소개 글 왼쪽에 360px — 16:9 로 높이 202px, 유튜브 규정 200px 을 넘긴다.
| 좁은 화면(620px 이하)에서는 위아래로 흐르므로 폭을 다 쓴다.
| 곡 줄(.sgv-song)은 가수 시트와 같은 모양을 쓴다.
*/
.sg-vids { width: 360px; max-width: 100%; margin: 12px 0 4px; }
.sg-vids .sgv-song { margin: 10px 0 0; }
.sg-vids .sgv-song[hidden] { display: none; }
.sgv-list { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 8px; }
.sgv-pick {
    display: inline-flex; align-items: center; gap: 5px; max-width: 100%;
    min-height: 32px; padding: 0 11px 0 9px;
    border: 1px solid var(--line); border-radius: 999px; background: var(--surface);
    color: var(--label-2); font: inherit; font-size: 12.5px; font-weight: 600; letter-spacing: -0.2px;
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis; cursor: pointer;
    -webkit-tap-highlight-color: transparent;
}
.sgv-pick span { font-size: 9px; color: var(--label-3); }
.sgv-pick.on { border-color: var(--blue); color: var(--blue); font-weight: 700; }
.sgv-pick.on span { color: var(--blue); }
.sgv-pick:focus-visible { outline: 2px solid var(--blue); outline-offset: 2px; }
@media (hover: hover) and (pointer: fine) { .sgv-pick:hover { border-color: var(--blue); color: var(--blue); } }
/*
| 좁은 화면에서는 .singer-hero-main 이 내용만큼만 넓어지는 칸이라, 그 안의 100% 가
| 기댈 폭이 없다. 재생을 시작하면 유튜브가 iframe 크기를 다시 매기면서 플레이어가
| 862×485 로 불어나 카드 밖으로 잘렸다(390px 실측). 칸을 한 줄 폭으로 펴 준다.
*/
@media (max-width: 620px) {
    .singer-hero-main { width: 100%; }   /* :has() 는 옛 웹뷰가 몰라 쓰지 않는다 — 사진만 있는 가수도 폭만 펴질 뿐 모양은 같다 */
    .sg-vids { width: 100%; }
}
.sg-vids .mv-frame { max-width: 100%; }

/* 관리자 패널 안의 사진 줄 */
.sg-adm-list { margin-bottom: 8px; }
.sg-adm-row { display: flex; gap: 6px; align-items: center; margin-bottom: 6px; }
.sg-adm-row img { width: 48px; height: 48px; object-fit: cover; border-radius: 7px; flex: 0 0 auto; }
.sg-adm-row input {
    flex: 1; min-width: 0; padding: 6px 8px; font-size: 12.5px; font-family: inherit;
    border: 1px solid var(--hairline); border-radius: 7px;
    background: var(--surface); color: var(--label);
}
.sg-adm-row button {
    flex: 0 0 auto; padding: 6px 9px; cursor: pointer; font-size: 12px;
    border: 1px solid var(--hairline); border-radius: 7px;
    background: var(--surface); color: var(--label-2);
}
.sg-adm-row button.danger { color: #d33; }
.sg-adm-row button[disabled] { opacity: .35; cursor: default; }

/* 관리 패널의 여러 줄 입력 · 파일 고르기 */
.adm-row textarea {
    flex: 1; min-width: 0; padding: 7px 9px; resize: vertical;
    border: 1px solid var(--hairline); border-radius: 8px;
    background: var(--surface); color: var(--label);
    font-size: 13px; font-family: inherit; line-height: 1.6;
}
.adm-row input[type="file"] {
    flex: 1; min-width: 0; padding: 6px; font-size: 12px;
    border: 1px dashed var(--hairline); border-radius: 8px;
    background: var(--surface); color: var(--label-2);
}

/* ── 곡 영상 (누르기 전에는 그림만) ── */

.song-mv { display: flex; gap: 10px; margin: 14px 0 4px; flex-wrap: wrap; }
.mv-box {
    position: relative; flex: 1 1 240px; max-width: 100%;
    aspect-ratio: 16 / 9; padding: 0; cursor: pointer;
    border: 0; border-radius: var(--radius-m); overflow: hidden;
    background: #000; -webkit-tap-highlight-color: transparent;
}
.mv-thumb { width: 100%; height: 100%; object-fit: cover; display: block; opacity: .88; }
.mv-box:hover .mv-thumb { opacity: 1; }
/*
| 재생 단추는 오른쪽 아래 (2026-09-15, 사용자 요청) — 가운데 큰 단추가 썸네일을 가려서.
| 모든 유튜브 썸네일(곡 페이지·주제 목록·유튜브 시트·가수 시트·가수 페이지·주제 카드)이
| 이 한 규칙을 쓴다. 자리가 좁은 곳(.tt-vid · .tc-cover)은 아래에서 더 작게 덮어쓴다.
| 누를 수 있는 곳은 여전히 썸네일 전체다.
*/
.mv-play {
    position: absolute; right: 8px; bottom: 8px;
    width: 42px; height: 30px; border-radius: 8px;
    background: rgba(0,0,0,.62); color: #fff;
    display: flex; align-items: center; justify-content: center;
    /*
    | 세모는 글자(▶)가 아니라 CSS 로 그린다 (2026-09-15) — 글꼴마다 ▶ 가 글줄
    | 기준선에 앉아 단추 아래쪽으로 치우쳐 보였다(사용자 제보). 마크업의 ▶ 는
    | 글자 크기 0 으로 숨기고 테두리로 세모를 그려 정확히 가운데 둔다.
    | 세모는 무게중심이 왼쪽에 있어 눈으로는 왼쪽에 쏠려 보이므로 조금 오른쪽으로 민다.
    | 크기는 --tri(세모 높이의 절반) 하나로 — 작은 단추는 그 값만 줄인다.
    */
    font-size: 0; line-height: 0; padding: 0;
    --tri: 6px;
}
.mv-play::before {
    content: ''; display: block;
    border-style: solid; border-color: transparent transparent transparent #fff;
    border-width: var(--tri) 0 var(--tri) calc(var(--tri) * 1.7);
    margin-left: calc(var(--tri) * 0.35);
}
.mv-box:hover .mv-play { background: #ff0000; }
.mv-label {
    position: absolute; left: 8px; bottom: 8px;
    /* 오른쪽 아래 재생 단추(42px + 여백)와 겹치지 않게 — 긴 이름은 말줄임 */
    max-width: calc(100% - 66px); white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
    padding: 3px 8px; border-radius: 6px;
    background: rgba(0,0,0,.62); color: #fff;
    font-size: 11.5px; font-weight: 600; letter-spacing: -0.2px;
}
/* 이용자가 요청해 넣은 영상 — 그림 왼쪽 위 (2026-09-14). 이름표(.mv-label)는 왼쪽 아래라 안 겹친다 */
.mv-req {
    position: absolute; left: 8px; top: 8px; max-width: calc(100% - 16px);
    padding: 3px 8px; border-radius: 6px;
    background: rgba(0,0,0,.62); color: #fff;
    font-size: 11px; font-weight: 600; letter-spacing: -0.2px;
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.mv-frame {
    flex: 1 1 240px; aspect-ratio: 16 / 9; width: 100%;
    border: 0; border-radius: var(--radius-m); background: #000;
}
/*
|--------------------------------------------------------------------------
| 영상 밑 주소 띠 (2026-09-11)
|--------------------------------------------------------------------------
| 재생을 누르면 그림 자리에 .mv-live 가 들어선다 — 영상과 띠를 묶은 틀이다.
| 곡 페이지(.song-mv)에서는 이 틀이 flex 항목이 되고, 목록(.tmv)에서는
| 그냥 폭을 다 쓰는 덩이가 된다. 어느 쪽이든 띠는 영상 바로 밑이다.
|
| 틀이 flex 자리를 넘겨받았으므로 안쪽 iframe 에서는 flex 를 푼다.
| 안 그러면 아래가 아니라 띠와 나란히 서려 한다.
|
| 모서리를 틀이 맡고 안쪽은 각지게 둔다 — 영상 밑변과 띠 윗변이 맞닿는
| 자리에 둥근 모서리가 남으면 둘이 붙어 보이지 않는다.
*/
/*
| 재생이 시작되면 그 틀이 한 줄을 다 쓴다 (2026-09-13).
|
| 유튜브 필수 기능 규정이 이렇게 못 박는다 —
|   "Embedded players must have a viewport that is at least 200px by 200px."
|   (https://developers.google.com/youtube/terms/required-minimum-functionality)
| 16:9 라 가로가 356px 아래면 세로가 200px 에 못 미친다. 240px 로 두 개를
| 나란히 놓으면 PC 에서도 319×179 라 규정 위반이었다.
|
| 그림(.mv-box)은 240px 두 개 그대로 둔다 — 규정이 그림에 요구하는 것은
| 120×70 뿐이고(그것도 재생을 시작하는 그림에 한한다), 목록 위에 16:9 를
| 둘씩 세로로 쌓으면 그것만으로 화면 하나를 넘긴다. 누른 것만 펴진다.
*/
.mv-live {
    flex: 1 1 100%; min-width: 0;
    /*
    | 플레이어와 띠를 한 틀로 감싸지 않는다 (2026-09-13).
    |
    | 예전에는 이 틀이 둥근 모서리 + overflow:hidden + 검정 배경으로 둘을
    | 하나처럼 묶었다. 띠가 플레이어 아래턱처럼 이어져 보이게 하려던 것인데,
    | 유튜브 감사에서는 그게 불리하게 읽힌다 —
    |   "You must not display overlays, frames, or other visual elements in
    |    front of any part of a YouTube embedded player"
    | 우리 띠는 iframe 밖 아래라 규정 위반이 아니지만, 틈이 0 이고 둥근
    | 모서리가 둘을 감싸면 스크린샷 한 장에서 '플레이어를 액자에 넣었다' 로
    | 보인다. 판정이 사람 눈에 달린 자리에서는 오해의 여지를 없애는 쪽이 낫다.
    |
    | 이제 플레이어가 제 모서리를 갖고, 띠는 4px 아래 별개의 덩이로 앉는다.
    */
    background: none;
}
.mv-live .mv-frame {
    flex: none; width: 100%; display: block;
    /* 플레이어가 제 모서리를 갖는다 — 감싸던 틀이 없어졌으므로 */
    border-radius: var(--radius-m); aspect-ratio: 16 / 9;
    /*
    | 좁은 폰에서는 폭을 다 써도 16:9 로는 200px 이 안 나온다
    | (328px 폰 → 184px). 그때만 위아래로 늘려 규정을 맞춘다 —
    | 영상은 그 안에서 레터박스로 앉는다. 넓은 화면에서는
    | aspect-ratio 가 이미 200px 을 넘으므로 이 값이 안 걸린다.
    */
    min-height: 200px;
}
/*
| 띠 자체.
|
| 높이는 26px — 영상(16:9)이 240px 폭일 때 135px 이니 그 5분의 1 이 안 된다.
| '너무 크지 않게' 는 이 정도를 뜻한다고 봤다. 글자는 11px 이라 읽히되
| 영상에서 눈을 뺏지 않는다.
|
| 유튜브 조작 막대와 닿는 자리라 색을 검정 계열로 맞춰 플레이어 아래턱처럼
| 보이게 한다. 흰 띠를 대면 영상이 거기서 끊겨 보인다.
|
| 고르기·누르기를 다 막는다 — 영상 밑을 무심코 문질렀을 때 글자가 잡히면
| 조작이 어긋난 것처럼 느껴진다.
*/
.mv-promo {
    /* 플레이어와 명확히 떨어진 별개의 덩이 — 위 .mv-live 주석 참고 */
    margin-top: 4px;
    height: 26px; overflow: hidden; position: relative;
    border-radius: var(--radius-s);
    background: linear-gradient(180deg, #141414 0%, #0a0a0a 100%);
    user-select: none; -webkit-user-select: none; pointer-events: none;
}
.mvp-track {
    display: flex; width: max-content; height: 100%;
    align-items: center;
    animation: mvpSlide 17s linear infinite;
}
.mvp-item {
    padding: 0 26px; white-space: nowrap;
    font-size: 11px; font-weight: 600; letter-spacing: 0.2px;
    color: rgba(255,255,255,.62);
}
/* 넷 중 절반(두 벌)만 밀면 처음과 같은 그림이라 이음매가 안 보인다 */
@keyframes mvpSlide {
    from { transform: translateX(0); }
    to   { transform: translateX(-50%); }
}
/*
|--------------------------------------------------------------------------
| 도메인 — 글자가 차례로 하나씩 커진다 (2026-09-11)
|--------------------------------------------------------------------------
| m 이 커졌다가 제자리, 다음은 y, 그 다음은 n … 타자를 치는 것처럼 왼쪽부터
| 훑어 간다. 흐르기만 하는 띠는 눈이 그냥 지나치는데, 글자가 하나씩 일어서면
| 거기서 한 번 걸린다. 그 한 번이 이름을 남긴다.
|
| 한 바퀴(--dur)를 글자 수(--n)로 나눈 것이 한 칸(--step)이다. 각 글자는
| 자기 차례(--i)만큼 늦게 시작해 같은 몸짓을 되풀이한다. 그래서 몇 글자로
| 바뀌든 CSS 는 그대로다 — 자바스크립트가 --n 과 --i 만 넘긴다.
|
| 빠르기는 --dur 하나로 잡는다. 칸 간격도 글자가 서 있는 시간도 여기에
| 딸려 오므로, 이 값만 늘리면 전체가 고르게 느려진다. 처음 4.4초(글자당
| 400ms)로 뒀더니 눈이 못 따라간다는 지적을 받아 8.8초로 늘렸다
| (글자당 800ms, 2026-09-11).
|
| 커지는 폭(1.5배)을 키에 반영하지 않는다. transform 은 자리를 안 밀어내므로
| 띠 길이가 변하지 않고, 네 벌을 겹쳐 만든 이음매도 어긋나지 않는다.
| 대신 글자가 띠 위아래로 삐져나가지 않게 .mv-promo 를 26px 로 잡고
| 기본 글자를 11px 로 뒀다 — 1.5배라도 16.5px 이라 넉넉하다.
|
| 평소를 조금 어둡게(.62), 커질 때 흰색으로 올린다. 크기만 바꾸면 흐르는
| 중에는 잘 안 보인다 — 밝기가 같이 움직여야 눈에 들어온다.
*/
.mvp-track { --dur: 8.8s; --step: calc(var(--dur) / var(--n)); }
/*
| 띠도 최상단과 같은 굵기로 맞춘다 — 900 (2026-09-12).
|
| 같은 이름을 다른 굵기로 쓰면 한 사이트에 상표가 둘이 된다. 그리고 값이
| 안 든다: 최상단 줄이 이미 Black subset.91 을 받아 오므로 여기서 900 을
| 써도 같은 파일이다. 800 으로 두면 오히려 ExtraBold subset.91(20,064 B)을
| 재생 경로에서 한 벌 더 받는다 — 이 띠가 그 파일의 유일한 소비자였다
| (.ha-q b 의 800 은 '나만의노래방' 이라 한글 조각을 받는다).
*/
.mvp-dom {
    font-weight: 900; letter-spacing: 0.3px;
    color: rgba(255,255,255,.88);
}
.mvp-c {
    display: inline-block; font-style: normal;
    animation: mvpType var(--dur) linear infinite;
    animation-delay: calc(var(--i) * var(--step));
    will-change: transform;
}
/*
| 한 칸 안에서만 일어섰다 앉는다.
| 9% 는 한 글자 몫(11글자면 9.1%)에 맞춘 것이다 — 이보다 넓으면 두 글자가
| 같이 서서 '타자' 로 안 읽힌다.
|
| 비율로 적었으므로 --dur 을 늘리면 서 있는 시간도 같이 늘어난다.
| 8.8초면 올라서는 데 264ms, 내려오는 데 528ms 다.
*/
@keyframes mvpType {
    /* 색을 또박또박 적는다 — keyframe 안의 inherit 은 브라우저마다 다르게 먹는다 */
    0%   { transform: scale(1); color: rgba(255,255,255,.88); }
    3%   { transform: scale(1.5) translateY(-0.5px); color: #fff; }
    9%   { transform: scale(1); color: rgba(255,255,255,.88); }
    100% { transform: scale(1); color: rgba(255,255,255,.88); }
}
/*
| 재생이 멈추면 띠도 선다 (2026-09-11).
|
| 한 화면에 영상이 둘이라, 멈춘 영상 밑에서 글자가 계속 돌아다니면 무엇이
| 재생 중인지가 흐려진다. 움직이는 것이 곧 '지금 이것' 이어야 한다.
|
| display 를 끄거나 animation 을 지우지 않고 play-state 만 세운다. 그래야
| 글자가 있던 자리에 그대로 멈추고, 다시 틀면 이어서 간다 — 처음으로
| 되감기면 멈췄다는 것보다 새로 켜진 것처럼 보인다.
|
| .is-idle 은 유튜브 IFrame API 가 붙여 준다(app.js 의 mvBindPromo).
| API 를 못 받은 화면에는 안 붙으므로 예전처럼 계속 흐른다.
*/
.mv-promo.is-idle .mvp-track,
.mv-promo.is-idle .mvp-c { animation-play-state: paused; }
/*
| 움직임을 덜어 달라고 한 사람에게는 세워서 보여 준다.
| 흐르지도 커지지도 않을 뿐 주소는 그대로 읽힌다 — 끄지 않는다.
*/
@media (prefers-reduced-motion: reduce) {
    .mvp-track { animation: none; width: 100%; justify-content: center; }
    .mvp-item:not(:first-child) { display: none; }
    .mvp-c { animation: none; }
}

/* ── 관리자 패널 (관리자에게만 렌더된다) ── */

.adm { margin-top: 14px; }
.adm-toggle {
    padding: 5px 12px; border-radius: 999px; cursor: pointer;
    border: 1px dashed var(--hairline); background: var(--surface-2);
    font-size: 11.5px; font-weight: 600; color: var(--label-3);
}
.adm-toggle span { color: #e00000; margin-left: 3px; }
.adm-copy { margin-left: 6px; color: var(--blue); border-style: solid; }
/* 유튜브 검색 바로가기 — 버튼이 아니라 <a> 라 높이만 맞춰 준다 */
.adm-yt { margin-left: 6px; color: var(--red); border-style: solid;
          text-decoration: none; display: inline-block; line-height: 1.45; }
.adm-body {
    margin-top: 10px; padding: 13px;
    border: 1px solid var(--hairline); border-radius: var(--radius-m);
    background: var(--surface-2);
}
.adm-sec { margin-bottom: 14px; }
.adm-sec:last-of-type { margin-bottom: 6px; }
.adm-sec > b {
    display: block; margin-bottom: 6px;
    font-size: 11.5px; font-weight: 700; color: var(--label-3); letter-spacing: 0.2px;
}
.adm-row { display: flex; gap: 6px; align-items: center; margin-bottom: 6px; }
.adm-fix { font-size: 12px; color: var(--label-2); white-space: nowrap; }
.adm-row input {
    flex: 1; min-width: 0; padding: 7px 9px;
    border: 1px solid var(--hairline); border-radius: 8px;
    background: var(--surface); color: var(--label);
    font-size: 13px; font-family: inherit;
}
.adm-row input.adm-lbl { flex: 0 0 84px; }
.adm-row button {
    flex: 0 0 auto; padding: 7px 12px; cursor: pointer;
    border: 1px solid var(--hairline); border-radius: 8px;
    background: var(--surface); color: var(--blue);
    font-size: 12.5px; font-weight: 600;
}
.adm-row button:hover { background: var(--surface-3); }
.adm-face {
    flex: 0 0 auto; display: inline-flex; align-items: center; gap: 4px;
    font-size: 11.5px; color: var(--label-2); cursor: pointer; white-space: nowrap;
    -webkit-tap-highlight-color: transparent;
}
.adm-face input { margin: 0; cursor: pointer; }
.adm-hint { margin: 2px 0 0; font-size: 11px; color: var(--label-3); }
.adm-stats { font-size: 12px; color: var(--label-2); line-height: 1.7; }
.adm-kv { word-break: break-all; }
.adm-msg { margin: 8px 0 0; font-size: 12px; min-height: 16px; }
.adm-msg.good { color: var(--blue); }
.adm-msg.bad  { color: #e00000; }

@media (max-width: 520px) {
    .adm-row { flex-wrap: wrap; }
    .adm-row input.adm-lbl { flex: 1 1 100%; }
}

/* ── 가수 정보 버튼 (곡 페이지 가수명 옆) ── */

/* 맨 위 공유 — 홈과 즐겨찾기 사이. 눈에 띄어야 하므로 채운 버튼으로 둔다 */
/*
| 공유 — 아이콘만 (2026-09-11).
|
| '공유' 두 글자를 뺐다. 어떤 폰에서 최상단 줄이 두 줄로 밀린다는 지적이
| 있었는데, 글자(약 30px)와 좌우 덧여백(6px×2)이 그만큼을 먹고 있었다.
| 공유 아이콘은 설명이 필요 없는 몇 안 되는 기호이고, 이름은 aria-label 과
| title 에 남아 있다.
|
| 덧여백을 없앤 이유 — .top-bar 가 이미 gap 을 주는데 여기만 6px 을 더
| 얹고 있어 이 단추만 떨어져 보였다. 이제 옆 칸들과 같은 간격이다.
|
| 32px 정사각 — 옆 즐겨찾기(하트)와 같은 키다. 홈·밝기(42px)보다 작은 것은
| 그대로 둔다. 브랜드와 설정이 앞이고 이 둘은 곁가지다.
*/
.share-top {
    display: inline-flex; align-items: center; justify-content: center;
    width: 32px; height: 32px; padding: 0; margin: 0;
    cursor: pointer; border: 0; border-radius: 999px;
    background: var(--blue); color: #fff;
    font-family: inherit; line-height: 1;
    -webkit-tap-highlight-color: transparent;
}
.share-top svg { width: 16px; height: 16px; flex-shrink: 0; }
.share-top:hover  { filter: brightness(1.08); }
.share-top:active { transform: translateY(0.5px); }

/*
| 밝기 단추 — '누르면 무엇이 되는지' 만 글자로 보인다.
|
| 넷(홈·밝기·공유·즐겨찾기)을 한 줄에 넣으면 좁은 폰에서 즐겨찾기가
| 다음 줄로 밀렸다. 글자 하나를 지우면 그만큼 자리가 난다.
|
| 지우는 쪽은 '지금 고른 것' 이다. 그건 배경색으로 이미 보이고, 눌러도
| 달라지는 게 없어 글자가 할 일이 없다. 반대로 안 고른 쪽은 누르면
| 화면이 바뀌는 자리라 무엇이 될지 글자로 말해 줘야 한다.
|   밝은 화면   [해] [달 어둡게]   ← 누르면 어두워진다
|   어두운 화면 [해 밝게] [달]
*/
/*
| 고른 칸 — 배경만으로 말한다.
|
| 예전에는 '고른 쪽의 글자를 지워' 좁은 폰에서 자리를 냈다(2026-09-09).
| 이제 양쪽 다 글자가 없으므로 그 장치는 필요 없어졌다 (2026-09-11).
*/
.theme-seg .seg-btn.on { background: var(--surface-3); color: var(--label); }

/* 가수명 옆 작은 얼굴 */
.sg-face {
    width: 28px; height: 28px; border-radius: 50%;
    object-fit: cover; vertical-align: middle;
    margin-right: 7px; background: var(--surface-2);
    display: inline-block;
}
.sg-face-btn {
    padding: 0; border: 0; background: none; cursor: pointer;
    vertical-align: middle; line-height: 0;
    -webkit-tap-highlight-color: transparent;
}
.sg-face-btn:hover .sg-face { box-shadow: 0 0 0 2px var(--blue); }

.sp-btn {
    display: inline-block; vertical-align: middle;
    margin-left: 8px; padding: 3px 9px;
    font-size: 11.5px; font-weight: 600; letter-spacing: -0.2px;
    color: var(--blue); background: var(--surface-2);
    border: 1px solid var(--hairline); border-radius: 999px;
    cursor: pointer; line-height: 1.5;
    transition: background 0.15s;
    -webkit-tap-highlight-color: transparent;
}
.sp-btn:hover  { background: var(--surface-3); }
.sp-btn:active { transform: translateY(0.5px); }

/* 시트 안쪽 — 가수 페이지의 .sp-* 를 그대로 쓰고 바깥 여백만 잡는다 */
.sg-body { padding: 2px 6px 4px; }
.sg-sheet-img {
    display: block; width: 100%; max-width: 240px; height: auto;
    margin: 0 auto 12px; border-radius: var(--radius-m);
    background: var(--surface-2);
}
.sg-body .sp-intro { font-size: 14px; line-height: 1.68; }
/*
| 가수 시트의 영상과 그 곡 (2026-09-15, app.js sgVideoHtml).
| 사진(240px)보다 넓게 — 플레이어는 폭을 다 써야 유튜브 규정 200px 높이를 넘긴다.
*/
.sg-mv { margin: 0 0 10px; }
.sgv-song {
    display: flex; align-items: center; flex-wrap: wrap; gap: 3px 8px;
    margin: 0 0 14px; padding: 10px 12px;
    border: 1px solid var(--hairline); border-radius: var(--radius-m);
    text-decoration: none; color: inherit; -webkit-tap-highlight-color: transparent;
}
.sgv-tag {
    flex: none; padding: 2px 8px; border-radius: 999px;
    background: var(--fill); color: var(--label-2); font-size: 11px; font-weight: 700;
}
.sgv-main { flex: 1 1 auto; min-width: 0; font-size: 14px; letter-spacing: -0.3px; word-break: keep-all; }
.sgv-t { color: var(--label); font-weight: 800; }
.sgv-s { color: var(--label-2); font-weight: 600; }
.sgv-nos { flex: 1 0 100%; order: 3; font-size: 12.5px; color: var(--label-3); font-variant-numeric: tabular-nums; }
.sgv-go { flex: none; margin-left: auto; font-size: 22px; line-height: 1; color: var(--label-3); }
.sgv-song:focus-visible { outline: 2px solid var(--blue); outline-offset: 2px; }
@media (hover: hover) and (pointer: fine) {
    .sgv-song:hover { border-color: var(--blue); }
    .sgv-song:hover .sgv-t, .sgv-song:hover .sgv-go { color: var(--blue); }
}
.sg-wait { padding: 18px 4px; text-align: center; font-size: 13px; color: var(--label-3); }
.sg-link {
    display: block; margin: 14px 0 10px; padding: 12px;
    text-align: center; text-decoration: none;
    font-size: 13.5px; font-weight: 600; color: var(--blue);
    border: 1px solid var(--hairline); border-radius: var(--radius-m);
    -webkit-tap-highlight-color: transparent;
}
.sg-link:hover { background: var(--surface-2); }

/* ── 유튜브 선택 시트 ── */

.yt-sheet {
    display: none; position: fixed; inset: 0; z-index: 400;
    background: var(--scrim);
    -webkit-backdrop-filter: blur(2px); backdrop-filter: blur(2px);
    align-items: flex-end; justify-content: center;
}
.yt-sheet.open { display: flex; }

.yt-panel {
    width: 100%; max-width: 460px;
    background: var(--surface);
    border-radius: 20px 20px 0 0;
    padding: 14px 16px calc(16px + env(safe-area-inset-bottom));
    box-shadow: 0 -8px 40px rgba(0,0,0,0.22);
    animation: yt-up 0.22s var(--ease);
    position: relative;                 /* 오른쪽 위 닫기(.yt-x) 의 기준점 */
    /*
    | 넘치면 시트 안에서 굴린다 (2026-09-09).
    |
    | 예전에는 제목·선택 두 줄·취소뿐이라 250px 이면 끝이었다. 이제 곡에
    | 붙여 둔 영상이 위에 들어오는데, 16:9 두 개면 그것만 480px 이라
    | 작은 화면에서는 아래가 잘린다. dvh 는 주소창이 접히고 펴지는 만큼을
    | 빼 주므로 휴대폰에서 vh 보다 정확하다 — 못 읽는 브라우저는 vh 를 쓴다.
    */
    max-height: 88vh;
    max-height: 88dvh;
    overflow-y: auto;
    overscroll-behavior: contain;
}
@keyframes yt-up { from { transform: translateY(14px); opacity: 0; } to { transform: none; opacity: 1; } }

.yt-song {
    font-size: 14px; font-weight: 600; letter-spacing: -0.2px;
    color: var(--label-2); text-align: center;
    margin-bottom: 10px; padding: 0 6px;
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}

.yt-opt {
    display: flex; align-items: center; gap: 13px;
    padding: 11px 15px; margin-bottom: 6px;
    border: 1px solid var(--hairline); border-radius: var(--radius-m);
    background: var(--surface); text-decoration: none;
    transition: background 0.15s;
    -webkit-tap-highlight-color: transparent;
}
.yt-opt:hover  { background: var(--surface-2); }
.yt-opt:active { background: var(--surface-3); }
.yt-ico { font-size: 21px; flex-shrink: 0; }

/*
| 시트 안의 영상·안내·신청 (2026-09-09)
|--------------------------------------------------------------------------
| 앱과 같은 차례로 놓는다 — 붙여 둔 영상이 맨 위, 없으면 그 자리에 안내,
| 그 아래 유튜브에서 찾는 두 줄, 마지막에 주소를 넣는 칸.
|
| [hidden] 을 따로 적는 이유: display 를 준 요소는 브라우저 기본 규칙과
| 특정도가 같아서, 이 파일이 뒤에 온다는 것만으로 [hidden] 을 이긴다.
| (.mic-btn 에서 같은 것에 한 번 당했다)
*/
.yt-mv { display: block; margin-bottom: 10px; }
.yt-mv[hidden] { display: none; }
/*
| 시트 안의 영상은 높이로 재고 폭은 따라오게 한다 (2026-09-09).
|
| width:100% 로 두면 16:9 라 폭이 넓어질수록 키가 같이 큰다 — 좁은 폰에서
| 198px 이던 것이 PC 폭(460px 패널)에서는 241px 이 되어, 정작 화면이 넉넉한
| 쪽에서 시트가 더 길어졌다. 키를 먼저 정하면 패널 길이가 폭과 무관해진다.
| 30dvh 는 키보드가 올라오면 같이 줄어든다.
*/
.yt-mv .mv-box,
.yt-mv .mv-frame {
    display: block; width: 100%; margin: 0 auto;
    aspect-ratio: 16 / 9;
    /*
    | 세로 화면에서는 이 상한에 안 걸린다 — 폭이 정하는 키(폰 198 · PC 241)가
    | 42dvh(650px 화면이면 273) 보다 작다. 가로로 눕혔을 때만 걸려서, 그때
    | 시트가 굴러가는 것을 막는다.
    */
    max-height: 42dvh;
}
/*
| 재생을 누르면 playMv() 가 .mv-box 를 iframe 으로 '갈아 끼운다'(replaceWith).
| 그래서 상자에만 상한을 걸면 누르는 순간 다시 16:9 로 커져 시트가 그때부터
| 굴러간다. 두 벌 다 같은 키를 줘야 눌러도 화면이 안 흔들린다.
*/
/*
| 주소 띠(26px)가 붙는 만큼 영상에서 뺀다 (2026-09-11).
|
| 시트는 위의 42dvh 로 '눌러도 굴러가지 않는다' 를 지켜 온 자리다. 띠를
| 그냥 얹으면 26px 이 더해져 그 장치가 깨진다. 영상 쪽 상한을 그만큼 낮춰
| 띠까지 합한 키를 예전과 같게 맞춘다.
|
| 특정도가 (0,3,0) 이라 바로 위 .yt-mv .mv-frame (0,2,0) 을 이긴다.
*/
.yt-mv .mv-live { max-height: 42dvh; }
/*
| 세로 상한은 그대로 두되 200px 아래로는 안 내려가게 한다. 가로로 눕히면
| 42dvh 가 200px 에 못 미쳐(화면높이 400px → 142px) 규정을 벗어난다.
| CSS 는 min-height 가 max-height 를 이기므로 그때만 시트가 조금 길어진다.
*/
.yt-mv .mv-live .mv-frame { max-height: calc(42dvh - 26px); min-height: 200px; }

/*
| 영상이 둘일 때의 탭.
|
| 나란히 쌓으면 16:9 두 개가 화면 하나를 넘겨, 아래 것도 유튜브 찾기 줄도
| 굴려야 나온다. 한 번에 하나만 보이면 시트 길이가 영상 수와 무관해진다.
*/
.yt-tabs { display: flex; gap: 6px; margin-bottom: 7px; }
.yt-tab {
    flex: 1 1 0; min-width: 0; height: 34px; padding: 0 8px;
    border: 1px solid var(--hairline); border-radius: var(--radius-s, 9px);
    background: var(--surface); color: var(--label-2);
    font: inherit; font-size: 13px; cursor: pointer;
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
    -webkit-tap-highlight-color: transparent;
    transition: background 0.15s, color 0.15s;
}
.yt-tab:hover { background: var(--fill); }
.yt-tab.on {
    background: var(--label); border-color: var(--label);
    color: var(--surface); font-weight: 600;
}

/*
| 등록을 청하는 자리.
|
| 유튜브에서 찾는 두 줄 아래에 놓고, 위에 가는 금을 그어 '다른 이야기' 임을
| 보인다. 없다는 말로 시작하지 않는다 — 시트를 열자마자 '없어요' 가 나오면
| 보여 줄 것이 없는 화면으로 읽힌다.
*/
.yt-ask {
    display: block; margin-top: 10px; padding-top: 10px;
    border-top: 1px solid var(--hairline);
}
.yt-ask[hidden] { display: none; }
.yt-ask-head {
    font-size: 14.5px; font-weight: 600; letter-spacing: -0.3px;
    color: var(--label); text-align: center; margin-bottom: 5px;
}
.yt-ask-msg {
    font-size: 12.5px; line-height: 1.5; color: var(--label-2);
    text-align: center; padding: 0 2px 8px;
}
.yt-ask-msg b { font-weight: 600; color: var(--label); }

.yt-req-row { display: flex; gap: 6px; }
.yt-req-url {
    flex: 1 1 auto; min-width: 0; height: 42px;
    padding: 0 12px; font-size: 15px;
    border: 1px solid var(--line-3); border-radius: var(--radius-m);
    background: var(--surface); color: var(--label); outline: none;
}
.yt-req-url:focus { border-color: var(--label-3); }
.yt-req-url:disabled { opacity: .6; }
/* 붙여넣기는 거들 뿐이라 테두리만, 신청은 채워서 — 무엇이 본 단추인지 보이게 */
.yt-req-paste, .yt-req-go {
    flex: 0 0 auto; height: 42px; padding: 0 13px;
    border-radius: var(--radius-m); font-size: 14px; cursor: pointer;
    white-space: nowrap; -webkit-tap-highlight-color: transparent;
}
.yt-req-paste {
    border: 1px solid var(--line-3); background: var(--surface); color: var(--label-2);
}
.yt-req-paste:active { background: var(--fill); }
.yt-req-go {
    border: 0; background: var(--label); color: var(--surface); font-weight: 600;
}
.yt-req-go:disabled { opacity: .5; cursor: default; }

.yt-msg {
    display: block; margin-top: 9px; padding: 0 2px;
    font-size: 13px; line-height: 1.5; text-align: center;
}
.yt-msg[hidden] { display: none; }
.yt-msg.good { color: var(--label-2); }
.yt-msg.bad  { color: #d0393e; }

/* 앱 안내 문구 */
.app-msg {
    padding: 4px 6px 16px; text-align: center;
}
.app-msg b {
    display: block; font-size: 15.5px; font-weight: 600;
    letter-spacing: -0.3px; color: var(--label); margin-bottom: 7px;
}
.app-msg em {
    display: block; font-style: normal;
    font-size: 13px; line-height: 1.6; color: var(--label-2); letter-spacing: -0.2px;
}
.yt-txt { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.yt-txt b  { font-size: 15px; font-weight: 600; color: var(--label); letter-spacing: -0.2px; }
.yt-txt em { font-style: normal; font-size: 12.5px; color: var(--label-3); }

/*
| 번호 크게 보기 시트.
|
| 숫자만 크게. 라벨('금영 노래방')은 위에 한 급 작게 두어, 기계 앞에서
| 눈이 숫자에 바로 꽂히게 한다. 칸에 칠한 색을 그대로 물려받아 어느
| 쪽을 눌렀는지가 색으로도 남는다.
|
| tabular-nums 는 여기서 특히 중요하다 — 자릿수가 고르지 않으면 숫자를
| 하나씩 짚어 누르는 동안 시선이 흔들린다.
*/
.num-big {
    display: flex; flex-direction: column; align-items: center; gap: 7px;
    padding: 24px 12px 26px; margin-bottom: 12px;
    border: 1px solid var(--hairline); border-radius: 16px;
    background: var(--surface-hover);
}
.num-big-lab {
    font-size: 13px; font-weight: 600; letter-spacing: 0.2px; color: var(--label-3);
}
.num-big-val {
    font-family: 'Roboto', sans-serif;
    font-size: 56px; font-weight: 700; line-height: 1;
    letter-spacing: 2px; font-variant-numeric: tabular-nums;
    color: var(--label);
}
.num-big.ky .num-big-val { color: var(--blue); }

/*
| 같은 곡의 다른 번호.
|
| 큰 번호 아래에 작게 깐다. 여기서 하는 일은 '이것도 된다' 를 알리는
| 것이지 고르라고 다그치는 것이 아니라, 눌린 것만 진하게 두고 나머지는
| 물러나 있게 한다.
*/
.num-big-alt {
    display: flex; flex-wrap: wrap; align-items: center; justify-content: center;
    gap: 5px; margin-top: 12px;
}
/*
| display 를 준 요소는 [hidden] 이 안 먹는다 — 브라우저 기본 규칙과 특정도가
| 같은데 이 파일이 뒤에 오기 때문이다 (2026-09-09 고침).
| 번호가 하나뿐인 곡에서도 이 줄이 남아 팝업에 빈 여백이 생기고 있었다.
*/
.num-big-alt[hidden] { display: none; }
.nba-lab {
    flex: 0 0 100%; margin-bottom: 2px;
    font-size: 11.5px; font-weight: 600; color: var(--label-3); letter-spacing: -0.2px;
}
.nba {
    padding: 5px 12px; border-radius: 999px;
    border: 1px solid var(--hairline); background: var(--surface);
    color: var(--label-2);
    font-family: 'Roboto', sans-serif; font-size: 14px; font-weight: 600;
    font-variant-numeric: tabular-nums; cursor: pointer;
    -webkit-tap-highlight-color: transparent;
    transition: all 0.15s var(--ease);
}
.nba.on { border-color: transparent; background: var(--label); color: var(--surface); }
.num-big.tj .num-big-val { color: var(--purple); }
@media (max-width: 360px) { .num-big-val { font-size: 48px; } }

.num-big-copy {
    width: 100%; height: 46px; margin-bottom: 8px;
    border: 0; border-radius: var(--radius-m);
    background: var(--blue); color: #fff;
    font-size: 15px; font-weight: 700; font-family: inherit;
    letter-spacing: -0.2px; cursor: pointer;
    display: flex; align-items: center; justify-content: center; gap: 5px;
    -webkit-tap-highlight-color: transparent;
    transition: background 0.15s;
}
.num-big-copy:active   { background: var(--blue-2); }
.num-big-copy.is-copied { background: var(--green, #34c759); }

/* 번호 칸을 단추로 만든 것 — 겉모습은 .num-tile 그대로다 */
.num-open {
    font-family: inherit; text-align: inherit; cursor: pointer;
    -webkit-tap-highlight-color: transparent;
}

/*
| 오른쪽 위 닫기 — 유튜브 시트에만 쓴다.
|
| 영상에 자리를 내주려고 아래 폭 전체짜리 단추를 걷어 낸 자리다. 손가락이
| 닿을 34px 을 주되 표는 작게 둔다 — 이 시트의 주인공은 영상이지 닫기가 아니다.
*/
.yt-x {
    position: absolute; top: 9px; right: 10px; z-index: 2;
    width: 34px; height: 34px; padding: 0;
    display: flex; align-items: center; justify-content: center;
    border: 0; border-radius: 50%;
    background: var(--fill-3); color: var(--label-2);
    font-size: 13px; line-height: 1; font-family: inherit; cursor: pointer;
    -webkit-tap-highlight-color: transparent;
    transition: background 0.15s, color 0.15s;
}
.yt-x:hover  { background: var(--fill-2); color: var(--label); }
.yt-x:active { background: var(--fill-2); color: var(--label); }

/* 가운데 놓인 곡 제목이 그 단추 밑으로 들어가지 않게 양쪽을 같이 비운다 */
#ytSheet .yt-song { padding: 0 38px; }

.yt-cancel {
    width: 100%; height: 41px; margin-top: 2px;
    border: none; border-radius: var(--radius-m);
    background: var(--fill); color: var(--label-2);
    font-size: 14.5px; font-weight: 600; font-family: inherit;
    cursor: pointer; -webkit-tap-highlight-color: transparent;
}
.yt-cancel:active { background: var(--fill-2); }

/*
| 관리자 — 인기순 손보기.
|
| 시트는 곡 번호 크게보기와 같은 부품(.yt-sheet/.yt-panel)을 쓰되, 목록이
| 길어 안쪽만 굴러가게 한다. 목록 전체가 굴러가면 저장 단추가 화면 밖으로
| 나가서, 다 고쳐 놓고 저장을 못 누른다.
*/
.adm-rank { border-color: var(--purple) !important; color: var(--purple) !important; font-weight: 700; }
.ar-panel { max-width: 520px; }
.ar-tip {
    margin: -6px 0 10px; font-size: 12px; line-height: 1.6;
    color: var(--label-3); letter-spacing: -0.2px; text-align: center;
}
.ar-tip b { color: var(--label-2); font-weight: 700; }
.ar-list {
    max-height: 52vh; overflow-y: auto;
    border: 1px solid var(--hairline); border-radius: 12px;
    background: var(--surface-2);
}
.ar-row {
    display: flex; align-items: center; gap: 8px;
    padding: 8px 10px; border-bottom: 1px solid var(--hairline);
}
.ar-row:last-child { border-bottom: 0; }
.ar-no {
    flex: 0 0 26px; text-align: center;
    font-family: 'Roboto', sans-serif; font-size: 12.5px; font-weight: 700;
    color: var(--label-3); font-variant-numeric: tabular-nums;
}
.ar-tx { flex: 1 1 auto; min-width: 0; }
.ar-ti {
    display: block; font-size: 13.5px; font-weight: 600; letter-spacing: -0.3px;
    color: var(--label); white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.ar-sub {
    display: block; margin-top: 1px; font-size: 11px; color: var(--label-3);
    font-family: 'Roboto', sans-serif; font-variant-numeric: tabular-nums;
}
.ar-btns { flex: 0 0 auto; display: flex; gap: 3px; }
.ar-btns button {
    width: 26px; height: 26px; padding: 0;
    border: 1px solid var(--hairline); border-radius: 7px;
    background: var(--surface); color: var(--label-2);
    font-family: inherit; font-size: 12px; line-height: 1; cursor: pointer;
    -webkit-tap-highlight-color: transparent;
}
.ar-btns button.top { width: auto; padding: 0 7px; font-size: 11px; font-weight: 700; color: var(--purple); }
.ar-btns button:hover { background: var(--surface-hover); }
.ar-save {
    width: 100%; height: 46px; margin: 10px 0 8px;
    border: 0; border-radius: var(--radius-m);
    background: var(--purple); color: #fff;
    font-family: inherit; font-size: 15px; font-weight: 700;
    cursor: pointer; -webkit-tap-highlight-color: transparent;
}
.ar-save:disabled { opacity: 0.5; cursor: default; }

/* ── 상단 이동 버튼 ── */

.top-btn {
    position: fixed;
    bottom: 26px; right: 20px;
    width: 46px; height: 46px;
    border: 1px solid var(--hairline);
    border-radius: 50%;
    background: var(--glass-2);
    -webkit-backdrop-filter: saturate(180%) blur(20px);
    backdrop-filter: saturate(180%) blur(20px);
    color: var(--label);
    font-size: 19px;
    cursor: pointer;
    box-shadow: 0 6px 20px rgba(0,0,0,0.15);
    display: none;
    align-items: center; justify-content: center;
    z-index: 300;
    transition: transform 0.2s var(--ease), background 0.15s;
    -webkit-tap-highlight-color: transparent;
}
.top-btn.visible { display: flex; }
.top-btn:hover  { background: var(--surface); }
.top-btn:active { transform: scale(0.9); }

/*
| 뽑기 입구 — '맨 위로' 바로 위에 떠 있다.
|
| 동그라미가 아니라 글자를 넣은 알약 꼴이다. 🎲 만으로는 무엇을 하는
| 버튼인지 알 수 없다. '맨 위로' 는 ↑ 하나로 뜻이 통하지만, 새 기능은
| 이름이 있어야 눌린다.
|
| '맨 위로' 와 달리 늘 보인다 — 스크롤을 내려야 나타나면, 목록 맨 위에서
| 부를 곡이 없어 막막한 순간에 정작 안 보인다.
*/
.dice-btn {
    position: fixed;
    bottom: 82px; right: 20px;          /* 맨 위로(26px) + 46px + 10px */
    height: 46px; padding: 0 15px 0 13px;
    display: inline-flex; align-items: center; gap: 6px;
    border: 1px solid var(--blue-line);
    border-radius: 23px;
    background: var(--blue);
    color: #fff;
    font-size: 18px; line-height: 1;
    text-decoration: none;
    box-shadow: 0 6px 20px rgba(0,122,255,0.32);
    z-index: 300;
    transition: transform 0.2s var(--ease);
    -webkit-tap-highlight-color: transparent;
}
.dice-btn span { font-size: 14px; font-weight: 700; letter-spacing: -0.3px; white-space: nowrap; }
/*
| '(뽑기)' 는 이름의 일부지만 무게가 달라야 한다.
| 같은 굵기로 두면 '랜덤노래방뽑기' 한 덩어리로 읽혀서 둘 다 흐려진다.
| 한 급 작고 흐리게 두면 이름은 '랜덤노래방', 괄호는 설명으로 읽힌다.
*/
.dice-btn span i { font-style: normal; font-weight: 600; font-size: 12.5px; opacity: 0.82; margin-left: 2px; }
.dice-btn:active { transform: scale(0.93); }
/*
| 플레이어를 가리는 순간에는 떠 있는 단추를 걷는다 (2026-09-13).
| 유튜브 규정이 임베드 플레이어를 가리는 요소를 금지한다. 어느 쪽이든
| 실제로 겹칠 때만 걷힌다 — app.js 의 mvGuardFloats() 가 재서 붙인다.
| display:none 이 아니라 visibility 로 걷는 이유: 다시 나타날 때 자리가
| 그대로라 화면이 안 흔들린다.
*/
.dice-btn.mv-hide,
.top-btn.mv-hide {
    visibility: hidden; opacity: 0; pointer-events: none;
    transition: opacity 0.15s var(--ease);
}

/* 화면이 좁으면 글자를 접고 주사위만 남긴다 */
/*
| 좁은 화면 — 이름이 길어져 화면을 가리므로 주사위만 남긴다.
| 뜻은 title·aria-label 에 그대로 남는다.
*/
@media (max-width: 460px) {
    .dice-btn { padding: 0; width: 46px; justify-content: center; }
    .dice-btn span { display: none; }
}

/* AI 인기순 표식 — 관리자에게만 보인다 */
.ai-pop-tag {
    display: inline-block; margin: 0 0 8px; padding: 3px 10px;
    border-radius: 20px; font-size: 11.5px; font-weight: 600;
    background: var(--blue-fill); color: var(--blue);
    border: 1px dashed var(--blue-line);
}
/* AI 가 순서를 정한 곡 — 순위 숫자를 파랗게 */
.hit-rank.ai-on { color: var(--blue); font-weight: 700; }

/* 제목 줄 오른쪽 — 곡정보·가수정보
   글자가 작고 테두리가 옅어야 제목을 가리지 않는다. 카드 전체를 덮은
   .hit-link::after 위로 올려야 눌린다(z-index). */
.row-info { grid-area: info; }
.row-sng  { grid-area: sng; }
.row-btn {
    position: relative; z-index: 1;
    display: inline-flex; align-items: center; justify-content: center; gap: 4px;
    height: 27px; padding: 0 11px; border-radius: 20px;
    border: 1px solid var(--line);
    background: var(--surface); color: var(--label-2);
    font-size: 12.5px; font-weight: 600; letter-spacing: -0.2px;
    text-decoration: none; white-space: nowrap; flex-shrink: 0;
    -webkit-tap-highlight-color: transparent;
    transition: background 0.15s, color 0.15s, border-color 0.15s;
}
/* 유튜브 표시 — 글자를 늘리지 않고 아이콘만 붙인다 */
.row-vid { width: 15px; height: 11px; fill: var(--red); flex-shrink: 0; }
/* 같은 가수 곡 목록 안의 유튜브 표시 — 제목 뒤에 붙는다 */
.also-cell .row-vid { width: 13px; height: 10px; flex-shrink: 0; }
.row-btn:hover { background: var(--fill); color: var(--label-2); }
.row-btn.row-sng { color: var(--blue); border-color: var(--blue-line); }
.row-btn.row-sng:hover { background: var(--blue-fill); }

@media (max-width: 400px) {
    .row-btn { padding: 0 8px; font-size: 11.5px; height: 25px; }
}

/*
| 곡 페이지 소개 문장 — 가사보다 앞이지만 제목·번호보다는 뒤다.
|
| 두 토막의 무게를 다르게 준다 (2026-08-31).
|   .sb-lead   순위·번호를 풀어 쓴 말. 위 번호판에 이미 숫자로 나와 있으니
|              곁들이는 설명이다. 작고 흐리게 둔다.
|   .sb-intro  가수 소개. 사람이 읽으라고 쓴 유일한 글이다. 한 급 키우고
|              굵기와 색을 올려 앞 문장에 묻히지 않게 한다.
| 한 덩어리로 두면 번호 설명과 소개글이 같은 무게라 정작 읽힐 글이 안 읽힌다.
*/
.song-blurb {
    margin: 10px 0 12px;
    font-size: 13.5px; line-height: 1.7;
    letter-spacing: -0.2px; color: var(--label-2);
}
.song-blurb .sb-intro {
    font-size: 14.5px; font-weight: 500; color: var(--label);
}

/*
| 같은 작곡가의 다른 곡 (.comp-list)
|
| 왜 칩이 아닌가
|   같은 페이지 안에 이미 칸 격자(.also-list)가 둘 있다 — 비슷한 곡, 그 가수의 곡.
|   여기에 셋째 격자를 얹으면 눈에는 하나로 뭉쳐 보여서, 갈래가 늘어난 것이
|   드러나지 않는다. 세로 줄 목록으로 모양을 아예 달리해 구역을 갈라 준다.
|
| 번호를 붙인다
|   ol 의 순서가 곧 인기 순(ai_pop)이라, 번호가 그 자체로 정보다.
|   목록 표시는 지우고 counter 로 직접 그린다 — 자릿수가 밀려도 제목 줄이 안 흔들린다.
|
| 가수명을 같이 보여 준다
|   칩은 제목만 보여 준다. 작곡가 갈래에서는 '이 곡이 누구 곡인지' 가 핵심이라
|   (좋은 날 → 씨야·BROWN EYED GIRLS) 가수명이 빠지면 따라갈 이유가 사라진다.
|   좁은 화면에서는 제목이 줄고 가수명은 제 폭을 지킨다.
*/
.comp-list { list-style: none; margin: 0; padding: 0; counter-reset: cp; }
.comp-list li { counter-increment: cp; }
.comp-list li + li { border-top: 1px solid var(--hairline); }
.comp-list a {
    display: flex; align-items: center; gap: 10px;
    padding: 9px 4px; text-decoration: none;
    -webkit-tap-highlight-color: transparent;
}
.comp-list a::before {
    content: counter(cp);
    flex: 0 0 18px; text-align: center;
    font-family: 'Roboto', sans-serif; font-size: 12px; font-weight: 700;
    color: var(--label-3);
}
.comp-list .cp-t {
    flex: 1; min-width: 0;
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
    font-size: 14px; font-weight: 500; color: var(--label);
}
.comp-list .cp-s {
    flex-shrink: 0; max-width: 40%;
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
    font-size: 12.5px; color: var(--label-2);
}
.comp-list a:hover .cp-t { color: var(--blue); }

/*
| 주제 대표 영상 (.theme-mv) — 목록 위 두 개
|
| 곡 페이지의 .song-mv 와 같은 그림·재생 부품(.mv-box)을 쓰되, 제목을
| 그림 안이 아니라 위에 따로 둔다. 곡 페이지는 제목이 이미 크게 나와 있어
| 그림 안 라벨('뮤직비디오')로 충분하지만, 주제 페이지는 곡이 수십 개라
| 어느 곡의 영상인지 제목이 제자리를 차지해야 한다.
|
| 제목은 그 곡으로 가는 링크다 — 영상만 보고 번호를 찾으러 갈 사람의 길.
| 누를 곳이 둘(제목·그림)이라 그림 쪽은 재생, 제목 쪽은 이동으로 갈린다.
*/
/*
| 목록 위 영상 구역과 '다른 영상 보기' 단추 (2026-09-09)
|
| 단추 자리를 위에 따로 비운다. 영상 칸 위에는 곡 제목 줄(.tmv-label)이
| 있어서, 단추를 그 위에 겹치면 가수 이름 끝을 덮는다. 좁은 화면에서는
| 칸이 한 줄로 접혀 첫 제목을 덮으므로 어느 쪽으로도 안전하지 않다.
| 22px 을 내주고 대신 아무 데서도 안 부딪히게 한다.
*/
.mv-wrap { margin: 4px 0 14px; }

/*
| 머리줄 — 왼쪽에 무엇인지, 오른쪽에 바꾸는 단추.
|
| 자리를 비워 단추만 띄우는 대신 한 줄을 제대로 쓴다. 절대 배치를 안 쓰므로
| 곡 제목 줄과 겹칠 일도 없다 (좁은 화면에서 칸이 한 줄로 접혀도 그렇다).
*/
.mv-head {
    display: flex; align-items: center; justify-content: space-between;
    gap: 8px; padding: 0 2px 4px;
}
.mv-head-t {
    font-size: 12px; font-weight: 500; letter-spacing: -0.2px;
    color: var(--label-3); min-width: 0;
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.mv-refresh {
    flex-shrink: 0;
    display: flex; align-items: center; gap: 4px;
    height: 26px; padding: 0 8px 0 6px;
    border: 1px solid var(--hairline); border-radius: 999px;
    background: var(--surface); color: var(--label-2);
    font: inherit; font-size: 12px; font-weight: 500; letter-spacing: -0.2px;
    cursor: pointer; -webkit-tap-highlight-color: transparent;
    transition: color 0.15s, background 0.15s, border-color 0.15s;
}
.mv-refresh svg { width: 14px; height: 14px; flex-shrink: 0; }
.mv-refresh:hover  { color: var(--label-1); background: var(--fill); border-color: var(--line-3); }
.mv-refresh:active { background: var(--fill-2); }
.mv-refresh.spin svg { animation: mvSpin 0.45s var(--ease); }
@keyframes mvSpin { from { transform: rotate(0); } to { transform: rotate(360deg); } }
@media (prefers-reduced-motion: reduce) { .mv-refresh.spin svg { animation: none; } }

.theme-mv { display: flex; gap: 10px; flex-wrap: wrap; }
.theme-mv .tmv { flex: 1 1 240px; min-width: 0; }
/* 재생을 누른 칸만 한 줄을 다 쓴다 — playMv() 가 붙인다 */
.theme-mv .tmv.is-playing { flex: 1 1 100%; }
.theme-mv .mv-box { display: block; width: 100%; }
.tmv-label {
    display: flex; align-items: baseline; gap: 6px;
    padding: 0 2px 5px; text-decoration: none;
    -webkit-tap-highlight-color: transparent;
}
.tmv-label .tmv-t {
    flex: 0 1 auto; min-width: 0;
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
    font-size: 13.5px; font-weight: 700; color: var(--label);
}
.tmv-label .tmv-s {
    flex-shrink: 0;
    font-size: 12px; font-weight: 500; color: var(--label-2);
}
.tmv-label:hover .tmv-t { color: var(--blue); }

/*
| 빠진 번호 알려주기 (.num-ask / .num-fill)
|
| '없음' 칸을 그대로 단추로 만든다. 새 자리를 만들지 않는 것이 중요하다 —
| 번호를 보러 온 사람의 눈길이 가는 곳이 곧 비어 있는 그 칸이라, 거기서
| 바로 물어야 한다. 입력칸은 누르기 전에는 접혀 있다.
*/
.num-ask {
    font-family: inherit; cursor: pointer; text-align: inherit;
    border: 1px dashed var(--hairline);
    -webkit-tap-highlight-color: transparent;
    transition: background 0.15s, border-color 0.15s;
}
.num-ask:hover { background: var(--surface-2); border-color: var(--blue-line); }
/* 한 줄에 셋은 좁으니 이것만 아랫줄로 내린다 (.num-tile 이 wrap) */
.num-ask .num-ask-cta {
    flex: 0 0 100%; text-align: center; margin-top: 1px;
    font-size: 11px; font-weight: 600; color: var(--blue); letter-spacing: -0.2px;
}
.num-fill {
    margin-top: 10px; padding: 12px 13px;
    background: var(--surface-2); border: 1px solid var(--hairline);
    border-radius: var(--radius-m);
}
.num-fill .nf-q { margin: 0 0 8px; font-size: 13px; color: var(--label-2); }
.num-fill .nf-q b { color: var(--label); font-weight: 700; }
.num-fill .nf-sub { color: var(--label-3); font-size: 12px; }
.num-fill .nf-row { display: flex; gap: 7px; }
.num-fill input {
    flex: 1; min-width: 0; height: 36px; padding: 0 11px;
    border: 1px solid var(--line); border-radius: var(--radius-s);
    background: var(--surface); color: var(--label);
    font-family: 'Roboto', sans-serif; font-size: 15px;
}
.num-fill input:disabled { opacity: .55; }
.nf-btn {
    flex-shrink: 0; height: 36px; padding: 0 15px;
    border: 0; border-radius: var(--radius-s); cursor: pointer;
    background: var(--blue); color: #fff;
    font-family: inherit; font-size: 13.5px; font-weight: 600;
}
.nf-btn:active { transform: scale(0.97); }
.num-fill .nf-msg { margin: 8px 0 0; font-size: 13px; color: var(--label-2); line-height: 1.6; }
.num-fill .nf-warn { color: var(--orange); }
.num-fill .nf-ok   { color: var(--label); font-weight: 600; }
.num-fill .nf-hit  { display: block; margin-bottom: 7px; color: var(--label); font-weight: 600; }
.num-fill .nf-ok.nf-btn { color: #fff; }

/* 관리 패널 — 영상이 어디서 왔고 얼마나 보였나 (곡 페이지, 관리자만) */
.adm-vmeta { margin: 2px 0 8px 30px; font-size: 11.5px; color: var(--label-3); letter-spacing: -0.2px; }
.adm-vmeta .vm-src {
    display: inline-block; padding: 1px 6px; margin-right: 3px; border-radius: 5px;
    background: var(--fill); color: var(--label-2); font-weight: 600;
}
.adm-vmeta .vm-src.vm-api { background: var(--blue-fill); color: var(--blue); }
.adm-vmeta .vm-chk { font-weight: 600; color: var(--orange); }
.adm-vmeta .vm-chk.ok  { color: var(--green, #34c759); }
.adm-vmeta .vm-chk.bad { color: var(--red); }
.adm-vmeta .vm-at { color: var(--label-3); }
