/* Jayone Foods buyer catalog — brand per jayone-data-lab/brand/BRAND_GUIDE.md
   Design rules (2026-09-19, user request "design it like Walmart"): Walmart Brand Center *principles* on our own brand —
   no Walmart colors, fonts or assets. Read 2026-09-19: brand-identity/layout · brand-os · typography · color · brand-voice.
   · Brand OS "Less is more / Don't decorate / Keep it clean" — a container has to do a job. Shadows only on things that
     float over the page (drawers, quote bar, floating Filters button). Product cards have no frame; the photo sits on a tile.
   · Brand OS tiles ground an isolated product on a white page; frame radius = longest side ÷ 15 (240px tile → 16px).
   · Brand OS buttons are pills — no square buttons — in sentence case.
   · Typography: no all caps, no tracking, levels kept apart, few weights → 5 sizes, 2 weights.
   · Color: two text colors; strong color only where it means something (action · selection · focus); text contrast AAA.
   · Layout starts from a grid: one spacing scale, one page margin, one card gutter. */
:root {
  /* Brand — Jayone Corporate Identity */
  --green: #008A5E;        /* Primary, Pantone 3415 C — focus ring (4.4:1 on white, ≥3:1 for UI) */
  --green-d: #005C3F;      /* actions: white on it 8.1:1 (white on #008A5E is only 4.38:1 — r2 P1-1) */
  --green-dd: #00442F;     /* action hover */
  --green-s: #E3F2EA;      /* chosen filter / added (green-d on it 7.0:1) */
  --lime: #7AC143;         /* Secondary, Pantone 368 C — logo/print accent only, never a UI state (r8 P2-1) */
  /* Neutrals — two text colors */
  --ink: #111814;          /* text 18:1 */
  --ink-2: #4A5550;        /* secondary text 7.8:1 (AAA) */
  --ink-off: #8A948F;      /* rows with no results (inactive controls are exempt from contrast rules) */
  --line: #E1E6E3;
  --line-strong: #C9D1CD;
  --field: #8A948F;        /* text-field outline, 3.1:1 (WCAG 1.4.11) */
  --page: #FFFFFF;
  --surface: #FFFFFF;
  --tile: #F3F5F4;         /* photo tile — ink-2 on it 7.1:1 */
  --tile-hover: #E9EDEB;
  --hover: #EEF1EF;
  --warn: #7A5000;
  --warn-s: #FFF4DB;
  --error: #9B1C1C;
  /* Type — 5 sizes, 2 weights */
  --t-meta: 13px;
  --t-body: 15px;
  --t-lead: 17px;          /* also every text field: iOS Safari zooms into fields under 16px */
  --t-section: 20px;
  --t-title: 24px;
  /* Space — 4px steps */
  --s1: 4px; --s2: 8px; --s3: 12px; --s4: 16px; --s5: 24px; --s6: 32px; --s7: 48px;
  --margin: 24px;          /* page side margin (phones 16) */
  --search-h: calc(var(--s4) + 50px + var(--s3));   /* 고정된 검색줄 높이(여백 + 입력칸 48 + 테두리 2) = 결과 칸이 붙는 자리 */
  --gutter: 16px;          /* between cards */
  /* Shape */
  --r-pill: 999px;
  --r-tile: 16px;
  --r-field: 12px;
  --r-mini: 8px;
  /* Elevation — only for what floats over the page */
  --shadow-float: 0 8px 28px rgba(17, 24, 20, .18);
  --shadow-bar: 0 -4px 16px rgba(17, 24, 20, .08);
  --font: "acumin-pro", "Acumin Pro", "Source Sans 3", "Source Sans Pro", system-ui, -apple-system, "Segoe UI", sans-serif;
}

/* 🔴 author CSS (display:flex 등)가 hidden 속성을 이기면 "숨긴" 버튼이 계속 보인다(2026-09-18 검증 P0-1). */
[hidden] { display: none !important; }
* { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; }
html.modal-open { overflow: hidden; }
body { margin: 0; font-family: var(--font); font-size: var(--t-body); line-height: 1.4; color: var(--ink); background: var(--page); }
h1, h2, h3, strong, b { font-weight: 600; }
img { display: block; max-width: 100%; }
.wrap { max-width: 1320px; margin: 0 auto; padding: 0 var(--margin); }
.sr { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
.nowrap { white-space: nowrap; }
.skip { position: fixed; left: -999px; top: 8px; background: var(--surface); color: var(--green-d); font-weight: 600; text-decoration: none; border: 1px solid var(--line-strong); box-shadow: var(--shadow-float); padding: var(--s2) var(--s4); border-radius: var(--r-pill); z-index: 10; } /* 기본 파랑 밑줄이었다(r16 P2-4) */
.skip:focus { left: 8px; }
:focus-visible { outline: 3px solid var(--green); outline-offset: 2px; }

/* Header */
.top { background: var(--surface); border-bottom: 1px solid var(--line); }
.top-inner { display: flex; align-items: center; gap: var(--s5); min-height: 72px; }
.logo-home { display: inline-flex; flex: none; border-radius: var(--r-mini); }
.logo { height: 33px; width: auto; }
.top-title { border-left: 1px solid var(--line); padding-left: var(--s5); min-width: 0; }
.top-title h1 { margin: 0; font-size: var(--t-section); line-height: 1.2; }
.asof { margin: 2px 0 0; font-size: var(--t-meta); color: var(--ink-2); min-height: 1.4em; } /* 데이터 도착 전에도 자리 확보 — CLS */
.top-contact { margin-left: auto; font-size: var(--t-body); font-weight: 600; color: var(--green-d); text-decoration: none; padding: var(--s3) var(--s1); white-space: nowrap; }
.top-contact:hover { text-decoration: underline; }
.contact-line { margin: var(--s4) 0 0; font-size: var(--t-body); color: var(--ink-2); }
.contact-line a { color: var(--green-d); }

/* Search — a pill (Brand OS search UI). Only the search line is sticky; chips/filters pinned too took 25% of the screen (r2 P2).
   grid 자식은 기본 min-width:auto 라 줄이 폭을 밀어낸다(375 가로 넘침 75px) → minmax(0,1fr) */
.searchbar { position: sticky; top: 0; z-index: 6; background: var(--page); padding: var(--s4) 0 var(--s3); }
.search { display: flex; align-items: center; gap: var(--s3); background: var(--surface); border: 1px solid var(--field); border-radius: var(--r-pill); padding: 0 var(--s5) 0 var(--s4); color: var(--ink-2); }
.search:focus-within { outline: 3px solid var(--green); outline-offset: 1px; border-color: var(--green); }
.search input { flex: 1; min-width: 0; border: 0; outline: 0; background: transparent; font: inherit; font-size: var(--t-lead); color: var(--ink); min-height: 48px; }
.search input:disabled { opacity: .6; cursor: progress; }
/* 브라우저 기본값이 색 규칙을 비껴가지 않게(r16 P2-4): 안내문은 보조 글자색(WebKit 기본 1.7:1) · Chrome 검색 지우기 × 는 파랑 대신 보조색 */
input::placeholder, textarea::placeholder { color: var(--ink-2); opacity: 1; }
.search input::-webkit-search-cancel-button { -webkit-appearance: none; appearance: none; width: 16px; height: 16px; cursor: pointer;
  background: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M6 6l12 12M18 6 6 18' fill='none' stroke='%234A5550' stroke-width='2.2' stroke-linecap='round'/%3E%3C/svg%3E") center / 16px no-repeat; }
select.f-brand { font: inherit; font-size: var(--t-body); color: var(--ink); background: var(--surface); border: 1px solid var(--field); border-radius: var(--r-pill); min-height: 40px; width: 100%; padding: 0 36px 0 var(--s4); appearance: none; text-overflow: ellipsis;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8'%3E%3Cpath d='M1 1l5 5 5-5' fill='none' stroke='%234A5550' stroke-width='1.6'/%3E%3C/svg%3E");
  background-repeat: no-repeat; background-position: right 14px center; }
select.f-brand:focus-visible { outline: 3px solid var(--green); outline-offset: 1px; border-color: var(--green); }
#sheet-body select.f-brand { font-size: var(--t-lead); min-height: 44px; } /* phones: iOS zooms into a select under 16px */
.link { font: inherit; font-size: var(--t-body); background: none; border: 0; color: var(--green-d); text-decoration: underline; cursor: pointer; padding: var(--s2) var(--s1); min-height: 40px; }
.count { margin: 0; font-size: var(--t-body); font-weight: 600; color: var(--ink); min-height: 1.4em; }
.howto { margin: 0; max-width: 78ch; font-size: var(--t-meta); color: var(--ink-2); }   /* 첫 제품을 첫 화면 안으로 — 폰에서 3줄 63px 를 먹었다(r22 P1-1) */   /* 110자 한 줄은 읽기 나쁘다(r21 P2-3) */ /* 검색줄 아래 여백 12 */
.howto strong { color: var(--ink); }
/* 🔴 불러오는 동안은 목록·결과·푸터를 그리지 않는다 — 최종 높이는 데이터가 와야 알 수 있어서, 미리 그려 두면 채워지며
   아래를 밀어낸다(1280 CLS 0.136 실측). 처음 나타나는 요소는 '밀림'이 아니다. 검색줄·안내 줄은 고정 높이라 처음부터(CLS 0.155 실측). */
body.loading .rail, body.loading .results-head, body.loading #grid, body.loading .more-wrap, body.loading .foot { display: none; }
body.loading.failed .foot { display: block; }
main.wrap { min-height: 100vh; } /* 로딩 중 푸터가 화면 끝에 걸려 있다가 멀리 밀려나면 CLS 가 0.98 까지 뛴다(375 실측) */

/* Grid + cards — every card is the same height, whatever the photo */
.status { margin: var(--s7) 0; text-align: center; color: var(--ink-2); }
.status a { color: var(--green-d); } /* 404 안내의 카탈로그 링크 — 기본 파랑이 아니라 우리 링크색 */
.status-error { color: var(--error); display: flex; flex-wrap: wrap; gap: var(--s3); justify-content: center; align-items: center; }
/* ── 첫 화면(사용자 결정 2026-09-20) — 우리가 차려 주는 묶음: 신제품 · 인기 · 분류 타일 ── */
.home { padding: var(--s5) 0 var(--s2); }
.shelf { margin-bottom: var(--s7); }
.shelf-head { display: flex; align-items: baseline; justify-content: space-between; gap: var(--s4); }
.shelf-head h2 { margin: 0; font-size: var(--t-title); line-height: 1.2; }
.shelf-sub { margin: var(--s1) 0 0; font-size: var(--t-meta); color: var(--ink-2); }
.shelf-all { flex: none; }
.shelf-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(220px, 1fr)); gap: var(--s5) var(--gutter); margin-top: var(--s4); }
.tiles { display: grid; grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); gap: var(--s4); margin-top: var(--s4); }   /* 묶음 카드 거터와 같은 16px(r21 P2-11) */
.tile { display: flex; align-items: center; justify-content: space-between; gap: var(--s3); min-height: 56px; padding: 0 var(--s4);
  font: inherit; font-size: var(--t-body); text-align: left; color: var(--ink); background: var(--tile); border: 0; border-radius: var(--r-tile); cursor: pointer; }
.tile-n { flex: none; font-size: var(--t-meta); color: var(--ink-2); font-variant-numeric: tabular-nums; }
@media (hover: hover) { .tile:hover { background: var(--hover); } }
/* 좁은 화면일수록 묶음을 짧게 — 폰은 한 줄에 한 장이라 8장이면 '분류' 타일이 5,000px 아래로 밀렸다(실측 2026-09-20).
   나머지는 'See all' 로 간다. */
@media (max-width: 1100px) { .shelf-grid .card:nth-child(n+5) { display: none; } }
@media (max-width: 700px) {
  .shelf-grid .card:nth-child(n+3) { display: none; }
  /* 폰에서는 분류 타일이 먼저 — 묶음 두 개를 지나 내려가느라 타일까지 3~5번 스와이프했다(r21 P1-1) */
  .home { display: flex; flex-direction: column; }
  .shelf-cats { order: -1; }
}

.grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(220px, 1fr)); gap: var(--s5) var(--gutter); padding: var(--s3) 0 var(--s2); }   /* 첫 제품을 첫 화면 안으로(r22 P1-1) */
.group-h { grid-column: 1 / -1; display: flex; align-items: baseline; gap: var(--s2); margin: var(--s4) 0 calc(-1 * var(--s2)); font-size: var(--t-section); line-height: 1.2; }
.group-h:first-child { margin-top: 0; }
.group-n { font-size: var(--t-body); font-weight: 400; color: var(--ink-2); }
/* No card frame — the photo tile and the text beneath it make the card (Brand OS: don't decorate). */
.card { display: flex; flex-direction: column; min-width: 0; }
/* 카드 = <article> 안에 '열기' 버튼 + 별도 '담기' 버튼(버튼 안에 버튼은 못 넣는다) */
.card-open { position: relative; display: flex; flex-direction: column; flex: 1; width: 100%; min-width: 0; text-align: left; font: inherit; color: inherit; background: none; border: 0; padding: 0; cursor: pointer; border-radius: var(--r-tile); }
/* 포커스 테두리는 사진 위에 얹는 층으로 — 안쪽 outline 은 사진 칸이 덮어 글자 부분만 감쌌다(r9 P2-2). */
.card-open:focus-visible { outline: none; }
.card-open:focus-visible::after { content: ""; position: absolute; inset: 0; z-index: 2; border: 3px solid var(--green); border-radius: var(--r-tile); pointer-events: none; }
/* 🔴 사진 칸은 정사각형으로 고정 — 사진이 세로로 길거나 아직 안 불러와도 칸 크기가 변하지 않는다(검증 P0-2, CLS).
   multiply: 흰 배경 사진이 타일 색에 녹아 '사진 속 흰 네모'가 보이지 않는다. */
.ph { position: relative; aspect-ratio: 1 / 1; width: 100%; overflow: hidden; background: var(--tile); border-radius: var(--r-tile); }
.ph img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: contain; padding: var(--s4); mix-blend-mode: multiply; }
.ph-none { position: absolute; inset: 0; display: grid; place-items: center; padding: var(--s3); text-align: center; font-size: var(--t-meta); color: var(--ink-2); background: var(--tile); }
/* 🔴 <button> 카드 안쪽은 내용 폭에 끌려간다(375 실측: 카드 167px · 본문 190~195px → 이름이 단어 중간에서 잘림, 검증 r2 P1-2) */
.card-body { display: flex; flex-direction: column; gap: 2px; padding: var(--s3) var(--s1) var(--s2); flex: 1; width: 100%; min-width: 0; max-width: 100%; }
.brand { margin: 0; font-size: var(--t-meta); color: var(--ink-2); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.name { margin: 0; font-size: var(--t-body); line-height: 1.3; overflow-wrap: anywhere; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; height: 2.6em; }
/* 같은 제품의 여러 사이즈가 카드로 나란히 선다 — 카드를 가르는 건 사이즈라 굵은 한 줄로(사용자 결정 2026-09-18) */
.size { margin: var(--s1) 0 0; font-size: var(--t-body); font-weight: 600; color: var(--ink); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.case { margin: 0; font-size: var(--t-meta); color: var(--ink-2); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.sku { margin: 0; font-size: var(--t-meta); color: var(--ink-2); font-variant-numeric: tabular-nums; white-space: nowrap; }
.card-foot { display: flex; align-items: center; justify-content: space-between; gap: var(--s2); min-width: 0; padding: 0 var(--s1); }
.add { font: inherit; font-size: var(--t-body); font-weight: 600; color: var(--green-d); background: var(--surface); border: 1px solid var(--line-strong); border-radius: var(--r-pill); min-height: 40px; padding: 0 var(--s4); cursor: pointer; white-space: nowrap; }
.add[aria-pressed="true"] { background: var(--green-s); border-color: var(--green-d); }
/* 보관 표시 — 이모지가 아니라 선 아이콘, 색은 아이콘에만 살짝(사용자 피드백 2026-09-20).
   Dry = 밀봉 상자(중립색) · Chilled = 온도계(청록) · Frozen = 눈꽃(파랑). 글자색은 그대로 회색이라 화면이 알록달록해지지 않는다. */
.storage { display: inline-flex; align-items: center; gap: var(--s1); min-width: 0; font-size: var(--t-meta); color: var(--ink-2); white-space: nowrap; }
.storage svg { flex: none; color: var(--st-ink); }
.st-dry { --st-ink: var(--ink-2); }
.st-chilled { --st-ink: #2A7D6F; }   /* 4.9:1 on white */
.st-frozen { --st-ink: #1C6EA4; }    /* 5.4:1 on white */
.more-wrap { display: flex; justify-content: center; padding: var(--s5) 0 var(--s7); }
@media (hover: hover) {
  .card-open:hover .ph, .card-open:hover .ph-none { background: var(--tile-hover); }
  .card-open:hover .name { text-decoration: underline; }
  .add:hover { border-color: var(--green-d); }
}

/* Buttons — pills (Brand OS: no square buttons) */
.btn { display: inline-flex; align-items: center; justify-content: center; gap: var(--s2); font: inherit; font-size: var(--t-body); font-weight: 600; min-height: 44px; padding: 0 var(--s5); border-radius: var(--r-pill); cursor: pointer; text-decoration: none; white-space: nowrap; }
.btn.primary { background: var(--green-d); color: #fff; border: 1px solid var(--green-d); }
.btn.primary:hover { background: var(--green-dd); border-color: var(--green-dd); }
.btn.secondary { background: var(--surface); color: var(--ink); border: 1px solid var(--line-strong); }
.btn.secondary:hover { border-color: var(--green-d); color: var(--green-d); }
a.btn[aria-disabled="true"], .btn:disabled { opacity: .5; pointer-events: none; }
.icon-btn { display: grid; place-items: center; flex: none; width: 44px; height: 44px; border-radius: var(--r-pill); border: 0; background: transparent; color: var(--ink-2); cursor: pointer; }
.icon-btn:hover { background: var(--hover); color: var(--ink); }
.copy { font: inherit; font-size: var(--t-meta); font-weight: 600; color: var(--green-d); background: var(--surface); border: 1px solid var(--line-strong); border-radius: var(--r-pill); padding: 0 var(--s3); margin-left: var(--s2); cursor: pointer; min-height: 36px; }
.copy:hover { border-color: var(--green-d); }

/* Drawers — product detail, quote and filters share one frame on the right (user decision 2026-09-19):
   head (title + close) / body (scrolls) / foot (actions stay on screen). Desktop: the grid stays visible on the left. */
dialog { padding: 0; border: 0; color: var(--ink); background: var(--surface); overscroll-behavior: contain; }
dialog:focus, dialog:focus-visible { outline: none; } /* WebKit 은 창 자체에 초록 테두리를 그렸다(r6 P2-2) */
dialog::backdrop { background: rgba(17, 24, 20, .4); }
dialog.drawer { position: fixed; inset: 0 0 0 auto; margin: 0 0 0 auto; width: min(560px, 100vw); max-width: 100vw; height: 100vh; height: 100dvh; max-height: 100vh; max-height: 100dvh;
  border-radius: var(--r-tile) 0 0 var(--r-tile); box-shadow: var(--shadow-float); overflow: hidden; }
dialog.drawer[open] { display: flex; flex-direction: column; }
dialog.drawer.sheet { width: min(420px, 100vw); }
@keyframes drawer-in { from { transform: translateX(40px); opacity: 0; } to { transform: none; opacity: 1; } }
@keyframes backdrop-in { from { opacity: 0; } to { opacity: 1; } }
/* 서랍끼리 바뀔 때(.swap — 상세 → 견적)는 다시 미끄러져 들어오지 않는다: 내용만 바뀐다 */
dialog.drawer[open]:not(.swap) { animation: drawer-in .2s ease-out; }
dialog.drawer[open]:not(.swap)::backdrop { animation: backdrop-in .2s ease-out; }
@media (prefers-reduced-motion: reduce) { dialog.drawer[open], dialog.drawer[open]::backdrop { animation: none; } }
.drawer-head { flex: none; display: flex; align-items: center; justify-content: space-between; gap: var(--s3); min-height: 60px; padding: var(--s2) var(--s3) var(--s2) var(--s5); border-bottom: 1px solid var(--line); }
.drawer-kicker { margin: 0; min-width: 0; font-size: var(--t-body); color: var(--ink-2); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.drawer-body { flex: 1 1 auto; min-height: 0; overflow: auto; overscroll-behavior: contain; padding: var(--s5); overflow-wrap: anywhere; } /* 붙여 쓴 긴 이름이 옆으로 삐져나갔다(r17 P2-1) */
.drawer-foot { flex: none; border-top: 1px solid var(--line); background: var(--surface); padding: var(--s3) var(--s5); padding-bottom: calc(var(--s3) + env(safe-area-inset-bottom)); }
.l-heading { min-width: 0; }
.l-heading h2 { margin: 0; font-size: var(--t-section); line-height: 1.2; }
.l-sub { margin: 2px 0 0; font-size: var(--t-body); color: var(--ink-2); }

/* Product detail drawer — photo beside the name so the key specs are on screen when it opens: on a 1366×768 laptop a
   full-width photo left 1 of 11 spec rows visible (r16 P1-2). Phones stack a larger photo (the drawer is the whole screen). */
.drawer h2[tabindex="-1"]:focus { outline: none; } /* 마우스·손가락으로 열면 제목에 포커스(테두리 없음) — 키보드로 열면 닫기 버튼(r16 P2-3) */
/* 사진은 화면 높이가 허락하는 만큼 크게(240~288) — 카드 사진(229~255)보다 작으면 '크게 보기'가 안 됐다(r17 P2-2). 768 높이에서도 핵심 사양 6개는 첫 화면. */
.d-top { display: grid; grid-template-columns: clamp(120px, calc(100vh - 488px), 288px) minmax(0, 1fr); gap: var(--s5); align-items: start; }
.d-top.big { grid-template-columns: minmax(0, 1fr); }   /* 사진을 누른 상태: 서랍 폭 가득 */
.d-top.big .d-intro { order: 1; }   /* 이름·Item # 이 먼저 — 큰 사진에서도 어느 제품인지 보인다(r20 P1-1) */
.d-top.big .d-photo { order: 2; }
/* 노트북을 최대화하면 실제로 보이는 높이가 600~660px 뿐이다(r19 P1-1) — 그 창에서도 핵심 사양 8줄이 첫 화면에 오게
   위 여백을 줄이고, 사양표 첫 두 줄(Pack size·Units per case)과 겹치는 굵은 줄은 접는다. 사진은 눌러서 크게 본다. */
@media (min-width: 641px) and (max-height: 640px) {
  .drawer-body { padding-top: var(--s3); }
  .d-pack { display: none; }
  .d-zoom-t { display: none; }        /* 사진 칸이 작을 땐 표지도 작게 — 120px 타일의 15% 를 덮었다(r20 P2-6) */
  .d-zoom { padding: 0 var(--s2); }
}
.d-photo { position: relative; display: block; width: 100%; padding: 0; border: 0; background: none; font: inherit; color: inherit; cursor: zoom-in; }
.d-top.big .d-photo { cursor: zoom-out; }
.d-photo:focus-visible { outline: 3px solid var(--green); outline-offset: 2px; }
.d-zoom { position: absolute; right: var(--s2); top: var(--s2); display: inline-flex; align-items: center; gap: var(--s1); min-height: 36px; padding: 0 var(--s3);
  border-radius: var(--r-pill); background: var(--surface); border: 1px solid var(--line-strong); font-size: var(--t-meta); font-weight: 600; color: var(--green-d); }
/* 누를 수 있다는 반응을 다른 부품과 같게(r20 P2-1) */
@media (hover: hover) { .d-photo:hover .ph { background: var(--tile-hover); } .d-photo:hover .d-zoom { border-color: var(--green-d); } }
.d-intro { min-width: 0; }
.d-photo .ph img { padding: var(--s4); }
.d-brand { margin: 0; font-size: var(--t-body); color: var(--ink-2); }
.d-name { margin: var(--s1) 0 0; font-size: var(--t-section); line-height: 1.25; }
.d-brand[hidden] + .d-name { margin-top: 0; }
.d-pack { margin: var(--s2) 0 0; font-size: var(--t-lead); color: var(--ink-2); }
.d-pack strong { color: var(--ink); }
.d-item { margin: var(--s3) 0 0; font-size: var(--t-body); color: var(--ink-2); }
.d-item span { font-variant-numeric: tabular-nums; font-weight: 600; color: var(--ink); }
.specs { display: grid; grid-template-columns: minmax(0, 12em) minmax(0, 1fr); margin: var(--s4) 0 0; border-top: 1px solid var(--line); }
.specs dt, .specs dd { margin: 0; padding: 6px 0; border-bottom: 1px solid var(--line); font-size: var(--t-body); }   /* 8→6px: 타일 두 줄이 늘린 높이를 되찾는다 — 노트북(1366×600)에서 열자마자 'Pallet' 까지(r16 P1-2·r19 P1-1) */
.specs dt { color: var(--ink-2); padding-right: var(--s4); }
.specs dd { font-variant-numeric: tabular-nums; }
.specs dd.na { color: var(--ink-2); }
/* 숫자가 여럿인 사양(상자 치수·팔레트) = 숫자마다 이름표를 붙인 타일 세 칸(사용자 결정 2026-09-20, B안).
   한 줄 글자("9.8 × 7.87 × 9.4 in (L × W × H)")는 숫자와 뜻을 눈으로 짝지어야 했다. 타일은 이 두 줄에만 —
   나머지 사양은 값이 하나라 글자가 맞다(상자는 일을 할 때만). 값 굵게·이름표 보조색, 사진 타일과 같은 바탕색. */
.specs dd.stats { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 6px; padding: var(--s1) 0; }
.stat { display: flex; flex-direction: column; min-width: 0; padding: var(--s1) var(--s2); background: var(--tile); border-radius: var(--r-mini); line-height: 1.25; }
.stat b { font-weight: 600; }
.specs dt.has-stats { padding-top: calc(var(--s1) * 2); }   /* 이름을 타일 속 값 줄에 맞춘다(칸 여백 4 + 타일 여백 4) */
.stat-k { font-size: var(--t-meta); color: var(--ink-2); }
.d-actions { display: flex; flex-wrap: wrap; gap: var(--s3); }
.d-actions .btn { flex: 1 1 auto; }

/* Quote drawer */
.l-body { padding: var(--s2) var(--s5) var(--s4); }
.l-items { list-style: none; margin: 0; padding: 0; }
/* 사진 | 이름·품번 / 수량 | 빼기 — 서랍 폭(560)에선 이름이 한 줄에 더 들어가게 수량을 이름 아래로 */
.l-row { display: grid; grid-template-columns: 56px minmax(0, 1fr) auto; grid-template-areas: 'ph text rm' 'ph cases rm'; gap: var(--s2) var(--s3); align-items: center; padding: var(--s3) 0; border-bottom: 1px solid var(--line); }
.l-row .ph { grid-area: ph; align-self: start; border-radius: var(--r-mini); }
.l-row .ph img { padding: var(--s1); }
.l-row .ph-none { font-size: 0; } /* 56px 칸엔 문구가 안 들어간다 — 빈 타일만 */
.l-text { grid-area: text; min-width: 0; }
.l-name { margin: 0; font-size: var(--t-body); font-weight: 600; line-height: 1.3; }
.l-meta { margin: 2px 0 0; font-size: var(--t-meta); color: var(--ink-2); }
.l-cases { grid-area: cases; display: flex; align-items: center; gap: var(--s2); min-width: 0; font-size: var(--t-meta); color: var(--ink-2); }
.l-remove { grid-area: rm; }
.l-cases input { width: 132px; min-width: 0; font: inherit; font-size: var(--t-lead); color: var(--ink); min-height: 40px; padding: 0 var(--s3); border: 1px solid var(--field); border-radius: var(--r-field); }
.l-form { border: 0; margin: var(--s5) 0 0; padding: 0; display: grid; grid-template-columns: 1fr 1fr; gap: var(--s3) var(--s4); min-width: 0; }
.l-form legend { padding: 0; margin-bottom: var(--s2); font-size: var(--t-body); font-weight: 600; }
.l-opt { font-weight: 400; color: var(--ink-2); }
.l-form label { display: flex; flex-direction: column; gap: var(--s1); font-size: var(--t-meta); color: var(--ink-2); min-width: 0; }
.l-form input, .l-form textarea { font: inherit; font-size: var(--t-lead); color: var(--ink); min-height: 40px; padding: var(--s2) var(--s3); border: 1px solid var(--field); border-radius: var(--r-field); resize: vertical; width: 100%; }
.l-cases input:focus-visible, .l-form input:focus-visible, .l-form textarea:focus-visible { outline: 3px solid var(--green); outline-offset: 1px; border-color: var(--green); }
.l-wide { grid-column: 1 / -1; }
/* 2026-09-22 견적을 바로 보낸다 — 필수 칸이 비었으면 그 칸 밑에 말하고(빨강은 글자에만), 칸 테두리도 바꾼다 */
.l-err { font-size: var(--t-meta); color: var(--error); }
.l-form input[aria-invalid="true"] { border-color: var(--error); }
/* 로봇 덫: 화면·키보드·보조기기 어디에도 안 보이게(display:none 은 일부 로봇이 건너뛴다) */
.l-hp { position: absolute; left: -9999px; width: 1px; height: 1px; overflow: hidden; }
.l-note p { margin: 0; }
.l-note .link { padding: var(--s1) 0; min-height: 32px; font-size: inherit; color: var(--warn); }
.l-body .contact-line { margin-top: var(--s4); }
.l-actions { display: flex; flex-wrap: wrap; gap: var(--s2) var(--s4); align-items: center; }
/* 첫 줄 = 보내기 + PDF 카탈로그(버튼 — 검증관 r23 P1-3: 밑줄 글자 넷 중 하나로는 안 보였다), 둘째 줄 = 나머지 링크 셋 */
.l-more { display: flex; flex-wrap: wrap; align-items: center; gap: 0 var(--s3); flex: 1 1 100%; }
.l-pdf { padding: 0 var(--s4); }
/* 견적 막대 — 왼쪽 개수, 오른쪽 PDF 카탈로그 + Review & send. 폰은 버튼 셋이 안 들어가 PDF 는 개수 밑 링크(r23 P1-3) */
.lb-left { display: flex; flex-direction: column; align-items: flex-start; min-width: 0; }
.lb-acts { display: flex; align-items: center; gap: var(--s3); flex: none; }
.lb-pdf-m { display: none; }
.l-clear { margin-left: auto; }
.l-after { margin: 0 0 var(--s3); padding: var(--s2) var(--s3); border-radius: var(--r-mini); background: var(--green-s); font-size: var(--t-body); color: var(--ink); }
.l-after p { margin: 0; }
.l-after a { color: var(--green-d); }
.l-after .link { padding: var(--s1) 0; min-height: 32px; font-size: inherit; }
.l-note { margin: 0 0 var(--s3); font-size: var(--t-body); color: var(--warn); background: var(--warn-s); padding: var(--s2) var(--s3); border-radius: var(--r-mini); }
/* .seg = 글자 사이를 줄바꿈 안 되는 공백으로 채운 한 덩어리(app.js segs) — CSS nowrap 은 WebKit 에서 칸 밖으로 1~3px 삐져나왔다 */

/* Filters drawer (phones/tablets) */
.sheet-body { padding: var(--s3) var(--s5); }
.sheet-foot { display: flex; align-items: center; gap: var(--s4); }
.sheet-foot #f-apply { flex: 1; }

/* Quote bar — appears once a product is added */
.listbar { position: fixed; left: 0; right: 0; bottom: 0; z-index: 7; background: var(--surface); border-top: 1px solid var(--line); box-shadow: var(--shadow-bar); padding-bottom: env(safe-area-inset-bottom); }
.listbar-inner { display: flex; align-items: center; justify-content: space-between; gap: var(--s3); min-height: 64px; }
.listbar-text { margin: 0; font-size: var(--t-body); font-weight: 600; }
.selbar-acts { display: flex; align-items: center; gap: var(--s3); flex-wrap: wrap; justify-content: flex-end; }
/* 고르는 중인 카드 — 담기 버튼이 그 자리에서 체크 토글이 된다(자리·높이 그대로) */
.card.is-pick .add[aria-pressed="true"] { background: var(--green-s); border-color: var(--green-d); }
.card.is-pick .card-open { cursor: pointer; }
body.has-list { padding-bottom: 72px; } /* 막대가 푸터·Show more 를 가리지 않게 */
/* 고르는 중 막대는 폰에서 두세 줄이 된다 — 그만큼 아래 여백을 준다(r22 P1-3: 320 에서 푸터가 41px 가려졌다) */
body.picking { padding-bottom: 116px; }
@media (max-width: 430px) { body.picking { padding-bottom: 168px; } }
.toast { position: fixed; left: 0; right: 0; bottom: 0; z-index: 8; background: var(--ink); color: #fff; padding-bottom: env(safe-area-inset-bottom); }
/* 🔴 알림은 견적 막대를 덮지 않는다 — 덮으면 'Review & send' 가 10초 넘게 막힌다(검증관 r22 P0-1, 18/18 · 마우스를
   올려두면 타이머가 멈춰 13초 뒤에도 그대로였다). 막대가 있을 때만 그 위로 올린다. */
body.has-list .toast { bottom: 65px; }   /* 막대 64 + 위 테두리 1 */
body.has-list.has-toast { padding-bottom: 136px; }
.toast-inner { display: flex; align-items: center; justify-content: space-between; gap: var(--s3); min-height: 64px; }
.toast-text { margin: 0; font-size: var(--t-body); }
.toast .btn.secondary { background: transparent; color: #fff; border-color: rgba(255, 255, 255, .6); }
.toast .btn.secondary:hover { border-color: #fff; color: #fff; }
.toast :focus-visible { outline-color: #fff; } /* 어두운 알림 위 포커스 = 흰색(17:1). #7AC143 은 UI 상태색으로 쓰지 않는다(r8 P2-1) */
body.has-toast { padding-bottom: 72px; }

/* Footer */
.foot { border-top: 1px solid var(--line); background: var(--surface); padding: var(--s5) 0 var(--s6); }
.foot p { margin: 0 0 var(--s2); font-size: var(--t-meta); color: var(--ink-2); max-width: 900px; }

/* Filters — left list on desktop, "Filters" drawer on phones/tablets (사용자 결정 2026-09-18: 칩 20개+드롭다운 줄이 정신없었다) */
/* 🔴 칩 띠가 떠도 이 칸은 문서에서 움직이지 않는다(margin-top 으로 띠 높이를 상쇄):
   칩 띠가 이 칸 **위**에 있던 동안은 띠가 생기거나 높이가 달라질 때마다 왼쪽 목록이 42~74px 밀렸고,
   그때마다 스크롤로 되돌려야 했다(페이지가 맨 위·맨 아래면 되돌릴 수도 없어 누른 줄이 32~74px 도망갔다
   — 게이트 rail-stable, 2026-09-20).
   이제 칩 띠는 결과 칸의 위 여백 자리에 **얹혀서** 뜨고(아래 .results padding-top), 왼쪽 목록은 아예 안 건드린다. */
.layout { display: grid; grid-template-columns: 224px minmax(0, 1fr); gap: var(--s6); align-items: start; padding-top: var(--s3); margin-top: calc(-1 * var(--subs-h, 0px)); } /* margin 이면 로딩 중(검색줄 숨김) main 밖으로 겹쳐 빠져 12px 밀림(CLS 0.159 실측) */
/* 목록은 페이지와 함께 흐른다(고정·높이 제한·안쪽 스크롤 없음). 안쪽 스크롤은 노트북(1366×768)에서 분류 17개 중 11개를
   표시 없이 숨겼고(r13 P1-1), 고정은 페이지 끝에서 검색줄 밑으로 밀려 들어갔다(r12 P2-1). 목록이 화면 밖이면 떠 있는 Filters.
   🔴 줄은 숨기지 않는다 — 결과 0개는 제자리에 흐리게(사용자 피드백 2026-09-19: 숨기면 누른 버튼 밑에서 목록이 36~72px 튀었다). */
.rail { grid-column: 1; grid-row: 1; padding: 0 0 var(--s4); }   /* DOM 에선 결과 뒤 — 자리만 왼쪽(r21 P1-6) */
.f-sec { padding: 0 0 var(--s4); }
.f-sec + .f-sec { border-top: 1px solid var(--line); padding-top: var(--s4); }
.f-h { margin: 0 0 var(--s2); font-size: var(--t-body); color: var(--ink); }
.f-cats { display: flex; flex-direction: column; gap: 2px; }
.f-cat { display: flex; align-items: center; justify-content: space-between; gap: var(--s3); width: 100%; min-height: 36px; padding: 0 var(--s3); font: inherit; font-size: var(--t-body); text-align: left; color: var(--ink); background: none; border: 0; border-radius: var(--r-pill); cursor: pointer; }
.f-cat[aria-pressed="true"] { background: var(--green-s); color: var(--green-d); font-weight: 600; }
.f-cat:disabled { color: var(--ink-off); cursor: default; }
.f-n { flex: none; min-width: 5ch; text-align: right; font-size: var(--t-meta); font-weight: 400; color: var(--ink-2); font-variant-numeric: tabular-nums; }
/* 🔴 개수 칸의 너비를 고정한다 — 개수가 '1,227' 에서 '3' 으로 바뀌면 이름 칸이 넓어져 긴 이름('Dumplings, Buns & Bakery')이
   한 줄로 붙고 그 줄이 6px 낮아지며 **아래 줄들이 밀렸다**(2026-09-20 실측). 필터 줄은 무엇을 눌러도 제자리여야 한다. */
.f-cat[aria-pressed="true"] .f-n { color: var(--green-d); }
.f-cat:disabled .f-n, .f-check.is-off .f-n { color: var(--ink-off); }
.f-check { display: flex; align-items: center; gap: var(--s3); min-height: 36px; padding: 0 var(--s3); font-size: var(--t-body); border-radius: var(--r-pill); cursor: pointer; }
.f-check input { flex: none; width: 18px; height: 18px; margin: 0; accent-color: var(--green-d); }
.f-check .f-n { margin-left: auto; }
.f-check.is-off { color: var(--ink-off); cursor: default; }
/* 소분류 = 결과 머리 바로 밑 칩 줄(검증관 r21 P0-1: 왼쪽 목록 아래 칸은 실사용 창 크기 전부에서 화면 밖이었다).
   데스크톱은 줄바꿈해 전부 보인다 — 가로 스크롤로 숨기지 않는다.
   🔴 띠는 **결과 칸의 위 여백 자리에 얹혀서** 뜬다(.layout 의 음수 margin-top + .results 의 padding-top):
   분류마다 띠 높이가 42~106px 로 달라지는데, 띠가 왼쪽 목록까지 밀던 동안은 그 차이가 그대로 목록의 움직임이 됐다
   (게이트 rail-stable 2026-09-20: 누른 줄 32~74px 도망 · 스크롤로 되돌리면 이번엔 누른 줄이 띠 뒤로 숨음).
   이제 띠 높이는 **결과 칸 안에서만** 뜻을 가진다 — 왼쪽 목록·페이지 위치는 띠와 무관하다. */
.subs { position: sticky; top: var(--search-h); z-index: 5; display: flex; flex-wrap: wrap; gap: 2px var(--s2);
  padding: var(--s1) 0 var(--s2); background: var(--page); }
/* 폰·태블릿(터치)에서는 칩이 열 줄까지 쌓여 400px(768 에선 138px)를 먹었다 — 한 줄로 두고 손가락으로 옆으로 넘긴다.
   높이가 42px 로 고정되니 위의 '띠 높이 고정' 문제도 같이 사라진다(문서 가로 스크롤은 생기지 않는다). */
@media (max-width: 1099px) {
  .subs { flex-wrap: nowrap; overflow-x: auto; min-height: 0; scrollbar-width: none; -webkit-overflow-scrolling: touch; }
  .subs::-webkit-scrollbar { display: none; }
  .sub-chip { flex: none; }
}
/* 🔴 relative 가 필요하다: 칩 안의 보조기기용 글자(.sr)는 position:absolute 라, 자리 기준이 칩이 아니면
   옆으로 넘기는 칩 줄(폰)을 **빠져나가** 문서를 1,424px 넓혔다(게이트 가로 넘침, 폰 4폭 × 7상태, 2026-09-20).
   폭 641~700px 에서만 안 걸린 이유 = 그 폭에선 .subs 가 sticky(=자리 기준)라 칩 줄이 도로 가둔 것. */
/* 🔴 굵기는 고르든 안 고르든 같다(600): 고른 칩만 굵게 하면 그 칩이 넓어지며 **누른 칩이 손 밑에서 1~2px**,
   430px 에서는 줄바꿈이 바뀌어 **193px** 옆으로 갔다(검증관 r22 P2-10 · 게이트 chip-stable 20/20).
   고른 표시는 초록 배경 + 진한 초록 글자로 — 왼쪽 목록·알약과 같은 방식이다. */
.sub-chip { position: relative; display: inline-flex; align-items: center; gap: var(--s2); min-height: 30px; padding: 0 var(--s3);
  font: inherit; font-size: var(--t-meta); font-weight: 600; color: var(--ink); background: var(--tile); border: 0; border-radius: var(--r-pill); cursor: pointer; }
.sub-chip[aria-pressed="true"] { background: var(--green-s); color: var(--green-d); }
.sub-chip[aria-pressed="true"] .sub-n { color: var(--green-d); }
.sub-chip:disabled { color: var(--ink-off); cursor: default; }
.sub-n { font-size: var(--t-meta); color: var(--ink-2); font-variant-numeric: tabular-nums; }
@media (hover: hover) { .sub-chip:not(:disabled):not([aria-pressed="true"]):hover { background: var(--tile-hover); } }

@media (hover: hover) { .f-cat:not(:disabled):not([aria-pressed="true"]):hover, .f-check:not(.is-off):hover { background: var(--hover); } }
.results { grid-column: 2; grid-row: 1; min-width: 0; padding-top: var(--subs-h, 0px); }   /* 칩 띠가 얹힐 자리 */ /* 불러오는 동안 왼쪽 목록이 없어도 오른쪽 칸에 선다 */
/* 지금 보고 있는 것 — 위치(Home › …) · 제목 · 한 줄 설명. 프리셋으로 들어온 바이어가 화면을 오해하지 않게(r21 P1-5) */
.crumbs { display: flex; align-items: center; gap: var(--s2); min-height: 24px; font-size: var(--t-meta); color: var(--ink-2); }
.crumbs .link { min-height: 24px; }
.crumb-sep { color: var(--ink-off); }
.res-title { flex: none; margin: 0; font-size: var(--t-section); line-height: 1.2; }   /* 머리줄 한 줄 안에서 가장 큰 글자 */
.res-sub { margin: 0 0 var(--s2); font-size: var(--t-meta); color: var(--ink-2); }
.results-head { display: flex; flex-wrap: wrap; align-items: center; gap: var(--s2) var(--s3); min-height: 48px; padding-bottom: var(--s3); border-bottom: 1px solid var(--line); }
.pills { display: flex; flex-wrap: wrap; gap: var(--s2); }
.pills:empty { display: none; }
.pill { display: inline-flex; align-items: center; gap: var(--s1); font: inherit; font-size: var(--t-body); font-weight: 600; color: var(--green-d); background: var(--green-s); border: 1px solid transparent; border-radius: var(--r-pill); min-height: 32px; padding: 0 var(--s3); cursor: pointer; }
.pill:hover { border-color: var(--green-d); }
.pill-x { font-size: var(--t-lead); line-height: 1; }
.reset { padding-left: 0; padding-right: 0; }
/* 여러 개 고르기의 입구('Select products')와 누른 뒤의 'Select all N' = 머리줄 오른쪽 끝의 같은 자리 버튼.
   🔴 사용자 피드백 2026-09-21(바이어 관점): 'Select several' 밑줄 글자는 'Clear all' 옆 보조 링크로 보여 못 찾았다 —
   게이트 search-select 가 '버튼으로 보이는가(밑줄 없음·테두리·40px)'와 '첫 화면 안'을 본다. */
.pick-btn { margin-left: auto; min-height: 40px; padding: 0 var(--s4); }
.pick-btn svg { flex: none; }
/* 폰: 'Select products' 가 한 줄을 따로 차지해 첫 제품이 48px 밀렸다 — 글자를 'Select' 로 접어 개수 줄에 같이 둔다(이름은 aria-label 로 온전히) */
@media (max-width: 640px) { .pick-more { display: none; } }
.filters-btn { display: none; gap: var(--s2); min-height: 40px; padding: 0 var(--s4); }
.filters-n { display: inline-grid; place-items: center; min-width: 20px; height: 20px; padding: 0 var(--s1); border-radius: var(--r-pill); background: var(--green-d); color: #fff; font-size: var(--t-meta); font-weight: 600; }
.fab { position: fixed; left: 50%; transform: translateX(-50%); bottom: calc(16px + env(safe-area-inset-bottom)); z-index: 7; display: inline-flex; align-items: center; gap: var(--s2); min-height: 44px; padding: 0 var(--s5); font: inherit; font-size: var(--t-body); font-weight: 600; color: #fff; background: var(--ink); border: 0; border-radius: var(--r-pill); box-shadow: var(--shadow-float); cursor: pointer; }
.fab .filters-n { background: #fff; color: var(--ink); }
body.has-list .fab, body.has-toast .fab { bottom: calc(80px + env(safe-area-inset-bottom)); } /* 견적 막대·Undo 알림 위로 */
/* 데스크톱: 목록이 지나간 왼쪽 빈 칸에 띄운다 — 가운데는 카드 글자·Add 버튼을 가렸다(r14 P2-2). 왼쪽 칸 = .wrap 안쪽 시작점 */
@media (min-width: 1100px) {
  /* 결과 칸은 검색줄(+칩 띠) 밑에 붙어 따라온다 — 왼쪽 목록을 누른 뒤 새 결과가 누른 줄 옆 화면 안에 선다(r17 P1-1).
     결과가 목록보다 길면 칸이 이미 꽉 차 붙을 여지가 없어 평소처럼 스크롤된다.
     🔴 이걸 걷어냈다가 되돌렸다(2026-09-20): 걷어낸 채로는 짧은 분류를 목록 아래쪽에서 누르면 볼 게 없어
     "결과의 처음으로" 규칙이 걸리고 **누른 줄이 418~782px 도망갔다**(게이트 rail-stable 47/101·laptop 50/101).
     r22 P1-2 의 칩 끌림은 sticky 탓이 아니라 **칩 줄이 이 칸 안에 있던 것** 탓이었다 → 칩은 이제 칸 밖(#subs).
     붙는 자리에 칩 띠 높이를 더한다(--subs-h, app.js 가 채운다) — 안 더하면 띠가 제목을 덮는다. */
  .results { position: sticky; top: var(--search-h); }   /* 띠 자리는 padding-top 이 맡는다 */
  .subs { margin-left: calc(224px + var(--s6)); }   /* 띠는 결과 칸 위에만 — 전체 폭이면 왼쪽 목록 줄이 띠 뒤로 숨었다(실측 2026-09-20) */
  .fab { left: max(24px, calc((100% - 1320px) / 2 + 24px)); transform: none; bottom: 24px; }
  body.has-list .fab, body.has-toast .fab { bottom: 88px; }
}
@media (max-width: 1099px) { /* 왼쪽 목록은 1100px 부터 — 960~1011 에선 카드가 2열로 좁아졌다(r12 P2-3) */
  .layout { grid-template-columns: minmax(0, 1fr); gap: 0; }
  .results { grid-column: 1; }
  .rail { display: none; }
  .filters-btn { display: inline-flex; }
}

/* Tab 으로 닿는 것들은 고정 검색줄 아래에 서게 한다 — 검색줄이 고정인 폭(641 이상) 전체에(r19 P2-4) */
@media (min-width: 641px) {
  .card-open, .add, #more, .rail .f-cat, .sub-chip, .rail .f-check, .rail select, .results-head button, #q {
    scroll-margin-top: calc(var(--search-h) + var(--subs-h, 0px) + var(--s2));   /* 칩 띠까지 피해서 — 안 더하면 Tab 으로 닿은 줄이 띠 뒤에 숨는다 */
  }
}

/* Phones — controls scroll away with the page so results get the screen */
@media (max-width: 640px) {
  :root { --margin: 16px; }
  .top-inner { min-height: 60px; gap: var(--s3); }
  .logo { height: 26px; }
  .top-title { padding-left: var(--s3); }
  .top-title h1 { font-size: var(--t-lead); }
  /* 🔴 폰 머리글은 두 줄 — 1줄: 로고·제목·연락처 / 2줄: 기준 시각(전체 폭). 한 줄에 다 넣으면 'Contact us' 가
     기준 시각 글자를 덮었다(검증 r4 P0-1: 375 78px · 390 67px · 412 43px · 430 27px 겹침). */
  .top-inner { display: grid; grid-template-columns: auto minmax(0, 1fr) auto; grid-template-areas: 'logo title contact' 'asof asof asof'; column-gap: var(--s3); row-gap: 2px; align-items: center; padding-top: var(--s3); padding-bottom: var(--s3); } /* 좌우는 .wrap 의 16px 그대로(r5 P1-1: 'padding:10px 0' 이 덮어써 양 끝에 붙었다) */
  .logo-home, .logo { grid-area: logo; }   /* 로고를 링크로 감싼 뒤 자리 지정이 img 에만 걸려 깨졌다(r21 P2-10) */
  .top-title { display: contents; }
  .top-title h1 { grid-area: title; border-left: 1px solid var(--line); padding-left: var(--s3); min-width: 0; }
  .asof { grid-area: asof; margin: 0; }
  .top-contact { grid-area: contact; }
  .searchbar { position: static; margin: 0; padding: var(--s3) 0 0; } /* 머리글 선에 붙어 얹혀 보였다(r16 P2-5) */
  /* 검색줄이 고정이 아니면 칩 띠의 고정 기준(78px)도 뜻이 없다 — 그대로 두면 띠가 화면 중간에 떠서 검색줄과 겹쳐
     칩을 누를 수 없었다(게이트 subcategory@좁은폭, 2026-09-20). 좁은 폭에서는 칩도 흐름대로 둔다. */
  .subs { position: static; padding-bottom: var(--s1); }
  .search { gap: var(--s2); padding: 0 var(--s3); } /* 375: 알약 안쪽 여백 24 면 안내 문구 끝 'UPC' 가 잘렸다 */
  /* 폰: 첫 제품 이름을 첫 화면 안으로 — 아이폰(WebKit)은 머리줄이 37px 더 높아 430·390 에서 1~5px 다달았다(게이트 first-product, 2026-09-20) */
  .howto { margin-top: var(--s2); }
  .grid { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--s5) var(--s3); padding-top: var(--s1); }
  .card-body { padding: var(--s2) 2px; }
  .card-foot { padding: 0; }
  .storage-t { display: none; }   /* 폰: 자리가 없어 글자만 접는다 — 보관 표시 자체는 아이콘으로 남는다 */
  .add { flex: 1; font-size: var(--t-meta); padding: 0 var(--s2); }
  .listbar-inner { min-height: 60px; }
  body.has-list .toast { bottom: 61px; }
  body.has-list.has-toast { padding-bottom: 132px; }
  dialog.drawer, dialog.drawer.sheet { width: 100vw; border-radius: 0; } /* 421~440px 에서 420 시트만 왼쪽에 틈(r16 P2-2) */
  .d-top { grid-template-columns: minmax(0, 1fr); gap: var(--s4); }
  .d-photo .ph { aspect-ratio: 4 / 3; }
  .d-top.big .d-photo .ph { aspect-ratio: 1 / 1; }
  .d-photo .ph img { padding: var(--s5); }
  .drawer-head { padding-left: var(--s4); }
  .drawer-body { padding: var(--s4); }
  .drawer-foot { padding: var(--s3) var(--s4); padding-bottom: calc(var(--s3) + env(safe-area-inset-bottom)); }
  .sheet-body { padding: var(--s3) var(--s4); }
  .l-body { padding: var(--s2) var(--s4) var(--s3); }
  .l-row { grid-template-columns: 48px minmax(0, 1fr) auto; }
  .l-form { grid-template-columns: 1fr; }
  .l-actions { column-gap: var(--s2); }
  .l-actions #l-send { flex: 1 1 auto; }   /* 보내기와 PDF 가 한 줄 — PDF 는 'PDF' 로 줄인다 */
  .pdf-more { display: none; }
  .lb-long, .lb-pdf { display: none; }
  .lb-pdf-m { display: inline-flex; align-items: center; min-height: 24px; padding: 0; font-size: var(--t-meta); }
  .l-after, .l-note { font-size: var(--t-meta); }
  /* 링크 줄이 좁은 폰에서 두 줄로 접히지 않게 간격만 줄인다(글자 크기는 그대로) */
  .l-more { gap: 0 var(--s2); }
  .l-more .link { padding-left: 0; padding-right: 0; }
}
/* 아주 좁은 폰(iPhone SE 320) — 기준 시각 문장이 한 덩어리로 38px 넘쳤다(r3 P2-5) */
@media (max-width: 360px) {
  /* 320: 이름 2줄이면 맛·종류가 잘려 서로 다른 제품이 같은 카드처럼 보였다(17묶음, r12 P2-5) — 3줄 */
  .name { -webkit-line-clamp: 3; height: 3.9em; font-size: var(--t-meta); }
  .nowrap { white-space: normal; }
  .top-contact { display: none; }
  /* 320: 세 링크 260px > 256px 라 Clear quote 가 따로 한 줄(r8 P2-3) — 간격은 폰 규칙, 여기선 글자만 줄인다 */
  .l-more .link { font-size: var(--t-meta); }
  .specs { grid-template-columns: minmax(0, 1fr); }
  .specs dt { border-bottom: 0; padding-bottom: 0; }
  .specs dd { padding-top: 2px; }
}
/* 폰: 타일 세 칸은 값 칸(≈180px)에 안 들어간다 — 글자가 'Lengt/h' 로 쪼개졌다(시안 실측 390px).
   타일 줄만 이름 밑으로 내려 표 전체 폭을 쓴다. */
@media (max-width: 640px) {
  .specs dt.has-stats { grid-column: 1 / -1; border-bottom: 0; padding-bottom: 0; }
  .specs dd.stats { grid-column: 1 / -1; padding-top: var(--s2); }
}
