/* ============================================================
   업종별 웹빌더 컴포넌트 시스템 — Foundation
   토큰 계약. 컴포넌트는 이 변수만 쓰고 하드코딩 색/시간을 넣지 않는다.
   근거: design.md §04 §06 §11 §13 (실사이트 16종 조사 기반)
   ============================================================ */

/* Pretendard 가변 다이나믹 서브셋 — KRDS·여기어때·직방 실사용 스택.
   여기서 @import 로 부르지 않는다(이 파일 수신 후에야 폰트 CSS 요청이 시작돼 직렬 왕복이 는다).
   이 파일을 <link> 하는 head 가 preconnect+stylesheet 쌍으로 함께 싣는다
   — 싣는 곳: shell-nail.html · catalog.py 셸. */

:root {
  /* ── color: light ── */
  --wb-ground:      #FCFCFD;
  --wb-surface:     #FFFFFF;
  --wb-surface-alt: #F7F8FA;
  --wb-rule:        #E4E7EC;
  --wb-rule-strong: #D0D5DD;
  --wb-ink:         #101828;
  --wb-ink-2:       #344054;
  /* #667085 였다. brand-soft 위에서 4.45 로 WCAG 4.5 에 못 미쳤다 —
     .wb-ph(11px, 아래 이미지 플레이스홀더)가 그 조합을 실제로 쓰고,
     빌드 산출물은 `<html data-skin="">` 로 출발하므로 스킨이 붙기 전 이 팔레트가 그대로 렌더된다.
     채널 일괄 -0.5% 로 색상비는 유지하고 4.51 로 올렸다(muted 는 어디서도 배경이 아니라
     ground 4.85→4.92 · surface 4.98→5.05 · surface-alt 4.68→4.75 로 나머지 짝도 같이 오른다). */
  --wb-muted:       #656F84;
  --wb-brand:       #1F4FD8;
  --wb-brand-ink:   #FFFFFF;
  --wb-brand-soft:  #EEF2FE;
  /* #0E9384 였다 — ok-soft 위 3.41 로 13px 배지(.wb-badge--open)가 4.5 미달.
     hue 유지 하향: ok-soft 4.69 · surface 5.22 · surface-alt 4.91 · ground 5.09 (상대휘도 실측) */
  --wb-ok:          #0A7A6E;
  --wb-ok-soft:     #E6F6F4;
  --wb-warn:        #B54708;
  --wb-warn-soft:   #FDF3E7;
  --wb-shadow-sm:   0 1px 2px rgba(16, 24, 40, .06);
  --wb-shadow-md:   0 4px 12px -4px rgba(16, 24, 40, .12);
  --wb-shadow-lg:   0 12px 28px -12px rgba(16, 24, 40, .22);

  /* ── type ── */
  --wb-font: "Pretendard Variable", Pretendard, -apple-system, BlinkMacSystemFont,
             "Apple SD Gothic Neo", "Malgun Gothic", "맑은 고딕", system-ui, sans-serif;
  --wb-mono: "JetBrains Mono", "Cascadia Mono", Consolas, "D2Coding", ui-monospace, monospace;

  /* ── 인격 토큰 — 스킨([data-skin])이 값만 갈아끼운다.
     색뿐 아니라 서체·굵기·자간이 함께 바뀌어야 "브랜드 인격"이 갈린다
     (근거: 네일숍HTML 테마 실험 — worklog 2026-08 초 절. 원문서는 2026-08-24 정리·삭제) ── */
  --wb-font-display: var(--wb-font);   /* 헤딩 전용 서체. 스킨이 세리프 등으로 교체 */
  --wb-display-weight: 700;
  --wb-display-spacing: var(--wb-ls-head);
  --wb-lh-tight: 1.25;   /* 헤딩 */
  --wb-lh-ui:    1.45;   /* UI·짧은 문구 */
  --wb-lh-read:  1.7;    /* 본문 문단 */
  --wb-ls-head:  -0.015em;

  /* ── space / radius ── */
  --wb-pad:      clamp(16px, 4vw, 40px);
  --wb-section:  clamp(56px, 9vw, 104px);
  --wb-max:      1200px;
  --wb-r-sm: 4px;
  --wb-r-md: 6px;
  --wb-r-lg: 8px;        /* Default radius for existing components. */
  --wb-r-scene: 32px;    /* Clipping window for expanded motion scenes. */

  /* ── motion (실측 관행값, design.md §13) ── */
  --wb-ease:     cubic-bezier(0, 0, .2, 1);
  --wb-d-reveal: 600ms;
  --wb-d-hover:  200ms;
  --wb-d-lift:   150ms;
  --wb-d-card:   250ms;
  --wb-d-press:  60ms;
  --wb-stagger:  80ms;

  --wb-tap: 44px;        /* 최소 터치 타겟 */

  /* ── z-스케일 — 고정·플로팅 크롬의 층 사다리 (실측 충돌 수리 2026-08-24) ──
     dock(30) < bar(90) < fab(95) < float(99) < dim(120) < sheet(121) < toast(130).
     div 기반 시트(location.e · booking.d)가 dim/sheet 를 쓴다 — 예전 z 59/60·94/96 은
     CTA 바(90)·FAB(95)·SNS 플로팅(99)에 덮여 딤 위 버튼이 실제로 클릭됐다(모달 불성립).
     네이티브 <dialog>(gallery·price.b·nav.e)는 top layer 라 이 사다리 밖(항상 위).
     밴드 안 국소 적층(hero 0~6 · nav 드롭다운 1~4)은 이 사다리와 무관하다. */
  --wb-z-dock:  30;
  --wb-z-bar:   90;
  --wb-z-fab:   95;
  --wb-z-float: 99;
  --wb-z-dim:  120;
  --wb-z-sheet: 121;
  --wb-z-toast: 130;

  /* ── 스킨이 표면 인격을 만들 수 있게 뚫어 둔 축 (2026-08-14) ───────────────
     기본값은 전부 **지금 렌더와 동일**이다 — 기존 스킨 5종은 이 셋을 선언하지 않으므로
     한 픽셀도 안 바뀐다(라이브 computedStyle 60항목 대조로 확인).
     나머지 축(shadow-*·d-*·stagger·section·pad·lh-*·ls-head)은 이미 여기 선언돼 있어
     `:root[data-skin=X]`(특이도 0,2,0)가 `:root`(0,1,0)를 이기므로 **신규 토큰 없이** 갈아끼운다. */
  --wb-elev:         none;                  /* 카드 정지상태 그림자. .wb-card 는 지금 :hover 에만 그림자가 있다 */
  --wb-elev-hover:   var(--wb-shadow-lg);   /* = 현재 .wb-card:hover 값. 없으면 뉴모피즘이 호버에서 튄다 */
  --wb-ground-layer: none;                  /* body 배경 레이어(그라디언트). Aurora 계열의 정체성 */
  /* 고정 크롬(nav)이 유리가 되는 축. 기본값은 지금 렌더와 동일하다 —
     `none` 은 backdrop-filter 의 **초기값**이라 스태킹 컨텍스트도 합성 레이어도 안 만든다. */
  --wb-blur:         none;
  --wb-chrome-bg:    var(--wb-surface);     /* = 현재 .nav-bar 배경과 같은 계산값 */
}

/* 스킨 12종과 같은 가드를 쓴다. 없으면 OS 다크 + 라이트 토글(셸이 실제로 만드는 상태)에서
   아래 :root[data-theme="light"] 가 **되돌리는 토큰만** 라이트로 돌아오고 나머지는 다크로 남는다 —
   실제로 --wb-shadow-sm/md/lg 3종이 그 구멍이라 라이트 표면에 알파 .4~.7 검은 그림자가 살아남았다.
   가드는 값을 베끼는 대신 블록째 안 켜므로 토큰이 늘어도 다시 새지 않는다. */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --wb-ground: #0C0E12; --wb-surface: #14171F; --wb-surface-alt: #1A1E27;
    --wb-rule: #242A35; --wb-rule-strong: #333B49;
    --wb-ink: #ECEFF3; --wb-ink-2: #C3CAD5; --wb-muted: #98A2B3;
    --wb-brand: #7C9BFF; --wb-brand-ink: #0C0E12; --wb-brand-soft: #1A2340;
    --wb-ok: #2DD4BF; --wb-ok-soft: #10312D;
    --wb-warn: #F0A345; --wb-warn-soft: #33260F;
    --wb-shadow-sm: 0 1px 2px rgba(0,0,0,.4);
    --wb-shadow-md: 0 4px 12px -4px rgba(0,0,0,.55);
    --wb-shadow-lg: 0 12px 28px -12px rgba(0,0,0,.7);
  }
}
:root[data-theme="dark"] {
  --wb-ground: #0C0E12; --wb-surface: #14171F; --wb-surface-alt: #1A1E27;
  --wb-rule: #242A35; --wb-rule-strong: #333B49;
  --wb-ink: #ECEFF3; --wb-ink-2: #C3CAD5; --wb-muted: #98A2B3;
  --wb-brand: #7C9BFF; --wb-brand-ink: #0C0E12; --wb-brand-soft: #1A2340;
  --wb-ok: #2DD4BF; --wb-ok-soft: #10312D;
  --wb-warn: #F0A345; --wb-warn-soft: #33260F;
  --wb-shadow-sm: 0 1px 2px rgba(0,0,0,.4);
  --wb-shadow-md: 0 4px 12px -4px rgba(0,0,0,.55);
  --wb-shadow-lg: 0 12px 28px -12px rgba(0,0,0,.7);
}
:root[data-theme="light"] {
  --wb-ground: #FCFCFD; --wb-surface: #FFFFFF; --wb-surface-alt: #F7F8FA;
  --wb-rule: #E4E7EC; --wb-rule-strong: #D0D5DD;
  --wb-ink: #101828; --wb-ink-2: #344054; --wb-muted: #656F84;   /* 위 :root 와 같은 값을 유지한다 — 토글이 색을 튀우면 안 된다 */
  --wb-brand: #1F4FD8; --wb-brand-ink: #FFFFFF; --wb-brand-soft: #EEF2FE;
  --wb-ok: #0A7A6E; --wb-ok-soft: #E6F6F4;
  --wb-warn: #B54708; --wb-warn-soft: #FDF3E7;
}

/* ── reset ── */
*, *::before, *::after { box-sizing: border-box; }
/* ★ [hidden] 은 UA 스타일이라 **작성자 스타일에 진다**. .wb-btn{display:inline-flex} 처럼
   display 를 주는 클래스가 붙으면 el.hidden=true 가 아무 일도 안 한다.
   실제 사고: motion.js:132 가 "더보기"를 다 쓴 뒤 숨기는데 .wb-btn 이 이겨서 죽은 버튼이 남았다
   (gallery.a·about.h 둘 다). 아래 .wb-tabpanel[hidden] 은 같은 문제를 국소로 막던 흔적이다.
   JS 가 .hidden 으로 숨기는 자리가 여럿이라(mixer.js 의 유형 토글 포함) 뿌리에서 한 번에 막는다. */
[hidden] { display: none !important; }
html { -webkit-text-size-adjust: 100%; }
body {
  margin: 0;
  background: var(--wb-ground);
  /* 이 줄은 반드시 background 숏핸드 **뒤**에 온다 — 앞에 두면 숏핸드가 none 으로 리셋한다.
     기본값 none 이라 숏핸드의 리셋 결과와 동일하다(= 지금 렌더 그대로). */
  background-image: var(--wb-ground-layer);
  color: var(--wb-ink);
  font-family: var(--wb-font);
  font-weight: 400;                 /* §18 DON'T — 300 금지 */
  font-size: 16px;
  line-height: var(--wb-lh-ui);
  word-break: keep-all;             /* 한글 어절 보존 */
  overflow-wrap: break-word;        /* 긴 URL 방어 — keep-all 단독 금지 */
  -webkit-font-smoothing: antialiased;
}
h1, h2, h3, h4 {
  margin: 0;
  font-family: var(--wb-font-display);
  line-height: var(--wb-lh-tight);
  letter-spacing: var(--wb-display-spacing);
  font-weight: var(--wb-display-weight);
  text-wrap: balance;
}
p { margin: 0; }
ul, ol { margin: 0; padding: 0; list-style: none; }
img, picture, video { max-width: 100%; display: block; }
a { color: inherit; text-decoration: none; }
button { font: inherit; color: inherit; background: none; border: 0; cursor: pointer; }

/* 숫자 정렬 — 가격·전화·사업자번호·영업시간 */
.wb-num { font-variant-numeric: tabular-nums; }

/* 라틴 전용 — 한글 자간 보정이 영문/숫자에 과하게 먹는 것 방지 */
/* 로마자 전용 축. **라틴 서체를 앞에 둔다** — 뒤에 두면 한글 서체의 라틴 글리프가 먼저 잡힌다.
   한글이 섞여 들어와도 안전하다: 라틴 서체엔 한글 글리프가 없어 다음 후보로 자연히 넘어간다.
   스킨이 이 토큰만 바꾸면 한글 서체를 늘리지 않고도 인상이 갈린다(조사 결론: 비용 대비 효과 1위).
   ★ 광학 보정은 아직 안 걸었다. 실측상 보정 방향은 통념과 **반대**다 —
     100px 기준 잉크 높이가 한글 '가' 79 vs 라틴 대문자 58~86(대개 67~75)이라 **라틴을 키우는** 쪽이다.
     다만 .wb-latin 이 아이브로·숫자·버튼에 두루 붙어 있어 일괄 확대는 레이아웃을 흔든다.
     슬롯별로 재고 걸어야 한다. */
:root { --wb-font-latin: Inter, var(--wb-font); }
.wb-latin { font-family: var(--wb-font-latin); letter-spacing: normal; }
/* 로마자 상호 훅 — 사장님이 「로마자로 표기」를 켜면 derive 가 v.shopNameLatin=1 을 내고
   파셜의 상호 자리 43곳이 data-attr 로 이 속성을 단다(안 켜면 속성째 사라진다). */
[data-latin="1"] { font-family: var(--wb-font-latin); letter-spacing: normal; }

/* ── layout ── */
.wb-container { width: 100%; max-width: var(--wb-max); margin-inline: auto; padding-inline: var(--wb-pad); }
.wb-section { padding-block: var(--wb-section); }
.wb-section--alt { background: var(--wb-surface-alt); }

.wb-eyebrow {
  font-size: 12px; font-weight: 600; letter-spacing: .12em; text-transform: uppercase;
  color: var(--wb-brand); margin-bottom: 10px; display: block;
}
.wb-h2 { font-size: clamp(24px, 3.4vw, 34px); }
.wb-lead { color: var(--wb-muted); font-size: 15px; line-height: var(--wb-lh-read); margin-top: 12px; max-width: 62ch; }

/* ── button ── */
.wb-btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 8px;
  min-height: var(--wb-tap); padding: 0 18px;
  border-radius: var(--wb-r-md); font-size: 15px; font-weight: 600;
  border: 1px solid transparent;
  transition: background-color var(--wb-d-hover) ease,
              color var(--wb-d-hover) ease,
              border-color var(--wb-d-hover) ease,
              transform var(--wb-d-lift) var(--wb-ease),
              box-shadow var(--wb-d-lift) var(--wb-ease);
}
.wb-btn--primary { background: var(--wb-brand); color: var(--wb-brand-ink); }
.wb-btn--primary:hover { transform: translateY(-2px); box-shadow: var(--wb-shadow-md); }
.wb-btn--ghost { border-color: var(--wb-rule-strong); color: var(--wb-ink); background: var(--wb-surface); }
.wb-btn--ghost:hover { border-color: var(--wb-brand); color: var(--wb-brand); }
.wb-btn:active { transform: scale(.98); transition-duration: var(--wb-d-press); }

:where(a, button, summary, [tabindex]):focus-visible {
  outline: 2px solid var(--wb-brand);
  outline-offset: 2px;
  border-radius: var(--wb-r-sm);
}

/* ── status badge — 색만으로 의미를 싣지 않는다 (WCAG 1.4.1) ── */
.wb-badge {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 3px 10px; border-radius: 999px;
  font-size: 13px; font-weight: 600; line-height: 1.5;
}
.wb-badge::before { content: ""; width: 7px; height: 7px; border-radius: 50%; background: currentColor; flex: none; }
.wb-badge--open   { background: var(--wb-ok-soft);   color: var(--wb-ok); }
.wb-badge--closed { background: var(--wb-warn-soft); color: var(--wb-warn); }
.wb-badge--muted  { background: var(--wb-surface-alt); color: var(--wb-muted); }

/* ── card ── */
.wb-card {
  background: var(--wb-surface); border: 1px solid var(--wb-rule);
  border-radius: var(--wb-r-lg); overflow: hidden;
  /* 정지상태 그림자. 기본 none = 지금 값(전 스킨 10조합에서 box-shadow:none 실측).
     이 한 줄이 없으면 스킨이 --wb-shadow-* 를 아무리 바꿔도 본문 카드에 도달하지 못한다. */
  box-shadow: var(--wb-elev);
  transition: transform var(--wb-d-card) var(--wb-ease),
              box-shadow var(--wb-d-card) var(--wb-ease),
              border-color var(--wb-d-card) var(--wb-ease);
}
/* :hover 가 그림자를 통째로 덮어쓰므로 여기도 토큰이어야 한다 —
   아니면 이중그림자 스킨이 마우스를 올리는 순간 일반 그림자로 튄다. 기본값이 같아 렌더는 그대로. */
.wb-card:hover { transform: translateY(-4px); box-shadow: var(--wb-elev-hover); border-color: var(--wb-rule-strong); }
.wb-card__media { aspect-ratio: 4 / 3; overflow: hidden; background: var(--wb-surface-alt); }
/* 예전엔 `> *` 였다. 크기를 선언하지 않은 자식이 전부 미디어 박스만큼 늘어나서,
   inset 으로만 배치한 .gallery-zoom(position:absolute) 이 카드 전체 크기의 흰 알약이 되어 사진을 덮었다.
   그러니 "박스를 채워야 하는 것"만 지목한다 — 덮개·칩 같은 absolute 자식은 자기 크기를 유지한다.
   .wb-ph 는 스스로 width/height 가 없어 여기에 의존한다. 빼지 마라(카탈로그 플레이스홀더가 납작해진다).
   :where() 는 특이도 0 이라 이 선택자는 `> *` 와 특이도가 같다(0,1,0) — 캐스케이드가 그대로 보존된다. */
.wb-card__media > :where(img, .wb-ph) { width: 100%; height: 100%; object-fit: cover; transition: transform var(--wb-d-card) var(--wb-ease); }
.wb-card:hover .wb-card__media > :where(img, .wb-ph) { transform: scale(1.04); }

/* ── image placeholder — 이미지 없음을 숨기지 않고 선언한다 ── */
.wb-ph {
  display: flex; align-items: center; justify-content: center;
  background: var(--wb-brand-soft); color: var(--wb-muted);
  font-family: var(--wb-mono); font-size: 11px; letter-spacing: .04em;
  border: 1px dashed var(--wb-rule-strong);
}

/* ── scroll reveal — .js 가 붙었을 때만 숨긴다 (스크립트 실패 시 백지 방지) ── */
.js [data-reveal] { opacity: 0; transform: translateY(24px); }
.js [data-reveal].is-in {
  opacity: 1; transform: none;
  transition: opacity var(--wb-d-reveal) var(--wb-ease), transform var(--wb-d-reveal) var(--wb-ease);
  transition-delay: var(--wb-delay, 0ms);
}

/* ── accordion — height:auto 는 보간 불가. grid 트릭이 표준 ── */
.wb-acc__panel { display: grid; grid-template-rows: 0fr; transition: grid-template-rows var(--wb-d-card) ease; }
.wb-acc__panel > div { overflow: hidden; min-height: 0; }
.wb-acc__item[aria-expanded="true"] + .wb-acc__panel { grid-template-rows: 1fr; }
/* 접힌 내용은 시각적 클리핑(overflow:hidden)만으로는 탭 순서·낭독에서 빠지지 않는다.
   닫힘 전환이 끝난 뒤 숨긴다 — 먼저 숨기면 내용이 증발하고 빈 상자만 접힌다(같은 관용구: nav.html:628). */
.wb-acc__item[aria-expanded="false"] + .wb-acc__panel > div { visibility: hidden; transition: visibility 0s var(--wb-d-card); }
.wb-acc__chev { transition: transform var(--wb-d-card) ease; }
.wb-acc__item[aria-expanded="true"] .wb-acc__chev { transform: rotate(180deg); }

/* ── tab panel ── */
.wb-tabpanel[hidden] { display: none; }
.wb-tabpanel { animation: wb-fade-in 180ms var(--wb-ease) both; }
@keyframes wb-fade-in { from { opacity: 0 } to { opacity: 1 } }

.wb-sr {
  position: absolute; left: 0; top: 0; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 1ms !important; animation-iteration-count: 1 !important;
    transition-duration: 1ms !important; scroll-behavior: auto !important;
  }
  .js [data-reveal] { opacity: 1; transform: none; }
}
