/* ============================================================
   shop-2026.css — 악보샵 커머스 레이아웃 (26-07-19)

   style.css 뒤에 로드된다. 전 페이지 공통.

   설계 근거: 악보바다·마이뮤직시트를 실측한 결과 국내 악보 사이트는
   전부 같은 문법을 쓴다 —
     · 브랜드 카피 히어로가 없다. 첫 화면부터 상품이다
     · 검색창이 헤더 정중앙에 크게 (곡명으로 찾아오는 손님이 대부분)
     · 악기/파트가 최상위 내비
     · 인기·최신을 세로로 늘어뜨리지 않고 2단으로 나란히
     · 정보 밀도가 높다. 여백이 아니라 곡이 채운다
   ============================================================ */

:root {
  --ease-out-expo: cubic-bezier(0.16, 1, 0.3, 1);
  --ease-out-quart: cubic-bezier(0.25, 1, 0.5, 1);
  --z-base: 1;
  --z-sticky: 20;
  --z-toast: 50;
}

/* ============================================================
   0. 한글 줄바꿈
   body에 word-break: keep-all이 걸려 있어 단어는 안 쪼개진다(좋다).
   대신 **마지막 줄에 조사 두세 글자만 남는** 어색한 줄바꿈이 잘 생긴다.
   balance = 제목의 줄 길이를 고르게, pretty = 본문 끝줄 고아를 줄인다.
   미지원 브라우저는 그냥 무시하므로 안전하다.
   ============================================================ */

h1, h2, h3, h4,
.promo-card h3,
.part-tile .label,
.score-title,
.rank-info .title {
  text-wrap: balance;
}

p, li, dd, td, figcaption,
.product-desc, .bm-foot-note, .hint {
  text-wrap: pretty;
}

/* ============================================================
   1. 헤더 — 2단 (로고+검색 / 파트 내비)
   ============================================================ */

.site-header {
  background: var(--paper);
  border-bottom: 1px solid var(--line);
  position: sticky;
  top: 0;
  z-index: var(--z-sticky);
}

/* style.css의 1단 헤더 규칙을 무력화 */
.site-header > .wrap {
  display: contents;
}

.header-main .wrap,
.header-parts .wrap {
  max-width: 1160px;
  margin: 0 auto;
  padding: 0 24px;
  display: flex;
  align-items: center;
  gap: 24px;
}

.header-main {
  padding: 14px 0;
}

.brand {
  flex-shrink: 0;
}

/* ---------- 검색: 이 사이트에서 가장 중요한 입력칸 ---------- */
.header-search {
  flex: 1;
  max-width: none;
  min-width: 0;
  background: var(--paper);
  border: 2px solid var(--ink);
  border-radius: 100px;
  padding: 0 0 0 20px;
  height: 46px;
  transition: box-shadow 0.18s var(--ease-out-quart);
}
.header-search:focus-within {
  box-shadow: 0 0 0 4px var(--accent-tint);
}
.header-search input[type="search"] {
  font-size: 15px;
  padding: 0;
  height: 100%;
}
.header-search input[type="search"]::placeholder {
  color: #7d766a; /* --ink-soft보다 진하게: placeholder도 4.5:1 넘겨야 한다 */
}
.header-search button {
  height: 38px;
  margin-right: 4px;
  padding: 0 22px;
  font-size: 14px;
  background: var(--ink);
}

.header-actions {
  gap: 18px;
  flex-shrink: 0;
  margin-left: 0;
}
.header-actions > a {
  font-size: 13.5px;
  font-weight: 600;
  color: var(--ink-soft);
  text-decoration: none;
  white-space: nowrap;
}
.header-actions > a:hover {
  color: var(--ink);
}
.header-actions .cart-link {
  color: var(--ink);
}

/* ---------- 파트 내비 ---------- */
.header-parts {
  border-top: 1px solid var(--line);
  background: var(--paper);
}
.header-parts .wrap {
  gap: 0;
  justify-content: space-between;
}
.part-nav {
  display: flex;
  align-items: center;
  gap: 2px;
  flex: 1;
  min-width: 0;
  overflow-x: auto;
  scrollbar-width: none;
  -webkit-overflow-scrolling: touch;
}
.part-nav::-webkit-scrollbar {
  display: none;
}
.part-nav a {
  flex: 0 0 auto;
  font-size: 14.5px;
  font-weight: 600;
  color: var(--ink-soft);
  text-decoration: none;
  padding: 13px 16px;
  border-bottom: 2px solid transparent;
  white-space: nowrap;
  transition: color 0.15s var(--ease-out-quart);
}
.part-nav a:first-child {
  padding-left: 0;
  font-weight: 700;
  color: var(--ink);
}
.part-nav a:hover {
  color: var(--ink);
}
.part-nav a.active {
  color: var(--ink);
  border-bottom-color: var(--accent);
}
.part-nav-cta {
  flex-shrink: 0;
  font-size: 13.5px;
  font-weight: 700;
  color: var(--accent-deep);
  text-decoration: none;
  padding-left: 16px;
  white-space: nowrap;
}

/* ============================================================
   2. 홈 — 상품이 첫 화면부터
   ============================================================ */

.shop-main {
  padding: 28px 0 8px;
}

.section {
  padding: 30px 0;
}
.section-head {
  align-items: center;
  margin-bottom: 16px;
}
.section-head h2 {
  font-size: 19px;
  letter-spacing: -0.01em;
}

/* ---------- 인기 | 최신 2단 ---------- */
.two-col {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 20px 40px;
  align-items: start;
}
@media (max-width: 860px) {
  .two-col {
    grid-template-columns: 1fr;
    gap: 8px;
  }
}

.list-panel {
  min-width: 0;
}
.list-panel .section-head {
  padding-bottom: 10px;
  border-bottom: 2px solid var(--ink);
  margin-bottom: 0;
}

/* 랭킹 행: 순위 · 커버 · 제목/아티스트 · 가격 */
.rank-row {
  gap: 14px;
  padding: 11px 2px;
}
.rank-num {
  font-family: var(--font-body);
  font-size: 14px;
  font-weight: 800;
  color: var(--ink-soft);
  width: 20px;
}
.rank-row:nth-child(-n + 3) .rank-num {
  color: var(--accent);
}
.rank-thumb {
  width: 44px;
  height: 44px;
  border: 1px solid var(--line);
  background: var(--paper-alt);
}
.rank-info .title {
  font-size: 14px;
  font-weight: 600;
}
.rank-price {
  font-size: 13.5px;
}

/* 최신 악보는 순위가 없으니 NEW 뱃지로 */
.new-chip {
  font-size: 10px;
  font-weight: 800;
  color: var(--danger);
  border: 1px solid currentColor;
  border-radius: 3px;
  padding: 1px 4px;
  margin-left: 6px;
  vertical-align: 1px;
}

/* ---------- 파트 바로가기 타일 ----------
   곡이 적을 때 화면을 채우는 몫도 하지만, 본래 목적은
   "내 악기부터 보고 싶다"는 가장 흔한 동선을 한 번에 열어주는 것 */
.part-tiles {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(120px, 1fr));
  gap: 12px;
}
.part-tile {
  display: flex;
  flex-direction: column;
  gap: 6px;
  padding: 18px 16px;
  border: 1px solid var(--line);
  border-radius: 12px;
  text-decoration: none;
  color: var(--ink);
  background: var(--paper);
  transition: border-color 0.2s var(--ease-out-quart), background 0.2s var(--ease-out-quart),
    transform 0.3s var(--ease-out-expo);
}
.part-tile:hover {
  border-color: var(--ink);
  background: var(--paper-alt);
  color: var(--ink);
  transform: translateY(-2px);
}
.part-tile .glyph {
  font-size: 22px;
  line-height: 1;
  color: var(--accent);
}
.part-tile .label {
  font-size: 14.5px;
  font-weight: 700;
}
.part-tile .count {
  font-size: 12px;
  color: var(--ink-soft);
}

/* 상품 상세의 미리보기도 같은 커버를 쓴다 (빈 회색 상자였음) */
.product-preview .score-cover {
  border: none;
  border-radius: 0;
  box-shadow: none;
  aspect-ratio: 3 / 4;
}
.product-preview .score-cover > svg,
.product-preview .score-cover > img {
  width: 100%;
  height: 100%;
  display: block;
  object-fit: contain;
}

/* 헤더에서 넘어온 검색어 표시 */
.query-chip {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  margin: 0 0 16px;
  padding: 7px 8px 7px 15px;
  border: 1px solid var(--line-strong);
  border-radius: 100px;
  background: var(--paper-alt);
  font-size: 13.5px;
  color: var(--ink-soft);
}
.query-chip strong {
  color: var(--ink);
}
.query-chip button {
  border: none;
  background: var(--line);
  color: var(--ink);
  border-radius: 50%;
  width: 20px;
  height: 20px;
  font-size: 11px;
  line-height: 1;
  cursor: pointer;
}
.query-chip button:hover {
  background: var(--line-strong);
}

/* ---------- 안내 배너 2단 ---------- */
.promo-row {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 16px;
}
@media (max-width: 720px) {
  .promo-row {
    grid-template-columns: 1fr;
  }
}
.promo-card {
  border: 1px solid var(--line);
  border-radius: 12px;
  padding: 22px 24px;
  background: var(--paper-alt);
}
.promo-card h3 {
  font-family: var(--font-kr-display);
  font-size: 18px;
  margin: 0 0 6px;
}
.promo-card p {
  margin: 0 0 14px;
  font-size: 14px;
  color: var(--ink-soft);
  max-width: 42ch;
}

/* ============================================================
   3. 카드 — 커버가 주인공
   ============================================================ */

.score-grid {
  grid-template-columns: repeat(auto-fill, minmax(178px, 1fr));
  gap: 26px 18px;
}

.score-card {
  position: relative;
  transition: transform 0.35s var(--ease-out-expo);
}
.score-card:hover {
  box-shadow: none;
  transform: translateY(-3px);
}

.score-cover {
  border: 1px solid var(--line);
  box-shadow: 0 1px 2px rgba(26, 22, 15, 0.05);
  border-radius: 8px;
  transition: box-shadow 0.35s var(--ease-out-expo), border-color 0.35s var(--ease-out-expo);
}
.score-card:hover .score-cover {
  border-color: var(--line-strong);
  box-shadow: 0 12px 26px -8px rgba(26, 22, 15, 0.26);
}
.score-cover > img,
.score-cover > svg {
  width: 100%;
  height: 100%;
  display: block;
  object-fit: cover;
  transition: transform 0.5s var(--ease-out-expo);
}
.score-card:hover .score-cover > img,
.score-card:hover .score-cover > svg {
  transform: scale(1.04);
}

.new-badge {
  left: auto;
  right: 8px;
  top: 8px;
  z-index: var(--z-base);
  box-shadow: 0 1px 4px rgba(0, 0, 0, 0.2);
}

.score-body {
  padding: 10px 2px 2px;
  gap: 3px;
}
.score-title {
  font-size: 14.5px;
}
.score-artist {
  font-size: 12.5px;
}
.card-meta-row {
  align-items: center;
}
.card-meta-row > span:first-child {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  min-width: 0;
}
/* 카드 폭에선 취소선 원가까지 넣으면 줄이 접혀 난이도 칩과 baseline이 어긋난다 */
.score-card .price-original {
  display: none;
}

/* 카드 전면 링크 + 그 위 담기 버튼 */
.score-link {
  text-decoration: none;
  color: inherit;
}
.score-link::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: var(--z-base);
}
.score-link:hover {
  color: inherit;
}

.quick-add {
  position: absolute;
  right: 8px;
  bottom: 8px;
  z-index: calc(var(--z-base) + 1);
  font-family: var(--font-body);
  font-size: 12px;
  font-weight: 700;
  color: var(--ink);
  background: rgba(255, 255, 255, 0.94);
  backdrop-filter: blur(6px);
  border: 1px solid var(--line-strong);
  border-radius: 100px;
  padding: 6px 13px;
  cursor: pointer;
  transition: background 0.16s var(--ease-out-quart), color 0.16s var(--ease-out-quart),
    border-color 0.16s var(--ease-out-quart), opacity 0.25s var(--ease-out-quart),
    transform 0.25s var(--ease-out-expo);
}
.quick-add:hover {
  background: var(--accent);
  border-color: var(--accent);
  color: #fff;
}
/* 마우스가 있는 기기: 평소엔 숨겼다가 카드에 올리면 뜬다 */
@media (hover: hover) and (pointer: fine) {
  .quick-add {
    opacity: 0;
    transform: translateY(6px);
  }
  .score-card:hover .quick-add,
  .quick-add:focus-visible {
    opacity: 1;
    transform: none;
  }
}

/* 터치 기기: 아예 두지 않는다.
   커버가 150px 남짓인데 누를 만한 크기(44px)로 만들면 커버의 30%를 덮는다.
   손가락으로는 카드를 눌러 상세로 가서 담는 동선이 자연스럽고,
   악보바다·마이뮤직시트도 모바일 카드에 퀵버튼을 두지 않는다. */
@media (hover: none) {
  .quick-add { display: none; }
}
@media (pointer: coarse) {
  .quick-add { display: none; }
}

/* ============================================================
   4. 카탈로그 필터 알약
   ============================================================ */

.category-tabs {
  border-bottom: none;
  padding-bottom: 4px;
  gap: 8px;
  flex-wrap: nowrap;
  overflow-x: auto;
  scrollbar-width: none;
  -webkit-overflow-scrolling: touch;
}
.category-tabs::-webkit-scrollbar {
  display: none;
}
.category-tabs a,
.category-tabs button {
  flex: 0 0 auto;
  white-space: nowrap;
  border-radius: 100px;
  border: 1px solid var(--line-strong);
  border-bottom: 1px solid var(--line-strong);
  background: var(--paper);
  color: var(--ink-soft);
  padding: 8px 16px;
  margin-bottom: 0;
  transition: background 0.16s var(--ease-out-quart), color 0.16s var(--ease-out-quart),
    border-color 0.16s var(--ease-out-quart);
}
.category-tabs a:hover,
.category-tabs button:hover {
  background: var(--paper-alt);
  color: var(--ink);
  border-color: var(--ink-soft);
}
.category-tabs a.active,
.category-tabs button.active,
.category-tabs a.active:hover,
.category-tabs button.active:hover {
  background: var(--ink);
  color: #fff;
  border-color: var(--ink);
}

/* ============================================================
   5. 반응형
   ============================================================ */

@media (max-width: 900px) {
  .header-actions > a:not(.cart-link) {
    display: none; /* 좁아지면 파트 내비와 장바구니만 남긴다 */
  }
}

@media (max-width: 719px) {
  /* ⭐iOS 사파리는 입력창 글자가 16px 미만이면 포커스할 때 페이지를 확대해 버린다.
     확대된 뒤엔 손으로 되돌려야 해서 검색 한 번에 화면이 망가진다.
     데스크톱은 15px 그대로 두고 모바일에서만 16px로 올린다. */
  input[type="text"],
  input[type="search"],
  input[type="email"],
  input[type="tel"],
  input[type="url"],
  input[type="number"],
  input[type="password"],
  input[type="date"],
  select,
  textarea,
  .header-search input[type="search"] {
    font-size: 16px;
  }

  /* 손가락으로 누르는 것들은 최소 44px (애플 HIG) */
  .header-actions > a,
  .part-nav a,
  .bm-foot-links a,
  .bm-foot-family a,
  .section-head .muted-link {
    display: inline-flex;
    align-items: center;
    min-height: 44px;
  }
  .category-tabs a,
  .category-tabs button,
  .period-tabs button,
  .btn,
  .brand {
    min-height: 44px;
  }
  .brand {
    align-items: center;
  }
  .header-search {
    height: 48px; /* 안쪽 검색 버튼이 44px를 확보할 수 있게 */
  }
  .header-search button {
    height: 44px;
    min-width: 64px;
  }

  .header-main {
    padding: 10px 0;
  }
  .header-main .wrap,
  .header-parts .wrap {
    padding: 0 16px;
    gap: 12px;
    flex-wrap: wrap;
  }
  .brand img {
    height: 26px;
  }
  .brand .wordmark {
    font-size: 15px;
  }
  .header-search {
    order: 3;
    flex: 1 1 100%;
    height: 42px;
    border-width: 1.5px;
  }
  .header-actions {
    margin-left: auto;
  }
  .part-nav a {
    padding: 11px 12px;
    font-size: 14px;
  }
  .part-nav-cta {
    display: none; /* 파트 내비 가로스크롤과 겹쳐서 잘린다 */
  }
  .shop-main {
    padding-top: 18px;
  }
  .section {
    padding: 22px 0;
  }
  .score-grid {
    grid-template-columns: repeat(auto-fill, minmax(144px, 1fr));
    gap: 22px 12px;
  }
  /* 좁은 폭에선 취소선 원가가 가격을 두 줄로 접는다 */
  .rank-row .price-original {
    display: none;
  }
  .rank-price {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    flex-shrink: 0;
  }
  .rank-info .title {
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
  }
}

/* ============================================================
   6. 모션 축소 — 선택이 아니라 필수
   ============================================================ */

@media (prefers-reduced-motion: reduce) {
  .score-card,
  .score-cover,
  .score-cover > img,
  .score-cover > svg,
  .quick-add,
  .part-tile,
  .category-tabs a,
  .category-tabs button {
    transition: none;
  }
  .score-card:hover,
  .part-tile:hover {
    transform: none;
  }
  .score-card:hover .score-cover > img,
  .score-card:hover .score-cover > svg {
    transform: none;
  }
}

/* ============================================================
   7. 스켈레톤 — 목록이 오기 전 카드 자리 (26-09-06)
   ============================================================
   홈은 /api/scores 응답이 와야 그려진다. 그전까지 "불러오는 중…" 한 줄만 있어서
   화면이 통째로 비어 보였고, 목록이 도착하는 순간 레이아웃이 크게 튀었다.
   같은 자리·같은 비율의 회색 카드를 미리 깔아 두 문제를 함께 없앤다. */

.score-card.skeleton {
  pointer-events: none;
}
.score-card.skeleton .score-cover {
  aspect-ratio: 400 / 566;
  background: var(--line, #e7e2d8);
}
.score-card.skeleton .score-body {
  display: flex;
  flex-direction: column;
  gap: 7px;
  padding-top: 10px;
}
.score-card.skeleton .score-body span {
  display: block;
  height: 11px;
  border-radius: 3px;
  background: var(--line, #e7e2d8);
}
.score-card.skeleton .score-body span:first-child { width: 82%; }
.score-card.skeleton .score-body span:last-child  { width: 54%; }

.score-card.skeleton .score-cover,
.score-card.skeleton .score-body span {
  animation: bm-skeleton-pulse 1.4s ease-in-out infinite;
}

@keyframes bm-skeleton-pulse {
  0%, 100% { opacity: 0.55; }
  50%      { opacity: 0.85; }
}

/* 미리보기 PNG가 도착하기 전에도 카드 높이가 정해져 있어야 목록이 안 밀린다 */
.score-cover > img {
  aspect-ratio: 400 / 566;
  background: var(--paper-2, #f5f2ec);
}

/* ⭐카드 표지는 곡의 '첫 장'을 보여야 한다.
   미리보기가 전 쪽을 세로로 이어붙인 긴 이미지라, object-fit:cover의 기본값(중앙)이
   하필 곡 한가운데(55마디쯤)를 잘라 보여주고 있었다 — 제목도 조표도 안 보인다.
   상품 상세의 큰 미리보기는 그대로 두고 목록 카드만 위쪽 기준으로 맞춘다. */
.score-card .score-cover > img {
  object-position: top center;
}

@media (prefers-reduced-motion: reduce) {
  .score-card.skeleton .score-cover,
  .score-card.skeleton .score-body span {
    animation: none;
  }
}

/* ============================================================
   8. 카탈로그 모바일 — 필터 접기 (26-09-06)
   ============================================================
   좁은 폭에서 필터 패널(난이도·장르·정렬)이 첫 화면을 통째로 차지해
   악보 한 장 보려면 한 화면을 스크롤해야 했다. 데스크톱은 그대로 두고
   모바일에서만 버튼 뒤로 접는다. */

.filter-toggle { display: none; }

@media (max-width: 820px) {
  .filter-toggle {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 8px;
    width: 100%;
    min-height: 44px;              /* 손가락 최소치 */
    margin: 0 0 16px;
    padding: 11px 16px;
    font: inherit;
    font-size: 14.5px;
    font-weight: 600;
    color: var(--ink, #2b2621);
    background: var(--paper, #fff);
    border: 1px solid var(--line-strong, #d8d2c6);
    border-radius: 999px;
    cursor: pointer;
  }
  .filter-toggle::after {
    content: "▾";
    font-size: 11px;
    color: var(--ink-soft, #77706a);
  }
  .filter-toggle[aria-expanded="true"]::after { content: "▴"; }

  /* 🚨display를 주면 UA의 [hidden]{display:none}을 덮어써서 0이 그대로 보인다 */
  .filter-badge[hidden] { display: none; }
  .filter-badge {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 19px;
    height: 19px;
    padding: 0 5px;
    border-radius: 999px;
    background: var(--accent-deep, #b45309);
    color: #fff;
    font-size: 11.5px;
    font-weight: 700;
  }

  /* 접힘이 기본. 펼칠 때만 보인다 */
  .filter-panel { display: none; }
  .filter-panel.open {
    display: block;
    margin-bottom: 24px;
    padding: 16px 16px 4px;
    border: 1px solid var(--line, #e7e2d8);
    border-radius: 12px;
  }
}

/* ============================================================
   11. 찜 · 최근 본 · 처음이라면 · 미리 보기 (26-09-06 개편 S3~S5)
   ============================================================ */
.wish-btn.on { border-color: var(--accent); color: var(--accent-deep); background: var(--accent-tint); }
.preview-strip {
  display: grid; grid-auto-flow: column; grid-auto-columns: minmax(150px, 1fr); gap: 12px;
  overflow-x: auto; padding-bottom: 6px; scroll-snap-type: x mandatory; -webkit-overflow-scrolling: touch;
}
.preview-strip a {
  scroll-snap-align: start; display: block; border: 1px solid var(--line); border-radius: 8px;
  overflow: hidden; background: var(--paper-alt); color: inherit; text-decoration: none;
}
.preview-strip a:hover { border-color: var(--line-strong); }
.preview-strip img { display: block; width: 100%; aspect-ratio: 210 / 297; object-fit: cover; object-position: top; background: #fff; }
.preview-strip .cap { font-size: 12.5px; color: var(--ink-soft); padding: 8px 10px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.related-section { margin-top: 36px; padding-top: 24px; border-top: 1px solid var(--line); }
