/* ============================================================
   components.css — 12페이지 + 게이트웨이가 공유하는 컴포넌트 전부
   tokens.css 변수만 참조한다. 하드코딩 hex/rgba 금지.
   로드 순서: tokens.css → base.css → components.css → (페이지별 css)
   ============================================================

   목차
   1. 유틸(헤더 오프셋, 스크림 레이어, 잠금)
   2. GNB(헤더) + 모바일 드로어
   3. 하단 고정 CTA 바
   4. 버튼 3종 (primary / ghost / text)
   5. 카드 — 공통 / 메뉴·제품 카드 / 뉴스 카드
   6. 뱃지
   7. 탭
   8. 모달
   9. 팝업
   10. 폼 요소 + 에러 상태
   11. 타임라인(연혁 / 절차 단계)
   12. 매운맛 게이지
   13. 스탬프 언더라인 + 세로쓰기 유틸
   14. 히어로 키네틱 타이포 구조
   15. 브랜드 라인아트 마크(형제 브랜드 연결용)
   ============================================================ */

/* ---------- 1. 유틸 ---------- */

/* 히어로가 없는 페이지의 <main> 상단에 붙여 고정 헤더와 겹치지 않게 함 */
.u-header-offset {
  padding-top: 4.5rem;
}
@media (min-width: 48rem) {
  .u-header-offset { padding-top: var(--header-h); }
}

/* 모달/드로어/팝업 열림 시 배경 스크롤 잠금 */
html.is-locked {
  overflow: hidden;
}

/* 반투명 스크림: 브랜드 토큰(--ink, --dark-bg)의 배경색 + opacity 조합으로만 구현
   (rgba(0,0,0,x) 하드코딩 금지 규칙 준수) */
.u-scrim {
  position: absolute;
  inset: 0;
  background: var(--ink);
  opacity: 0.55;
}

/* 하단 고정 CTA 바 높이만큼 본문 하단 여백 확보용 */
.u-cta-offset {
  padding-bottom: 4rem;
}
@media (min-width: 64rem) {
  .u-cta-offset { padding-bottom: 3.5rem; }
}
/* 고정 CTA가 있는 문서는 푸터 마지막 줄까지 가려지지 않게 보호 */
body:has(.fixed-cta) .site-footer {
  padding-bottom: 5.5rem;
}
@media (min-width: 64rem) {
  body:has(.fixed-cta) .site-footer { padding-bottom: 5rem; }
}

/* ---------- 2. GNB(헤더) + 모바일 드로어 ----------

   마크업 계약(각 페이지 공통):
   <header class="site-header header--transparent" data-header>
     <div class="site-header__inner container--wide">
       <a class="site-header__logo" href="./index.html">까투리</a>
       <nav class="site-nav" aria-label="주요 메뉴">
         <ul class="site-nav__list"> <li><a href="./menu.html">메뉴</a></li> ... </ul>
       </nav>
       <a class="btn btn--primary btn--sm site-header__cta" href="./franchise.html">가맹문의</a>
       <button class="nav-toggle" data-nav-toggle aria-expanded="false" aria-controls="mobileNav">
         <span class="nav-toggle__bar"></span><span class="nav-toggle__bar"></span><span class="nav-toggle__bar"></span>
         <span class="sr-only">메뉴 열기</span>
       </button>
     </div>
   </header>
   <div class="mobile-nav__backdrop" data-nav-backdrop></div>
   <div class="mobile-nav" id="mobileNav" data-mobile-nav aria-label="모바일 메뉴">
     <nav> <ul class="mobile-nav__list"> ... 동일 링크 ... </ul> </nav>
     <a class="btn btn--primary mobile-nav__cta" href="./franchise.html">가맹문의</a>
   </div>
------------------------------------------------------------- */

.site-header {
  position: fixed;
  inset-inline: 0;
  top: 0;
  height: 4.5rem;
  z-index: var(--z-header);
  display: flex;
  align-items: center;
  color: var(--text);
  background: transparent;
  transition:
    background var(--dur-base) var(--ease-out),
    box-shadow var(--dur-base) var(--ease-out),
    backdrop-filter var(--dur-base) var(--ease-out),
    color var(--dur-base) var(--ease-out);
}
@media (min-width: 48rem) {
  .site-header { height: var(--header-h); }
}

.site-header__inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-5);
  width: 100%;
  /* width:100%가 container--wide 거터를 무효화하므로 전 테마 공통으로 거터를 직접 재현
     (와이드 화면에서 로고·CTA가 모서리에 붙는 결함의 근원 수정) */
  padding-inline: max(var(--gutter), calc((100% - var(--container-wide)) / 2));
}

.site-header__logo {
  font-family: var(--font-display);
  font-size: var(--fs-lg);
  font-weight: var(--fw-bold); /* GmarketSans 최대 700 */
  letter-spacing: var(--ls-tight);
  white-space: nowrap;
}

.site-nav { display: none; }
@media (min-width: 48rem) {
  .site-nav { display: block; }
}
.site-nav__list {
  display: flex;
  align-items: center;
  gap: var(--sp-6);
}
.site-nav__list a {
  position: relative;
  font-size: var(--fs-md);
  font-weight: var(--fw-semibold);
  padding-block: var(--sp-2);
}
.site-nav__list a::after {
  content: "";
  position: absolute;
  left: 0; right: 0; bottom: 0;
  height: 2px;
  background: currentColor;
  transform: scaleX(0);
  transform-origin: left;
  transition: transform var(--dur-fast) var(--ease-out);
}
@media (hover: hover) and (pointer: fine) {
  .site-nav__list a:hover::after { transform: scaleX(1); }
}
.site-nav__list a[aria-current="page"]::after { transform: scaleX(1); }

.site-header__cta { display: none; }
@media (min-width: 48rem) {
  .site-header__cta { display: inline-flex; }
}

/* 스크롤 상태 */
.header--transparent { background: transparent; box-shadow: none; }
.header--solid {
  background: var(--paper);
  backdrop-filter: saturate(180%) blur(12px);
  -webkit-backdrop-filter: saturate(180%) blur(12px);
  box-shadow: var(--shadow-card);
  color: var(--text);
}

/* 까투리: 히어로가 다크 → 투명 상태에서 크림 텍스트 + 상단 스크림 */
[data-theme="katoori"] .header--transparent { color: var(--dark-text); }
[data-theme="katoori"] .header--transparent::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  background: linear-gradient(var(--dark-bg), transparent);
  opacity: 0.5;
}

/* 대박: 히어로가 라이트 → 투명 상태에서도 --ink 유지, 얇은 블러만 */
[data-theme="daebak"] .header--transparent {
  color: var(--text);
  backdrop-filter: blur(4px);
  -webkit-backdrop-filter: blur(4px);
}

.nav-toggle {
  display: grid;
  place-items: center;
  /* auto 행이 버튼 높이만큼 stretch되면 바 간격이 벌어져 X 교차가 깨짐 */
  align-content: center;
  gap: 0.3rem;
  width: 2.75rem;
  height: 2.75rem;
}
@media (min-width: 48rem) {
  .nav-toggle { display: none; }
}
.nav-toggle__bar {
  display: block;
  width: 1.5rem;
  height: 2px;
  background: currentColor;
  transition: transform var(--dur-fast) var(--ease-out), opacity var(--dur-fast) var(--ease-out);
}
/* 드로어 열림 시 헤더(토글 X 포함)를 패널 위로 — 헤더가 스태킹 컨텍스트라
   버튼만 올릴 수 없어 헤더 전체를 승격 (패널 상단은 헤더 높이만큼 비워둠) */
body:has(.mobile-nav.is-open) .site-header {
  z-index: calc(var(--z-header) + 2);
}
.nav-toggle[aria-expanded="true"] .nav-toggle__bar:nth-child(1) { transform: translateY(6px) rotate(45deg); }
.nav-toggle[aria-expanded="true"] .nav-toggle__bar:nth-child(2) { opacity: 0; }
.nav-toggle[aria-expanded="true"] .nav-toggle__bar:nth-child(3) { transform: translateY(-6px) rotate(-45deg); }

.mobile-nav__backdrop {
  position: fixed;
  inset: 0;
  z-index: var(--z-header);
  background: var(--ink);
  opacity: 0;
  pointer-events: none;
  transition: opacity var(--dur-base) var(--ease-out);
}
.mobile-nav__backdrop.is-open { opacity: 0.45; pointer-events: auto; }

.mobile-nav {
  position: fixed;
  inset-block: 0;
  right: 0;
  width: min(20rem, 85vw);
  z-index: calc(var(--z-header) + 1);
  background: var(--card-bg);
  color: var(--text);
  box-shadow: var(--shadow-lift);
  padding: calc(4.5rem + var(--sp-5)) var(--sp-5) var(--sp-6);
  overflow-y: auto;
  transform: translateX(100%);
  transition: transform var(--dur-base) var(--ease-in-out);
}
.mobile-nav.is-open { transform: translateX(0); }
.mobile-nav__list {
  display: grid;
  gap: var(--sp-5);
  margin-bottom: var(--sp-6);
}
.mobile-nav__list a {
  font-size: var(--fs-h3);
  font-weight: var(--fw-semibold);
}
.mobile-nav__cta { width: 100%; justify-content: center; }

@media (min-width: 48rem) {
  .mobile-nav, .mobile-nav__backdrop { display: none; }
}

/* ---------- 3. 하단 고정 CTA 바 ---------- */

.fixed-cta {
  position: fixed;
  left: 0; right: 0; bottom: 0;
  z-index: var(--z-cta);
  height: 4rem;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--sp-5);
  /* 콘텐츠를 와이드 컨테이너 좌우선에 정렬 */
  padding-inline: max(var(--gutter), calc((100% - var(--container-wide)) / 2));
  background: linear-gradient(to top, var(--point-deep), var(--point));
  color: var(--on-point);
  box-shadow: 0 -6px 24px var(--point-glow);
  transition: opacity var(--dur-base) var(--ease-out);
}
/* 상단 서브컬러 헤어라인 — 인쇄물의 금박 띠 */
.fixed-cta::before {
  content: "";
  position: absolute;
  inset-inline: 0;
  top: 0;
  height: 2px;
  background: var(--sub);
  opacity: 0.9;
}
@media (min-width: 64rem) {
  .fixed-cta { height: 3.5rem; }
}
@media (min-width: 30rem) {
  .fixed-cta { justify-content: space-between; }
}
.fixed-cta__text {
  font-size: var(--fs-md);
  font-weight: var(--fw-semibold);
  letter-spacing: 0.01em;
  display: none;
}
@media (min-width: 30rem) {
  .fixed-cta__text { display: inline; }
}
/* 진짜 버튼 형태: 바탕색 반전 + 화살표. .btn--primary와 같이 쓰여도 이기도록
   두 클래스 특이성으로 선언(버튼 섹션이 이 뒤에 오므로 단일 클래스면 밀림). */
.fixed-cta .fixed-cta__btn {
  display: inline-flex;
  align-items: center;
  gap: 0.5em;
  min-height: 2.75rem;
  padding: 0.1em 1.3rem 0;
  background: var(--paper);
  color: var(--point-deep);
  border-radius: var(--radius-sm);
  font-family: var(--font-display);
  font-weight: var(--fw-bold);
  font-size: var(--fs-md);
  letter-spacing: 0.02em;
  white-space: nowrap;
}
.fixed-cta.is-near-footer { opacity: 0.85; }

/* 데스크탑: 전폭 바 대신 우하단 퀵버튼 (실측: 대기업 사이트엔 전폭 바 없음 — 삼양사식 퀵메뉴)
   모바일은 명세(전 페이지 상시 노출·모바일 필수)대로 바 유지 */
@media (min-width: 64rem) {
  .fixed-cta {
    left: auto;
    right: var(--sp-5);
    bottom: var(--sp-5);
    height: auto;
    padding: 0;
    background: none;
    box-shadow: none;
    justify-content: flex-end;
  }
  .fixed-cta::before { display: none; }
  .fixed-cta__text { display: none; }
  .fixed-cta .fixed-cta__btn {
    flex-direction: column;
    justify-content: center;
    gap: 0.35em;
    width: 5rem;
    height: 5rem;
    padding: 0.2em 0.4em 0;
    border-radius: 0.875rem;
    background: var(--point);
    color: var(--on-point);
    font-size: var(--fs-sm);
    text-align: center;
    white-space: normal;
    line-height: 1.25;
    box-shadow: var(--shadow-lift);
  }
  @media (hover: hover) and (pointer: fine) {
    .fixed-cta .fixed-cta__btn:hover {
      background: var(--point-deep);
      transform: translateY(-2px);
      transition: background var(--dur-fast) var(--ease-out), transform var(--dur-fast) var(--ease-out);
    }
  }
  /* 데스크탑은 바가 없으므로 푸터 하단 보호 패딩 불필요 */
  body:has(.fixed-cta) .site-footer { padding-bottom: var(--sp-6); }
  .u-cta-offset { padding-bottom: 0; }
}

/* ---------- 4. 버튼 3종 ---------- */

.btn {
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.5rem;
  min-height: 2.75rem;
  /* G마켓 산스는 글리프가 위로 붙는 특성 — 상단 패딩 미세 보정으로 광학 중앙 정렬 */
  padding: 0.8rem 1.5rem 0.7rem;
  font-family: var(--font-display);
  font-size: var(--fs-md); /* 버튼 크기 대비 글자가 작다는 지적 반영(15→17px급) */
  font-weight: var(--fw-bold);
  line-height: 1;
  white-space: nowrap;
  transition:
    background var(--dur-fast) var(--ease-out),
    border-color var(--dur-fast) var(--ease-out),
    box-shadow var(--dur-fast) var(--ease-out),
    transform var(--dur-fast) var(--ease-out),
    color var(--dur-fast) var(--ease-out);
}
.btn svg { width: 1rem; height: 1rem; flex: 0 0 auto; }

.btn--primary {
  border-radius: var(--radius-pill);
  background: var(--point);
  color: var(--on-point);
  padding-inline: 2rem;
}
@media (hover: hover) and (pointer: fine) {
  .btn--primary:hover {
    background: var(--point-deep);
    box-shadow: var(--shadow-cta);
    transform: translateY(-2px);
  }
}
.btn--primary:active { transform: translateY(0) scale(0.98); }

.btn--ghost {
  border-radius: var(--radius-sm);
  border: 1px solid var(--line-strong);
  background: transparent;
  color: var(--text);
}
@media (hover: hover) and (pointer: fine) {
  .btn--ghost:hover { border-color: var(--point); color: var(--point); }
}
.btn--ghost:active { transform: scale(0.98); }

.btn--text {
  padding: 0.25rem 0;
  min-height: 2.75rem;
  color: var(--point);
  font-weight: var(--fw-semibold);
}
.btn--text::after {
  content: "";
  position: absolute;
  left: 0; right: 0; bottom: 0.5rem;
  height: 1px;
  background: currentColor;
  transform: scaleX(1);
  transform-origin: left;
  transition: transform var(--dur-fast) var(--ease-out);
}
@media (hover: hover) and (pointer: fine) {
  .btn--text:hover::after { transform: scaleX(0); transform-origin: right; }
}

.btn--sm { min-height: 2.25rem; padding: 0.5rem 1.25rem; font-size: var(--fs-xs); }
/* 터치 기기에서는 최소 터치 타깃 44px 보장 */
@media (pointer: coarse) {
  .btn--sm { min-height: 2.75rem; }
}
.btn--block { width: 100%; }
.btn[disabled], .btn[aria-disabled="true"] {
  opacity: 0.45;
  pointer-events: none;
}

/* ---------- 5. 카드 ---------- */

.card {
  position: relative;
  background: var(--card-bg);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-card);
  overflow: hidden;
  transition: box-shadow var(--dur-base) var(--ease-out), transform var(--dur-base) var(--ease-out);
}
@media (hover: hover) and (pointer: fine) {
  .card:hover { box-shadow: var(--shadow-lift); transform: translateY(-4px); }
}

/* 메뉴 / 제품 카드 — 1:1 정사각 미디어 + hover 슬라이드업 리빌
   마크업:
   <button class="menu-card reveal" type="button" data-menu-item="fried" ...데이터 속성>
     <span class="menu-card__media">
       <img src="..." alt="..." loading="lazy" width="600" height="600">
       <span class="menu-card__badges"><span class="badge">인기</span></span>
       <span class="menu-card__reveal">
         <span class="menu-card__desc">설명 한 줄</span>
         <span class="menu-card__meta">
           <span class="allergy-list">닭고기·밀·대두</span>
           <span class="spice-gauge" data-spice="2"> ... </span>
         </span>
       </span>
     </span>
     <span class="menu-card__body">
       <span class="menu-card__name">까투리 후라이드</span>
       <span class="menu-card__price">19,000원</span>
     </span>
   </button>
*/
.menu-card {
  display: block;
  width: 100%;
  text-align: left;
  background: var(--card-bg);
  border: 1px solid var(--line);
  border-radius: var(--radius-md);
  overflow: hidden;
  cursor: pointer;
  transition: box-shadow var(--dur-base) var(--ease-out), transform var(--dur-base) var(--ease-out);
}
@media (hover: hover) and (pointer: fine) {
  .menu-card:hover { box-shadow: var(--shadow-lift); transform: translateY(-4px); }
}

.menu-card__media {
  display: block; /* span 마크업에서도 비율 박스 유지 */
  position: relative;
  width: 100%;
  padding-bottom: 100%;
  overflow: hidden;
  background: var(--sub-tint);
}
.menu-card__media img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  transition: transform var(--dur-slow) var(--ease-out);
}
@media (hover: hover) and (pointer: fine) {
  .menu-card:hover .menu-card__media img { transform: scale(1.05); }
}
.menu-card:focus-visible .menu-card__media img { transform: scale(1.05); }

.menu-card__badges {
  position: absolute;
  top: var(--sp-3);
  left: var(--sp-3);
  z-index: 2;
  display: flex;
  gap: var(--sp-2);
  flex-wrap: wrap;
}

.menu-card__reveal {
  position: absolute;
  inset: 0;
  z-index: 1;
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  gap: var(--sp-2);
  padding: var(--sp-4);
  color: var(--dark-text);
  transform: translateY(100%);
  transition: transform var(--dur-base) var(--ease-out);
}
.menu-card__reveal::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  background: linear-gradient(to top, var(--dark-bg) 0%, transparent 100%);
  opacity: 0.88;
}
@media (hover: hover) and (pointer: fine) {
  .menu-card:hover .menu-card__reveal { transform: translateY(0); }
}
.menu-card:focus-visible .menu-card__reveal { transform: translateY(0); }

.menu-card__desc {
  font-size: var(--fs-xs);
  line-height: var(--lh-body);
}
.menu-card__meta {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-3);
}
.allergy-list {
  font-size: var(--fs-xs);
  color: var(--dark-text-mute);
}

.menu-card__body {
  display: grid;
  gap: var(--sp-1);
  padding: var(--sp-4);
}
.menu-card__name {
  font-size: var(--fs-lg);
  font-weight: var(--fw-semibold);
}
.menu-card__price {
  font-size: var(--fs-sm);
  font-weight: var(--fw-bold);
  color: var(--point);
  font-variant-numeric: tabular-nums;
}

/* 뉴스(소식) 카드 — 리스트 행 */
.news-card {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--sp-2);
  padding-block: var(--sp-5);
  border-bottom: 1px solid var(--line);
}
@media (min-width: 48rem) {
  .news-card { grid-template-columns: auto 1fr auto; align-items: center; gap: var(--sp-5); }
}
.news-card__tag { justify-self: start; }
.news-card__title {
  position: relative;
  display: inline-block;
  width: fit-content;
  font-size: var(--fs-lg);
  font-weight: var(--fw-semibold);
}
.news-card__title::after {
  content: "";
  position: absolute;
  left: 0; right: 0; bottom: -0.15em;
  height: 1px;
  background: currentColor;
  transform: scaleX(0);
  transform-origin: left;
  transition: transform var(--dur-fast) var(--ease-out);
}
@media (hover: hover) and (pointer: fine) {
  .news-card:hover .news-card__title::after { transform: scaleX(1); }
}
.news-card__date {
  font-variant-numeric: tabular-nums;
  /* 접근성: --ink-mute 3.69:1은 4.5:1 미달 — --ink 20% 혼합으로 4.89:1 보정 */
  color: color-mix(in srgb, var(--ink-mute) 80%, var(--ink) 20%);
  font-size: var(--fs-sm);
  white-space: nowrap;
}
.news-card__excerpt {
  color: var(--ink-soft);
  font-size: var(--fs-sm);
  grid-column: 1 / -1;
}

/* ---------- 6. 뱃지 ---------- */

/* 뱃지 — 대기업 관용 칩: 흰 바탕+브랜드색 텍스트(사진 위 선명),
   강조(solid)는 브랜드색 바탕+흰 텍스트. 골드 온 크림슨 같은 저대비 조합 금지. */
.badge {
  display: inline-flex;
  align-items: center;
  gap: 0.3em;
  border-radius: var(--radius-pill); /* 실측: 굽네·푸라닭 모두 캡슐형 */
  padding: 0.4em 0.85em 0.3em; /* G마켓 산스 상단 붙음 광학 보정 */
  font-family: var(--font-display);
  font-size: var(--fs-xs);
  font-weight: var(--fw-bold);
  letter-spacing: 0.04em;
  white-space: nowrap;
  background: var(--paper);
  color: var(--point-deep);
  box-shadow: var(--shadow-card);
}

.badge--outline {
  background: transparent;
  border: 1px solid var(--line-strong);
  /* 접근성: --ink-mute 3.69:1 → 4.5:1 미달 보정 */
  color: color-mix(in srgb, var(--ink-mute) 80%, var(--ink) 20%);
}
.badge--solid {
  background: var(--point);
  color: var(--on-point);
}
/* 대박 그린(#33AC45)은 흰 글씨와 대비 미달 — 딥그린 바탕으로 보정 */
[data-theme="daebak"] .badge--solid { background: var(--point-deep); }

/* ---------- 7. 탭 ----------
   마크업: <div class="tabs" role="tablist" aria-label="카테고리">
     <button class="tab" role="tab" aria-selected="true" data-tab="all">전체</button>
     ...
   </div>
*/
/* 다크 캡슐 탭바 — 활성 탭은 브랜드 컬러 필로 반전 (밋밋한 언더라인 탭 탈피) */
.tabs {
  display: flex;
  width: fit-content;
  max-width: 100%;
  flex-wrap: nowrap;
  gap: 0.25rem;
  padding: 0.375rem;
  border-radius: var(--radius-pill);
  background: var(--ink);
  overflow-x: auto;
  scrollbar-width: none;
}
.tabs::-webkit-scrollbar { display: none; }
.tab {
  position: relative;
  padding: 0.62rem 1.15rem 0.48rem; /* G마켓 산스 광학 보정 */
  min-height: 2.375rem;
  border-radius: var(--radius-pill);
  font-family: var(--font-display);
  font-size: var(--fs-sm);
  font-weight: var(--fw-medium);
  color: var(--dark-text-mute);
  white-space: nowrap;
  transition:
    color var(--dur-fast) var(--ease-out),
    background-color var(--dur-fast) var(--ease-out);
}
@media (pointer: coarse) {
  .tab { min-height: 2.75rem; }
}
@media (hover: hover) and (pointer: fine) {
  .tab:not([aria-selected="true"]):hover { color: var(--dark-text); }
}
.tab[aria-selected="true"] {
  background: var(--point);
  color: var(--on-point);
}
/* 다크 섹션 안에서 쓰일 때 바탕과 겹치지 않게 얇은 보더 */
.section--dark .tabs { border: 1px solid var(--dark-line); }

/* ---------- 8. 모달 ----------
   마크업:
   <div class="modal" data-modal hidden>
     <div class="modal__scrim" data-modal-close></div>
     <div class="modal__dialog" role="dialog" aria-modal="true" aria-labelledby="modalTitle" tabindex="-1">
       <button class="modal__close" data-modal-close aria-label="닫기"><svg aria-hidden="true">...</svg></button>
       <div class="modal__body" data-modal-body></div>
     </div>
   </div>
*/
.modal {
  position: fixed;
  inset: 0;
  z-index: var(--z-modal);
  display: grid;
  place-items: center;
  padding: var(--sp-5);
}
.modal[hidden] { display: none; }

.modal__scrim {
  position: absolute;
  inset: 0;
  background: var(--ink);
  opacity: 0.55;
}

.modal__dialog {
  position: relative;
  z-index: 1;
  width: min(100%, 40rem);
  max-height: 90svh;
  overflow-y: auto;
  background: var(--card-bg);
  color: var(--text);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-lift);
  padding: var(--sp-6);
  transform: scale(0.96);
  opacity: 0;
  transition: transform var(--dur-base) var(--ease-out), opacity var(--dur-base) var(--ease-out);
}
.modal.is-open .modal__dialog { transform: scale(1); opacity: 1; }

.modal__close {
  position: absolute;
  top: var(--sp-4);
  right: var(--sp-4);
  width: 2.75rem;
  height: 2.75rem;
  display: grid;
  place-items: center;
  border-radius: var(--radius-pill);
  color: var(--ink-mute);
  transition: background var(--dur-fast) var(--ease-out), color var(--dur-fast) var(--ease-out);
}
.modal__close svg { width: 1.25rem; height: 1.25rem; }
@media (hover: hover) and (pointer: fine) {
  .modal__close:hover { background: var(--sub-tint); color: var(--point); }
}

.modal__body { display: grid; gap: var(--sp-5); }
.modal__media {
  width: 100%;
  aspect-ratio: 1 / 1;
  border-radius: var(--radius-md);
  overflow: hidden;
  background: var(--sub-tint);
}
.modal__media img { width: 100%; height: 100%; object-fit: cover; }
.modal__title { font-size: var(--fs-h2); font-weight: var(--fw-bold); }
.modal__nutrition {
  width: 100%;
  border-collapse: collapse;
  font-size: var(--fs-sm);
}
.modal__nutrition th, .modal__nutrition td {
  text-align: left;
  padding: var(--sp-2) var(--sp-3);
  border-bottom: 1px solid var(--line);
}

/* ---------- 9. 팝업(이벤트) ----------
   마크업:
   <div class="popup" data-popup data-popup-key="katoori" hidden>
     <div class="popup__scrim" data-popup-close></div>
     <div class="popup__dialog" role="dialog" aria-modal="true" aria-labelledby="popupTitle" tabindex="-1">
       <button class="modal__close" data-popup-close aria-label="닫기"><svg aria-hidden="true">...</svg></button>
       <img class="popup__media" src="..." alt="..." width="480" height="480">
       <div class="popup__body"> <p id="popupTitle">...</p> ... </div>
       <div class="popup__actions">
         <button class="btn--text" data-popup-hide-today>오늘 하루 보지 않기</button>
         <button class="btn--text" data-popup-close>닫기</button>
       </div>
     </div>
   </div>
*/
.popup {
  position: fixed;
  inset: 0;
  z-index: var(--z-popup);
  display: grid;
  place-items: center;
  padding: var(--sp-5);
}
.popup[hidden] { display: none; }
.popup__scrim {
  position: absolute;
  inset: 0;
  background: var(--ink);
  opacity: 0.6;
}
.popup__dialog {
  position: relative;
  z-index: 1;
  width: min(100%, 24rem);
  background: var(--card-bg);
  border-radius: 0.75rem; /* 실측: 굽네식 네이티브 알림창 라운드(8~14px) */
  box-shadow: var(--shadow-lift);
  overflow: hidden;
  transform: scale(0.96);
  opacity: 0;
  transition: transform var(--dur-base) var(--ease-out), opacity var(--dur-base) var(--ease-out);
}
.popup.is-open .popup__dialog { transform: scale(1); opacity: 1; }
.popup__media { width: 100%; aspect-ratio: 1 / 1; object-fit: cover; }
.popup__body { padding: var(--sp-5); display: grid; gap: var(--sp-2); }
/* 실측 표준: 하단 액션은 풀폭 절반 분할 버튼(네이티브 알림창 형태) */
.popup__actions {
  display: grid;
  grid-template-columns: 1fr 1fr;
  border-top: 1px solid var(--line);
  padding: 0;
}
.popup__actions .btn--text,
.popup__actions button {
  min-height: 3.25rem;
  padding: 0.15em 0 0;
  font-family: var(--font-display);
  font-size: var(--fs-md);
  font-weight: var(--fw-bold);
  text-align: center;
}
.popup__actions > * + * { border-left: 1px solid var(--line); }
.popup__actions .btn--text::after { display: none; }
/* 원격 설정으로 링크(CTA)가 주입되면 3열이 되므로 자동 균등 분할 */
.popup__actions:has(.popup__cta) { grid-template-columns: repeat(3, 1fr); }
.popup__actions .popup__cta {
  border-radius: 0;
  background: var(--point);
  color: var(--on-point);
  min-height: 3.25rem;
  padding: 0.15em 0 0;
}

/* ---------- 10. 폼 요소 + 에러 상태 ---------- */

.form { display: grid; gap: var(--sp-5); }
.form-row { display: grid; gap: var(--sp-5); }
@media (min-width: 48rem) {
  .form-row--2 { grid-template-columns: 1fr 1fr; }
}
.form-field { display: grid; gap: var(--sp-2); }
.form-field label {
  font-size: var(--fs-sm);
  font-weight: var(--fw-semibold);
}
.form-field .is-required {
  color: var(--point);
  margin-left: 0.2em;
}
.form-field input[type="text"],
.form-field input[type="tel"],
.form-field input[type="email"],
.form-field input[type="number"],
.form-field textarea,
.form-field select {
  width: 100%;
  min-height: 2.75rem;
  padding: 0.7rem 1rem;
  border: 1px solid var(--line-strong);
  border-radius: var(--radius-sm);
  background: var(--paper);
  color: var(--text);
  font-size: var(--fs-md);
  transition: border-color var(--dur-fast) var(--ease-out), box-shadow var(--dur-fast) var(--ease-out);
}
.form-field textarea { min-height: 8rem; resize: vertical; }
.form-field input:focus-visible,
.form-field textarea:focus-visible,
.form-field select:focus-visible {
  border-color: var(--point);
  outline: none;
  box-shadow: 0 0 0 3px var(--point-tint);
}
.form-field.has-error input,
.form-field.has-error textarea,
.form-field.has-error select {
  border-color: var(--point);
}
.form-error {
  display: none;
  align-items: center;
  gap: 0.35em;
  font-size: var(--fs-xs);
  color: var(--point);
}
.form-error svg { width: 0.9rem; height: 0.9rem; flex: 0 0 auto; }
/* form-checkbox(동의 체크박스)는 form-field가 아니라 form-checkbox 클래스를 쓰므로
   버그: has-error가 붙어도 아래 규칙이 없으면 에러 메시지가 시각적으로도, 접근성
   트리에서도(display:none) 영원히 숨겨진 채로 남는다 — 두 클래스 모두 대응 */
.form-field.has-error .form-error,
.form-checkbox.has-error .form-error { display: flex; }

.form-checkbox {
  display: flex;
  align-items: flex-start;
  gap: 0.65rem;
  font-size: var(--fs-sm);
  min-height: 2.75rem;
}
.form-checkbox input {
  width: 1.25rem;
  height: 1.25rem;
  margin-top: 0.15em;
  flex: 0 0 auto;
  accent-color: var(--point);
}

.form-hint {
  font-size: var(--fs-xs);
  /* 접근성: --ink-mute 3.69:1 → 4.5:1 미달 보정 */
  color: color-mix(in srgb, var(--ink-mute) 80%, var(--ink) 20%);
}

.form-success {
  display: none;
  align-items: center;
  gap: var(--sp-2);
  padding: var(--sp-4);
  border-radius: var(--radius-sm);
  background: var(--point-tint);
  color: var(--point-deep);
  font-weight: var(--fw-semibold);
}
.form-success.is-visible { display: flex; }

/* ---------- 11. 타임라인 (연혁 / 절차 단계) ----------
   연혁: <ol class="timeline"><li class="timeline__item"><span class="timeline__year">1998</span><p>...</p></li>...</ol>
   절차: <ol class="timeline timeline--steps"><li class="timeline__item"><span class="timeline__num">1</span><h3>...</h3><p>...</p></li>...</ol>
*/
.timeline {
  position: relative;
  display: grid;
  gap: var(--sp-7);
  padding-inline-start: var(--sp-6);
}
.timeline::before {
  content: "";
  position: absolute;
  left: calc(var(--sp-2) - 1px);
  top: 0.35em;
  bottom: 0.35em;
  width: 2px;
  background: var(--line-strong);
}
/* base.css의 ol[class]{padding:0} 리셋(0,1,1)보다 우선하도록 동일 특이성으로 재선언 */
ol.timeline, ul.timeline { padding-inline-start: var(--sp-6); }
.timeline__item { position: relative; }
.timeline__item::before {
  content: "";
  position: absolute;
  left: calc(-1 * var(--sp-6) + var(--sp-2) - 5px);
  top: 0.3em;
  width: 10px;
  height: 10px;
  border-radius: 50%;
  background: var(--point);
  box-shadow: 0 0 0 4px var(--card-bg);
}
.timeline__year {
  display: block;
  font-weight: var(--fw-extra);
  color: var(--point);
  font-variant-numeric: tabular-nums;
  margin-bottom: var(--sp-1);
}

.timeline--steps {
  padding-inline-start: 0;
  gap: var(--sp-6);
}
.timeline--steps::before { display: none; }
.timeline--steps .timeline__item {
  display: flex;
  gap: var(--sp-4);
  align-items: flex-start;
}
.timeline--steps .timeline__item::before { display: none; }
.timeline__num {
  flex: 0 0 auto;
  width: 2.5rem;
  height: 2.5rem;
  display: grid;
  place-items: center;
  border-radius: 50%;
  background: var(--point);
  color: var(--on-point);
  font-weight: var(--fw-bold);
  font-variant-numeric: tabular-nums;
}
@media (min-width: 64rem) {
  .timeline--steps {
    position: relative;
    display: grid;
    grid-auto-flow: column;
    grid-template-columns: repeat(auto-fit, minmax(0, 1fr));
    align-items: start;
  }
  .timeline--steps::after {
    content: "";
    position: absolute;
    top: 1.25rem;
    left: 0; right: 0;
    height: 2px;
    background: var(--line-strong);
    z-index: 0;
  }
  .timeline--steps .timeline__item {
    position: relative;
    z-index: 1;
    flex-direction: column;
    align-items: center;
    text-align: center;
    padding-inline: var(--sp-2);
  }
}

/* ---------- 12. 매운맛 게이지 ----------
   <span class="spice-gauge" data-spice-gauge aria-label="매운맛 2단계">
     <span class="spice-gauge__unit is-filled"><svg aria-hidden="true">...고추...</svg></span>
     <span class="spice-gauge__unit is-filled"><svg aria-hidden="true">...</svg></span>
     <span class="spice-gauge__unit"><svg aria-hidden="true">...</svg></span>
   </span>
*/
.spice-gauge {
  display: inline-flex;
  align-items: center;
  gap: 0.2rem;
}
.spice-gauge__unit {
  width: 1rem;
  height: 1rem;
  color: var(--ink-mute);
}
[data-theme="katoori"] .menu-card__reveal .spice-gauge__unit,
.menu-card__reveal .spice-gauge__unit {
  color: var(--dark-text-mute);
}
.spice-gauge__unit svg { width: 100%; height: 100%; display: block; }
.spice-gauge__unit.is-filled {
  color: var(--point);
  transform: scale(0);
  opacity: 0;
  transition:
    transform var(--dur-base) var(--ease-out) var(--reveal-delay, 0ms),
    opacity var(--dur-base) var(--ease-out) var(--reveal-delay, 0ms);
}
.spice-gauge__unit.is-filled.is-visible {
  transform: scale(1);
  opacity: 1;
}
@media (prefers-reduced-motion: reduce) {
  .spice-gauge__unit.is-filled { transform: scale(1); opacity: 1; }
}

/* ---------- 13. 스탬프 언더라인 + 세로쓰기 유틸 ---------- */

/* 텍스트 아래 골드/브랜드색 밑줄이 도장처럼 scaleX(0)→1 드러나는 장치.
   .reveal 컨테이너 안에서 쓰거나, 자체에 .is-visible을 받아도 동작 */
.stamp-underline {
  position: relative;
  display: inline-block;
}
.stamp-underline::after {
  content: "";
  position: absolute;
  left: 0; right: 0; bottom: -0.2em;
  height: 2px;
  background: var(--sub);
  transform: scaleX(0);
  transform-origin: left;
  transition: transform 240ms var(--ease-out) var(--reveal-delay, 0ms);
}
.stamp-underline.is-visible::after,
.reveal.is-visible .stamp-underline::after,
.is-visible.stamp-underline::after {
  transform: scaleX(1);
}

/* 전통 간판/세로 스탬프 느낌의 세로쓰기 포인트 (까투리 전용 사용 권장) */
.vertical-rl {
  writing-mode: vertical-rl;
  text-orientation: mixed;
  letter-spacing: 0.15em;
}

/* ---------- 14. 히어로 키네틱 타이포 구조 ----------
   <h1 class="hero-kinetic">
     <span class="hero-kinetic__line hero-kinetic__line--1">바삭함에도</span>
     <span class="hero-kinetic__line hero-kinetic__line--2">족보가 있다</span>
   </h1>
   <span class="hero-kinetic__seal" aria-hidden="true"></span>
   (커튼 리빌은 페이지 로드시 자동 재생 — 히어로는 최초 뷰포트에 항상 보이므로 IO 불필요)
*/
@keyframes heroKineticReveal {
  to { clip-path: inset(0 0 0 0%); letter-spacing: var(--ls-tight); }
}
@keyframes heroKineticSeal {
  to { transform: scaleX(1); }
}

.hero-kinetic { display: grid; }
.hero-kinetic__line {
  display: block;
  overflow: hidden;
  clip-path: inset(0 0 0 100%);
  letter-spacing: 0.05em;
  animation: heroKineticReveal var(--dur-reveal) var(--ease-out) both;
}
.hero-kinetic__line--1 { animation-delay: 0ms; }
.hero-kinetic__line--2 { animation-delay: 150ms; }

.hero-kinetic__seal {
  display: block;
  width: 3.5rem;
  height: 3px;
  margin-top: var(--sp-4);
  background: var(--sub);
  transform: scaleX(0);
  transform-origin: left;
  animation: heroKineticSeal 240ms var(--ease-out) 900ms both;
}

/* ---------- 15. 브랜드 라인아트 마크 (게이트웨이 + 형제 브랜드 연결 섹션 공용) ----------
   <span class="brand-mark">
     <svg viewBox="0 0 64 64" aria-hidden="true" focusable="false">
       <path class="mark-arc mark-arc--a" d="..." />
       <path class="mark-arc mark-arc--b" d="..." />
     </svg>
   </span>
*/
.brand-mark {
  width: 3.5rem;
  height: 3.5rem;
  flex: 0 0 auto;
  display: grid;
  place-items: center;
  border-radius: var(--radius-pill);
  background: var(--dark-bg-soft);
  border: 1px solid var(--dark-line);
}
.brand-mark--sm { width: 2.5rem; height: 2.5rem; }
.brand-mark svg { width: 60%; height: 60%; overflow: visible; }
.mark-arc {
  fill: none;
  stroke-width: 3;
  stroke-linecap: round;
}
.mark-arc--a { stroke: var(--katoori-sub, var(--sub)); }
.mark-arc--b { stroke: var(--daebak-point, var(--point)); }
