@layer site.modules {
  /* santa-here — 브랜드 컴포넌트 (디자인 핸드오프, design_handoff_component_system/component-sheet.html).
     /static/css/components.css(base, 중립) 뒤에 로드되는 사이트 레이어.

     브랜드 차이는 tokens.css 재정의가 1차 수단이다 — base 컴포넌트가 토큰만 참조하므로
     색·모서리·그림자는 여기서 다시 쓸 필요가 없다. 이 파일에 오버라이드를 추가하기 전에
     "토큰으로 표현 가능한 차이인가"를 먼저 묻는다. 가능하면 tokens.css로, 대응 토큰이
     없으면 토큰을 신설하는 쪽이 우선이고, 오버라이드는 구조가 실제로 다를 때만 쓴다.

     base에 없는 컴포넌트(상품 카드·칩·배너·갤러리·옵션 선택기·토스트·Rudolph-touch
     아이콘)는 sh- 접두 클래스로 신규 정의한다.
     santa-here-global은 이 파일이 없어 FallbackStaticFiles가 이 파일로 폴백한다(공유). */

  /* ── -1. 카드 — base .card 컴포넌트 슬롯(--card-*) 값 공급 (DR-030, EN-052).
     선택자를 재선언하지 않고 슬롯에 값만 대입한다(rule/css-guide.md 3절).
     구 .sh-checkout-card가 쓰던 값(반경 --radius-md, 여백 --spacing-xl, 테두리
     --border-width, 그림자 없음)으로 맞춰 구매자 화면의 카드 두 세계를 하나로 합친다.
     브랜드 톤(색)은 이번 회차 대상이 아니다 — background·border-color는 base와
     동일한 --color-bg·--color-border를 그대로 받는다. */
  :root {
    --card-radius: var(--radius-md);
    --card-padding: var(--spacing-xl);
    --card-shadow: none;
    --card-shadow-hover: none;
  }

  /* ── 0. 헤딩 폰트 — Bricolage Grotesque(라틴)+Pretendard(한글, tokens.css --font-family-heading) ── */
  h1, h2, h3, .sh-hero h1, .prod-name, .partner-banner h2 {
    font-family: var(--font-family-heading);
  }

  /* ── 1. 버튼 — base .btn* 오버라이드 ──
     base가 이미 토큰만 참조하므로 색·모서리는 tokens.css 재정의로 반영된다.
     여기 남는 것은 토큰으로 표현되지 않는 차이뿐이다. */
  .btn {
    font-family: var(--font-family-heading);
  }
  /* 버튼 — base .btn-* 컴포넌트 슬롯에 값만 대입한다(선택자 재선언 금지, css-guide 3절).
     EN-051 6번에서 여기 .btn-primary { color }를 재선언해 글자색을 되돌렸었는데, 그건
     증상 처리였다. 원인은 아래 body a의 광역 선택자였고 EN-052에서 그것을 좁혀 없앴다. */
  :root {
    --btn-dark-bg: var(--color-secondary);
    --btn-dark-bg-hover: var(--color-secondary-hover);
  }
  .btn-primary:hover {
    box-shadow: none;
  }
  .btn-dark:hover {
    background: var(--color-secondary-hover);
  }
  /* M3 버튼 위계의 셋째 단계(채움 > 톤 > 외곽선 > 글자). 담기가 이 단계다 —
     구매와 담기가 둘 다 채움이라 "한 화면에 가장 센 버튼은 하나"와 어긋나 있었고,
     담기를 한 단계 내려 해소했다(EN-060 회차 3).
     색은 지우지 않고 초록을 테두리·글자로 남긴다. 테두리를 굵게(strong) 두는 이유는
     고정 바가 흰 바탕이라 버튼이 배경에 묻히기 때문이다 — 굵기는 M3가 단계를 가르는
     기준(면을 채우느냐)에 들어가지 않아 브랜드 재량이다. */
  /* 굵기는 규격이 1dp로 못박아 브랜드 재량이 아니다 — 종전 2px은 규격 밖이었다. */
  .btn-outline {
    background: transparent;
    border: var(--border-width) solid var(--color-secondary);
    color: var(--color-secondary);
  }
  .btn-outline:hover {
    background: var(--m3-secondary-container);
  }
  .btn:disabled,
  .btn[aria-disabled="true"] {
    background: var(--color-sand);
    color: var(--color-text-disabled);
    cursor: not-allowed;
    pointer-events: none;
  }

  /* ── 2. 배지 & 태그 — base .badge에 브랜드 변형만 추가 ──
     .badge-highlight가 상품 카드 상태 뱃지(popular·new·oliveyoung_pick 등)의 기본형이다.
     taxonomy(sites/santa-here-global/content/taxonomy.json)의 badges 슬러그가 늘어도
     이 클래스 하나를 공유하고, 라벨만 바뀐다 — 톤이 달라지는 슬러그만 변이를 추가한다. */
  .badge-highlight {
    background: var(--color-gold);
    color: var(--color-accent);
    /* elevation 예외 — 띄운 그림자가 아니라 안쪽 테두리다(레이아웃을 밀지 않으려고
       border 대신 inset을 쓴다). 두께는 컨트롤 외곽선과 같은 1.5px. */
    box-shadow: 0 0 0 var(--border-width) var(--color-accent) inset;
  }
  /* 올리브영 그린은 산타 M3 팔레트 밖의 외부 참조색(올리브영 시그니처 컬러) —
     소비처가 이 변이 하나뿐이라 토큰화하지 않고 리터럴로 둔다. 채워진 알약형으로
     정했고(테두리 없음), 그래서 base의 인셋 테두리를 명시적으로 지운다. */
  .badge-highlight--oliveyoung {
    background: #A4CE39;
    color: #21390A;
    box-shadow: none;
  }
  /* 품절 — base .badge 기본색(브랜드 액션 색)을 그대로 빌리면 "품절"이 아니라
     강조처럼 보인다. 비활성 배지 전용 토큰(tokens.css --color-surface-dim)으로
     버튼 disabled와 같은 규칙(--color-text-disabled, M3 38%)을 쓴다. */
  .badge-soldout {
    background: var(--color-surface-dim);
    color: var(--color-text-disabled);
  }
  /* ── 3. 카테고리 칩 & 검색 인풋 ── */
  .sh-chip {
    display: inline-flex;
    align-items: center;
    padding: var(--spacing-sm) var(--spacing-lg);
    border-radius: var(--radius-full);
    font-family: var(--font-family);
    font-size: var(--m3-label-small-size); line-height: var(--m3-label-small-line); font-weight: var(--m3-label-small-weight); letter-spacing: var(--m3-label-small-tracking);
    
    background: var(--color-sand);
    color: var(--color-accent);
    cursor: pointer;
    border: none;
  }
  .sh-chip.active {
    background: var(--color-accent);
    color: var(--color-text-inverse);
  }
  .sh-search-input,
  .input {
    background: var(--color-bg);
    border: var(--border-width) solid var(--color-sand);
    border-radius: var(--radius-md);
    color: var(--color-text);
    font-family: var(--font-family);
  }
  .sh-search-input::placeholder,
  .input::placeholder {
    color: var(--color-text-muted);
  }

  /* ── 4. 상품 카드 ── */
  /* 선물 소포다 — 흰 면에 포장 끈이 둘리고 교차점에 리본이 앉는다 (EN-060 5-3b,
     2026-08-14 배경 크래프트→흰색 전환 — 카탈로그 페이지 크림 배경 위에서 카드
     경계는 여전히 뚜렷하고, 카드 자체는 가벼워진다).
     끈은 카드 여백에 홀로 있고, 이미지·글자가 --product-gap만큼 물러나 끈과 띄운다.
     둘이 같은 값으로 물러나므로 이미지와 글자의 왼쪽은 여전히 한 선이다.
     굵기는 바깥으로만 자란다(세로는 왼쪽, 가로는 아래) — 굵혀도 그 선이 안 흔들린다. */
  .sh-product-card {
    /* 자기 색을 정한다 — 예전에는 site의 body a { color: inherit }에 얹혀 있었고,
       그 광역 선택자를 좁히자(EN-052) 기본 파랑으로 떨어졌다. */
    color: inherit;
    background: var(--color-bg);
    border-radius: var(--radius-lg);
    padding: var(--spacing-md);
    box-shadow: var(--shadow-sm);
    /* flex-column — 옵션은 상품명 줄 수를 그대로 따라가 바로 밑에 붙게 두고(카드마다
       시작 y좌표가 달라도 됨), 가격만 margin-top: auto로 카드 하단에 고정한다.
       그리드가 같은 행의 카드 높이를 stretch로 맞춰주므로, 가격 위치는 행 안에서 정렬된다. */
    display: flex;
    flex-direction: column;
    position: relative;
    /* 끈이 둥근 모서리 밖으로 나가는 끝을 카드가 자른다 — 포장지에 눌린 끈으로 읽힌다 */
    overflow: hidden;
    --product-tie: 2px;       /* 끈 굵기 */
    --product-gap: 6px;       /* 이미지·글자를 끈에서 띄우는 거리 */
    transition: transform var(--m3-duration-short2);
  }
  .sh-product-card:hover { transform: translateY(-2px); }
  /* 세로 끈 — 카드 위 끝에서 아래 끝까지. 오른쪽 끝이 카드 안쪽 여백선에 닿고,
     이미지·글자는 거기서 --product-gap만큼 더 안쪽에 있다 */
  .sh-product-card::before {
    content: "";
    position: absolute;
    top: 0;
    bottom: 0;
    left: calc(var(--spacing-md) - var(--product-tie));
    width: var(--product-tie);
    background: var(--color-border-strong);
  }
  /* 이미지도 글자와 같은 만큼 끈에서 띄운다 — 끈만 카드 여백에 남고 이미지·글자는
     같은 왼쪽 선에서 다시 만난다 */
  .sh-product-media {
    position: relative;
    margin-left: var(--product-gap);
  }
  /* 가로 끈 — 이미지 아래에서 --product-gap만큼 내려와 카드 좌우 끝까지. 이미지
     폭까지만 그으면 끈이 아니라 밑줄로 읽힌다 */
  .sh-product-media::after {
    content: "";
    position: absolute;
    top: calc(100% + var(--product-gap));
    height: var(--product-tie);
    /* 이미지가 들여쓰인 만큼 더 빼야 카드 왼쪽 끝에 닿는다 */
    left: calc(-1 * (var(--spacing-md) + var(--product-gap)));
    right: calc(-1 * var(--spacing-md));
    background: var(--color-border-strong);
  }
  /* 리본 — 두 끈이 실제로 만나는 점. 이미지 모서리가 아니라 끈의 교차라, 이미지가
     물러나도 따라가지 않는다. 카드에서 채도를 갖는 유일한 지점이라 포인트가 된다 —
     그래서 가격은 중립으로 내렸다 */
  .sh-product-bow {
    position: absolute;
    /* 이미지가 아니라 세로 끈 위에 앉는다 — 이미지가 들여쓰여도 교차점을 따라간다 */
    left: calc(-1 * var(--product-gap) - var(--product-tie) / 2);
    top: calc(100% + var(--product-gap) + var(--product-tie) / 2);
    transform: translate(-50%, -50%);
    color: var(--color-primary-text);
    line-height: 0;
    z-index: 2;
  }
  /* 썸네일 — 이미지가 없으면 파일명 텍스트가 가운데 보이는 플레이스홀더가 된다.
     비율을 정한다 — 높이 고정이던 종전에는 폭을 격자가 정해 375에서 5:4, 980+에서
     2.2:1로 뷰포트마다 다른 비율이 됐다 */
  .sh-product-card .sh-product-thumb {
    aspect-ratio: 1 / 1;
    border-radius: var(--radius-md);
    background: var(--color-sand);
    position: relative;
    overflow: hidden;
    display: flex;
    align-items: center;
    justify-content: center;
    color: var(--color-tan);
    font-size: var(--m3-body-small-size); line-height: var(--m3-body-small-line); font-weight: var(--m3-body-small-weight); letter-spacing: var(--m3-body-small-tracking);
  }
  .sh-product-card .sh-product-thumb img {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    object-fit: cover;
  }
  .sh-product-card .sh-product-badge {
    position: absolute;
    top: 8px;
    left: 8px;
  }
  /* 브랜드 / 상품명 / 용량 — 셋을 형식으로 가른다. 종전에는 용량과 브랜드가 같은
     스타일 두 줄이라 구분 단서가 없었고, 상품명이 두 줄로 흐르면 경계가 사라졌다.
     브랜드가 맨 위에 있으면 상품명이 몇 줄이든 시작점이 고정된다. */
  .sh-product-card .sh-product-brand {
    font-family: var(--font-family);
    font-size: var(--m3-label-medium-size); line-height: var(--m3-label-medium-line); font-weight: var(--m3-label-medium-weight); letter-spacing: .08em;
    text-transform: uppercase;
    color: var(--color-text-muted);
    /* 가로 끈이 지나갈 자리를 비켜준다 */
    margin-top: var(--spacing-xl);
  }
  .sh-product-card .sh-product-title {
    font-family: var(--font-family);

    font-size: var(--m3-body-medium-size); line-height: var(--m3-body-medium-line); font-weight: var(--m3-body-medium-weight); letter-spacing: var(--m3-body-medium-tracking);
    color: var(--color-text);
    /* 두 줄로 자른다 — 상품명 길이가 제각각이라 카드 높이가 흔들린다 */
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
  }
  .sh-product-card .sh-product-option {
    font-family: var(--font-family);

    font-size: var(--m3-body-small-size); line-height: var(--m3-body-small-line); font-weight: var(--m3-body-small-weight); letter-spacing: var(--m3-body-small-tracking);
    color: var(--color-text-muted);
  }
  /* "+N" 뱃지 — 옵션 텍스트 자체가 "Set" "+" 같은 말을 이미 쓰는 경우가 있어(카탈로그
     실사례: "Serum 30ml + Cream 30ml Set"), 추가 옵션 수를 그냥 이어 붙이면 상품명의
     일부처럼 읽힌다. 배경 있는 pill로 텍스트 흐름에서 시각적으로 떼어낸다. */
  .option-more-badge {
    display: inline-block;
    background: var(--color-bg-subtle);
    color: var(--color-primary);
    font-weight: var(--m3-label-medium-weight);
    border-radius: var(--radius-full);
    padding: 1px 6px;
    margin-left: 2px;
  }
  /* 브랜드가 없는 상품은 상품명이 첫 줄이 된다 — 그때도 가로 끈 자리를 비운다 */
  .sh-product-card .sh-product-media + .sh-product-title { margin-top: var(--spacing-xl); }
  /* 글자만 끈에서 띄운다 — 끈은 이미지에 붙어 있다 */
  .sh-product-card .sh-product-brand,
  .sh-product-card .sh-product-title,
  .sh-product-card .sh-product-option,
  .sh-product-card .sh-product-price { padding-left: var(--product-gap); }
  /* 가격은 중립이다 — 크래프트 면에서는 빨강이 가격·리본 둘이 되어 서로를 잡아먹는다.
     채도를 리본 하나로 몰아야 그것이 포인트가 된다 */
  .sh-product-card .sh-product-price {
    font-family: var(--font-family);

    font-size: var(--m3-title-medium-size); line-height: var(--m3-title-medium-line); font-weight: var(--m3-title-medium-weight); letter-spacing: var(--m3-title-medium-tracking);
    color: var(--color-text);
    display: block;
    /* 카드가 flex-column이라 margin-top: auto로 밀어 항상 카드 하단에 고정한다 —
       상품명·옵션이 몇 줄이든 가격은 같은 행의 카드들과 y좌표가 맞는다(grid stretch로
       카드 높이가 같아짐). spacing-sm은 유지해 위 요소와 최소 간격은 보장한다. */
    margin-top: auto;
    padding-top: var(--spacing-sm);
  }
  /* 전체 단색 변형 — 끈·리본·테두리 세 지점을 한 색으로 묶는다(2026-08-14 후보 검토).
     M3 팔레트 밖의 축제색이라 토큰이 아니라 카탈로그 배지 아이콘(catalog.html의
     인라인 hex)과 같은 방식으로 리터럴을 쓴다. 기본 카드(끈 중립·리본 --color-primary-text)는
     그대로 두고, 이 두 클래스를 추가로 붙였을 때만 적용된다. */
  .sh-product-card--accent-green::before,
  .sh-product-card--accent-green .sh-product-media::after { background: #2E6B4A; }
  .sh-product-card--accent-green .sh-product-bow { color: #2E6B4A; }
  .sh-product-card--accent-green { border: 1.5px solid #2E6B4A; }

  /* --accent-red — 카탈로그는 초록 고정 운영 중(dcb26119, 2026-08-15)이라 현재 어느
     상품 카드에도 안 붙지만, 디자인 시스템 선택지로는 남겨둔다(2026-08-15 재확인).
     초록과 대칭 구조, 값은 삭제 전 원본(dcb26119 이전)과 동일. */
  .sh-product-card--accent-red::before,
  .sh-product-card--accent-red .sh-product-media::after { background: #C41E3A; }
  .sh-product-card--accent-red .sh-product-bow { color: #C41E3A; }
  .sh-product-card--accent-red { border: 1.5px solid #C41E3A; }

  /* --accent-gold — 초록·빨강과 달리 M3 팔레트 안의 색이라 리터럴이 아니라 토큰을 쓴다
     (2026-08-15, 카탈로그 색 다양화 논의). --color-gold(Fixed 계열, 밝은 톤)는 흰 배경 위
     선으로 쓰면 대비가 없어 안 보인다 — 선·테두리엔 --color-gold-deep(짙은 tertiary 톤)을
     쓴다(2026-08-15, "기본과 동일해 보인다" 확인 후 교정). */
  .sh-product-card--accent-gold::before,
  .sh-product-card--accent-gold .sh-product-media::after { background: var(--color-gold-deep); }
  .sh-product-card--accent-gold .sh-product-bow { color: var(--color-gold-deep); }
  .sh-product-card--accent-gold { border: 1.5px solid var(--color-gold-deep); }

  /* --accent-blue — M3 팔레트 밖의 색(--color-blue-postal, 항공우편 줄무늬 세 번째 색과
     공유하는 토큰)이라 초록·빨강처럼 다룬다(2026-08-15, 브랜드 색 다양화 논의). */
  .sh-product-card--accent-blue::before,
  .sh-product-card--accent-blue .sh-product-media::after { background: var(--color-blue-postal); }
  .sh-product-card--accent-blue .sh-product-bow { color: var(--color-blue-postal); }
  .sh-product-card--accent-blue { border: 1.5px solid var(--color-blue-postal); }

  /* ── 5. 프로모 배너 ── */
  .sh-banner {
    background: linear-gradient(135deg, var(--color-primary), var(--color-primary-hover));
    border-radius: var(--radius-lg);
    padding: var(--spacing-2xl);
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    text-align: center;
    gap: var(--spacing-lg);
  }
  .sh-banner .sh-banner-eyebrow {
    font-family: var(--font-family);
    
    font-size: var(--m3-label-small-size); line-height: var(--m3-label-small-line); font-weight: var(--m3-label-small-weight); letter-spacing: var(--m3-label-small-tracking);
    color: var(--m3-primary-fixed);
    
  }
  .sh-banner .sh-banner-headline {
    font-family: var(--font-family-heading);
    
    font-size: var(--m3-title-large-size); line-height: var(--m3-title-large-line); font-weight: var(--m3-title-large-weight); letter-spacing: var(--m3-title-large-tracking);
    color: var(--color-text-inverse);
    margin-top: var(--spacing-xs);
  }
  .sh-banner .sh-banner-headline em {
    font-style: normal;
  }
  .sh-banner .sh-banner-body {
    font-family: var(--font-family);
    
    font-size: var(--m3-body-large-size); line-height: var(--m3-body-large-line); font-weight: var(--m3-body-large-weight); letter-spacing: var(--m3-body-large-tracking);
    color: var(--m3-inverse-on-surface);
    margin: 0;
    
  }
  .sh-banner .sh-banner-cta {
    background: var(--color-gold);
    color: var(--color-accent);
    padding: var(--spacing-lg) var(--spacing-3xl);
    border-radius: var(--radius-full);
    font-family: var(--font-family);
    
    font-size: var(--m3-title-medium-size); line-height: var(--m3-title-medium-line); font-weight: var(--m3-title-medium-weight); letter-spacing: var(--m3-title-medium-tracking);
    white-space: nowrap;
  }

  /* ── 6. 상품 이미지 갤러리 ── */
  .sh-gallery-thumb {
    width: 40px;
    height: 40px;
    border-radius: var(--radius-sm);
    background: var(--color-sand);
    opacity: 0.7;
    border: none;
  }
  /* 선택은 굵기가 아니라 색과 밝기로 표현한다 — 규격에 선택용 굵기 단계가 없다.
     선택 안 된 썸네일은 opacity로 물러나 있어 대비는 유지된다. */
  .sh-gallery-thumb.active {
    border: var(--border-width) solid var(--color-primary);
    opacity: 1;
  }
  .sh-gallery-dot {
    width: 8px;
    height: 8px;
    border-radius: 50%;
    background: var(--color-surface-dim);
  }
  .sh-gallery-dot.active {
    background: var(--color-primary);
  }

  /* ── 7. 옵션 선택기 — product_landing.html의 .variant-picker__item 구조에 브랜드 입힘.
     구조 클래스(.variant-picker*)·히든 라디오 처리는 공용 파샬 _variant_picker.html과 짝인
     base components.css가 갖는다(이름을 바꾸지 않는다). 원래는 표면(테두리·반경·색·
     글꼴·여백)만 여기서 재선언하는 경계였는데, 칩 그리드(가로 wrap)가 옵션이 많은
     상품(예: 6종)에서 폭이 라벨 길이 따라 들쭉날쭉하고 줄바꿈까지 겹쳐 정신없어 보이는
     문제(2026-08-13)로 세로 목록으로 바꿨다 — 방향(줄바꿈 여부) 자체가 이 결정의 핵심이라
     레이아웃까지 여기서 재선언한다. santa-here-global이 이 파샬의 유일한 소비자라 base
     회귀 위험은 없다.

     선택 강조는 필드(배경 채움)를 안 쓴다 — 바로 아래 구매 바의 .btn-primary가 이미
     검정이라, 옵션 선택까지 검정이면 정작 눌러야 할 CTA가 두 검은 덩어리로 묻힌다.
     왼쪽 색 바 + 연한 배경 정도로 약하게 강조한다. */
  .variant-picker {
    display: flex;
    flex-direction: column;
    flex-wrap: nowrap;
    gap: 0;
    justify-content: flex-start;
    background: var(--color-bg);
    border-radius: var(--radius-lg);
    box-shadow: var(--shadow-sm);
    overflow: hidden;
  }
  .variant-picker__item label {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--spacing-md);
    padding: var(--spacing-md) var(--spacing-lg);
    border: none;
    border-left: 3px solid transparent;
    border-radius: 0;
    color: var(--color-text);
    text-align: left;
    font-family: var(--font-family);
  }
  .variant-picker__item:last-child label { border-bottom: none; }
  .variant-picker__item label .variant-picker__label {
    font-size: var(--m3-body-medium-size); line-height: var(--m3-body-medium-line); font-weight: var(--m3-body-medium-weight); letter-spacing: var(--m3-body-medium-tracking);
  }
  .variant-picker__item label .variant-picker__price {
    font-size: var(--m3-label-large-size); line-height: var(--m3-label-large-line); font-weight: var(--m3-label-large-weight); letter-spacing: var(--m3-label-large-tracking);
    white-space: nowrap;
  }
  .variant-picker__item input:checked + label {
    background: var(--color-kraft);
    border-left-color: var(--color-primary);
  }
  .variant-picker__item input:checked + label .variant-picker__label,
  .variant-picker__item input:checked + label .variant-picker__price {
    font-weight: var(--m3-title-small-weight);
  }
  .variant-picker__item input:disabled + label {
    color: var(--color-text-disabled);
    opacity: .6;
    cursor: not-allowed; /* base label의 pointer를 덮는다 — 표면 이관 시 유실됐던 선언 */
  }
  .variant-picker__item input:disabled + label .variant-picker__label {
    text-decoration: line-through;
  }

  /* ── 8. 체크아웃 폼 ──
     포커스 상태는 base가 --color-border-focus·--shadow-focus로 처리한다(tokens.css에서
     브랜드 값으로 재정의됨). 에러 테두리만 --color-error가 아닌 브랜드 red를 쓴다. */
  .input-error {
    border-color: var(--color-primary);
  }
  .sh-checkbox {
    width: 20px;
    height: 20px;
    border-radius: var(--radius-xs);
    background: var(--color-secondary);
    color: var(--color-text-inverse);
    display: inline-flex;
    align-items: center;
    justify-content: center;
    font-size: var(--m3-label-small-size); line-height: var(--m3-label-small-line); font-weight: var(--m3-label-small-weight); letter-spacing: var(--m3-label-small-tracking);
    
  }
  .sh-radio {
    width: 16px;
    height: 16px;
    border-radius: 50%;
    border: var(--border-width) solid var(--color-accent);
    position: relative;
    display: inline-block;
  }
  .sh-radio.checked::after {
    content: "";
    position: absolute;
    inset: 3px;
    border-radius: 50%;
    background: var(--color-primary);
  }

  /* ── 9. 빈 / 에러 상태 — base .alert-error 오버라이드 ──
     재고 없음 카드(.sh-card-outofstock·.sh-outofstock-pill)는 걷었다(EN-060 5-3b).
     규칙만 있고 이를 발행하는 화면이 없었다 — 품절 표시 기능이 생기면 그때 그 기능과
     함께 만든다. */
  .alert-error {
    background: var(--color-error-bg);
    border: var(--border-width) solid var(--color-error-border);
    color: var(--color-text);
    border-radius: var(--radius-lg);
  }

  /* ── 10. 토스트 / 확인 배너 ── */
  .sh-toast {
    display: flex;
    align-items: center;
    gap: var(--spacing-md);
    padding: var(--spacing-md) var(--spacing-xl);
    border-radius: var(--radius-md);
    font-family: var(--font-family);
    
    font-size: var(--m3-label-small-size); line-height: var(--m3-label-small-line); font-weight: var(--m3-label-small-weight); letter-spacing: var(--m3-label-small-tracking);
    color: var(--color-text-inverse);
  }
  .sh-toast.sh-toast-neutral {
    background: var(--color-accent);
  }
  .sh-toast.sh-toast-order {
    background: var(--color-secondary);
  }
  .sh-toast .sh-toast-check {
    width: 20px;
    height: 20px;
    border-radius: 50%;
    display: flex;
    align-items: center;
    justify-content: center;
    
    font-size: var(--m3-label-small-size); line-height: var(--m3-label-small-line); font-weight: var(--m3-label-small-weight); letter-spacing: var(--m3-label-small-tracking);
    flex: none;
  }
  .sh-toast-neutral .sh-toast-check {
    background: var(--color-secondary);
    color: var(--color-text-inverse);
  }
  .sh-toast-order .sh-toast-check {
    background: var(--color-gold);
    color: var(--color-accent);
  }

  /* ── 11. 이행 상태색 — buyer_order_purchasing_agency.html의 .fulfil-step 구조에
     브랜드 상태색을 입힌다(base 마크업 재사용). ── */
  .fulfil-step.done .name { color: var(--color-text); }
  .fulfil-step.current .name { color: var(--color-primary-text); }
  .fulfil-step.todo .name { color: var(--color-text-muted); }

  /* ── 12. Rudolph-touch 아이콘 (눈-눈-코, CSS-only) ── */
  /* 모티프 — 브랜드 재량이다. M3는 크기를 부품 사양에 두지 눈금으로 주지 않아
     여기 값들이 규격에서 파생될 자리가 없다(EN-060 회차 5-3a). */
  .sh-rudolph {
    width: 24px;
    height: 24px;
    border-radius: 50%;
    background: var(--color-tan);
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: var(--spacing-xs);
    flex: none;
  }
  .sh-rudolph .sh-rudolph-eyes {
    display: flex;
    gap: var(--spacing-xs);
  }
  .sh-rudolph .sh-rudolph-eye {
    width: 4px;
    height: 4px;
    border-radius: 50%;
    background: var(--color-accent);
  }
  .sh-rudolph .sh-rudolph-nose {
    width: 4px;
    height: 4px;
    border-radius: 50%;
    background: var(--color-primary);
    margin-top: var(--spacing-xs);
  }

  /* ── 주문 상태 카드 (ink bg, Rudolph 아이콘 + 총액) ── */
  .sh-order-status-card {
    width: 220px;
    background: var(--color-accent);
    border-radius: var(--radius-lg);
    padding: var(--spacing-lg);
    color: var(--color-sand);
    display: flex;
    flex-direction: column;
    gap: var(--spacing-md);
  }
  .sh-order-status-card .sh-order-status-head {
    display: flex;
    align-items: center;
    gap: var(--spacing-sm);
  }
  .sh-order-status-card .sh-order-status-eyebrow {
    font-family: var(--font-family);
    
    font-size: var(--m3-label-small-size); line-height: var(--m3-label-small-line); font-weight: var(--m3-label-small-weight); letter-spacing: var(--m3-label-small-tracking);
    
    opacity: 0.65;
    text-transform: uppercase;
  }
  .sh-order-status-card .sh-order-status-headline {
    font-family: var(--font-family-heading);
    
    font-size: var(--m3-title-small-size); line-height: var(--m3-title-small-line); font-weight: var(--m3-title-small-weight); letter-spacing: var(--m3-title-small-tracking);
    color: var(--color-text-inverse);
  }
  .sh-order-status-card .sh-order-status-total {
    display: flex;
    justify-content: space-between;
    font-family: var(--font-family);
    
    font-size: var(--m3-label-small-size); line-height: var(--m3-label-small-line); font-weight: var(--m3-label-small-weight); letter-spacing: var(--m3-label-small-tracking);
    color: var(--color-gold);
  }

  /* ── 사이트 크롬 — 헤더·푸터·문의 FAB·메일 모달·상담 채팅 ──
     base.html이 _header/_footer를 include하고 이 파일을 로드하므로, 여기 두면 base를
     확장하는 모든 페이지(주문 조회·환불 등 공용 화면 포함)가 자동으로 적용받는다.
     페이지별 <style> include로 나눠 갖던 것을 옮긴 것 — 그 방식은 새 페이지마다 include를
     빠뜨려 크롬이 스타일 없이 렌더되는 사고를 냈다. */

  /* 페이지 표면 — 클래스로 한정하지 않는다. 이 파일 자체가 이 사이트에서만 로드되므로
     body 한정자(구 .sh-page)는 누락 가능한 중복 관문일 뿐이었다. */
  body {
    background: var(--color-bg-subtle);
    color: var(--color-text);
    font-family: var(--font-family);
    margin: 0;
    /* 콘텐츠가 짧은 화면(주문 확인 등)에서 푸터가 중턱에 뜨지 않도록 세로 flex로 세우고
       푸터만 아래로 민다 — 콘텐츠 블록 개수와 무관하게 동작한다. */
    min-height: 100vh;
    display: flex;
    flex-direction: column;
  }
  /* 링크 기본 — 클래스 없는 링크만 대상으로 한다. 예전에는 `body a`로 전부 잡아
     레이어 순서상 base 컴포넌트(.btn-primary)의 글자색까지 특이도와 무관하게 덮었고,
     그것이 무효 토큰·error·cart 화면 버튼의 AA 미달 원인이었다(EN-051 6번).
     클래스를 가진 링크는 그 부품이 자기 색을 정한다. */
  body a:not([class]) { color: inherit; text-decoration: none; }
  .sh-footer { margin-top: auto; }
  /* 헤더·본문·푸터 사이 공통 여백 — 페이지마다 제각각 주던 위/아래 여백을 여기 하나로
     통일한다(설계 논의 08-14). body > main만 잡아 페이지 클래스(cart-page·l-checkout·
     l-product·sh-catalog 등)와 무관하게 항상 적용된다. 페이지별로 이 여백을 따로 주고
     있었다면 중복되니 함께 뺀다(카트·카탈로그 히어로가 그런 경우였다). */
  body > main { margin-top: var(--spacing-xl); margin-bottom: var(--spacing-2xl); }
  /* .cart-page(style.css, base 레이어)의 margin: var(--spacing-xl) auto는 여기 따로
     취소할 필요가 없다 — cascade layer 순서(@layer base, site, dashboard, base.html)상
     site 레이어가 base보다 항상 이겨서, 이 body > main 규칙이 specificity와 무관하게
     자동으로 이긴다. 처음엔 여기 .cart-page { margin-top: 0 } 오버라이드를 따로 뒀는데,
     그게 오히려 site 레이어 *안에서* 이 규칙과 클래스 대 태그조합 specificity로 싸워
     0으로 밀어버리는 버그였다(CSS in Depth 8장 확인 — 같은 레이어 안에선 레이어가 아니라
     specificity가 결정한다). 다른 사이트 코드는 site 레이어가 없어 base 값(spacing-xl)이
     그대로 적용된다. */
  /* .l-checkout·.l-product·.sh-catalog(sections.css)는 애초에 margin-left/right: auto만
     선언해 세로 margin 자체를 안 갖는다 — body > main과 같은 레이어 안에서 아예 겨룰
     대상이 없게 만드는 방식(CSS in Depth 1장 "선택자 재설계"). .cart-page처럼 다른
     레이어의 값을 취소해야 하는 경우가 아니면 이 편이 더 단순하다. */
  .centered-box { padding-top: 0; padding-bottom: 0; }

  /* 페이지 폭 — body.sh-product·body.sh-checkout(sections.css)과 같은 --page-max
     메커니즘을 카트·주문확인에도 맞춘다(설계 논의 08-14). 이 둘만 그 메커니즘을 안 쓰고
     있었다 — 카트는 style.css(base 레이어)의 .cart-page가 720px을 하드코딩했고,
     주문확인(.centered-box)은 --page-max/폭 역할 토큰 체계 자체를 안 썼다.
     .cart-page 자체는 base 파일이라 다른 사이트도 쓰므로 여기서 site 레이어로만
     max-width를 var(--page-max, ...)로 다시 선언해 이 사이트에서만 메커니즘을 따르게
     한다(다른 사이트는 base의 하드코딩 720px 그대로 유지, 영향 없음). */
  body.sh-cart, body.sh-order { --page-max: var(--width-content); }
  .cart-page { max-width: var(--page-max, var(--width-wide)); }
  .centered-box { max-width: var(--page-max, var(--width-content)); margin-left: auto; margin-right: auto; }

  .sh-header { background: var(--color-bg-subtle); border-bottom: var(--border-width) solid var(--color-secondary); }
  /* 사이트 크롬은 본문 폭과 독립된 넓은 기준선을 유지한다. */
  .sh-header .head-in { display: flex; align-items: center; justify-content: space-between; height: 58px; max-width: var(--width-wide); margin: 0 auto; padding: 0 var(--spacing-lg); }
  /* 밑줄은 문장 안 링크의 표시다 — 블록을 감싸는 링크(로고·카트·상품 카드)는
     받지 않는다. UA 기본값이 그어 오던 것이라 규칙이 없어 보였을 뿐이다. */
  .sh-header .logo,
  .sh-header .head-cart,
  .sh-product-card { text-decoration: none; }

  .sh-header .logo { font-family: var(--font-family-heading); font-size: var(--m3-title-large-size); line-height: var(--m3-title-large-line); font-weight: var(--m3-title-large-weight); letter-spacing: var(--m3-title-large-tracking); color: var(--color-accent); }
  .sh-header .head-right { display: flex; align-items: center; gap: var(--spacing-md); }
  .sh-header .head-cart { position: relative; isolation: isolate; display: inline-flex; align-items: center; color: var(--color-accent); padding: var(--spacing-xs); }
  .sh-header .cart-badge { position: absolute; top: -3px; right: -5px; min-width: 17px; height: 17px; padding: 0 var(--spacing-xs); box-sizing: border-box; display: inline-flex; align-items: center; justify-content: center; background: var(--color-primary); color: var(--color-text-on-primary); font-size: var(--m3-label-small-size); line-height: var(--m3-label-small-line); font-weight: var(--m3-label-small-weight); letter-spacing: var(--m3-label-small-tracking); border-radius: var(--radius-full); }
  .sh-header .locale-switcher summary { position: relative; isolation: isolate; border: none; border-radius: 0; padding: var(--spacing-xs); background: none; color: var(--color-accent); font-size: var(--m3-title-small-size); line-height: var(--m3-title-small-line); font-weight: var(--m3-title-small-weight); letter-spacing: var(--m3-title-small-tracking); }
  /* base(components.css)의 summary:hover 회색 배경을 무효화한다 — 헤더는 hover를
     상태 층(아래 ::after)으로만 표현한다. 두 배경이 겹치면 상태 표현이 이중이 된다. */
  .sh-header .locale-switcher summary:hover { background: none; }
  .sh-header .locale-switcher-globe { opacity: 1; }
  .sh-header .locale-switcher-menu { border-color: var(--color-border); background: var(--color-bg); }

  /* 접촉 영역 48×48dp — 카트 링크·로케일 스위처 summary만 대상이다(로고는 접촉 영역
     결정에 없다). 보이는 크기(카트 아이콘 22px·로케일 요약 글자)는 그대로 두고 투명
     오버레이(::after)로 눌리는 범위만 넓힌다(css-guide 2-4절 수단 3). 오버레이가 실제
     클릭을 받는 것은 anchor/summary의 자손 노드라 부모의 클릭 영역으로 취급되기 때문이다
     — 레이아웃은 absolute라 흐름에 영향을 주지 않는다.
     같은 요소가 hover 상태 층(M3 규격 8%, css-guide 2-3절)의 배경도 겸한다 — 상태 층은
     기준 색(onSurface) 위에 얹는 배경 겹침 방식이며 hover 시에만 칠해진다(EN-060 5-3b).

     **접촉 영역과 상태 층은 크기가 다르다.** 규격에서 눌리는 범위는 손가락 기준 48이고
     상태 층은 부품 컨테이너 크기(icon-button·text-button 모두 container.height 40)를
     따른다 — Material Web 구현도 `.touch { height: max(48px, 100%) }`를 상태 층과 별개
     요소로 둔다. 둘을 한 박스로 합치면 손가락 기준 크기가 그대로 눈에 보여, 헤더 59px에
     48짜리 음영이 얹히는 형태가 된다(81%). 그래서 ::before가 접촉 48, ::after가 상태 40이다.

     둘 다 고정 크기가 아니라 **컨트롤을 덮되 최소 40/48**이다. 정사각 카트(30×30)에는
     고정값이 맞지만 로케일 요약은 글자가 들어가 가로 96이라, 고정을 씌우면 좌우가 남고
     상태 층도 긴 컨트롤 한가운데 원으로 뜬다.

     z-index는 콘텐츠 아래다 — 규격이 상태 층을 컨테이너 위·콘텐츠 아래에 둔다.
     host에 isolation을 걸어 음수 z가 헤더 배경 밑으로 내려가지 않게 가둔다. 접촉 영역이
     상태 층보다 먼저 칠해지도록 ::before에 둔다(둘 다 투명이라 순서는 시연 판에서만 보인다). */
  .sh-header .head-cart::before,
  .sh-header .locale-switcher summary::before,
  .sh-header .account-menu summary::before,
  .sh-header .account-menu-login::before {
    content: "";
    position: absolute;
    inset: 50%;
    width: 100%;
    height: 100%;
    min-width: 48px;
    min-height: 48px;
    transform: translate(-50%, -50%);
    z-index: -1;
  }
  .sh-header .head-cart::after,
  .sh-header .locale-switcher summary::after,
  .sh-header .account-menu summary::after,
  .sh-header .account-menu-login::after {
    content: "";
    position: absolute;
    inset: 50%;
    width: 100%;
    height: 100%;
    min-width: 40px;
    min-height: 40px;
    transform: translate(-50%, -50%);
    border-radius: var(--radius-full);
    z-index: -1;
  }
  .sh-header .head-cart:hover::after,
  .sh-header .locale-switcher summary:hover::after,
  .sh-header .account-menu summary:hover::after,
  .sh-header .account-menu-login:hover::after {
    background: var(--color-state-hover);
  }
  .sh-header .account-menu summary,
  .sh-header .account-menu-login { position: relative; isolation: isolate; border: none; border-radius: 0; padding: var(--spacing-xs); background: none; color: var(--color-accent); font-size: var(--m3-title-small-size); line-height: var(--m3-title-small-line); font-weight: var(--m3-title-small-weight); letter-spacing: var(--m3-title-small-tracking); }
  .sh-header .account-menu summary:hover,
  .sh-header .account-menu-login:hover { background: none; }
  .sh-header .account-menu-user { opacity: 1; }
  .sh-header .account-menu-dropdown { border-color: var(--color-border); background: var(--color-bg); }

  /* 배경을 --color-bg(흰색)에서 --color-bg-subtle로 바꿨다(헤더·페이지와 같은 값,
     EN-060 5-3b) — 상단 테두리가 페이지와의 유일한 경계가 되므로 유지한다. */
  .sh-footer { background: var(--color-bg-subtle); border-top: var(--border-width) solid var(--color-secondary); padding: var(--spacing-2xl) var(--spacing-lg); color: var(--color-text-muted); font-size: var(--m3-body-small-size); line-height: var(--m3-body-small-line); font-weight: var(--m3-body-small-weight); letter-spacing: var(--m3-body-small-tracking); }  /* 2026-08-15, 헤더 하단선(--color-secondary)과 통일 */
  /* 푸터는 base.html이 모든 페이지에 include하는 사이트 크롬이다. 그래서 안쪽 배치와
     링크 상태층까지 이 파일에서 완결한다 — sections.css는 페이지가 opt-in할 때만
     로드되어 로그인·내 공간에서는 푸터 규칙의 일부가 빠지는 경로가 생긴다. */
  .sh-footer-in {
    display: flex; flex-direction: column; align-items: center;
    gap: var(--spacing-md);
    width: 100%; /* body가 display:flex(세로)라 이게 없으면 콘텐츠 폭만큼 shrink-wrap된다 */
    max-width: var(--width-wide);
    margin: 0 auto;
    box-sizing: border-box;
  }

  /* 정책 링크 4개 — <nav>에 링크만 담은 블록이라 문장 안 링크가 아니다. */
  .sh-footer-links {
    display: flex; flex-wrap: wrap; align-items: center;
    gap: var(--spacing-xs) var(--spacing-lg);
  }
  .sh-footer-links a {
    position: relative; isolation: isolate;
    color: var(--color-accent); text-decoration: none;
    padding: var(--spacing-xs) 0;
  }

  /* 사업자등록·연락처 정보는 하나의 4열 grid를 공유해 두 행의 열을 맞춘다. */
  .sh-footer-info-grid {
    display: grid; grid-template-columns: repeat(4, auto);
    column-gap: var(--spacing-lg); row-gap: var(--spacing-xs);
  }
  .sh-footer-info-grid > div { display: flex; gap: var(--spacing-sm); align-items: baseline; }
  .sh-footer-info-grid .k { color: var(--color-text-muted); font-size: var(--m3-label-small-size); line-height: var(--m3-label-small-line); font-weight: var(--m3-label-small-weight); letter-spacing: var(--m3-label-small-tracking); white-space: nowrap; }
  .sh-footer-info-grid .k::after { content: ":"; }
  .sh-footer-info-grid .v { color: var(--color-accent); font-size: var(--m3-label-small-size); line-height: var(--m3-label-small-line); font-weight: var(--m3-label-small-weight); letter-spacing: var(--m3-label-small-tracking); font-variant-numeric: tabular-nums; white-space: nowrap; }
  /* 메일 주소는 라벨 뒤에 바로 오는 값이라 문장 안 링크 취급 — 밑줄 유지. */
  .sh-footer-info-grid .v a { color: var(--color-accent); text-decoration: underline; }

  /* 정책 링크의 접촉 영역(48dp)과 상태 층(40dp)은 헤더와 같은 방식이다. */
  .sh-footer-links a::before {
    content: "";
    position: absolute;
    inset: 50%;
    width: 100%;
    height: 100%;
    min-width: 48px;
    min-height: 48px;
    transform: translate(-50%, -50%);
    z-index: -1;
  }
  .sh-footer-links a::after {
    content: "";
    position: absolute;
    inset: 50%;
    width: 100%;
    height: 100%;
    min-width: 40px;
    min-height: 40px;
    transform: translate(-50%, -50%);
    border-radius: var(--radius-full);
    z-index: -1;
  }
  .sh-footer-links a:hover::after {
    background: var(--color-state-hover);
  }

  /* 문의 플로팅 2단 — 둥근 컬러 아이콘 버튼. 채팅(카톡)=녹색 위, 메일=적색 아래. 라벨은 접근성용. */
  .fab { position: fixed; right: 20px; z-index: var(--z-overlay); width: 52px; height: 52px; display: inline-flex; align-items: center; justify-content: center; padding: 0; border-radius: 50%; box-shadow: var(--shadow-md); transition: transform var(--m3-duration-short3), box-shadow var(--m3-duration-short3); cursor: pointer; border: none; }
  .fab:hover { transform: translateY(-2px); box-shadow: var(--shadow-lg); }
  .fab .icon { display: inline-flex; align-items: center; justify-content: center; color: var(--color-text-inverse); }
  .fab .icon svg { display: block; }
  .fab .label { position: absolute; width: 1px; height: 1px; padding: 0; margin: -var(--spacing-xs); overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0; }
  /* 세로 위치는 좌표가 아니라 관계식으로 쓴다 — 종전에는 페이지가 최종 좌표를 직접
     박았고(상품 페이지 86·144), 그래서 FAB 사이 간격이 페이지마다 12px·6px로 갈려
     있었다. 관계식이 하나면 갈릴 수 없다.
     max()의 두 항: 사이트 공통 최소 여백(--fab-inset-bottom)과, 바닥 점유분 위로 한 칸
     띄운 자리. 평상시엔 앞이 커서 전 페이지가 같은 높이에 서고, 고정 바가 최소 여백보다
     더 차지하면 그때만 뒤가 이겨 그 페이지의 FAB이 비켜난다.
     위 FAB은 아래 FAB의 지름(52px)과 간격(--spacing-md)만큼 더 올라간다. */
  .chat-fab, .kakao-fab {
    bottom: calc(env(safe-area-inset-bottom)
                 + max(var(--fab-inset-bottom), var(--anchor-bottom) + var(--spacing-xl)));
    background: var(--color-secondary);
  }
  .mail-fab {
    bottom: calc(env(safe-area-inset-bottom)
                 + max(var(--fab-inset-bottom), var(--anchor-bottom) + var(--spacing-xl))
                 + 52px + var(--spacing-md));
    background: var(--color-primary);
  }

  /* 메일 문의·채팅 모달 텍스트 — 표면(배경·라운드·폭)은 표준 .card/.modal-panel이 담당하고,
     여기는 그 안의 제목·부제 타이포만 잡는다(EN-071 모달 통합, 옛 .modal-box 표면 규칙은
     .card/.modal-panel/.input/.btn으로 대체되어 제거). */
  .modal-panel h3 { font-size: var(--m3-title-medium-size); line-height: var(--m3-title-medium-line); font-weight: var(--m3-title-medium-weight); letter-spacing: var(--m3-title-medium-tracking); margin: 0 0 var(--spacing-xs); }
  .modal-panel .sub { font-size: var(--m3-body-small-size); line-height: var(--m3-body-small-line); font-weight: var(--m3-body-small-weight); letter-spacing: var(--m3-body-small-tracking); color: var(--color-text-muted); margin: 0 0 var(--spacing-lg); }
  .modal-actions { display: flex; justify-content: flex-end; gap: var(--spacing-sm); }

  /* 채팅 패널 헤더 — 제목 좌측, 언어 스위처(헤더 로케일 스위처와 동일 부품, US-057) 우측.
     .modal-panel h3의 기본 margin-bottom을 여기서 0으로 눌러 한 줄 정렬을 유지한다. */
  .chat-panel-header { display: flex; align-items: center; justify-content: space-between; gap: var(--spacing-sm); margin: 0 0 var(--spacing-md); }
  .chat-panel-header h3 { margin: 0; }
  .chat-lang-switcher summary { padding: var(--spacing-xs) var(--spacing-sm); font-size: var(--m3-label-small-size); }

  /* 상담 채팅 메시지 — 발신자별 정렬·색 구분 (US-057). 내 메시지 우측·강조, 운영자 좌측·중립 */
  .chat-messages { display: flex; flex-direction: column; gap: var(--spacing-md); max-height: 320px; overflow-y: auto; margin-bottom: var(--spacing-md); padding: var(--spacing-xs) var(--spacing-xs); }
  .chat-message { display: flex; flex-direction: column; max-width: 78%; }
  .chat-message-label { font-size: var(--m3-label-small-size); line-height: var(--m3-label-small-line); font-weight: var(--m3-label-small-weight); letter-spacing: var(--m3-label-small-tracking); color: var(--color-text-muted); margin-bottom: var(--spacing-xs); }
  .chat-message-body { display: inline-block; padding: var(--spacing-sm) var(--spacing-md); border-radius: var(--radius-md); font-size: var(--m3-body-medium-size); line-height: var(--m3-body-medium-line); font-weight: var(--m3-body-medium-weight); letter-spacing: var(--m3-body-medium-tracking); white-space: pre-wrap; word-break: break-word; }
  .chat-message-buyer { align-self: flex-end; align-items: flex-end; }
  .chat-message-buyer .chat-message-body { background: var(--color-primary); color: var(--color-text-on-primary); border-bottom-right-radius: 3px; }
  .chat-message-seller { align-self: flex-start; align-items: flex-start; }
  .chat-message-seller .chat-message-body { background: var(--color-bg-subtle); color: var(--color-text); border: var(--border-width) solid var(--color-border); border-bottom-left-radius: 3px; }

  /* 채팅 첫 진입 안내 — 메시지가 없을 때만 중앙 표시 */
  .chat-empty-notice { display: flex; flex-direction: column; align-items: center; justify-content: center; text-align: center; gap: var(--spacing-xs); flex: 1; padding: var(--spacing-xl) var(--spacing-md); }
  .chat-empty-notice[hidden] { display: none; }
  .chat-empty-notice-title { font-size: var(--m3-title-medium-size); line-height: var(--m3-title-medium-line); font-weight: var(--m3-title-medium-weight); letter-spacing: var(--m3-title-medium-tracking); margin: 0; }
  .chat-empty-notice-body { font-size: var(--m3-body-small-size); line-height: var(--m3-body-small-line); font-weight: var(--m3-body-small-weight); letter-spacing: var(--m3-body-small-tracking); color: var(--color-text-muted); margin: 0; }
}
