/* /shared/ui/tokens.css */
/* Size-adjusted local fallbacks so the swap to web fonts does not shift layout. */
@font-face { font-family: 'Plex KR Fallback'; src: local('Apple SD Gothic Neo'), local('Malgun Gothic'), local('Noto Sans KR'), local('NanumGothic'); size-adjust: 98%; ascent-override: 102%; descent-override: 26%; }
@font-face { font-family: 'Plex Mono Fallback'; src: local('Menlo'), local('Consolas'), local('DejaVu Sans Mono'); size-adjust: 100%; }
@font-face { font-family: 'Sign Fallback'; src: local('Arial Narrow'), local('Roboto Condensed'), local('Helvetica Neue'); size-adjust: 92%; }

/* ui/tokens.css — design tokens shared by customer, admin and dev.
   Visual language: off-white paper, ink, warm-gray heat, ONE yellow accent that
   means "places to stop / the route" and nothing else. Hairlines, not cards.
   Light by default; a designed dark theme follows the phone setting or the header toggle
   (client 2026-11-14) — html[data-theme] wins over prefers-color-scheme.
   Contrast: --ink-2 and --ink-3 on --paper ≥ 4.5:1 in both themes.
   --inv/--on-inv = the "black plate" surfaces (badges, sign, selected); --on-stop = text on yellow. */
:root {
  --paper: #FFFFFF;
  --white: #FFFFFF;
  --ink: #111111;
  --ink-2: #3D3D3D;
  --ink-3: #636363;      /* secondary text, 5.9:1 on paper */
  --ink-4: #8A8A8A;      /* disabled / decorative only, never body text */
  --line: #EEEEEB;
  --line-2: #E1E0DB;
  --edge: #C4C7C3;       /* structural outlines (fields, walls, line buttons): soft, never black */
  --heat-0: #F5F5F2;
  --heat-1: #E9E7E1;
  --heat-2: #D5D1C7;
  --heat-3: #6E695E;     /* heatmap "많이 붐빔"; white text on it = 5.6:1 */
  --stop: #FFD21F;       /* the only accent */
  --focus: #111111;
  --aisle: #F6F7F5;      /* floor-plan aisles: a breath off white */
  --heat-bar-0: #CFE5D6;  /* hour strip 한산 (soft pharmacy green) */
  --heat-bar-1: #8FC2A1;  /* 보통 */
  --heat-bar-2: #4F9A6C;  /* 붐빔 */
  --inv: #111111;
  --on-inv: #FFFFFF;
  --on-inv-2: rgba(255, 255, 255, .78);
  --on-stop: #111111;
  --bay-fill: rgba(255, 255, 255, .55);
  --glass: rgba(255, 255, 255, .94);
  color-scheme: light;
  --hl-mark: inset 0 -0.38em 0 var(--stop); /* search-match mark; the customer app overrides it (yellow = route there) */

  --font-sans: 'IBM Plex Sans KR', 'Plex KR Fallback', system-ui, -apple-system, 'Apple SD Gothic Neo', 'Malgun Gothic', sans-serif;
  --font-mono: 'IBM Plex Mono', 'Plex Mono Fallback', ui-monospace, 'SFMono-Regular', Menlo, monospace;
  --font-sign: 'Barlow Condensed', 'Sign Fallback', 'IBM Plex Sans KR', sans-serif;

  /* Fluid type: min at 280px, max at 1240px */
  --fs-12: 0.75rem;
  --fs-13: 0.8125rem;
  --fs-14: 0.875rem;
  --fs-15: 0.9375rem;
  --fs-16: 1rem;
  --fs-18: clamp(1rem, 0.95rem + 0.3vw, 1.125rem);
  --fs-22: clamp(1.1875rem, 1.1rem + 0.45vw, 1.375rem);
  --fs-28: clamp(1.375rem, 1.2rem + 0.9vw, 1.75rem);
  --fs-hero: clamp(3.75rem, 2.6rem + 6vw, 6rem);

  --lh-tight: 1.25;
  --lh: 1.55;
  --track: -0.012em;

  --space-1: 4px;
  --space-2: 8px;
  --space-3: 12px;
  --space-4: 16px;
  --space-5: 24px;
  --space-6: 32px;
  --space-7: 48px;
  --gutter: clamp(12px, 4vw, 20px);
  --maxw: 1240px;
  --tap: 44px;

  /* radii (benchmark scale): sheets/drawers 16 · buttons/inputs 10 · tags 6 · chips 99 */
  --r-16: 16px;
  --r-10: 10px;
  --r-6: 6px;
  --r-99: 99px;

  /* semantic colours + 13% tint pairs (text on tint keeps ≥ 4.5:1) */
  --ok: #1E6B3A;
  --ok-t: rgba(30, 107, 58, .13);
  --warn: #7A5300;
  --warn-t: rgba(255, 210, 31, .30);
  --danger: #B3261E;
  --danger-t: rgba(179, 38, 30, .13);

  --dur: 160ms;
  --dur-2: 240ms;
  --draw: 900ms;
  --grow: 600ms;         /* signature: the route redraws when it grows */
  --ease: cubic-bezier(.2, .8, .2, 1);

  --safe-top: env(safe-area-inset-top, 0px);
  --safe-bottom: env(safe-area-inset-bottom, 0px);
  --safe-left: env(safe-area-inset-left, 0px);
  --safe-right: env(safe-area-inset-right, 0px);
}

/* dark (customer site only: html.themable): explicit choice, or the phone setting */
:root.themable[data-theme="dark"] {
  --paper: #111412;
  --white: #1A1E1B;
  --ink: #ECEEEA;
  --ink-2: #C8CCC6;
  --ink-3: #A0A59E;      /* 6.9:1 on paper */
  --ink-4: #6F756E;
  --line: #242925;
  --line-2: #2E3430;
  --edge: #48504A;
  --heat-0: #1E2320;
  --heat-1: #29302B;
  --heat-2: #39413B;
  --heat-3: #9AA39B;
  --focus: #ECEEEA;
  --aisle: #161A17;
  --heat-bar-0: #24412F;
  --heat-bar-1: #2F7049;
  --heat-bar-2: #5CC285;
  --inv: #2B312D;
  --on-inv: #FFFFFF;
  --bay-fill: rgba(255, 255, 255, .04);
  --glass: rgba(26, 30, 27, .94);
  --ok: #6FD08F;
  --ok-t: rgba(111, 208, 143, .14);
  --warn: #FFD866;
  --danger: #FF8A80;
  --danger-t: rgba(255, 138, 128, .14);
  color-scheme: dark;
}
@media (prefers-color-scheme: dark) {
  :root.themable:not([data-theme="light"]) {
  --paper: #111412;
  --white: #1A1E1B;
  --ink: #ECEEEA;
  --ink-2: #C8CCC6;
  --ink-3: #A0A59E;      /* 6.9:1 on paper */
  --ink-4: #6F756E;
  --line: #242925;
  --line-2: #2E3430;
  --edge: #48504A;
  --heat-0: #1E2320;
  --heat-1: #29302B;
  --heat-2: #39413B;
  --heat-3: #9AA39B;
  --focus: #ECEEEA;
  --aisle: #161A17;
  --heat-bar-0: #24412F;
  --heat-bar-1: #2F7049;
  --heat-bar-2: #5CC285;
  --inv: #2B312D;
  --on-inv: #FFFFFF;
  --bay-fill: rgba(255, 255, 255, .04);
  --glass: rgba(26, 30, 27, .94);
  --ok: #6FD08F;
  --ok-t: rgba(111, 208, 143, .14);
  --warn: #FFD866;
  --danger: #FF8A80;
  --danger-t: rgba(255, 138, 128, .14);
  color-scheme: dark;
  }
}

/* 큰글씨 mode: everything sized in rem scales together. */
:root.is-large { font-size: 118.75%; }

@media (prefers-reduced-motion: reduce) {
  :root { --dur: 0ms; --dur-2: 0ms; --draw: 0ms; --grow: 0ms; }
}

/* /shared/ui/base.css */
/* ui/base.css — reset + typography + primitives shared by all apps. */
*, *::before, *::after { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; text-size-adjust: 100%; }
body {
  margin: 0;
  background: var(--paper);
  color: var(--ink);
  font-family: var(--font-sans);
  font-size: var(--fs-15);
  line-height: var(--lh);
  letter-spacing: var(--track);
  word-break: keep-all;
  overflow-wrap: anywhere;
  -webkit-font-smoothing: antialiased;
  -webkit-tap-highlight-color: transparent;
}
h1, h2, h3, p, dl, dd, ol, ul, figure { margin: 0; }
ol, ul { padding: 0; list-style: none; }
img, svg { display: block; max-width: 100%; }
button, input, select, textarea { font: inherit; color: inherit; letter-spacing: inherit; }
button { cursor: pointer; }
a { color: var(--ink); text-underline-offset: 3px; }
/* match highlight: the look is a token so each app decides (admin keeps the yellow
   marker; the customer app, where yellow means stops/route only, uses an ink underline) */
mark.hl { background: transparent; color: inherit; font-weight: 700; box-shadow: var(--hl-mark, inset 0 -0.38em 0 var(--stop)); }
.mono { font-family: var(--font-mono); font-variant-numeric: tabular-nums; letter-spacing: 0; }
.sr-only {
  position: absolute !important; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}
:focus-visible { outline: 2px solid var(--focus); outline-offset: 2px; }
.skip-link { position: absolute; left: var(--space-2); top: -60px; z-index: 100; background: var(--inv); color: var(--on-inv); padding: var(--space-2) var(--space-3); }
.skip-link:focus { top: calc(var(--space-2) + var(--safe-top)); }

/* Text button: underline, ≥44px hit area, never hover-only. */
.tbtn {
  background: transparent; border: 0; padding: 0 2px; min-height: var(--tap);
  display: inline-flex; align-items: center; gap: 6px;
  font-size: var(--fs-14); font-weight: 600; color: var(--ink);
  text-decoration: underline; text-decoration-color: var(--ink-4); text-underline-offset: 4px;
}
.tbtn[disabled] { color: var(--ink-4); cursor: default; }
/* Solid button */
.btn {
  min-height: var(--tap); padding: 0 var(--space-4); border: 1.5px solid var(--ink); border-radius: var(--r-10);
  background: var(--inv); color: var(--on-inv); font-weight: 600; font-size: var(--fs-15);
  display: inline-flex; align-items: center; justify-content: center; gap: 8px;
}
.btn--ghost { background: transparent; color: var(--ink); }
.btn[disabled] { opacity: .45; cursor: default; }
.kbd { font-family: var(--font-mono); font-size: 11px; border: 1px solid var(--line-2); border-radius: 3px; padding: 1px 5px; color: var(--ink-3); }
.hair { border: 0; border-top: 1px solid var(--line); margin: 0; }

/* Skeleton shimmer is a flat pulse (no gradient wash). */
.skel { background: var(--heat-0); border-radius: 2px; animation: skel 1.1s ease-in-out infinite alternate; }
@keyframes skel { from { opacity: 1; } to { opacity: .45; } }
@media (prefers-reduced-motion: reduce) { .skel { animation: none; } }

/* Inputs: 16px+ so iOS never zooms. */
.field {
  width: 100%; min-height: 48px; font-size: max(16px, var(--fs-16)); padding: 10px 12px;
  border: 1px solid var(--edge); border-radius: var(--r-10); background: var(--white); color: var(--ink);
}
/* chip: removable "understanding" tokens etc. — hairline, never a coloured pill row */
.chip { display: inline-flex; align-items: center; gap: 4px; min-height: 32px; padding: 0 4px 0 10px; border: 1px solid var(--line-2); border-radius: var(--r-99); background: var(--white); font-size: var(--fs-13); }
.chip-x { min-width: 32px; min-height: 32px; border: 0; background: transparent; border-radius: var(--r-99); font-size: 15px; color: var(--ink-3); }
.tag { display: inline-flex; align-items: center; min-height: 22px; padding: 0 6px; border-radius: var(--r-6); font-size: var(--fs-12); font-weight: 600; }
.tag--ok { background: var(--ok-t); color: var(--ok); }
.tag--warn { background: var(--warn-t); color: var(--warn); }
.tag--danger { background: var(--danger-t); color: var(--danger); }
.tag--ink { background: var(--inv); color: var(--on-inv); }
.num { font-variant-numeric: tabular-nums; letter-spacing: -0.02em; }
.field:focus-visible { outline-offset: 3px; }
.field[aria-invalid="true"] { border-color: var(--danger); }
.err { color: var(--danger); font-size: var(--fs-14); }

/* css/app.css */
/* css/app.css — customer layout, shell and shared primitives. MOBILE FIRST.
   Phone (base) → ≥768px two-column find area → ≥1100px roomier.
   Components size themselves with @container (every .feat is a container),
   because foldable inner screens are wide but short. No fixed heights on text. */

/* ── customer-only token choices ──────────────────────── */
/* yellow means stops/route here, so a search match is an ink underline + bold */
:root { --hl-mark: inset 0 -2px 0 var(--ink); }
/* `hidden` always wins over a component's display (buttons are inline-flex) */
[hidden] { display: none !important; }

/* ── buttons: three tiers ─────────────────────────────── */
/* 1 primary   .btn         ink fill, 44px, radius 10 — one per view
   2 secondary .btn--line   1px ink outline, 40px face (44px hit area)
   3 tertiary  .tbtn        13px text (+ icon), no underline — quiet actions
   Icon-only: .ibtn (44px square). Underlined text is for real links only. */
.btn { min-height: var(--tap); border-radius: var(--r-10); }
.btn--line, .btn--ghost {
  position: relative; min-height: 40px; padding: 0 14px; border: 1px solid var(--edge); border-radius: var(--r-10);
  background: transparent; color: var(--ink); font-size: var(--fs-14); font-weight: 600;
  display: inline-flex; align-items: center; justify-content: center; gap: 6px;
}
.btn--line::after, .btn--ghost::after { content: ''; position: absolute; inset: -2px; } /* 44px hit area */
.btn--line:hover, .btn--ghost:hover { background: var(--heat-0); }
.btn--line[disabled], .btn--ghost[disabled] { opacity: .45; cursor: default; }
.btn--line[aria-pressed="true"] { background: var(--inv); color: var(--on-inv); }
.tbtn { text-decoration: none; font-size: var(--fs-13); font-weight: 600; color: var(--ink-2); padding: 0 4px; border-radius: var(--r-6); }
.tbtn:hover { color: var(--ink); background: var(--heat-0); }
.tbtn[disabled]:hover { background: transparent; }
.ibtn { flex: none; width: var(--tap); height: var(--tap); padding: 0; border: 0; border-radius: var(--r-10); background: transparent; color: var(--ink); display: inline-flex; align-items: center; justify-content: center; }
.ibtn:hover { background: var(--heat-0); }
.ico { width: 18px; height: 18px; flex: none; fill: none; stroke: currentColor; stroke-width: 1.6; stroke-linecap: round; stroke-linejoin: round; }
.tbtn .ico { width: 16px; height: 16px; }
/* choice chips (quick words, other candidates, did-you-mean): a button that LOOKS pressable */
.chip--btn { position: relative; padding: 0 12px; cursor: pointer; color: var(--ink); font-weight: 500; min-height: 36px; }
.chip--btn::after { content: ''; position: absolute; left: 0; right: 0; top: -4px; bottom: -4px; } /* 44px hit area */
.chip--btn:hover { border-color: var(--ink); }
.chip--btn .ico { width: 14px; height: 14px; color: var(--ink-3); }

/* focus: ONE ring. Bordered controls thicken their own border instead of adding
   an outline outside it (no stacked rings, nothing past the 16px gutter). */
.app .field:focus-visible, .dk-field:focus-visible, .dk-memo:focus-visible, .btn--line:focus-visible, .btn--ghost:focus-visible {
  outline: none; box-shadow: inset 0 0 0 1.5px var(--ink);
}
.app .field:focus-visible, .dk-field:focus-visible, .dk-memo:focus-visible { border-color: var(--ink); }
.app .field:focus:not(:focus-visible) { outline: none; }

/* ── layout ───────────────────────────────────────────── */
.wrap { width: 100%; max-width: var(--maxw); margin-inline: auto; padding-inline: max(var(--gutter), var(--safe-left)) max(var(--gutter), var(--safe-right)); }
.app { min-height: 100svh; display: flex; flex-direction: column; }
/* --dock-h: the phone tab bar (56px tabs + 1px rule); home adds the search row (8 + 48 + 4). */
:root { --dock-h: 57px; --dock-search-h: 60px; }
/* the footer (below main) is what clears the fixed tab bar; main only keeps rhythm */
.r-main { flex: 1; display: flex; flex-direction: column; gap: var(--space-5); padding-bottom: var(--space-6); }
.r-main > [hidden] { display: none; }
.r-hero { min-height: 196px; }

/* home: phone = one column in reading order (hero → 매장 한눈에 → 찾은 칸 → 오늘 매장);
   ≥768 = main column (search, memo, 오늘 매장) + aside (plan + ceiling sign, sticky). */
.r-home { display: flex; flex-direction: column; gap: var(--space-6); padding-top: var(--space-4); }
.r-home-main, .r-home-aside, .r-find-side { display: contents; }
/* phone order (client 2026-11-14): search + 메모 → map with 담은 것 → result → busy hours → rest */
.r-find-side { order: 0; }
.r-glance { order: 1; min-width: 0; }
.r-find-result { order: 2; }
.r-hero { order: 3; }
.r-below { order: 4; }
.r-glance[hidden], .r-find-result[hidden], .r-below[hidden], .r-find-side[hidden] { display: none; }
html.is-loading .r-glance:empty::before, #sec-glance:not(.is-ready)::before { content: ''; display: block; aspect-ratio: 3 / 2; margin-top: 56px; background: var(--heat-0); border-radius: var(--r-6); }
.r-find-map { min-width: 0; }
.r-when, .r-tools, .r-guide, .r-directory, .r-visit, .r-ask { display: flex; flex-direction: column; gap: var(--space-6); }
.feat { container-type: inline-size; min-width: 0; }
.r-when > .feat, .r-tools > .feat, .r-guide > .feat, .r-directory > .feat, .r-visit > .feat, .r-ask > .feat { border-top: 1px solid var(--line); padding-top: var(--space-5); }

@media (min-width: 768px) {
  .r-main { padding-bottom: var(--space-7); gap: var(--space-6); }
  .r-hero { min-height: 168px; }
  .r-home { display: grid; grid-template-columns: minmax(300px, 5fr) minmax(0, 7fr); align-items: start; gap: var(--space-6); }
  .r-home-main { display: flex; flex-direction: column; gap: var(--space-6); min-width: 0; }
  .r-home-aside { display: flex; flex-direction: column; gap: var(--space-5); min-width: 0; position: sticky; top: var(--space-4); max-height: calc(100vh - 2 * var(--space-4)); overflow-y: auto; overscroll-behavior: contain; scrollbar-width: thin; padding-bottom: var(--space-4); }
  .r-find-side { display: flex; flex-direction: column; gap: var(--space-5); }
  .r-find-side > .feat + .feat { border-top: 1px solid var(--line); padding-top: var(--space-5); }
  .r-find-result { border-top: 1px solid var(--line); padding-top: var(--space-5); }
  .r-glance[hidden] + .r-find-result { border-top: 0; padding-top: 0; }
  .r-find-map { display: flex; flex-direction: column; gap: var(--space-4); }
  .r-visit { display: grid; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); column-gap: var(--space-7); }
  .r-tools { display: grid; grid-template-columns: repeat(auto-fit, minmax(320px, 1fr)); column-gap: var(--space-7); align-items: start; }
}

/* ── panes & home layout ──────────────────────────────── */
.pane { display: flex; flex-direction: column; gap: var(--space-5); outline: none; }
.pane[hidden] { display: none; }
.r-find-result { min-width: 0; display: flex; flex-direction: column; gap: var(--space-4); }
.r-below { min-width: 0; display: flex; flex-direction: column; gap: var(--space-4); }
.r-mapmain, .r-pane-main { padding-top: var(--space-4); }
/* phone map: the page is scroll-locked (shell/sheets.js), so the pane is exactly
   the space between header and tab bar. The plan fills it (no blank band under
   it) and the details live in a bottom sheet the map feature owns (132px peek). */
@media (max-width: 767.98px) {
  :root { --hd-h: 57px; }
  body[data-pane="map"] .r-main { padding-bottom: 0; }
  .pane--map { height: calc(100dvh - var(--hd-h) - var(--safe-top) - var(--dock-h) - var(--safe-bottom)); overflow: hidden; overscroll-behavior: contain; }
  .pane--map .r-mapmain { height: 100%; padding-top: var(--space-3); padding-bottom: 0; display: flex; flex-direction: column; }
  .pane--map .r-mapmain > .feat--map { flex: 1; min-height: 0; display: flex; flex-direction: column; }
}
.r-more { display: flex; flex-direction: column; gap: var(--space-6); padding-top: var(--space-4); }
.r-group { display: flex; flex-direction: column; gap: var(--space-6); }
.r-group[hidden] { display: none; }
.r-group > .feat { border-top: 1px solid var(--line); padding-top: var(--space-5); scroll-margin-top: var(--space-4); }
.mi-kicker { font-size: var(--fs-12); color: var(--ink-2); margin-bottom: var(--space-1); }
.mi-title { font-size: var(--fs-28); font-weight: 700; letter-spacing: -0.03em; line-height: 1.3; margin-bottom: var(--space-2); }
.mi-group { margin-top: var(--space-5); }
.mi-h { font-size: var(--fs-12); font-weight: 400; color: var(--ink-2); margin-bottom: var(--space-2); }
.mi-row { padding-right: 4px; }
.mi-arrow { width: 18px; height: 18px; color: var(--ink-3); }
@media (min-width: 768px) {
  .r-more { display: grid; grid-template-columns: minmax(240px, 300px) minmax(0, 1fr); column-gap: var(--space-7); align-items: start; }
  .r-more-index { position: sticky; top: var(--space-4); grid-row: 1 / span 6; }
  .r-more > .r-group { grid-column: 2; }
}

/* ── header ───────────────────────────────────────────── */
.r-header { border-bottom: 1px solid var(--line); padding-top: var(--safe-top); }
/* One line at every width (280 → 1440): brand never shrinks, the status line
   ellipsizes, the redundant hours range only appears on wide screens. */
.hd { display: flex; flex-wrap: nowrap; align-items: center; gap: var(--space-3); min-height: 56px; padding-block: 6px; }
.hd-brand { flex: none; display: inline-flex; align-items: center; gap: 6px; text-decoration: none; min-height: var(--tap); white-space: nowrap; }
.hd-name { font-size: var(--fs-18); font-weight: 700; letter-spacing: -0.03em; }
.hd-branch { font-size: var(--fs-14); color: var(--ink-3); }
.hd-status { flex: 0 1 auto; min-width: 0; display: inline-flex; flex-wrap: nowrap; align-items: center; gap: 6px; font-size: var(--fs-13); color: var(--ink-3); white-space: nowrap; font-variant-numeric: tabular-nums; }
.hd-line { min-width: 0; overflow: hidden; text-overflow: ellipsis; }
.hd-open { color: var(--ink); font-weight: 600; }
.hd-dot { flex: none; width: 6px; height: 6px; border-radius: 50%; background: var(--ink-4); }
.hd-dot.is-open { background: var(--ok); box-shadow: 0 0 0 3px var(--ok-t); }
.hd-hours { display: none; color: var(--ink-3); font-size: var(--fs-12); letter-spacing: -0.01em; padding-left: 6px; border-left: 1px solid var(--line-2); }
@media (max-width: 329.98px) { .hd-branch { display: none; } }
@media (min-width: 1024px) { .hd { gap: var(--space-5); } .hd-hours { display: inline; } }
.hd-link[aria-current="page"] { color: var(--ink); font-weight: 600; box-shadow: inset 0 -2px 0 var(--ink); }
.hd-nav { display: none; }
.hd-tools { display: flex; gap: var(--space-3); margin-left: auto; }
.hd-tools:empty { display: none; }
.hd-link { min-height: var(--tap); display: inline-flex; align-items: center; gap: 6px; text-decoration: none; color: var(--ink-3); font-size: var(--fs-14); }
.hd-link:hover { color: var(--ink); }
.hd-count:not(:empty) { min-width: 20px; height: 20px; padding: 0 5px; border-radius: 10px; background: var(--inv); color: var(--stop); font-size: 11px; display: inline-flex; align-items: center; justify-content: center; }
@media (min-width: 768px) {
  .hd-nav { flex: none; display: flex; flex-wrap: nowrap; gap: 0 var(--space-5); margin-left: auto; }
  .hd-tools { margin-left: 0; }
}

/* ── banner / footer ──────────────────────────────────── */
.r-banner:empty { display: none; }
.bn { display: flex; flex-wrap: wrap; align-items: center; gap: 4px var(--space-4); min-height: var(--tap); font-size: var(--fs-14); }
.bn--soft { border-bottom: 1px solid var(--line); }
.r-footer { border-top: 1px solid var(--line); padding-bottom: calc(var(--dock-h) + var(--space-3) + var(--safe-bottom)); }

.ft { padding-block: var(--space-5); display: flex; flex-direction: column; gap: 6px; font-size: var(--fs-12); color: var(--ink-3); line-height: 1.7; }
@media (min-width: 768px) { .r-footer { padding-bottom: var(--space-5); } }

/* ── dock (phone bottom bar) ──────────────────────────── */
.r-dock { position: fixed; left: 0; right: 0; bottom: var(--kb, 0px); z-index: 30; background: var(--paper); border-top: 1px solid var(--line-2); padding: 0 max(8px, var(--safe-left)) var(--safe-bottom) max(8px, var(--safe-right)); }
html.kb-open .r-dock .dk-tabs { display: none; }
.dk { max-width: 640px; margin-inline: auto; display: flex; flex-direction: column; }
.dk-search { display: flex; gap: var(--space-2); }
.dk-search[hidden] { display: none; }
/* home.top: the phone search row, first thing on home (desktop has the inline launcher) */
.r-top { order: -1; margin-bottom: calc(-1 * var(--space-3)); }
.r-top:empty { display: none; }
@media (min-width: 768px) { .r-top { display: none; } }
.dk-field-l { overflow: hidden; text-overflow: ellipsis; }
.dk-memo { flex: none; min-width: 64px; min-height: 48px; padding: 0 12px; border: 1px solid var(--edge); border-radius: var(--r-10); background: transparent; font-weight: 600; font-size: var(--fs-14); }
.dk-tabs { display: flex; }
.dk-tab { flex: 1 1 0; min-width: 0; min-height: 56px; padding: 6px 2px 4px; border: 0; background: transparent; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 2px; font-size: 11px; color: var(--ink-3); position: relative; }
.dk-tab.is-on { color: var(--ink); font-weight: 700; }
/* active tab: an ink bar (yellow is reserved for stops and the route) */
.dk-tab.is-on::before { content: ''; position: absolute; top: -1px; left: 34%; right: 34%; height: 2px; background: var(--inv); }
.dk-ico { width: 22px; height: 22px; fill: none; stroke: currentColor; stroke-width: 1.7; stroke-linecap: round; stroke-linejoin: round; }
.dk-tab .dk-badge { position: absolute; top: 4px; left: calc(50% + 6px); }
.dk-tab-l { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 100%; }
.dk-field { flex: 1 1 auto; min-width: 0; min-height: 48px; display: flex; align-items: center; gap: 10px; padding: 0 14px; border: 1px solid var(--edge); box-shadow: 0 1px 3px rgba(17,17,17,.06); border-radius: var(--r-10); background: var(--white); color: var(--ink-3); font-size: 16px; text-align: left; white-space: nowrap; overflow: hidden; }
.dk-glass { width: 14px; height: 14px; border: 2px solid var(--ink); border-radius: 50%; position: relative; flex: none; }
.dk-glass::after { content: ''; position: absolute; width: 6px; height: 2px; background: var(--inv); right: -5px; bottom: -3px; transform: rotate(45deg); }
.dk-btn { flex: none; min-width: 52px; min-height: 48px; padding: 0 10px; border: 0; background: transparent; font-size: var(--fs-14); font-weight: 600; display: inline-flex; align-items: center; justify-content: center; gap: 4px; }
.dk-btn[aria-current="true"] { box-shadow: inset 0 -2px 0 var(--ink); }
.dk-badge:not(:empty) { min-width: 20px; height: 20px; padding: 0 5px; border-radius: 10px; background: var(--inv); color: var(--stop); font-size: 11px; display: inline-flex; align-items: center; justify-content: center; }
@container (max-width: 300px) { .dk-btn { min-width: 44px; padding: 0 6px; } }
@media (max-width: 330px) { .dk-field span:last-child { overflow: hidden; text-overflow: ellipsis; } }
@media (min-width: 768px) { .r-dock { display: none; } }

/* ── toast ────────────────────────────────────────────── */
.r-toast { position: fixed; left: 50%; bottom: calc(var(--kb, 0px) + 84px + var(--safe-bottom)); transform: translate(-50%, 12px); opacity: 0; pointer-events: none; z-index: 60; width: min(560px, calc(100% - 2 * var(--gutter))); transition: opacity var(--dur) var(--ease), transform var(--dur) var(--ease); }
.r-toast.is-on { opacity: 1; transform: translate(-50%, 0); pointer-events: auto; }
.ts { display: flex; align-items: center; gap: var(--space-3); min-height: 48px; padding: 6px 8px 6px 14px; background: var(--inv); color: var(--on-inv); font-size: var(--fs-14); border-radius: 2px; }
.ts span { flex: 1; min-width: 0; }
.ts-undo { min-height: 40px; padding: 0 12px; border: 1px solid var(--on-inv-2); border-radius: var(--r-10); background: transparent; color: var(--on-inv); font-weight: 600; }
@media (min-width: 768px) { .r-toast { bottom: var(--space-5); } }

/* ── sheets (phone) ───────────────────────────────────── */
.sh-head { display: none; }
@media (max-width: 767.98px) {
  [data-sheet] {
    position: fixed; z-index: 50; left: 0; right: 0; top: calc(var(--safe-top) + 10vh); bottom: var(--kb, 0px);
    background: var(--paper); border-top: 1px solid var(--line-2);
    padding: 0 max(var(--gutter), var(--safe-left)) calc(var(--space-5) + var(--safe-bottom)) max(var(--gutter), var(--safe-right));
    overflow-y: auto; overscroll-behavior: contain; -webkit-overflow-scrolling: touch;
    transform: translateY(calc(100% + 24px)); visibility: hidden;
    transition: transform var(--dur) var(--ease), visibility 0s linear var(--dur);
  }
  [data-sheet="search"] { top: var(--safe-top); border-top: 0; }
  [data-sheet].is-open { transform: translateY(var(--drag, 0px)); visibility: visible; transition: transform var(--dur) var(--ease); }
  [data-sheet].is-dragging { transition: none; }
  .sh-head { display: flex; align-items: center; gap: var(--space-3); position: sticky; top: 0; z-index: 2; background: var(--paper); min-height: 52px; margin-inline: calc(-1 * var(--gutter)); padding: 0 var(--gutter); border-bottom: 1px solid var(--line); touch-action: none; }
  .sh-grab { position: absolute; left: 50%; top: 6px; width: 36px; height: 4px; margin-left: -18px; border-radius: 2px; background: var(--line-2); }
  .sh-title { flex: 1; font-size: var(--fs-16); font-weight: 700; }
  .sh-close { margin-right: -10px; }
  html.is-locked, html.is-locked body { overflow: hidden; }
  html.is-dimmed body::after { content: ''; position: fixed; inset: 0; z-index: 45; background: rgba(17, 17, 17, .28); }
}


/* ── shared primitives used by features ───────────────── */
.sec-head { display: flex; flex-wrap: wrap; align-items: baseline; justify-content: space-between; gap: 4px var(--space-4); margin-bottom: var(--space-3); }
.sec-h { font-size: var(--fs-22); font-weight: 700; letter-spacing: -0.03em; line-height: var(--lh-tight); }
.sec-h--sm { font-size: var(--fs-16); }
.sec-sub { font-size: var(--fs-12); color: var(--ink-3); }
.note { font-size: var(--fs-13); color: var(--ink-3); line-height: 1.65; }
.note--ink { color: var(--ink-2); }
.meta { font-size: var(--fs-12); color: var(--ink-3); }
.rows { display: flex; flex-direction: column; }
.row { border-top: 1px solid var(--line); min-height: 56px; display: flex; align-items: center; gap: var(--space-3); }
.row:last-child { border-bottom: 1px solid var(--line); }
.row-main { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 2px; padding-block: 8px; }
.row-title { font-size: var(--fs-15); font-weight: 600; line-height: 1.4; }
.row-btn { flex: 1; min-width: 0; min-height: 56px; display: flex; align-items: center; gap: var(--space-3); padding: 0; background: transparent; border: 0; text-align: left; color: var(--ink); }
.bnum { font-family: var(--font-mono); font-weight: 600; font-variant-numeric: tabular-nums; letter-spacing: -0.02em; min-width: 2.2ch; text-align: right; font-size: var(--fs-22); line-height: 1; }
.bnum--sm { font-size: var(--fs-16); }
.ord { width: 28px; height: 28px; flex: none; border-radius: 50%; display: inline-flex; align-items: center; justify-content: center; font-family: var(--font-mono); font-size: 12px; font-weight: 600; border: 1.5px solid var(--ink-4); color: var(--ink); background: transparent; }
.ord.is-on { background: var(--inv); border-color: var(--ink); color: var(--stop); }
.tog { flex: none; min-width: var(--tap); min-height: var(--tap); padding: 0 10px; border: 0; background: transparent; display: inline-flex; align-items: center; justify-content: center; gap: 6px; font-size: var(--fs-13); font-weight: 600; color: var(--ink); }
.tog .ord { width: 26px; height: 26px; }
.empty { padding: var(--space-4) 0; font-size: var(--fs-14); color: var(--ink-3); display: flex; flex-direction: column; gap: var(--space-2); }
.feat-error { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-3); font-size: var(--fs-14); color: var(--ink-3); padding: var(--space-3) 0; }
.stock-low { color: var(--ink); font-weight: 600; }
.stock-out { color: var(--ink-3); text-decoration: none; }
.dl { display: grid; grid-template-columns: max-content 1fr; gap: 8px 16px; font-size: var(--fs-14); }
.dl dt { color: var(--ink-3); }
.dl dd { margin: 0; min-width: 0; }

/* ── boot: skeletons reserve space (no CLS) ───────────── */
html.is-loading .r-hero:empty::before { content: ''; display: block; height: 150px; max-width: 420px; background: var(--heat-0); }
html.is-loading .r-find-map:empty::before { content: ''; display: block; aspect-ratio: 3 / 2; background: var(--heat-0); border: 2px solid var(--line-2); }
.fatal { padding-block: var(--space-7); display: flex; flex-direction: column; gap: var(--space-3); max-width: 560px; }
.fatal-title { font-size: var(--fs-22); font-weight: 700; }
.fatal-actions { display: flex; flex-wrap: wrap; gap: var(--space-3); margin-top: var(--space-3); }
.noscript { padding: var(--space-5); }

@media print {
  .r-header, .r-dock, .r-toast, .r-banner, .r-footer { display: none !important; }
}

/* add/remove pill (shelf rows, search rows): "+ 담기" outline ↔ "✓ 담음 | 빼기" filled with a
   visible remove half, so taking an item out never relies on guessing that a re-tap removes it */
.pill-tog { flex: none; min-height: 36px; padding: 0 12px; border: 1px solid var(--edge); border-radius: var(--r-99); background: var(--white); color: var(--ink); font-size: var(--fs-13); font-weight: 600; display: inline-flex; align-items: center; gap: 8px; white-space: nowrap; position: relative; }
.pill-tog::after { content: ''; position: absolute; inset: -4px 0; } /* 44px hit area */
.pill-tog.is-in { background: var(--stop); border-color: var(--stop); padding-right: 4px; color: var(--on-stop); }
.pill-on { font-weight: 700; }
.pill-x { display: inline-flex; align-items: center; min-height: 28px; padding: 0 10px; border-radius: var(--r-99); background: rgba(17, 17, 17, .1); font-weight: 600; }
.sg-tog.is-in { background: var(--stop); border-color: var(--stop); color: var(--on-stop); gap: 10px; padding-right: 6px; }
.sg-tog-x { display: inline-flex; align-items: center; min-height: 30px; padding: 0 12px; border-radius: var(--r-6); background: rgba(17, 17, 17, .1); font-weight: 600; }

/* light/dark toggle: a quiet 44px icon button at the end of the header */
.hd-theme { flex: none; margin-left: auto; width: var(--tap); height: var(--tap); padding: 0; border: 0; border-radius: var(--r-99); background: transparent; color: var(--ink-2); display: inline-flex; align-items: center; justify-content: center; }
.hd-theme .ico { width: 20px; height: 20px; fill: none; stroke: currentColor; stroke-width: 1.6; stroke-linecap: round; stroke-linejoin: round; }
.hd-theme:hover { background: var(--heat-0); color: var(--ink); }
@media (min-width: 768px) { .hd-nav + .hd-theme { margin-left: 0; } }
body { background: var(--paper); color: var(--ink); }
